코드 구성요소 분류하기
이틀동안, 커스텀 키보드로 입력한 코드 구성요소를 따로따로 저장하고
저장한 요소를 조합하여 코드로 띄우는 기능을 만들었다.
이때 코드 구성요소를 저장하는 방법때문에 삽질을 많이 했다..
코드 구성요소는 다음과 같다.
루트, 루트#/b, 루트 텐션,
마이너, 마이너텐션, 메이저, 메이저텐션,
텐션#/b, 텐션, ASDA, ASDA텐션,
베이스, 베이스#/b
이렇게 구성요소가 매우 많은 데에는 텐션의 위치가 여러군데 가능하기 때문이다.
C2 와 같은 코드는 루트가 C이고, 루트 텐션이 2인 것으로 보았다.
루트 텐션과 그냥 텐션을 나눈 이유는 간단하다.
C2(#9) 과 같은 코드를 작성하기 위해서이다.
ASDA는 add, sus, dim, aug 의 첫글자를 따서 지었다.
저 4가지 종류의 코드타입은 서로 중복될 수 없기에 종류에 맞게 저장하도록 하였다.
이때 add, sus 는 반드시 숫자가 따라붙고, dim, aug도 경우에 따라 숫자가 붙는데
이 숫자를 ASDA 텐션으로 명명하였다.
이 조합으로도 모든 코드를 나타내지는 못한다.
검색해보니 Cadd2add4 같은 코드도 있던데...
이건 그냥 나타내는 걸 포기했다.
저런 코드를 과연 실제로 쓸 일이 얼마나 있을까..ㅋㅋㅋ
다만 Cm7(b9)(b11) 과 같은 코드는 종종 쓸 수도 있겠지만 안타깝게도 나타내지 못한다..
코드 구성요소를 저장할 공간 만들기
이 부분때문에 시간을 꽤 소비했다.
처음에는 저 모든 요소를 변수를 따로 나눠 ChordCell 위젯의 state에 저장했다.
그러다 이걸 변수로 관리하지 말고 비슷한 '코드'라는 그룹의 변수니까
맵으로 관리하면 어떨까 싶어서 맵으로 고쳐보았다.
모든 변수이름을 하나하나 맵의 key로 고쳐서 맵을 만들었다.
작동도 테스트했고, 맵에 맞게 코드도 모두 고쳤다.
그러나 이렇게 하고나니 걱정거리가 생겼다.
첫번째는 코딩할 때 맵의 key를 잘못 쓰는 경우이다.
이 경우 컴파일 오류없이 새로운 key에 값을 저장해버리니 디버깅이 힘들 것 같다고 생각했다.
또한 이렇게 나누어서 저장한 코드 요소를 결국에 하나의 코드 문자열로 변환해야 하는데
그 변환 과정이 꽤 복잡해서 하나의 함수로 만들고 싶었다.
그런데 이걸 그냥 함수로 빼놓기보다 기존의 맵과 합쳐서 하나의 클래스로 관리하면 어떨까 하는 생각이 들었다.
(도대체 왜 이 생각을 처음부터 하지 못했을까....!!!)
프로젝트의 버전관리를 시작하기
그러다 문득 갑자기 한가지 걱정거리가 생겼다.
저장 구조를 맵에서 클래스로 고치다가 오류가 발생하면, 복원하기가 생각보다 힘들 것 같이 느껴졌다.
여기에서 Git의 필요성을 느꼈다.
내가 만약 이걸 깃으로 관리하고 있었다면 그냥 따로 브랜치를 파서 만들어 보고,
오류가 없으면 기존 코드에 머지하면 되는 일이다.
그래서 당장 깃을 공부해서 써보기로 했다.
(전에 개발학회에서 깃을 가볍게 공부한 적이 있었는데,
당장 필요하다고 느껴지지도 않는 공부를 CLI 환경에서 실습하고있자니 지루해서 공부를 포기했었다.)
깃을 공부할 때는 유튜브를 활용했다.
어떤 블로그 글을 봐도 잘 와닿지가 않던 와중, 이 영상을 보고 갈증이 해소되었다.
https://www.youtube.com/watch?v=FXDjmsiv8fI&t=441s
진짜.. 설명을 너무 잘해주셨다.
바로바로 쏙쏙 이해되고 실무 예시를 들면서 설명해주셔서 너무 좋았다.
하지만 이 강좌는 매우 짧고 간단하게만 설명이 되어있어서 이 강의를 보고나면 새로운 갈증이 느껴진다.
이제 깃을 이해했으니 더 자세하게 알고싶다는 욕구가 들 때쯤 이 영상을 보고 다시 갈증을 해소했다.
https://www.youtube.com/watch?v=Z9dvM7qgN9s
전에 깃 공부해봐야지 하고 절반쯤 봤다가 지루해서 껐었는데,
필요성을 절실히 느끼는 상황 & 앞서 소개한 영상으로 깃을 이해한 상황에서 이 영상을 보니
전혀 지루하지 않게 한번에 47분짜리 영상을 다 봤다. (물론 2배속으로 봤다)
https://github.com/kckc0608/Chord-Everdu
그래서 이렇게 원격 저장소까지 만들었다.
그동안 깃허브는 나에게 '소스코드 저장소' 같은 공간이었다.
오로지 '커밋'만 할 뿐 뭔가 합치거나 브랜치를 나누는 작업은 할 줄도 몰랐었다.
지금은 깃허브의 브랜치를 덕분에 신세계를 경험중이다!
입력한 코드를 텍스트로 띄우기
깃허브로 버전관리를 하면서 안전하게 성공적으로 클래스를 이용해 코드를 저장하게 되었다.
다음과 같이 버튼을 터치하여 코드를 입력할 수 있게 되었다.
조금 더 복잡하게 코드를 써보았다.
dim, aug 같은 경우에는 7만 넣을 수 있도록 했다.
다른 숫자를 터치하면 추가 텐션을 넣는 모양이 나온다.
이렇게 숫자 텐션을 넣을 수도 있다.
코드를 저장할 DB 테이블 만들기
이제 코드를 저장할 시간이다.
우선 악보 id 를 FK로 사용하여 join할 생각이다.
그리고 코드 테이블에서 코드를 구분하는 PK는 3가지를 사용한다.
악보 id, page id, chord id
같은 악보의 같은 페이지에 있는 코드들을 id로 구분하는 것이다.
코드 구성요소를 모두 따로따로 저장해야 하기 때문에 이렇게 DB를 만들었다.
완성된 코드 스트링을 저장하는 방법도 고민했지만, 그 경우 코드를 불러와서 커스텀 키보드로 보여줄 때,
코드 스트링을 다시 요소별로 분할해야 한다.
이때 C#9 의 경우 C# + 9 인지 C + #9 인지 모호한 경우가 생긴다.
그래서 이런 부분을 피하고자 그냥 구성요소별로 나눠서 저장하도록 했다.
아직 테이블에 데이터는 아무것도 들어있지 않다.
사실 데이터를 임의로 넣고 앱에서 받아오는 테스트를 해보았고 성공적으로 데이터를 가져왔지만,
테이블에서 코드 데이터를 일일이 임의로 넣는다는 노가다를 하고 싶지가 않아서
그냥 빨리 DB에 코드를 저장하는 코드를 짜기로 마음먹었다.
그리고 이걸 구현하는 도중 문제가 발생했다.
Chord 클래스를 코드셀 내부에서 외부로 옮기기
플러터는 프레임워크 특성상 부모 위젯에서 자식 위젯의 프로퍼티를 가져오기가 힘들다.
반대로 자식위젯이 부모위젯의 프로퍼티를 가져다가 쓰는 방식이다.
이런 구조이기 때문에 매우 불편하지만, 값을 가져옴에 있어서 안전성을 보장받을 수 있다.
(상속 관계에서 업캐스팅과 다운캐스팅을 생각해보면 좋다.)
코드를 서버에 저장하려면 각 ChordCell 위젯에 저장되어 있는 Chord 클래스를 참조하여
그 클래스 데이터를 리스트에 모아서 담고,
최종적으로 리스트에 다 담았으면 이걸 json으로 인코딩해서 웹서버에 전송한다.
백엔드에서는 받은 json을 디코딩해서 array로 만들고, 이 데이터를 가지고
SQL 쿼리를 돌려 DB에 데이터를 추가하면 된다.
이 과정의 첫 발자국이 바로
ChordCell 위젯에 저장되어 있는 Chord 클래스를 참조하는 것
그런데 위에서 말한대로 ChordCell 위젯에서 Chord클래스를 참조할 수가 없다.
물론 어떻게든 어거지로 가져오려고 한다면 가져올 수는 있겠지만.. 쉽지 않다.
그래서 스택오버플로우를 검색해보니 다음과 같은 답을 얻었다.
'자식 위젯에 담을 데이터는 부모위젯에서 가지고 있다가
자식 위젯을 만들 때 넘겨주어야 합니다.'
그래서 불가피하게 코드셀 내부에 있는 코드 객체를 바깥으로 빼고,
이 과정에서 꼬이는 문제들을 해결하는데 하루종일 시간을 썼다.
다행히 코드 입력, 코드셀 추가/삭제/줄넘김/줄넘김취소, 새 악보 저장
모두 문제없이 작동하는 것을 확인했다.
최종적으로 깃허브에 모든 변경사항을 커밋하는 것으로 오늘의 작업은 끝났다.
내일은 본격적으로 DB에 코드 데이터를 저장하는 기능을 구현해 볼 것이다.
'개인 프로젝트 > [2021] 코드악보 공유APP' 카테고리의 다른 글
15. 파이어베이스로 백엔드 이전 & 악보에 대한 CRUD 구현 (0) | 2021.07.28 |
---|---|
14. 악보 편집 기능 만들기 - UI수정, Provider, 편집한 악보 저장 (0) | 2021.07.21 |
12. 악보 편집 기능 만들기 - 커스텀 키보드 토글 버튼 기능 구현 (0) | 2021.07.16 |
11. 악보 편집 기능 만들기 - 코드 줄넘김/줄넘김 취소 & 커스텀 키보드 (0) | 2021.07.15 |
10. 악보 편집 기능 만들기 - 커스텀 탭, wrap 위젯, 커스텀 키보드 (0) | 2021.07.13 |