오랫동안 꾸준히 받은 요청 - '영어 자막 같이 나오게 해 주세요'


그리고 나는 이 요청을 꽤 오랫동안 미뤄왔다. 왠지 한글/영어 자막이 동시에 나오는 순간, 훌륭한 강연이 어학 공부용 샘플 영상으로 전락하는게 아닌가 싶은 걱정이 들었기 때문이다. 그런 걱정 때문에 오랫 동안 고민의 고민을 거듭했고, 그래서 이 기능을 계속해서 미뤄왔다.


그러다가 작년 말, 영어로 발표되는 한 원어 그 자체가 갖는 뉘앙스가 제대로 전달되지 않으면 발표 또한 제대로 전달되지 않는 건 아닐까? 하는 생각이 들었다. 그리고 빠른 프로토타이핑을 통해 해당 기능을 구현해 시청해 본 결과 - 잘 모르겠다;


솔직히 말하자면 잘 모르겠다. 어떤 강연은 조금 나아진 것 같았다. 하지만 어떤 강연은 정신 사나웠다. 시간 제한을 두고 많은 내용을 발표하기 때문에 말이 빠르다. 한글 자막만 봐도 따라가기 힘든데 영어 자막까지 같이 볼 겨를이 있겠는가?


그래서 재생 속도를 조금 늦춰봤다. 많이 늦추면 소리가 이상해져서 0.8 배속으로 돌려봤다. 아- 이제 좀 볼만하다. 하지만 발표가 좀 더 제대로 전달되는 느낌 보다는 그냥 '같이 나오니까 좋네' 싶은 생각이 더 컸다. 


그러던 중 TED 공식 앱이 자막을 지원하기 시작했다. TEDiSUB 출시 3년만이다. TED 공식 앱 개발팀으로부터 메일로 어떻게 비디오에 자막을 입히냐고 문의가 와서 안되는 영어로 이렇게 저렇게 했어요- 라고 답한지 2년 만이다. (한 차례 더 자세한 질문을 해왔지만 답장을 쓰다가 포기했다. 나는 영어에 굉장히 약하다)


이제 '강연의 시청' 에 중점을 둔 TEDiSUB은 더 이상 그 가치를 지속하기 어렵다. 선택의 여지가 없다. 최대한 강연의 본질을 훼손하지 않는 범위 내에서 새로운 목표를 세워야 할 필요가 생겼다.






새로운 목표 - '강연의 활용'


그래서 그 다음 발걸음으로 '강연의 활용' 에 중점을 두기로 했다. 다만 나는 여기에 한 가지 제약을 걸었다. 강연의 본질을 최대한 훼손시키지 말 것!


서로 다른 두 언어의 자막을 지원하는 것 만으로도 강연의 본질이 훼손되는 것이 아닌가 하는 논란에 대해서는 솔직히 자신있게 '훼손되지 않습니다' 라고 답할 자신은 없다. 나는 이 질문에 대한 대답을 사용자에게 맡긴다. 어학용으로 강연을 본다 한들 그래서 더 자세하게 강연의 내용을 탐구하게 된다면 이는 훼손이 아닌, 긍정적 효과를 낳는다고 믿는다. 또는 원어가 갖는 뉘앙스를 보충하고자 영어 자막을 별도로 켜는 사람들도 있을 것이다.


어쨌든, 나는 두 개 언어의 자막을 동시에 보는 기능을 구현하기로 결정했다. 하지만 동시에 영어 사전 기능, 일부 단어를 스크랩하는 기능, 스크랩한 단어를 단어장처럼 보여주는 기능 등의 어학용 기능들을 모두 배제했다. 앞으로도 이러한 기능들은 구현하지 않을 것이다.


내가 생각하는 강연의 활용은 어학 도구로서의 그것이 아니다. 강연의 내면을 좀 더 이해할 수 있게 하고, 강연의 감상을 잘 정리할 수 있게 돕고, 정리한 강연을 쉽게 공유할 수 있는 인터페이스를 제공하는 것을 목표로 하고 있다. 물론 이번 TEDiSUB 3.0 버전에서는 이러한 기능들이 구현되어 있지 않다. 하지만 목표로 삼은 이상 수 차례의 업데이트를 통해 이 목표를 달성할 계획이다.




