LINE의 웹 기반 서비스와 기술 – LINE은 앱 만드는 회사 아닌가요?

들어가며

안녕하세요. LINE에서 웹 서비스를 개발하고 있는 허석입니다. 오늘은 LINE에서 웹을 기반으로 하는 여러 서비스에 대해 설명을 드리고, 각 서비스를 어떤 아키텍처나 기술 스택, 방법으로 만들고 있는지를 소개하겠습니다. 소개하기 위해 LINE의 웹 기반 서비스를 웹 서비스, 하이브리드 웹 앱, 메신저, 라이브러리 & 플랫폼으로 분류해 봤습니다.

 

각 분류별 서비스 소개

 

웹 서비스 – LINE 타임라인 웹

LINE 타임라인 웹은 텍스트나 사진, 동영상 등으로 자신의 소식을 친구들에게 공유하거나 친구들이 공유한 소식을 확인할 수 있는 소셜 서비스입니다. 현재 7개 언어로 글로벌하게 운영되고 있습니다.

아래 이미지의 오른쪽이 글쓰기 화면입니다. 웹에서 실제로 어떤 스티커를 전송하거나 링크를 공유하고, 텍스트를 애니메이션으로 처리해서 보여줄 수도 있는 서비스인데요. 여기서 작성하면 모바일과 웹에서 동일하게 보입니다.

아래는 LINE 타임라인 웹을 개발하면서 사용한 기술 스택과 방법론입니다. 타임라인 웹은 자바스크립트로 개발되었습니다. 그리고 다양한 형태의 뷰를 관리하기 위해서 React나 Redux를 사용하고 있습니다. 또한 Node.js 와 Express를 사용해서 SSR(Server-Side Rendering)을 위한 WAS(Web Application Server)를 제공하고 있습니다. 타임라인 서비스는 SNS다 보니 사용자에게 첫 화면을 최대한 빨리 보여 주어야 하고, 검색 엔진에서 잘 검색될 수 있도록 SSR을 사용하고 있습니다. 

아래는 타임라인 웹을 개발하면서 거치게 된 리팩토링 과정입니다. 다른 프로젝트와는 달리 꽤 많은 리팩토링 과정이 있었습니다. 첫 버전은 ES5 버전의 Vanilla JS로 개발했는데요. 시간이 흘러 자바스크립트 모듈을 관리하고 번들링(bundling)하는 기법이 발전하면서 타임라인 웹 프로젝트가 레거시 코드가 되어가고 있다는 것을 느꼈습니다. 그래서 AMD(Asynchronous Module Definition) 방식으로 RequireJS를 이용해서 모듈화한 것이 첫 번째 리팩토링입니다. 그렇게 한동안 운영하다가 React나 Vue.js와 같은 프레임워크가 많이 도입되고 있고, 실제로 서비스에 활용하기에도 문제가 없다고 판단하여 React 버전으로 두 번째 리팩토링을 진행했습니다. React 버전으로 리팩토링을 진행하면서 Vanilla JS 버전과는 다르게 모듈의 재사용성, 상태 관리의 일원화 등 기존의 웹 앱들이 가지고 있던 비효율적인 부분을 많이 개선할 수 있었습니다. 세 번째 리팩토링은 Node.js 도입입니다. 팀에서 Node.js를 직접 운영하면서 SSR을 적용할 수 있는 토대를 마련하였고 검색 엔진 최적화(Search Engine Optimization, SEO), 첫 페이지 렌더링 속도 향상(Time to Interactive)등을 꾀할 수 있었습니다.

만약 LINE의 프론트엔드 개발팀에서 새로운 기술을 도입하는 것을 주저했다면, 아마도 타입라인 웹이 지금처럼 유지되지 않았거나 레거시(legacy) 코드를 다루며 매우 고통스럽게 개발하고 있었을 거라고 생각합니다.

 

하이브리드 웹 앱

하이브리드 웹 앱에선 LINE 검색(Search)과 LINE More 탭, LINE Chat 앱을 예시로 소개드리겠습니다.

 

