Loading
2022. 4. 3. 23:15 - lazykuna

[개발회고록] LyricsMaster

가장 마지막으로 개발했던 0.45 버전의 스크린샷을 가져왔습니다.

상당히 오래전에 개발했던 프로그램입니다. 언제지... 포스트 쓴 날짜로 보니 2011년입니다. 무려 10년 전에 만들었던 프로그램이네요.

다시 생각해보니 저 프로그램을 만든지 10년밖에 지나지 않았는데, 세상이 놀라울 정도로 많이 바뀌었습니다!

더 시간이 지나 제가 기억하고 있는 기억들이 사라지기 전에, 이제라도 글로 기억을 남겨 봅니다.

당시의 개발 환경

먼저 지금과 당시는 개발환경이 상당히 달랐습니다. 이는 당시의 인프라에서 비롯한 점도 있지만, 제가 접했던 환경에서 비롯한 요인도 있다고 봅니다.

기억하는 당시의 개발 환경

  • StackOverflow 같은 사이트가 없었거나, 혹은 영향력이 작았다. 그 자리를 대신 codeproject나, 국내에서는 kldp 혹은 네이버 지식iN이 그나마 활성화된 커뮤니티였다.
    • 지금처럼 개발자들이 서로 앞다투어 블로그에 온갖 개발 정수를 올리는 시절은 상상도 못 했다. 그랬다면 훨씬 덜 해매었겠지...
  • Visual Studio C++ 6.0이 C++ IDE와 컴파일러의 정수였다. C++ 언어 자체나 c++98과 같은 스펙에 대한 심도깊은 고민보다는, 저 툴 자체에 대한 서적과 정보가 많았던 시기였다.
    • 그나마 당시에는 VC2010이 나와서, 최신툴이면 우와우와하고 사족을 못 쓰던 시기라 좋다고 구해다 썼던 기억이 있다 (...)
  • Github 같은 건 없었다. 그래서 블로그에 정보를 공유하기보다는 만든 바이너리를 올리곤 했다. 지금에서는 Github release가 있으니 굳이 그럴 필요가 없다.

나 자신이 마주했던 개발 환경

  • C++에 한창 재미가 들렸었던 시기였다. Win32 API를 사랑했고, 그걸로 별의 별 짓을 다했던 기억이 새록새록...
  • 오픈소스도, 프레임워크에 대한 지식도 전무했다. 그냥 내가 다 만들고 구현한 게 전부였다. 심지어 ID3 태깅도 documentation 하나 안 보고 내가 손수 포멧 다 일일이 분석해서 로직을 짰다 (...)
    • 어쩌면 당시 제대로 된 라이브러리가 없었을지도 모르겠다. 당시 mp3 라이브러리가 오픈소스가 아니었고, 찾아봤던 기억이 있는데 모두 직접 손으로 짠 코드 예시밖에 없었던 기억이 얼핏 난다.
  • Windows 프로그래밍을 좋아했다. 왜냐하면 그걸로 유용한 프로그램을 만들 수 있었고, 결과가 눈에 바로 보이는 점도 매력적이었고, 클라이언트 프로그램을 만들 수 있어, serverless(?)한 개발을 할 수 있다는 점이 나에게 큰 매력이었다.
    • 당장 처음 시작했던 개발 언어가 html/javascript, flash 였던 걸로 기억하는데, 배포할 서버가 있어야 했던 점이 나에게 장벽이었다.
  • 마지막으로, 당시 나는 일반계 고등학생이었다. 당시 똑똑한 친구들(흔히 말하는 정보올림피아드 고수)과 접하기도 어려웠다.

MP3P 그리고 J-POP

이 프로그램을 설명하기 전에 빼놓을 수 없는 게 음악 이야기입니다.

이제는 추억의 물건이지만, 2010년 즈음에는 MP3P / PMP라는 물건이 있었습니다. CDP가 플래시 메모리로 바뀌고, 2인치 남짓의 큼지막한(?) 액정이 달리게 되어 나중에는 동영상까지 재생할 수 있게 되면서 당시 하루종일 학교에 있어야 했던 수많은 학생들의 몇 안되는 즐거움을 책임졌습니다.

제 중학생부터 고등학생까지의 시절을 책임졌던 YP-P2가 떠오르네요 ㅎㅎ. 이마저도 돈이 없었던 저는 이걸 직접 구매한 것이 아니고, 대회 공모전 나가서 타왔던 상품으로 기억하고 있습니다.

그리고 재미있는 점 중 하나가, 당시의 MP3P는 어째서인지 가사 기능을 대부분 모두 지원하고 있었습니다. 그리고 그 기능은 당시 어쩌다 보니 접한 J-POP에 심취해 있던 저에게 굉장히 유용했습니다 ㅎㅎ. 아마 제로의 사역마 한번 잘못 봤다가 맛들렸던 걸로 기억을 합니다...