소스 코드를 열어보면 언제나 멘붕


2011년 1월, TED+SUB의 첫 버전을 공개한 이후 수 차례 업데이트가 있었고, 그 와중에 이름이 TEDiSUB으로 변경되었다. 3년차에 접어든 소스 코드는 말 그대로 멘붕.


TED+SUB을 개발할 당시 iOS의 기초를 공부하면서 만들었기 때문에 다소 억지로 짜여진 부분이 많았고, 오랫동안 iOS 4 버전에 맞춰서 개발해온 탓에 상위 버전을 요구하는 새로운 Objective-C 문법이라던가 구조화 방법을 적용하기가 어려웠다. 그 상태에서 이루어진 수차례의 기능 개선과 버그 수정은 코드를 점점 더 복잡하게 만들었고, 급기야 개발자 본인이 알아보기가 쉽지 않은 지경에 이르렀다. 새로운 기능 하나 추가하려 하면 복잡한 연관 관계에 의해 수 많은 소스 코드를 한꺼번에 고쳐야 하는... 그야말로 '나쁜 냄새' 가 나는 코드가 되어버렸다. 숙성을 넘어 상했다고 해야 하나?


이번 업데이트를 통해 추가하려는 기능 자체는 간단했지만, 그걸 위해 이 복잡한 코드를 해집을 자신이 없었다. 새로운 목표로 인해 앞으로 수 차례 업데이트를 해야 하는데 이 상태로 계속 진행하다간 미쳐버릴 것 같은 기분이 들었다. (본인이 작성한 코드는 늘 부끄럽지만, 그 부끄러움이 단계를 넘어 짜증으로 변한 순간부터 멘탈은 위협을 받는다)


MatrixCAM을 애플에 제출하고 이틀 정도의 휴식기를 가진 다음 크게 한 숨 내뱉고 나서 새로운 프로젝트를 생성했다. 코드.. 새로 짜자.




배포 타깃 결정하기


가장 먼저 결정해야 할 문제는 배포 타깃이었다. iOS 4 보다는 위를 바라보기로 했는데 그러면 5, 6 라는 선택지가 생긴다. 가장 최신의 기술들을 사용하려면 iOS 6 버전을 선택해야 하지만 여기엔 커다란 함정이 숨어 있다. iOS 6 는 아이패드 1을 지원하지 않는다!


고성능을 요구하는 3D 게임을 제외하면 아이패드 1도 훌륭한 현역이기 때문에 나는 배포 타깃을 iOS 5로 결정했다. iOS 6에 추가된 새로운 컴포넌트를 이용할 순 없지만 iOS 4에서 5로 올라가는 것만으로도 상당히 많은 기술을 이용할 수 있다.




맨땅에 헤딩은 하지 않아요


새로운 프로젝트를 열었다고 해서 처음부터 새로 코드를 작성하는 건 아니다. 새로 적용할 테크닉은 주로 UI 뷰컨트롤러를 상속한 하위 클래스에 해당하기 때문에 독립적인 로직을 갖는 컴포넌트들은 그대로 가져와 쓸 수 있었다. iOS 5 부터 사용 가능한 ARC 옵션을 켰고, 새로운 Objective-C 문법을 적용했다.


  • 프로퍼티 지시자인 retain을 strong으로 변경 (사실 바꿀 필요 없음, 그 놈이 그놈)
  • 신시사이즈 구문 제거 (Objective-C 언어의 개선 덕분에 자동으로 생성된다)
  • 배열 및 딕셔너리 접근 API 변경 (Objective-C 언어의 개선)


사실 위의 세 가지는 굳이 적용할 필요가 없다. 하지만 적용하면 코드의 가독성이 높아지고 코드량이 줄어드는 효과가 있다. 예를 들어-


 [[dict objectForKey:@"hello"] objectAtIndex:0]


위와 같이 딕셔너리에서 hello 키를 갖는 배열을 얻어와 0 번째 요소에 접근하는 코드는


 dict[@"hello"][0]


으로 간략하게 작성할 수 있다. 