LINE 검색

먼저 소개할 하이브리드 웹 앱은 LINE 검색입니다. LINE 메신저에서 사용하는 데이터에 대한 검색을 제공합니다. 현재 뉴스, 마토메(일본에서 사용하는 인터넷 용어로 게시판의 로그를 따로 저장해 놓은 것을 의미), 인플루언서와 같은 외부 웹 검색뿐만 아니라 친구, 대화, 공식계정, 스티커, 테마와 같은 내부 데이터에 대한 검색도 제공하고 있습니다.

이 프로젝트는 특이하게 Vanilla JS와 Vue.js 프레임워크를 동시에 사용하고 있습니다. 이벤트 드리븐 방식(Event Driven Development)으로 개발되었고 웹 뷰와 네이티브 애플리케이션 사이에 양방향 통신 인터페이스가 구현되어 있습니다.

LINE은 글로벌하게 서비스하고 있어서 낮은 품질의 네트워크에서도 좋은 성능을 보여주어야 합니다. LINE 검색은 검색어를 입력하기 위한 ‘진입 창’과, 검색 결과를 보여주는 ‘검색 결과 창’으로 구분되어 있는데요. 다른 서비스와 마찬가지로 첫 페이지(진입 창)를 빠르게 렌더링할 수 있도록 많이 고민했습니다. 그 결과 프레임워크 번들링 파일을 다 내려받을 때까지 대기하지 않도록 진입 창은 Vanilla JS로 만들었고, 검색 결과 창은 굉장히 다양한 형태의 컴포넌트를 보여주어야 하기 때문에 Vue.js 프레임워크를 도입하게 되었습니다. 또한 진입 창과 검색 결과 창을 별도의 번들 파일로 분리했고, 검색 결과 창의 번들 파일은 진입 창을 렌더링할 때 필요한 모든 자바스크립트, CSS, 이미지 파일 다운로드와 비동기 네트워크 작업이 끝난 후에 로딩하도록 구현했습니다.

일반적으로 자바스크립트 파일을 비동기로 로딩하려면 Async나 Defer 속성을 이용하면 된다고 생각할 수 있습니다. 그런데 이 속성을 이용하면 저희가 원하는 시점에 타이밍을 제어할 수 없었습니다(참고). 단순히 HTML의 파싱이 끝난 시점으로 JS 파일 로딩이나 평가(evaluation)을 미루는 것이 아니라, 위에 설명한 것처럼 진입 창의 렌더링을 방해하지 않는 특정한 최종 시점으로 미루고 싶었습니다. 그래서 특정 시점에 별도로 리소스 파일을 로딩할 수 있도록 비동기 로더(loader)를 구현하여 현재 서비스하고 있습니다.

그리고 이렇게 검색 결과 번들 파일을 초기 시점에서 분리하다 보니 Vue.js 프레임워크가 로딩되기 전에 사용자가 검색어를 입력하면 검색이 실행돼버리는 문제가 있었습니다. 그래서 진입 창과 검색 결과 창 가운데에 큐(queue)를 도입해서 검색 결과 창이 정상적으로 로딩된 후 검색이 실행되도록 구현했습니다.

또 진입 창과 검색 결과 창은 서로 다른 콘텍스트(혹은 스테이트(state))를 가지고 있는데요. 검색 진입 창은 일반적인 Vanilla JS로 구현되었고 검색 결과 창은 Vuex를 사용하고 있기 때문에 다른 콘텍스트 간 정보를 공유하기 위해서 ‘이벤트 버스(Event Bus)’라는 인터페이스를 구현했습니다. 이벤트 버스 인터페이스는 Vanilla JS와 Vue.js 사이의 통신뿐만 아니라, 웹 뷰와 네이티브 애플리케이션 간의 통신을 중개하는 데에도 사용하고 있습니다.

 

LINE More 탭과 LINE Chat 앱