그런데, 가사 기능을 막상 사용하기에는 꽤 불편함이 있었습니다. 첫번째로, 가사를 넣기 위해서는 메이커의 전용 프로그램을 반드시 이용해야만 했습니다. 이를테면 아이리버, 코원, 삼성 3개의 MP3P를 사용중이었다면 3가지의 프로그램들을 설치해야만 했습니다. 두번째로, 가사를 넣으려면 가사를 담고 있는 lrc 파일을 준비해야 했고, 각 파일마다 일일이 가사를 입혀주어야 했습니다. 노래가 100곡 있으면 lrc 파일을 준비해놓고, lrc파일을 선택해서 가사를 입히는 작업을 100번 반복해야 한다는 이야기인데, 정말 단순 노가다라서 직접 해보면 기분이 좋지 않습니다. 마지막으로, 자동으로 가사 파일을 찾아주는 기능이 없었습니다.

개발 일지

대부분의 정보는 이 포스트에 쓰여 있습니다. 다만 글이 다 깨져있네요 (...)

몇가지 생각나는 정보들을 더듬어서 써 보면...

MP3 파일에 가사 삽입

이 부분이 프로그램의 주된 목표이자, 가장 어려웠던 부분이었습니다. 목표를 달성하기 위해서 넘어야 할 문제가 크게 두 가지가 있었는데,

  • MP3 파일 tagging 포멧에 대한 개념적 이해와 구현
  • 가사 데이터의 구조 파악과 구현

이 중 첫번째는 당시 취미로 개발하던 저에게 있어 마냥 쉬운 일은 아니었습니다. 당시 오픈소스의 존재도 잘 몰랐고, 아마 기억하기로 mp3 파일 자체가 closed format 이었던 시절이라서 직접 구현해야 했었던 것으로 기억합니다.

출처: Wikipedia

그래서 위와 같은 mp3 file structure 같은 정보를 직접 찾아 보고 이해하면서 구현하는 것이 또 하나의 큰 난관이었습니다. 지금에서야 그닥 어렵지 않은 내용이지만, 당시 생소한 섹션의 개념과, 섹션별로 붙은 생소한 용어들을 이해하고, 직접 hex 에디터로 파일을 열어보기도 하며, 구현하면서 디버거를 몇번이나 붙였는지 싶습니다. 데이터 검증은 ID3 Tag Viewer이나 foobar로 했던 것 같네요. 당시에는 잘 몰랐는데, 개발 역량을 기르는 데 굉장히 큰 도움을 주었던 것 같습니다.

가사 데이터의 구조 파악은 도메인 로직에 해당되는 부분이었는데, 문제는 해당 부분은 closed format이었습니다. 파일 포멧을 파악하기 위해서 hex diff도 떠보고, 간단한 가사 파일 테스트 셋과 바이너리 리버싱을 통해 결국 어느 정도 자료 구조를 유추하는데 성공했습니다. 이런 류의 작업은 검증이 으레 문제가 되는데, 다행히도 가사 삽입 프로그램 자체에 가사 뷰어 기능이 있어서 직접 기기 없이도 테스트를 쉽게 해 볼수 있었습니다.

자동으로 가사 찾기

이 점 또한 당시 저에게 있어서 큰 난관이었습니다. 대략 기억나는 것들을 정리해보면...

  • 네트워크 통신은 어떻게 하지?
  • 어떻게 가사 데이터를 가지고 올 수 있을까?

네트워크 통신 같은 경우는 당시 오픈소스를 잘 써볼 생각도 안 했지만, 오픈소스 문화 자체가 그렇게 활성화되어 있지 않았던 것으로 기억합니다. 그래서, 애당초 오픈소스를 알아볼 생각도 안 했고 당시 Win32 바탕으로 개발을 하다 보니, Windows socket API를 그대로 써서 어쩌저찌 개발했던걸로 기억합니다. API 호출을 위해서 socket open을 하고, 데이터를 보내고, 받아오고 gracefully close하는 방법까지 모두 직접 익히고 개발했습니다. 부족한 점이 많았지만, 어쨌든 첫 네트워킹 프로그램을 개발했다는 데 의의를 두는 것으로... 지금 보면 정말 난잡하기 그지없네요 헛헛...

가사 데이터를 가지고 오는 부분은 설계의 영역이 컸습니다. 사운드 파일과 일치하는 가사를 어떻게 가져올 것인지를 고민할 필요가 있었습니다. 사실 이 설계는 제가 한 게 아니라 기존 있는 것을 그대로 쓴 것이지만요.