내가 작성한 코드는 적을 수록 좋다. 코드가 짧고 적을 수록 가독성이 높아져서 유지보수가 쉽고, 버그가 나타날 확률이 줄어든다. '내가 작성한 코드는 항상 최소한으로 유지해라!' 코드량을 줄일 수 있는 방법이 있다면 무조건 적용할 것!




UI 뷰컨트롤러를 분리하고 계층 구조를 이용하자


이전 버전에서 비디오 플레이어를 위한 UI 뷰컨트롤러는 비디오, 재생을 제어하는 컨트롤, 상단 메뉴, 세부 설정 등을 위한 코드가 모두 한 클래스에 짬뽕되어 있었다. 덕분에 한 클래스의 소스 코드가 수천 라인에 이르는 지경에 이르렀다.


iOS 5 버전부터는 UIViewController를 계층화 할 수 있다. 조금 풀어서 설명하자면 관련 있는 뷰와 제어 로직끼리 분리해서 각각을 별도의 컨트롤러로 분리하고 이를 조합하는 패턴을 이용할 수 있다는 뜻이다.


TEDiSUB 3.0 에서는 비디오 재생을 위한 메인 뷰컨트롤러, 상단 메뉴를 위한 뷰컨트롤러, 각각의 세부 설정을 위한 뷰컨트롤러들, 재생 버튼 및 진행 상태 등을 위한 뷰컨트롤러로 클래스를 분리했다. 클래스가 늘어나는 단점이 있지만 각각의 클래스가 갖는 코드량이 적고, 세부 목적에 집중되어 있기 때문에 가독성이 크게 향상되었고, 수정 및 개선이 훨씬 더 편해졌다.


각각의 컨트롤러들은 딜리게이트 패턴을 써서 연결하고 (클래스를 직접 참조하는 것보다 프로토콜을 참조하는 것이 훨씬 더 연약한 연관 관계를 유지할 수 있다) 연결이 어려운 경우에 한해서 알림 센터(NSNotificationCenter)를 이용한 블랙보드 패턴을 사용했다. 블랙보드 패턴을 남용하면 Xcode의 코드 어시스턴트를 사용할 수 없고, 문서화가 어려워지는 단점이 있기 때문에 주의해야 한다.




두 개의 자막 동시에 보이기


이미 자막을 백그라운드에서 다운로드해서 화면에 표시하는 기술을 갖고 있기 때문에 자막을 한 개 보이나 두 개 보이나 구현의 어려움은 차이가 없다. 하지만 정작 어려운 문제는 이를 어떻게 화면에 그리는가- 바로 UI/UX이다. 


우선 두 개의 자막에 대해 따로 설정해야 할 옵션과 함께 설정해야 할 옵션을 분리했다. 자막 언어와 글꼴 크기, 자막이 나타나는 시간은 개별적으로 설정되어야 하고 자막 배경은 공통으로 설정되어야 할 것 같았다.


특히 자막 크기의 경우 개별 설정으로 두어야 할지, 아니면 공통 설정으로 두어야 할지 고민이 많았는데 실험 결과 개별적으로 설정하는게 더 좋겠다고 판단했다. 두 자막의 글꼴 크기가 동일하면 시선이 동일하게 분산되서 집중력이 떨어지더라. 반대로 글꼴 크기가 다르면 큰 쪽에 집중하게 되고 작은 쪽을 참고하게 되서 흐트러지는 집중력을 최대한 보정할 수 있었다.


구현 막바지에 자막 오프셋 옵션을 제거했다. 설정 메뉴가 너무 많아지는게 싫었고, TED 공식 자막이기 때문에 영상과 자막의 싱크가 항상 맞아서 굳이 이 설정이 필요하지 않다고 생각했기 때문이다. 하지만 업데이트 직후 첫 피드백이 '자막 오프셋 되살려 주세요-' 였기 때문에 다음 버전에는 다시 살릴 계획이다.