아래 이미지는 LINE 메신저의 탭 가운데 ‘More 탭’이라고 부르는 화면입니다. 설정, 프로필, 통화 등 다양한 메뉴에 접근할 수 있는데요. 이 중 스티커샵, 테마샵, 게임, LINE Pay 등 대다수 기능을 웹 앱으로 서비스하고 있습니다. 약 5년 전만 해도 웹 앱은 하나도 없었습니다. 하지만 지금은 네이티브로 만들어진 것보다 웹 앱으로 구현된 메뉴들이 훨씬 많습니다. 

More 탭뿐만 아니라 대화방 내에도 웹 앱으로 만들어진 기능이 많습니다. 투표, 일정, 사다리 타기, 게임 등 대화방 안에서 대화하며 사용할 수 있는 유용한 기능들을 웹 앱으로 구현하여 서비스하고 있습니다.

 

메신저

 LINE은 메신저에서 출발한 회사입니다. 그렇기 때문에 당연히 웹 기반으로 구현된 메신저도 하나쯤은 있어야겠죠. LINE의 미션은 ‘사람과 사람 사이의 거리를 좁히는 것(Closing the distance)’이기 때문에, 어떠한 플랫폼을 사용하더라도 ‘대화’를 할 수 있어야 한다는 것을 중요하게 생각하고 있습니다.

 

LINE Chrome 메신저

Chrome 익스텐션(extension) 기반의 메신저입니다. 기술 스택은 다음과 같습니다.

뷰(view)를 구현하기 위해서 백본(backbone) 프레임워크로 Marionette를 사용했습니다. 현재 대부분 React나 Vue.js를 사용하는데요. 상대적으로 오래된 기술을 사용한 이유는 뒤에서 조금 더 자세히 설명하겠습니다. 사용자 간에 주고받은 대화 내용이나 이미지, 설정 등 각종 데이터를 클라이언트에 저장하기 위하여 Indexed DB를 사용했고, 서버와 통신하기 위해서 Apache Thrift를 이용하고 있습니다.

LINE은 보안을 매우 중요하게 생각합니다. 따라서 이미 HTTPS를 이용해 통신하고 있는데도 불구하고, HTTP Body를 별도로 다시 암호화하여 통신하고 있습니다. 그래서 중간자 공격(man in the middle attack, MITM)으로 내부 패킷을 탈취하더라도 암호화된 내용 밖에 볼 수 없습니다. 또한 종단 간 암호화(End to End Encryption, E2EE)를 도입해서 대화를 진행하는 사용자 이외에는 LINE의 관리자라 하더라도 대화를 살펴볼 수 없습니다. LINE의 웹 기반 메신저는 하나의 소스 코드를 이용해서 멀티플랫폼에 대응(One Source Multi Platform)하고 있고, 소스 코드 분석을 방지하기 위해 자체적으로 개발한 난독화 도구로 난독화를 진행하고 있습니다.

 

LINE 웹 기반 메신저의 발전 과정

LINE의 웹 기반 메신저는 굉장히 다양한 형태로 발전되어 왔습니다.

Firefox OS

첫 번째가 Firefox OS인데요. 2014년 초에 Firefox OS에 웹 기술로 만든 LINE을 스페인, 중남미 등지에 출시했습니다. 당시 출시된 기기의 CPU는 약 1GHz, RAM이 128MB밖에 되지 않는 저사양 단말기였습니다. 그래서 리소스의 크기를 최대한 줄여야 했지만, 그렇다고 Vanilla JS로 개발하기에는 어려움이 있어 백본을 도입하였습니다. 128MB의 메모리 중에서 기본 OS가 할당하는 메모리를 제외하고 애플리케이션을 위해 할당된 가용 메모리는 거의 절반도 되지 않았는데요. 서비스를 운영하면서 사용자 간 사진을 전송하고 수신할 때 RAM 사용량이 80MB까지 올라가는 바람에 크래시가 발생한 적도 있었습니다. 이를 개선하기 위해 여러 최적화 포인트를 발견하고 수정하여 다음 버전에서는 사진을 전송하고 수신하더라도 RAM을 40MB 정도만 사용하도록 만든 뒤 서비스한 기억이 있습니다. 이처럼 매우 낮은 성능의 기기에서도 동작할 수 있도록 최적화, 경량화에 많은 신경을 썼던 프로젝트로 기억에 남았습니다.

