틱톡 데스크탑 라이브러리를 통한 멀티 플랫폼 운영

안녕하세요, 멀티플랫폼개발팀 엄태현 매니저입니다. 이번 포스팅을 통해 틱톡을 개발하면서 고민했던 점에 대해 말씀 드리려고 합니다.

새로운 플랫폼?

맥용 틱톡 클라이언트를 시작하며, 가장 고민한 부분은 윈도우 플랫폼을 위해 C++로 개발한 틱톡 서비스 로직들을 어떻게 효율적으로 맥에서 구축하는지 여부였습니다. 방법은 애플의 어플리케이션 개발 기본 언어인 Objective C를 사용하여 기존 로직들을 신규로 개발하는 것과 기존 로직들을 재사용 가능한 형태로 계층화 하고 정형화 하여 C++/Objective C 혼합 형태로 사용하는 방법의 두 가지였습니다.(이후 편의를 위해 전자를 신규개발과 후자를 재사용으로 칭하겠습니다.)

각각의 장단점을 검토해보니 신규개발의 경우

+ 짧은 시간 내에 개발이 가능

+ 구조적인 설계가 단순해짐

소스코드의 파편화가 발생

각기 다른 운영 계획을 수립해야 함

재사용의 경우엔

+ 서비스 로직 추가등 변경 적용이 용이해짐

+ 동일한 코드의 사용으로 운영 계획 수립이 용이해짐

기존 서비스 로직을 분류, 재조립, 패키징 작업에 추가 시간이 발생

여러 운영체제를 추상화 할 수 있는 구조적인 리팩터링이 필요

다 같이 검토하고 회의한 결과 팀이 얻어낸 결론은 재사용이었습니다. 이런 결정을 하게 된 가장 큰 매력포인트는

– 데스크탑용 클라이언트는 완벽하게 서비스 로직이 동일하다.

– 초기 개발 비용이 다소 증가할 수 있지만, 향후 운영 계획 수립 및 추가 개발에서는 그 비용을 감수할 만한 가치가 있다.

그렇게 해서 아래의 구조가 탄생하게 되었습니다.

공통 서비스 라이브러리

그림 1. 틱톡 데스크탑 공용 라이브러리 구성

공용 서비스 라이브러리는 틱톡 데스크탑 클라이언트에게 필요한 모든 기능이 C++로 구현되어 포함되어 있습니다. 주요 항목을 정리하면,

서버와의 데이터 송수신

boost의 asio를 이용한 틱톡 기본 소켓 모델을 구성하고, 이를 이용한 파일/대화/친구정보를 안정적으로 주고 받을 수 있는 기반 기능이 포함되어 있습니다. 기본적으로 여러 개의 쓰레드를 이용하여 전송 지연이나, I/O 부하를 사용자가 사용하는 GUI 쓰레드로부터 분리하도록 구현되어 있습니다.

– 친구관리/대화하기

대화 서버, 친구 서버등과 통신하는 모든 기능이 포함되어 있습니다.

– 파일전송

별도의 파일전송 쓰레드를 사용하여 구현되어 있으며 사용성을 떨어뜨리지 않기 위해 최대 5개정도의 쓰레드를 이용하여 다수의 파일전송을 처리하도록 구현되어 있습니다.

– 부가서비스

파일함, 스티커, 이모티콘 등 사용가능한 모든 부가서비스 기능이 포함되어 있습니다.

플랫폼별 추상화

이렇게 공통 라이브러리를 구축할 때 가장 애매했던 부분은 기존 윈도우 메시지 큐를 이용한 쓰레드 간 통신을 어떻게 효율적으로 맥 플랫폼에 적용시킬 수 있는지 여부였습니다. 많은 선택지들이 존재하지만 그 중에 고려된 방법은 이벤트를 처리할 수 있는 공통 이벤트 큐를 구현하여 이벤트를 수신할 쓰레드에서 폴링(주기적으로 이벤트를 꺼내어 처리)하는 방법과 각각의 운영체제에서 제공하는 동기/비동기 이벤트 처리 방식을 추상화하여 적용하는 방법이었습니다.

결국 후자의 방법을 채용하게 되었는데 이유는

– 이벤트 큐를 구현하고 검증하는데 시간이 소요되며, 검증이 되었다고 확신할 수 없다.

멀티쓰레드 상황에서는 일반적인 사용패턴으로는 검출되지 않는 오류가 존재할 수 있습니다. 예를 들어 네트워크에서 지연 및 손실이 일어나는 경우 같은 특정상황에서만 발생하는 경우 충분한 검증을 거치더라도 확신할 수 없습니다. 결국 검증은 구조 및 설계 레벨에서 수행해야 하며, 이것이 불확실한 상태라면, 충분한 검증 시간을 가진다 하여도 보장되지 않습니다. 시간 및 인적 자원이 부족한 상황에서 이 방법은 위험도가 있다고 판단하였습니다.

– 이벤트 큐 방식은 이벤트가 없는 상황에서도 동작하여야 하며, 기존 쓰레드 로직에 주기적인 폴링 로직을 추가하여야 한다.

이벤트 큐를 구성하게 되면 이벤트를 수신할 쓰레드는 주기적으로 이벤트를 큐에서 꺼내와야 합니다. 하지만, 이벤트가 없는 상황에서도 이 주기적인 확인은 계속 동작할 수 밖에 없다는데 문제가 있습니다. 운영 체제에서 제공하는 이벤트 처리는 우리가 추가적으로 사용하든 사용하지 않든 내부적으로 어플리케이션을 구동하기 위해 기본적으로 돌아가는 서비스입니다. 여기에 우리 서비스의 이벤트를 추가하여 사용하는 것과 추가적인 이벤트 큐를 구성하고 위에 설명한 처리하는 비용(이벤트가 없는 상황, 추가적인 폴링 로직 구성)을 고려할 때 자체적인 구현보다는 운영체제의 서비스를 사용하는 것이 적당하다고 판단하였습니다.

위의 결과로 구현한 방식이 아래 그림 2. 입니다.

그림 2. 이벤트 처리 요약

객체지향 프로그래밍의 기본 개념 중의 하나인 인터페이스-구현을 이용하여, 전체가 공유할 이벤트 인터페이스를 정의하고 각각의 운영체제에서 제공하는 이벤트 서비스를 이용하여 해당 인터페이스를 구현하고

1) 이벤트 처리를 시작하기 전에 해당 구현의 인스턴스를 서비스 로직에 등록하고

2) 이벤트 발생시 서비스 로직은 해당 인터페이스를 참조하여

3) 인스턴스를 호출하는

방식으로 구현되었습니다.

저비용 고효율 서비스 운영

그림 3. 소스 코드 기준 공통 라이브러리 비율

위와 같이 공통 라이브러리를 적용한 결과 그림 3.과 같이 상당한 분량(OS X의 경우 약 37%의 비율)의 소스 코드를 재사용 하여 결과적으로 자원(시간/인력)이 부족한 상황에서 오히려 복잡한 방식처럼 보이는 공용 서비스 로직 라이브러리를 통해, 기능 추가/변경을 위해 여러 번의 반복적인 작업이 필요하지 않고 상대적으로 적은 인적자원을 가진 환경에서도 최소한의 비용으로 안정적인 서비스 운영이 가능해졌습니다.

엄태현 멀티플랫폼개발팀

SK Planet Studio M, 멀티플랫폼 개발팀 소속
멀티플랫폼 개발팀은 틱톡의 맥/윈도우/윈도우 모바일 버전을 만들고 있습니다.

공유하기