설정에서 자막 언어를 선택하기 위해 언어 버튼을 선택했을 때 사용 가능한 모든 언어를 표시해야 하는데 이 때 UINavigationController를 쓰면 되겠지- 하는 안일한 생각은 보기 좋게 빗나갔다. 사용자 경험(UX)은 적합하지만 인터페이스(UI)가...;; 뒤로가기 버튼을 포함한 상단 바의 세로 폭이 너무 컸다. 그런데 이를 줄일 수 있는 방법이 없는게 아닌가! 네비게이션 컨트롤러는 기기가 가로 모드일 때 상단바의 세로 폭을 얇게 줄이는데 이건 전체 화면으로 사용했을 때만 그렇게 동작할 뿐, 이 경우처럼 별도의 작은 설정 창 안에서 동작할 때는 그리 되지 않았다. 강제로 세로폭을 줄일 방법도 없었다.


그래서 이 설정 화면은 스크롤뷰를 이용해서 네비게이션 컨트롤러의 UX를 흉내냈다. 결과는 대만족! 페이징 기법을 이용하면 쉽게 구현할 수 있다.



자막 설정 뷰는 네비게이션 컨트롤러가 아니다.


스크롤뷰를 사용했고, 네비게이션 컨트롤러의 UX를 흉내냈다.




재생 속도 조절


TED는 제한된 짧은 시간 안에 많은 내용을 발표하기 때문에 말이 상당히 빠르다. 너무나 인상 깊어 몇 번어나 다시 본 블레즈 아게라 이 아카스의 포토신스 데모는 볼 때마다 자막을 쫓느라 영상에 집중하기가 어려웠다.


그래서 비디오 재생 속도 조절 기능을 추가했다. TEDiSUB은 비디오 재생을 위해 AVPlayer 컴포넌트를 이용하는데 play 함수가 재생 속도(rate)를 항상 1.0으로 설정한다는 점을 주의할 필요가 있다. 따라서 play 함수를 호출하는 대신 rate 값을 변경하는 방법을 사용하도록 변경했다. 이 문제는 yaPlayer를 업데이트 하면서 이미 겪었기 때문에 미리 대비할 수 있었다.




공유 기능의 제한


이전 버전에서는 공유를 위해 ShareKit 오픈소스 라이브러리를 이용했다. 하지만 이 라이브러리는 업데이트 된지 너무 오래됐고, ARC를 지원하지 않는 점이 마음에 안들어서 과감히 걷어냈다. 대신 iOS SDK가 제공하는 공유 기능을 이용하게 했다. 


여기서 한 가지 문제가 발생했다. iOS 6는 트위터, 페이스북, 시나 웨이보까지 지원하는 반면 iOS 5는 트위터까지만 지원하고 사용하는 API도 다르다.


다시 ShareKit을 사용해야 하나- 하고 한참을 고민하다가 결국 iOS SDK를 이용하기로 결정했다. 외부 라이브러리도 물론 훌륭하지만 SDK에 의존하는 것이 보다 안정적이고, 무엇보다 운영체제와 통합된 인터페이스를 제공하기 때문에 편의성이 크게 증가하기 때문이다.


에버노트로의 공유 기능은 이번 버전에서 완전히 제외되었다. 하지만 강연의 활용 측면을 좀 더 강화한 뒤 에버노트로의 공유 기능을 되살릴 계획이다.




AirPlay, AirPlay Mirroring, AV 어뎁터 연결 대응


아직까지 기술적인 문제로 AirPlay를 이용하면 TV로 비디오만 전송할 뿐 자막을 함께 전송하지는 못하고 있다. 대신 AirPlay Mirroring을 이용하거나 AV 어뎁터 케이블을 연결하면 강연을 자막과 함께 볼 수 있다.


이전 버전에서는 외부 디스플레이 연결처리가 매끄럽지 못했다. 외부 디스플레이가 연결되면 이벤트를 수신하여 설정을 변경하는데 이미 외부 디스플레이가 연결된 상태에서 앱을 실행하면 연결이 되지 않는 문제가 있었다.


사용자 경험 측면에서도 좋지 않았다. 외부 디스플레이가 연결된 상태에서 아이폰/아이패드의 비디오 설정 메뉴를 가릴 수 있었고, 아이패드의 경우 전체화면이 가능했다. 다 부질 없는 것! 강연을 TV로 쏘고 있는 동안 아이폰/아이패드는 리모콘과 같은 컨트롤러로써의 역할에 충실해야 하고, 아이패드에서는 전체화면을 방지하여 불필요한 검정 픽셀을 최소화해야 한다.