당시 사용하던 방식이 크게 두가지였는데, 장단점이 있었습니다. 첫번째는 음악 파일의 태그 정보(제목 및 가수)를 통해 검색하는 것이었고, 두번째는 음악 파일의 데이터를 해시하여 이와 exact match하는 오디오 파일을 가지고 오는 방법이었습니다. 전자의 경우 그럭저럭 가사는 잘 가져오지만, 오디오파일에 메타데이터가 빠져있거나 특수문자가 들어있거나, 그리고 일부 오디오 파일에 패딩이 있는 경우 싱크가 안 맞는 문제가 있었습니다. 후자의 경우 오디오 자체를 해시하여 검색하기 때문에 메타데이터 누락이나 오디오 싱크에 강점이 있지만, 오디오 데이터가 조금이라도 바뀌면 해시가 완전히 달라져서 distance search를 할 수 없는 단점이 있습니다. 하지만 후자의 방식이 꽤 강력했는데, 이유는 오디오 데이터는 보통 재가공을 하지 않고 공유되는 일이 많기 때문이죠.

다만 아쉬운 점은 생각해보면 이렇게 서버로부터 데이터를 가져와서 쓰는 일은 자료의 출처나 저작권 등을 신경쓰고 했어야 할 작업이었는데, 당시에는 그런 점이 부족했습니다.

Worker thread와 UI의 분리

“여러 파일들에 가사를 입히는 작업"은 엄연히 오랜 시간이 걸리는 작업입니다. 그런 작업을 할 때는 으레 프로그레스 바를 달아서, 사용자가 기다리거나 혹은 취소할 수 있도록 하게 만들어집니다. 그런데, 이런 것을 직접 만드려니 생각보다 고민해야 할 점이 많았습니다.

첫 번째로, worker 스레드에서 건드릴 수 없는 UI 컴포넌트가 절 괴롭혔습니다. 이게 왜 안 되는지 이해하기까지 오랜 시간이 걸리기도 했고, 당시 모듈화나 객체화 그런거 없이 코드를 이벤트 핸들러에 그냥 뭉터기로 넣어서 짜던 저에게는 상당히 괴로운 첫번째 난관이었습니다. 당시에는 정말 더럽게 전역변수 떡칠로 어떻게 처리했던 기억이 있는데, 지금 생각해보면 Message Queue를 이용해서 짰어야 하는 게 아니었나 싶네요.

두번째로 작업의 취소 방법이었습니다. 프로그램 종료하듯이 쓰레드를 그냥 종료시켜 버리면 작업을 취소될 줄 알았는데, 그게 아니더라고요 ^^; 직접 짜고서야 알 수 있었습니다. 워커 스레드를 종료하기 위해서는 cancel 시그널을 보내고 스레드 join을 시켜야 한다는 것은 지금 생각해보면 당연한 이야기지만, 이 당연한 이야기들은 당시의 저에게 너무나도 생소한 내용들이었습니다.

공모전 출품

그때 어떤 일이었는지는 잘 기억이 안 나는데... 어쩌다 보니 이 프로그램을 KOI에 출품하게 되었습니다. 그런데 또 운이 좋게 시상을 했던 기억이 있네요.

주변 과고 출신 분들의 공모전 작품들은 파형 계산같은 신기하고 멋진 작품들이 많았는데, 그런 것들에 비해 제 작품은 너무 초라하기 그지 없어서 그냥 참가에 의미를 두기로 했었는데, 의외로 높은 평가를 받게 되어서 기뻤으면서도 아리송했던 기억이 있었습니다. 당시 작품에 대한 설명은 미흡했지만, 위의 저 문제들을 해결하고 궁극적으로 목표를 달성했던 점을 전달할 수 있었고, 그 점에 대해서 높은 점수를 받은 게 아니었나 생각해 봅니다.

스스로 해보는 평가

당시 만들었던 저 프로그램은 성공적이었다고 생각합니다.

왜냐하면 기본적인 목표였던 “쉽게 가사를 넣을 수 있도록 해주는 툴"로서의 기능을 완벽하게 수행하는 데 성공했고, 또한 개발하면서 많은 중요 개념들(소켓통신, 멀티스레딩, UI 스레드, 데이터 구조, 리버싱 등)을 직접 공부하고 체험하며 제 스스로가 발전할 수 있었던 기회였으니까요.

이와 더불어 여러 기능요청(=댓글)을 보면서 이른바 “이슈 처리” 작업을 해볼 수 있는 기회도 있었던 점도 좋은 경험이었습니다. 물론, 기한도 없고 보수도 없고 핵심 기능은 이미 다 만들었던지라 그렇게 큰 비중을 차지하지는 않았지만요 ㅎㅎ.

코드

모르겠습니다. 어지간하면 개발하고 남은 코드를 함부로 날려버리는 일은 없는데, 어디 갔을까요? 하드를 뒤지면 나올까... 혹시 찾게 되면 개인 깃허브에 올려보도록 하겠습니다.

운 좋게 코드를 찾아 올려두었습니다.

'개발 > Product' 카테고리의 다른 글

[개발회고록] iidx ranktable service  (4) 2022.04.24
bmx2ogg 프로그램 - bms 파일을 음악파일로 변환  (0) 2015.12.25
안드로이드 BMS 에디터 - sabuneditor  (2) 2014.07.13
LR2Server  (4) 2014.01.15
DCImageRename  (0) 2013.08.25