Chrome 앱

다음 프로젝트는 Chrome 앱입니다. FireFox OS 기반의 앱에서 웹 메신저의 기반을 닦고 성공 가능성을 점쳤다면, Chrome 플랫폼에서는 메신저로 구현하고 싶었던 모든 기능을 구현하고 서비스할 수 있었습니다. 2015년도에 스티커 구매와 전송, 음성이나 비디오와 같은 리치(rich) 메시지 전송, 스크린 캡처, 핀코드 인증 등 LINE 메신저의 거의 모든 기능을 담고 출시되었습니다.

Tizen

2016년에는 Chrome 앱을 Tizen 플랫폼에 이식하기도 했습니다. Tizen 역시 Firefox와 마찬가지로 10만 원 이하의 저가 기기였고 사양이 그다지 좋지 못했습니다. 이러한 환경에서도 성능은 기존 버전보다 더 높일 수 있도록 꽤 많은 노력을 기울였습니다. 단순한 친구 목록 화면이라도 수 천명의 친구를 가진 사용자들에게 부드럽고 미려한 UX를 제공하기 위해 수십 번의 프로토타이핑을 진행했습니다. 또한 모바일 환경이다 보니 스크린 활동, 물리 키 조작, 푸시 알림 같은 기능이 네이티브 앱과 차이가 없도록 개발하는 데 중점을 두었습니다. 굉장히 짧은 기간동안 이식을 진행해서 Tizen 기기에 성공적으로 프리로드(preload)하여 출시한 프로젝트였습니다.

Chrome 확장 프로그램

2018년 중순, Google이 정책을 변경하면서 Chrome 앱 스토어에서 Chrome 애플리케이션이 전부 종료되고 지원이 중단되었습니다. 그래서 저희도 기존 Chrome 앱 버전의 LINE 웹 메신저를 Chrome 확장 프로그램(extension) 버전으로 출시하게 되었습니다. 이 과정은 조금 수월했는데요. 기존의 Google Chrome 애플리케이션에서 Chrome 확장 프로그램으로 변경만 하는 것이어서 기존 Chrome 앱에서 제공되었던 API 중 Chrome 확장 프로그램에서 제공되지 않는 것들만 제 2의 해결책으로 개발한 프로젝트였습니다.

브라우저

2018년말 즈음, LINE의 공식 계정(Official Account)을 관리하기 위한 순수한 웹 기반의 메신저가 필요했습니다. 손쉽고 빠르게 개발하기 위하여 기존의 Chrome 버전을 활용하기로 논의하였습니다. 하지만 기존 버전은 백본 기반이어서 코드 자체와 개념이 이미 레거시 수준이었고, 이런 기반으로 다음 프로젝트를 시작하는 것은 앞으로 운영하고 확장할 때 무리가 있을 것이라고 판단했습니다. 따라서 대화를 전송하고 수신받는 네트워크 모듈, 대화 내용을 클라이언트에 저장하거나 조회하는 데이터베이스 모듈, 각종 이벤트에 대응하는 비즈니스 로직과 같은 핵심 코어 모듈은 재활용하고, 프레젠테이션 계층(presentation layer)만 Vue.js를 이용해 리팩토링을 진행했습니다. 역시나 꽤 빠르고 성공적으로 개발을 진행할 수 있었습니다.

이렇게 하나의 소스 코드를 이용하여 다양한 플랫폼을 지원하도록 개발할 수 있었던 건 웹이라서 가능했다고 생각합니다.

소스코드 난독화