어떻게 동작해야 하는지- 가능한 케이스에 대한 UI 흐름을 그리고 동작을 명확하게 규정했다. 명확하게 정의된 동작은 구현하기 쉽다. 


AirPlay를 이용해 TV로 강연을 시청하다가 도중에 기기로 화면을 복귀 시키면 아직 재생이 끝나지도 않았는대도 불구하고 비디오 재생이 완료되었음을 알리는 이벤트가 개시되는 이상한 문제가 발생했다. 이게 iOS 6의 버그인지, 그 이전 버전에서도 그랬는지 알 수 없지만, 이벤트 처리 함수에서 현재 재생 시간과 전체 재생 시간을 비교하는 구문을 추가해서 이 문제를 피하도록 했다.




업데이트가 안되잖아!


구현을 마무리하는 단계에서, 이전 버전과의 호환성을 검토하는 도중 큰 문제가 발생했다. 이전 버전이 설치된 환경에서 새 버전이 제대로 설치되지 않는 문제가 발생한 것이다. 앱의 고유 ID도 동일한데 도대체 뭐가 문제일까?


이 문제는 아주 간단하게 해결할 수 있다. 프로젝트 이름이 같아야 한다; 새로운 프로젝트를 생성하면서 프로젝트 이름을 다르게 했는데 그게 문제였다. Xcode 좌측 프로젝트 탐색기에서 프로젝트 명을 지긋이 클릭하면 이름을 변경할 수 있다. 이름을 변경하면 덩달아 관련 설정 몇가지가 변경되는데 이게 핵심이다. 자세한 내막까지는 알 필요가 없으므로 이걸로 끝- 문제 해결!




하나의 앱을 3년째 유지보수하기란?


솔직히 힘들다. TEDiSUB은 TED 공식 사이트의 웹페이지 구조에 밀접하게 관계하기 때문에 TED 웹페이지에 작은 변화라도 생기면 제대로 동작하지 않을 수 있다. 다행히 TED 웹사이트는 디자인 유행을 타지 않기 때문에 변화가 자주 있는 편은 아니지만, 그래도 1년에 두 세 차례 변화가 발생한다.


TED 웹사이트 변경으로 인해 앱 동작에 문제가 생기면, 일단 나는 앱을 앱스토어에서 내려버린다. 문제가 있는 앱이 판매되는걸 방지하기 위해서다. 이 때 '개발자가 먹튀했다' 라는 소문이 무럭무럭 자라는 모습을 지켜봐야하는게 참으로 고달프지만 어쩔 수 없다. 참아야 하느니라-


간단한 문제의 경우 하루면 충분히 고친다. 하지만 수정된 버전을 애플에 제출하면 그걸로 끝이 아닌게 문제 - 앱 심사에 보통 10~15일 가량 소요된다. 무럭무럭 자라나는 소문과 비방, 쏟아지는 이메일을 감수하기엔 너무나 긴 시간. 


다행히 애플은 '빠른 심사' 라는 창구를 열어두고 있다. 심각한 오류 수정에 한해 2~3일 내에 심사한다. 다만 항상 가능한 것은 아니고, 심각한 오류임이 명확하게 드러나야 한다. TEDiSUB의 오동작은 심각한 오류로 받아들여져 작년 몇 차례의 업데이트가 빠른 심사를 받았다. 진심으로 다행이다.


앱을 3년째 유지보수하던 10년째 유지보수하던 그 차이는 내게 별로 없다. 손익을 따져야 하는 기업이라면 모를까 나 같은 개인 개발자에게 자신이 만든 앱은 자식과도 같아서 아무리 시간이 지나도 질리지 않고 새로운 아이디어가 떠오르면 노후된 코드를 완전히 갈아 엎을 정도의 열의가 생긴다. (가만.. 자식과 비교해놓고 갈아 엎는다고 쓰니 좀 그르네? 그 만큼 애정이 넘친다는 뜻임! )


하고 싶어서 하는 일이니, 하루 두 끼 밥 먹는데 지장만 없으면 꾸준히 유지보수하고 개선할 계획이다. 으라차!



추신: 게을러서 블로그 제대로 확인 안하고 있습니다. 문의 사항은 이메일로 해 주세요! 





신고

CATEGORIES

티스토리 툴바