Tech-Verse 2022에서 박광용 님이 발표한 Headless CMS in LINE 세션 내용을 옮긴 글입니다.
안녕하세요. 노 코드(no-code) 패러다임에 관심이 많고, 개발자를 편하게 만드는 기술을 좋아하며, LINE에서 서버 엔지니어로 일하고 있는 박광용입니다. 이번 글에서는 백엔드 개발 없이 프런트엔드 개발만으로 동적 웹페이지를 제작할 수 있는 헤드리스 CMS를 소개하려고 합니다.
프런트엔드 기술로만 만든 Tech-Verse 웹사이트
작년에 LINE에서 개최한 기술 콘퍼런스 Tech-Verse의 웹사이트는 서버 개발자 없이 프런트엔드 개발자만 모여서 만들었습니다. 서버와 데이터베이스 없이 개발한 것인데요. 헤드리스(headless) CMS(content management system)를 이용하면 프런트엔드 기술만으로 웹사이트를 개발할 수 있습니다.
헤드리스 CMS를 이용하기 전에는, 데이터 파일에 사이트 정보를 저장하고 React 프레임워크에서 데이터 파일을 로드하는 방법을 생각해 봤는데요. 이 방법은 기획자가 오타나 새로운 페이지 추가 등으로 사이트를 변경해 달라고 요청할 때마다 개발자가 데이터 파일을 수정해야 했습니다.
기획자가 직접 사이트를 개발할 수 있는 관리자 페이지를 제공하는 방법도 생각해 봤는데요. 관리자 페이지를 만들려면 백엔드 개발이 필요해서 서버 및 각종 인프라 설정을 준비해야 했습니다.
이런 단점 없이 기획자의 요청에 조금 더 쉽고 빠르게 대응하기 위해 Tech-Verse 웹사이트는 헤드리스 CMS로 개발했습니다. 덕분에 백엔드 개발 없이 프런트엔드 개발만으로 웹사이트를 만들 수 있었는데요. 이 헤드리스 CMS가 무엇인지 소개하겠습니다.
헤드리스 CMS 소개
프런트엔드가 없는 CMS
헤드리스 CMS는 전통적인 CMS와 조금 다릅니다. 전통적인 CMS는 프런트엔드와 하나로 밀접하게 연결돼 있기 때문에 프런트엔드 개발 언어나 구조 같은 것을 쉽게 바꿀 수 없습니다. 또한 요구 사항이 많아지면 사이트에 적용하기가 어려워지고 정해진 틀에 따라서만 적용해야 한다는 단점이 있습니다.
반면 헤드리스 CMS는 CMS에 좀 더 집중합니다. 헤드리스란 말 그대로 머리가 없다는 뜻인데요. 여기서 머리란 바로 프런트엔드를 말합니다. 헤드리스 CMS를 사용하면 프런트엔드는 각자의 프로젝트에 맞춰 개발 플랫폼이나 개발 언어 등을 선택해 개발하면 됩니다. 재미있을 것 같지 않나요?
그렇다면 프런트엔드는 헤드리스 CMS와 어떻게 연동할까요? 헤드리스 CMS는 API를 통해서 프런트엔드와 통신합니다. 따라서 웹 개발자 입장에서는 헤드리스 CMS로 개발하면 React나 Vue, Vanila JS 등 프로젝트에 맞게 프레임워크를 자유롭게 선택할 수 있습니다.
백엔드 영역의 반복 업무도 줄일 수 있는 헤드리스 CMS
헤드리스 CMS는 이외에도 장점이 많습니다. 아래 예시를 보겠습니다. 양쪽 화면 모두 같은 공지 사항 기능이지만 디자인은 다릅니다. 그동안 웹사이트를 개발할 때마다 이런 공지 사항 기능을 반복해서 개발해야 했습니다.
헤드리스 CMS를 이용하면 백엔드 영역에서 반복해야 했던 이런 업무를 획기적으로 줄일 수 있습니다. 백엔드 서버와 헤드리스 CMS 개발에 어떤 차이가 있는지 비교해 보면서 어떻게 반복 업무가 줄어드는지 살펴보겠습니다. 비교에 사용할 예시는 공지 사항 API 개발입니다.
백엔드 개발 과정
먼저 백엔드 개발 과정을 살펴보겠습니다.
개발 과정에는 여러 작업이 있을 수 있는데요. 여기서는 총 세 단계(데이터베이스 설계, 서버 개발, 배포 과정)로 나눠 진행하겠습니다.
먼저 데이터베이스 설계입니다. notice
테이블에 title
을 비롯해서 여러 칼럼을 DDL(Data Definition Language) 명령문으로 작성한 후 데이터베이스 시스템에 입력해서 테이블을 생성합니다.
다음으로 서버 개발입니다. 먼저 notices
API를 만들고, notices
API가 호출되면 테이블에서 데이터를 조회한 후 결과를 응답하는 코드를 간단히 만듭니다.
마지막으로 작성한 코드를 빌드해서 서버로 배포합니다.
헤드리스 CMS 개발 과정
다음으로 헤드리스 CMS로 개발하는 과정을 살펴보겠습니다. 먼저 notice
컬렉션을 생성합니다.
이어서 title
을 비롯한 필드를 생성합니다.
이것으로 끝입니다. API 생성을 완료했고 바로 이용할 수 있습니다.
헤드리스 CMS를 이용하면 앞서 살펴본 백엔드 개발 과정을 API로 손쉽게 진행할 수 있고, 배포 과정도 필요하지 않은 것을 확인했습니다.
기존 헤드리스 CMS의 문제점
LINE DEVELOPER DAY 2020에서도 소개했었는데요(참고). LINE에서는 약 3년 전부터 오픈소스 기반으로 헤드리스 CMS를 구축하기 시작해서 적극적으로 헤드리스 CMS를 사용해서 프로젝트를 개발하고 운영하고 있습니다. 아래와 같이 LINE CREATIVE와 LINE CAREERS와 같은 정적 웹사이트를 헤드리스 CMS로 개발했고 지금까지 잘 운영하고 있습니다.
그런데 왜 정적 웹사이트에 한해서만 운영했을까요? 앞서 살펴본 것처럼 헤드리스 CMS는 데이터베이스보다 변경이 자유로운 저장 구조인 모델을 통해서 API를 만들 수 있습니다. 그런데 이 모델을 적용하기 위해서는 재부팅 시간이 조금 필요한데요. 재부팅하는 동안에는 클라이언트 API 요청을 받을 수 없다는 제약이 있었습니다. 또한 기존 헤드리스 CMS는 API 요청 처리 속도가 낮았기 때문에 API 요청을 제한적으로 받을 수밖에 없었습니다.
이런 이유로 헤드리스 CMS에서 실시간으로 API 요청을 받는 것은 조금 어렵다고 판단해 API 호출이 필요없는 JAM(JavaScript APIs Markup) 스택 방식으로 헤드리스 CMS를 활용했습니다. JAM 스택 방식을 간단히 설명하면, SSG(static site generator)를 이용해서 헤드리스 CMS로 데이터를 조회하면, 조회한 데이터를 기반으로 자동으로 HTML이 생성됩니다. 이렇게 생성한 HTML을 웹 정적 호스팅 서버에 배포하면 사용자는 정적 웹 페이지에 접속할 수 있습니다.
물론 JAM 스택 방식도 웹사이트를 변경할 때마다 빌드하고 배포해야 한다는 단점은 있습니다.
헤드리스 CMS 개선하기
앞서 말씀드린 대로 헤드리스 CMS는 장점이 많지만 단점도 있습니다. 재부팅 시간이 있고, 처리 속도가 조금 느립니다. 저희 역시 3년 전부터 헤드리스 CMS를 활용하고 있었지만 제한적으로 사용했는데요. 개발자가 조금 더 편해질 수 있도록 단점을 보완해 조금 더 좋은 헤드리스 CMS를 만들어 보기로 결정했습니다.
더 좋은 헤드리스 CMS를 만들기 위해 기존 오픈 소스를 가져와서 수정할지 새로 개발할지 고민했는데요. 오픈 소스를 수정하는 방식은 오픈 소스에서 코드를 분기해야 하기 때문에 분기 후 새로 릴리스된 버전을 적용하기 어려울 것이라고 판단했고, 앞서 말씀드린 기존 헤드리스 CMS의 여러 제약 사항을 해결하는 것은 더욱 어려울 것이라고 생각했습니다. 이에 새로 개발하기로 결정했습니다.
구조 개선 1: 파일에서 데이터베이스로 저장 방식 변경
개발은 구조를 변경하는 것으로 시작했습니다. 먼저 파일에서 데이터베이스로 데이터를 저장하는 방식을 변경했습니다.
데이터 저장 방법으로 파일을 사용할 때에는 개발자가 모델을 수정하면 모델을 변경하는 동안 재부팅해야 했고, 재부팅하는 동안에는 새로운 API 요청을 받지 못하는 문제가 있었습니다.
하지만 이제 데이터베이스에 모델 정보를 저장하기 때문에 재부팅 과정이 없어서 언제든지 API 요청을 받을 수 있습니다. 또한 과거에 모델 정보가 파일로 돼 있을 때는 서버 간에 파일을 공유하는 것도 쉽지 않았고, 재부팅하려고 하면 여러 대의 서버를 순차적으로 그레이스풀(graceful)하게 배포해야 한다는 어려움도 있었는데요. 이제 데이터베이스로 모델 정보를 이전했기 때문에 재부팅 과정도 없고 서버 간 파일 공유도 쉽습니다.
과거에는 앞서 말씀드린 문제 때문에 서버를 한 대만 운영했습니다. 따라서 그 서버 한 대에 장애가 발생하면 새로운 요청을 받을 수 없다는 문제가 있었지만, 데이터베이스로 변경하면서 서버를 여러 대 운영할 수 있게 돼 문제를 해결할 수 있었습니다.
데이터베이스로 변경하면서 스케일 아웃이 자유로워졌습니다.
그 덕분에 기존 대비 성능을 400%나 향상시킬 수 있었습니다.
이 수치는 스케일 아웃으로 얻은 효과이기 때문에 만족하기 어려웠고, 400%라는 숫자는 놀랍지만 실제 수치는 300TPS(transaction per second) 정도로 사용자가 많은 서비스에서 사용하기에는 아직 턱없이 부족했습니다. 이에 추가로 성능을 개선했는데요. 그 전에 두 번째 구조 개선을 살펴보겠습니다.
구조 개선 2: 컴포넌트 도입
헤드리스 CMS는 일반 백엔드 데이터베이스 테이블보다 구조가 복잡합니다. 예시를 보겠습니다. 아래와 같이 텍스트용, 이미지용, 비디오용, 총 세 가지 유형의 공지 사항 게시판을 만든다고 가정하겠습니다.
일반적인 백엔드를 생각해 보면, notice
테이블에 유형을 추가하고 유형에 따라 칼럼을 추가할 수 있습니다. 다른 방법도 있겠지만 극단적인 경우를 살펴보기 위해 아래와 같이 비디오와 이미지, 텍스트 정보를 각각 다른 필드에 저장하는 방법으로 진행해 보겠습니다.
이 방식으로 진행하면 아래와 같이 각 유형별로 다른 칼럼에 저장하고 사용하지 않는 칼럼에는 NULL
을 채워 넣게 되며, 향후 다른 유형을 추가할 때마다 번거롭게 계속 칼럼을 추가해야 합니다.
이런 번거로운 작업을 줄이기 위해 저희는 '컴포넌트'라는 개념을 도입해서 자료 구조를 간단하게 바꿨습니다.
아래와 같이 '컴포넌트 존'이라는 기능을 통해 사용자는 쉽게 컴포넌트를 선택해서 공지 사항 유형을 선택할 수 있습니다.
예를 들어 이미지 유형의 공지 사항을 작성한다면 컴포넌트 존에서 이미지를 선택하면 됩니다. 그러면 아래와 같이 사용자가 쉽게 입력할 수 있는 화면이 나타납니다.
API에도 type
에 image
를 넣는 방식으로 사용자에게 유형을 전달합니다. 프런트엔드에서는 API 호출 후 전달받은 유형에 따라 처리하면 됩니다.
컴포넌트 도입 후 발생한 문제
꽤 괜찮은 방법으로 동적 구조로 API를 만들 수 있게 됐는데요. 여기서 또 다른 문제가 발생합니다. 컴포넌트를 동적으로 관리하면서 각 컴포넌트 테이블을 별도로 관리했는데요. 다양한 컴포넌트가 서로 관계를 맺으면서 모델이 점점 복잡해지며 속도가 느려졌습니다.
만약 notice
테이블을 조회한다면, notice
테이블이 관계를 맺은 모델과 다 관계를 맺어야 했고, 해당 모델에 컴포넌트가 있다면 컴포넌트와도 관계를 맺어야 했습니다.
헤드리스 CMS는 사용자가 자유롭게 모델을 선택하거나 늘리고 확장할 수 있기 때문에 이와 같은 특성은 헤드리스 CMS 사용에 많은 제약이 될 수밖에 없습니다. 관계가 늘어나면 데이터 모델을 만드는 것은 물론 데이터를 조회할 때도 부하가 커지고 시간이 오래 걸립니다.
아래 그래프를 보겠습니다. x축은 연결돼 있는 관계 수, y축은 처리 시간입니다. 모델의 관계가 늘어날수록 처리 시간이 증가하는 것을 볼 수 있습니다.
성능 개선 1: 모델 캐시 스토리지를 도입해 모델 생성 시간 단축
이 문제를 어떻게 해결해야 할지 많이 고민했습니다. 밤에 잠도 못 이루는 날도 많았는데요. 고민 끝에 모델 캐시 스토리지에 모델 정보를 저장하기로 결정했습니다.
모델 캐시 스토리지에는 모델 정보를 종합해서 저장합니다. 이를 통해 API 요청이 들어올 때마다 모델 정보를 만들지 않고 모델 캐시 스토리지에서 종합된 정보를 조회할 수 있도록 만들었습니다.
모델 캐시 스토리지를 도입하기 전과 후의 흐름을 비교해 보겠습니다. 먼저 도입하기 전에는 프런트엔드에서 Get
API 요청이 들어오면 notice
라는 모델 정보를 조회합니다.
조회 후 notice
라는 모델을 생성합니다.
notice
모델 생성 후 notice
와 연관 관계가 있는 컴포넌트까지 재귀적으로 호출합니다.
그다음 데이터베이스를 조회합니다.
마지막으로 프런트엔드로 응답을 전송합니다.
과정이 참 길죠? 이제 모델 캐시 스토리지를 적용해 개선한 과정을 살펴보겠습니다. 먼저 모델 캐시 스토리지에서 연관 관계가 있는 모든 정보를 조회합니다.
notice
를 조회하면서 notice
와 연관 관계가 있는 정보를 한꺼번에 가져왔기 때문에 재귀적으로 호출하는 과정이 없습니다.
이제 데이터베이스에서 모델을 조회한 후 프런트엔드에 응답하면 끝입니다.
아래는 모델 캐시 스토리지 적용 전후 처리 속도를 비교한 그래프입니다. 적용 후에는 모델 연관 관계가 늘어나도 성능이 급격히 저하되지 않는 것을 확인할 수 있습니다.
성능 개선 2: 역정규화로 데이터 조회 시간 개선
이제 모델 생성 시간은 해결했습니다. 하지만 아직 데이터 조회 시간이 남아 있습니다. 앞서 말씀드렸듯 복잡할수록 JOIN이 많아지고, JOIN이 많아지면 속도가 저하될 수밖에 없습니다. notices
라는 API를 조회하는 경우를 보면, notice
에 연관돼 있는 연관 관계랑 컴포넌트 존까지 다 JOIN하기 때문에 이 간단한 조회도 최소 10개의 JOIN을 통해서 데이터를 만들 수밖에 없습니다. 사용자가 컴포넌트를 추가한다면 JOIN은 기하급수적으로 늘어날 수밖에 없겠죠.
이런 이유로 JOIN
으로 데이터를 조회하는 것은 무리라고 판단해서 다른 해결책을 찾아봤고, 먼저 데이터 역정규화를 떠올렸지만 역정규화도 쉽지는 않았습니다.
역정규화를 하기 전에는, 예를 들어 Reaction
이라는 데이터를 삭제할 때 칼럼만 삭제하면 됐습니다.
그렇지만 역정규화 후에는 데이터를 모두 검색해서 Reaction
이라는 필드가 있는 내용을 모두 삭제해야만 데이터의 일관성을 유지할 수 있게 됐습니다.
저희는 이 부분을 어떻게 처리할지 또 고민했습니다.
마이크로 서비스 아키텍처 및 CDC 도입
역정규화에 대한 처리 외에도 헤드리스 CMS로 개발할 때는 환경을 옮겨야 하거나 웹훅, 스케줄링 등 서버를 개발할 때와는 다른 여러 문제가 발생할 수 있고 이를 해결하기 위해 여러 기능이 필요합니다.
먼저 개발 환경에서 개발한 뒤 운영 환경으로 옮겨야 하는 문제를 살펴보겠습니다. 개발 환경으로는 일반 클라이언트가 접속할 수 없기 때문에 운영 환경에 릴리스해야 하는데요. 이 문제는 프로젝트 클론이라는 기능을 이용해 해결할 수 있습니다.
개발자가 데이터를 변경했을 때 특정 서버에 이벤트 트리거 방식으로 변경 내용을 반영해야 하는 문제는 웹훅(webhook) 기능을 활용해 해결할 수 있습니다.
특정 날짜나 특정 시간에 아이템을 공개하거나 비공개하는 기능도 필요했습니다. 이 역시 헤드리스 CMS에 포함해야 하는 기능이었습니다.
저희는 이런 기능을 헤드리스 CMS에 종속되지 않게 개발하고 싶어서 마이크로 서비스 아키텍처로 구조를 개선하면서 CDC(change data capture)라는 기술을 도입했습니다.
CDC는 데이터베이스에서 변경 사항을 식별해 후속 처리를 진행할 수 있게 해주는 기술입니다. 이 기술을 이용해 Reaction
필드가 삭제됐을 때 CDC 모듈을 이용해 후처리를 진행해서 역정규화 후 발생한 문제를 해결했습니다.
헤드리스 CMS로 개발한 LINE 서비스 소개
지금까지 LINE에서 기존 헤드리스 CMS의 단점을 개선해 더욱 안정적이면서 성능이 향상됐을 뿐 아니라 확장 가능한 아키텍처로 개선한 헤드리스 CMS를 소개했습니다. 이렇게 개선한 헤드리스 CMS로 개발한 LINE의 주요 서비스를 소개하겠습니다.
먼저 앞서 소개한 Tech-Verse 웹사이트인데요. Tech-Verse 웹사이트는 서버와 데이터베이스가 별도로 존재하지 않습니다. 모두 헤드리스 CMS를 이용해서 개발했습니다.
다음으로 LINE DEVELOPER DAY 2021 웹사이트입니다. LINE DEVELOPER DAY 2020에서는 서버를 총 23대를 운영했었는데 헤드리스 CMS를 도입하면서 한 대로 줄일 수 있었습니다.
다음은 지금 여러분이 보고 계시는 LINE Engineering 블로그입니다. 기존 시스템은 워드프레스였는데요. 약 1,500개 게시물을 모두 헤드리스 CMS로 이전해서 현재는 헤드리스 CMS로 운영하고 있습니다.
마지막으로 LINE NFT 플랫폼 DOSI입니다. DOSI 프런트엔드 개발자분들이 최근 DOSI 웹사이트를 헤드리스 CMS를 이용하는 것으로 리뉴얼했습니다. 또한 DOSI와 관련된 다른 여러 웹사이트도 앞으로 헤드리스 CMS로 이전하는 것을 계획하고 있다고 합니다.
이처럼 새로운 프로젝트뿐 아니라 기존에 론칭했던 서비스도 헤드리스 CMS로 재개발하고 있다는 것은 그만큼 편리하다는 방증이겠죠?
마치며
저희는 헤드리스 CMS를 개선해서 TPS를 약 4,400%나 향상시킬 수 있었습니다. 이를 통해 실시간으로 프런트엔드에서 API를 호출할 수 있으며 24시간 안정적으로 운영되는 환경을 구축해서 다양한 서비스를 헤드리스 CMS로 운영하고 있습니다. 현재 LINE에서는 매달 131개가 넘는 프로젝트가 헤드리스 CMS로 개발 및 운영되고 있습니다.
이 글을 읽고 계신 독자 여러분도 헤드리스 CMS를 이용해 백엔드 개발 없이 자유롭게 프런트엔드를 개발할 수 있는 환경을 경험해 보셨으면 좋겠습니다. 긴 글 읽어주셔서 감사합니다.