이러한 웹 기반의 서비스는 이식성이 좋아서 다양한 플랫폼에 적용할 수 있지만 보안이 취약할 수 있다는 단점이 있습니다. 앞서 이야기한 것과 같이 LINE은 보안을 매우 중요하게 생각합니다. 이에 난독화를 진행하려고 했는데요. 이미 시중에서 많이 사용되고 있는 난독화 도구를 이용하여 난독화를 수행해 보면 객체 안에 있는 프로퍼티나 프로토타입의 멤버 변수, 메서드가 난독화되지 않았습니다. 이는 LINE에서 생각하는 적절한 보안 수준이 아니라고 판단해서 직접 ‘ENIL’이라는 난독화 도구를 만들게 되었습니다. ENIL은 LINE을 역순으로 써서 만든 이름입니다.

난독화 도구를 만들면서 중요하게 생각한 것은 ‘사람이 쉽게 읽을 수 없어야 한다’였습니다. 공격자가 쉽게 소스 코드를 읽고 이해한 뒤 LINE에서 대화를 주고 받는 방식을 파악하기 어렵도록 개발하였습니다. 그래서 위 이미지에서 볼 수 있듯이, 바코드처럼 보이는 유니코드 문자를 이용하여 치환하는 것을 중점으로 개발했고, 이를 통해 공격자가 분석을 포기하거나 어렵게 느끼도록 만들 수 있었습니다.

 

라이브러리 & 플랫폼 – LINE Social Plugin

LINE Social Plugin은 LINE으로 ‘공유하기’나 ‘좋아요’, ‘친구하기’와 같은 버튼을 개인 페이지에 부착할 수 있는 라이브러리를 제공하고 있습니다.

이러한 서비스는 일반적으로 어떤 사이트에서 어떻게 사용되어 어느 정도 규모의 트래픽이 발생할지 예측하기 어렵습니다. 오늘은 트래픽이 적지만 당장 내일 대규모 트래픽이 발생하는 서비스에 적용될 수도 있기 때문입니다. 그래서 효율적으로 설계해야 했습니다. 

또한 이런 서비스에는 어뷰저(abuser)가 광고나 물품 판매 등의 목적으로 버튼을 숨겨 사용자가 부정클릭을 발생시키도록 만드는 클릭재킹(clickjacking) 시도가 많이 발생합니다. 어뷰저는 버튼을 투명하게 만든다던가, 상품을 준다고 유혹한다거나, 버튼을 미디어 재생 버튼 뒤에 숨기는 등의 다양한 방법으로 클릭재킹을 시도하며, 이를 막기 위한 개발자들의 방법도 나날이 발전하고 있습니다(추후 LINE Social Plugin에 어뷰저가 시도했던 공격과 그에 대응했던 방법도 소개하겠습니다).

 

LINE 웹 앱의 두 가지 개발 방식

LINE에서는 많은 서비스를 웹 앱으로 개발했는데요. LINE에서 웹 앱을 개발하는 방식은 크게 두 가지로 구분할 수 있습니다. 첫 번째는, LCS라고 부르는 ‘LINE Channel SDK’이고, 두 번째는 LIFF라고 부르는 ‘LINE Frontend Framework’입니다.

 

LINE Channel SDK

Apache Cordova, 예전에는 PhoneGap이라고 불렸던 것을 이용해서 개발된 LINE의 SDK입니다. Cordova는 기기의 각종 기능에 접근할 수 있는데요. LINE의 Channel SDK는 Cordova가 제공하는 기능 이외에도 LINE 사용자의 환경, 채팅방의 아이디, 가입자의 지역이나 친구 정보 등 사용자의 소셜 그래프 정보를 얻을 수 있도록 개발되었습니다. 또한 LINE 메신저 앱의 비콘(beacon), 초음파와 같은 시스템 서비스를 웹에서 사용할 수 있도록 제공하고 있습니다. 또 LCS에서 사용하고 있는 웹 뷰는 화면 전체를 차지하는 것이 아니라 일부는 네이티브 SDK로 구현되어 있는데요. 이런 네이티브 영역들을 웹 뷰에서 제어할 수 있도록 인터페이스가 구현되어 있습니다. 현재 이 LCS를 이용해서 만들어진 앱은 대부분 LINE 내부에서 자체적으로 개발했습니다. 소수의 인증받은 업체들만 LCS를 이용해서 개발하고 있습니다.

 

LINE Frontend Framework

두 번째는 LIFF입니다. 앞에서 이야기한 위의 LINE Channel SDK와는 다르게 네이티브와 밀접하게 통신하지 않고 독립적인 환경, 즉 순수한 웹 뷰를 이용하여 개발할 수 있도록 만들어진 프레임워크입니다. 이미 LINE이 공개하고 있는 오픈 API가 굉장히 많은데요. 이런 API를 이용해서 소셜 그래프를 취득하거나 친구에게 메시지를 보내는 기능 등을 수행할 수 있습니다.
LINE Developer 사이트에서 Getting started 문서 이외에도 자세한 문서들을 제공하고 있기 때문에 직접 웹 애플리케이션을 만들고 LINE에서 사용해 볼 수 있습니다.

 

LINE의 웹 개발 기술 스택

다음은 LINE에서 사용하고 있는 웹 개발 기술 스택입니다.

가장 중요하게 생각하는 것은 역시나 파란색으로 표시된 자바스크립트 영역입니다. React나 Vue.js처럼 현재 유행하고 있는 프레임워크뿐만 아니라 ES6, ECMAScript, TypeScript 같은 Vanilla JS의 원리나 이해에도 많은 비중을 할애하고 있습니다. 빨간색으로 표시된 영역은 네트워크 부분입니다. 네트워크 기초나 백엔드 기술도 중요하게 다루고 있는데요. SSR을 자체적으로 개발하기 위해서 Node.js를 사용해서 WAS를 자체 개발 운영하고 있고, 이런 Node.js 인스턴스를 관리하기 위해서 PM2 등을 사용하고 있습니다. 녹색으로 표시된 영역에는 기반 기술들이 많이 포함되어 있습니다. 그 외에도 ESLint와 같이 코드의 정적 품질을 관리하기 위한 도구나 Prettier와 같이 코드의 형식을 맞추기 위한 코드 포매터(formatter) 등도 사용하고 있습니다.

 

LINE에서 사용하는 웹 개발 방법론

개발 방법론도 몇 가지 정리해보았습니다. 

대부분의 웹 서비스나 웹 애플리케이션이 Vue.js나 React를 이용하여 SPA(Single Page Application)로 개발되었고, 필요에 따라서는 Node.js를 이용하여 SSR 같은 방법을 사용하고 있습니다. 이전에 블로그에 소개된 ‘PM2를 활용한 무중단 배포 시스템‘도 구축되어 있습니다. 그리고 테스트 코드를 작성하여 개발 안정성을 높이고 리팩토링을 진행할 때에도 좀 더 손쉽게 개발할 수 있었습니다.

 

마치며

여기까지 준비하면서 한 가지 걱정이 있었습니다. 지금까지 설명드린 많은 기술을 다 알아야만, 그리고 잘해야만 LINE에서 프론트엔드 개발자로 일할 수 있을 거라고 생각하시는 건 아닐까 걱정했습니다. 물론 다 잘하면 좋습니다. 하지만, 여러분도 아시다시피 프론트엔드 기술은 굉장히 빠르게 변하고 있습니다. 그러므로 이 글에서 설명드린 많은 기술을 전부 알진 못하더라도, 이렇게 빠르게 변하고 있는 시점에서 적절한 기술을 적절한 시기에 맞게 잘 사용할 수 있는 능력을 갖추고 있으면 된다고 말씀드리고 싶습니다. 자바스크립트 기초에 대한 이해와 프론트엔드를 좋아하는 열정만 있다면, LINE에서 프론트엔드 개발자로 충분히 함께 일할 수 있다고 생각합니다. 긴 글 읽어주셔서 감사합니다.

P.S. 저희와 함께 일할 프론트엔드 개발자를 찾고 있습니다. 많은 지원 부탁드립니다.