요즘IT
위시켓
최근 검색어
전체 삭제
최근 검색어가 없습니다.

*FEConf2024에서 발표한 <7가지 플랫폼 서버로 프론트엔드 버프 마법 걸기>를 정리한 글입니다. 발표 내용을 2회로 나누어 발행합니다. 1회에서는 프론트엔드의 라이프 사이클에 대해 간단히 알아보고 4가지 버프 방법에 대해 알아보겠습니다. 2회에서는 나머지 3가지 버프에 대해 알아보고, 시행착오로 배운 것들에 대해 알아봅니다. 본문에 삽입된 이미지의 출처는 모두 이 콘텐츠와 같은 제목의 발표 자료로, 따로 출처를 표기하지 않았습니다.

회원가입을 하면 원하는 문장을
저장할 수 있어요!

다음

회원가입을 하면
성장에 도움이 되는 콘텐츠를
스크랩할 수 있어요!

확인

개발

7가지 플랫폼 서버로 프론트엔드 버프 마법 걸기 (2)

년차,
어떤 스킬
,
어떤 직무
독자들이 봤을까요?
어떤 독자들이 봤는지 궁금하다면?
로그인

*FEConf2024에서 발표한 <7가지 플랫폼 서버로 프론트엔드 버프 마법 걸기>를 정리한 글입니다. 발표 내용을 2회로 나누어 발행합니다. 1회에서는 프론트엔드의 라이프 사이클에 대해 간단히 알아보고 4가지 버프 방법에 대해 알아보겠습니다. 2회에서는 나머지 3가지 버프에 대해 알아보고, 시행착오로 배운 것들에 대해 알아봅니다. 본문에 삽입된 이미지의 출처는 모두 이 콘텐츠와 같은 제목의 발표 자료로, 따로 출처를 표기하지 않았습니다.


FEConf2024에서 발표된 ‘7가지 플랫폼 서버로 프론트엔드 버프 마법 걸기’/정석호 토스 코어 Frontend Infra Ops Unit Lead

 

 

이번 글에서는 앞선 글의 4가지 버프, 이미지 최적화, 비디오 썸네일, 폴리필, 스켈레톤 마법에 이어 다양한 마법을 알아보려고 합니다. 우선 애셋 마법에 대해 알아보겠습니다.

 

애셋 마법

토스 앱을 사용할 때 유저별로 다양한 UI를 적용하여 사용할 수 있습니다. 예를 들어 다크 테마와 라이트 테마, 큰 글씨 모드, 그리고 기기별로 다른 세이프 에어리어인 노치 UI 등이 있습니다. 이렇게 유저마다, 기기마다 다른 UI에 어떻게 대응할 수 있을까요?

 

네이티브 앱 정보

앞서 설명한 기기별 정보는 네이티브 앱에서만 얻을 수 있는 정보입니다. 즉, 네이티브 앱에서 전달하는 정보들을 활용해 웹페이지에서 이를 읽어서 대응하는 방식이 필요합니다.

 

 

위 그림의 순서와 같이 HTML을 로드하고 자바스크립트와 CSS를 로드합니다. 그리고 JS 앱 브릿지를 호출하여 네이티브 앱으로부터 정보들을 동적으로 불러오고, 이 정보를 토대로 동적으로 CSS를 그리고 적용하여 렌더링 할 수 있습니다.

 

하지만 토스에서는 HTML, 자바스크립트, CSS가 모두 로드되고 앱 브릿지를 호출하는 과정까지 시간이 너무 느리다고 생각했습니다. 이를 해결하기 위한 아이디어는 어떤 것이 있을까요?

 

동적 CSS Variables

다양한 아이디어를 생각해 보았는데요, 그 중 대표적인 방법이 동적 CSS Variable이라는 방법입니다. 유저 에이전트를 통해서 기기별 정보를 넘겨주면 애셋 서버에서 CSS Variables를 동적으로 전달해 주는 방식입니다.

 

 

간단한 예시를 보겠습니다. 네이티브 앱에서 웹뷰를 설정할 때 아래처럼 유저 에이전트를 커스텀할 수 있습니다. 아래 이미지의 노란색 부분이 바로 유저 에이전트 뒤에 붙인 커스텀 유저 에이전트입니다. SafeArea와 4개의 숫자를 적었고, ColorPreference와 dark라는 문자열을 적어뒀습니다. 이 정보들을 통해 SafeArea의 수치가 몇인지, 그리고 ColorPreference는 다크인지 라이트인지를 미리 알 수 있습니다.

 

 

이러한 정보들을 토대로 애셋 서버에서는 아래 이미지와 같이 CSS Variables를 미리 작성해서 브라우저에게 넘겨줄 수 있습니다.

 

 

애셋 서버 덕분에 HTML, 자바스크립트, CSS를 로드한 다음 JS 앱브릿지를 호출할 필요 없이 바로 CSS를 적용해서 화면을 보여줄 수 있었습니다. 즉, 자바스크립트 의존성 없이 CSS 로드 직후 바로 적용이 될 수 있습니다. 로드 의존성 없이 완성된 CSS를 내려받기 때문에 화면이 깜빡거리는 문제 없이 화면이 뜨자마자 다크 테마, 큰 글씨 모드, 네이티브 노치 UI까지 모두 대응할 수 있었습니다.

 

 

오픈 그래프 마법

다음은 오픈 그래프 마법입니다. 지금부터 설명할 마법은 앱과 관련 없는 다른 외부의 마법이라고 보시면 됩니다. 이 마법은 유저들끼리 URL을 서로 공유할 때 뜨는 미리 보기 이미지와 관련이 있습니다. 아래와 같이 토스 테크 블로그의 URL을 트위터에 공유하면 아래와 같은 미리 보기 이미지가 뜨게 됩니다. 바로 이런 미리 보기 썸네일을 만드는 방법이 바로 오픈 그래프 마법입니다.

 

 

URL의 미리 보기가 바뀐다면?

만약 위의 글의 제목이 바뀐다면 어떤 과정이 필요할까요? 아마도 설정해둔 이미지를 교체해야 할 것입니다. 제목을 수정하고, 이미지를 다시 만들어 내려받고, CDN에 업로드하고, 업로드한 이미지를 다시 적용시켜야 하는 번거로움이 발생합니다.

 

제목과 배경 이미지를 조합하여 해결하기

이런 번거로움을 해결하기 위해 제목과 배경 이미지를 조합하면 어떨까요? 제목에 따라 이미지를 동적으로 불러오는 방법을 사용해 보겠습니다.

 

 

아티클 제목인 ‘똑똑하게…’와 배경 이미지를 조합해 그림의 오른쪽과 같은 이미지를 만들 수 있습니다. 즉, 아티클 제목은 타이틀 변수를 통해 전달하고, 배경 이미지는 URL을 전달한 다음 이미지를 생성하여 사용하는 것입니다. 이번에 자세한 구현 방법은 소개하지 않겠습니다. 대신 이 동작을 구현하는 힌트, Headless Browser Puppeteer Screenshots를 찾아보시면 좋을 것 같습니다.

 

이 마법을 사용하면, 아티클 제목이 바뀔 때마다 새로운 이미지를 만들어 업로드할 필요 없이, 타이틀 파라미터와 URL만 수정하면 썸네일을 수정할 수 있습니다. 타이틀 변수가 서버로부터 받는 정보라면, 서버에서 타이틀 변수만 수정하면 사실 프론트엔드에서는 건드릴 것 없이 썸네일 이미지를 수정할 수 있습니다.

 

 

웹 모듈 마법

드디어 마지막 마법인 웹 모듈 마법입니다. 웹 모듈에 대해서는 생소하실 거라고 생각합니다. 웹 모듈은 디자인 시스템과 디자인 툴에 영향력을 끼치는 요소입니다. 웹 모듈에 대해 설명하기 전에 우선 토스의 디자인 툴에 대해 설명드리고 싶습니다.

 

Framer Code Component

토스 디자이너분들이 가장 많이 사용하는 강력한 디자인 툴은 Framer입니다. Framer의 가장 대표적인 기능 중 하나는 Framer Code Component입니다. 이 기능을 활용하면 실제 리액트 컴포넌트를 가져와서 UI로 보여줄 수 있습니다. 즉, 실제로 디자인 시스템에서 작성한 리액트 컴포넌트를 Framer에 불러와서 디자인을 확인할 수 있습니다.

 

Framer Code Component의 제약 사항

다만 이 기능에서 토스 디자인 시스템 (TDS)와 같은 외부 디자인 시스템 코드를 가져와서 사용하려면 다양한 제약들이 있습니다. 대표적으로 Framer에서 NPM Import 기능은 실험적 기능이기 때문에 상황에 따라 제대로 동작하지 않는 경우가 발생할 수 있습니다.

 

다른 제약은 바로 ES 모듈 기반 코드만 가져올 수 있다는 점입니다. 이 제약은 토스 팀에 가장 큰 제약 사항이었습니다. 왜냐하면 TDS는 CommonJS 기반으로 번들링 되기 때문입니다. 따라서 TDS를 Code Component에서 사용하는 것이 불가능했습니다.

 

제약 사항 해결하기

아래 그림은 토스에서 이를 해결한 구조입니다. TDS와 Framer Code Component 사이에 TDS 웹 모듈 (ES 모듈)을 볼 수 있습니다. 토스에서는 중간에 TDS 웹 모듈을 배치하여 이를 해결했습니다. 웹 모듈에 대해 자세히 알아볼까요?

 

 

아래 그림과 같이 Framer Code Component를 사용할 때 URL을 기준으로 컴포넌트를 불러올 수 있습니다. HTTPS 프로토콜을 사용하여 의존성을 가져오고 있는 부분이 바로 웹 모듈입니다. URL Imports, HTTPS Imports, Network Imports와 같은 키워드를 들어본 적 있나요? 이런 방법을 통해 모듈을 임포트 하는 방법입니다.

 

 

esm.sh와 같은 클라우드 웹 모듈 서비스가 대표적인 예시입니다. esm.sh에서 React 라이브러리를 가져와서 컴포넌트를 그릴 수 있습니다.

 

ES 모듈과 웹 모듈에는 차이점이 있습니다. 일반적으로 사용하는 ES 모듈은 node_modules를 통해 의존성을 임포트 합니다. 반면 웹 모듈은 CDN을 통해 전송받은 파일을 통해 의존성을 임포트 합니다. Framer에서는 아래 그림과 같이 웹 모듈을 이용해서 CDN을 통해 웹 모듈을 임포트 합니다.

 

 

따라서 토스 UX 팀에서는 디자인 시스템에 있는 코드들을 디자인 팀에 넘길 때, 웹 모듈을 통해서 Framer에 적용한다고 볼 수 있습니다.

 

웹 모듈 마법을 통해 토스 디자인 시스템의 코드 베이스는 그대로 가져가서 서비스 코드에 전혀 영향을 주지 않게 되었습니다. 그리고 Framer Code component를 사용할 수 있어서 미리 만들어 놓은 디자인 시스템과 동일한 일관성 있는 디자인을 사용하면서 개발을 빠르게 할 수 있는 생산성까지 얻을 수 있었습니다.

 

웹 모듈을 제공하는 클라우드 서비스는 다양합니다. 앞에서 살펴본 esm.sh를 비롯해 esm.run, skypack.dev 등이 대표적입니다. 하지만 토스에서는 이 서비스를 그대로 쓰기는 어려웠습니다. self-hosted가 미제공되었고, 제공이 되더라도 esm 표준을 준수하지 않았기 때문에 export map이 제대로 작동하지 않는 문제도 생겼습니다. 그리고 유명한 라이브러리에 대응하기 위해 하드코딩으로 대응된 부분도 있었습니다.

 

이런 문제점으로 인해 토스만의 웹 모듈 서버를 만들게 되었고, 아래와 같이 URL과 캐럿 버전까지 명시하여 웹 모듈을 사용할 수 있게 되었습니다.

 

 

참고로, esm.sh는 self-hosted와 프라이빗 레지스트리를 제공하는 Go 언어 기반의 오픈소스입니다. 현재 토스에서도 esm.sh 도입하려고 검토 중입니다. 여러분들도 esm.sh를 활용해 웹 모듈 서비스를 사용해 보면 좋을 것 같습니다.

 

 

구현을 위한 Cheat Sheet

지금까지 7가지 마법에 대해 알아보았습니다. 이번 글에서는 실제 구현을 위한 코드나 내용은 최대한 빼고 설명했는데, 혹시 실제 구현에 대한 질문이 생길 수도 있을 것 같아서 아래와 같은 목록을 작성했습니다.

 

 

실제 구현을 위해 이와 같은 라이브러리들을 활용을 했습니다. 위 키워드를 활용하면 여러분도 구현에 필요한 힌트를 얻을 수 있을 것 같습니다.

 

 

시행착오 (7가지 마법 절망편)

지금까지는 7가지 마법을 희망차게 소개하면서 이 마법들을 사용하면 프론트엔드에 버프를 걸 수 있다고 소개했습니다. 하지만 뒤에는 절망 편도 존재합니다. 바로 다양한 시행착오를 겪은 내용인데, 하나씩 설명드리겠습니다.

 

클라우드 인프라 이중화의 어려움

AWS 람다를 통해 서비스를 구현할 때 만약 람다 자체가 장애를 일으키면 서비스를 운영할 수 없을 것입니다. 토스는 안정성이 가장 중요한 서비스이기 때문에 AWS에 장애가 나도 서비스가 정상적으로 동작 되어야 합니다. 이를 대비하기 위해 다른 업체에 이중화를 구현할 수 있습니다. AWS에 구현된 내용을 Cloudflare에도 구현해두는 것입니다.

 

이중화를 통해 장애 대응을 할 수 있지만 이로 인해 다양한 클라우드 제공 업체에 따로 배포해야 하고, 로그나 모니터링도 따로 확인해야 합니다. 즉, 운영 복잡도가 올라간다는 단점이 존재합니다. 이러한 문제점을 해결하기 위해 토스에서는 자체적으로 서버들을 구현하게 됐습니다.

 

Serverless Node.js 버전 따라가기

이미지 최적화 서비스가 처음 만들어질 때 사용한 Node.js의 버전은 14, 16 정도였습니다. 이 버전을 사용하여 서비스를 운영하다가 반드시 버전 변경을 해야 하는 상황을 만나면 많은 번거로움이 생깁니다. AWS에서는 현재 Node.js 16기반의 람다를 수정하는 것조차 허용하지 않습니다. Node.js 16은 너무 오래된 버전이기 때문입니다. 따라서 운영 중인 서비스의 코드 베이스를 강제로 올려서 빌드한 후 알맞은 버전으로 배포를 해야 합니다.

 

이런 과정은 감당하기 힘든 리스크가 될 수도 있습니다. 이렇게 버전에 대한 End-Of-Life를 만나게 되더라도 클라우드 제공 업체가 아닌 토스 팀 스스로 주도권을 가져가고 싶었습니다. 직접 구현한 서버를 통해 강제 업데이트를 최대한 피하고 시간이 여유로울 때 차근차근 버전을 올릴 수 있도록 했습니다.

 

API 호출 비용

세 번째는 바로 API 호출에 따른 비용 문제입니다. 타임 어택과 같은 이벤트성 트래픽은 매우 짧은 시간 동안 급격한 트래픽이 발생하기 때문에 CDN이 있어도 캐시가 제대로 동작하지 않을 수 있습니다. 캐싱 되지 않았을 때 발생하는 트래픽 비용은 람다가 호출되는 만큼 발생하기 때문에 트래픽을 미리 예측하고 비용을 계산해야 할 수 있습니다. 반면 토스에서는 자체 서버를 통해 람다 서비스 비용을 아낄 수 있었습니다.

 

QueryString 기반의 API 인터페이스

다음 시행착오는 인터페이스에 관한 내용입니다. 앞서 설명드린 다양한 서버들의 인터페이스는 대부분 QueryString으로 동작합니다. 이로 인해 CDN에서 캐시를 적용하기 조금 어려웠습니다. 아래와 같이 컬러, 사이즈 순서의 요청과 사이즈, 컬러 순서의 요청은 서로 다른 별개의 캐시로 기록됩니다. 즉, 같은 요청이지만 2개의 캐시가 생기는 문제점이 발생합니다.

 

 

이러한 문제에 대해 QueryString보다는 Path 기반으로 적용하여 이 문제를 해결했습니다. 아래와 같이 ‘src=이미지주소&q=80&w=200’의 QueryString 기반이 아닌 ‘width=80,quality=75/이미지주소’와 같이 Path 기반으로 만들었습니다.

 

 

이 아이디어는 직접 고안해낸 방법은 아니고, Cloudflare의 이미지 최적화 API에서 사용하는 기법 중 하나입니다. 이 방법을 도입하여 캐싱 기간을 많이 늘릴 수 있었고 관리도 쉬워지는 장점을 얻었습니다.

 

람다 최대 응답 페이로드 제한

또 다른 시행착오는 람다의 최대 응답 페이로드의 크기에 제한이 걸려있다는 것입니다. 6MB를 넘는 요청은 비용을 더 지불해도 해결할 수 없는 문제였습니다. 실제로 6MB를 넘는 요청은 제대로 된 응답을 주지 못합니다.

 

토스에서는 앞서 설명한 비디오 썸네일 서비스에서 6MB가 넘는 경우가 발생했습니다. 가로 영상과 세로 영상이 존재하는데, 가로 영상만 생각하고 가로 길이로 이미지 최적화를 하다 보니 세로 영상의 경우는 썸네일 이미지 사이즈가 엄청 커저버리는 경우가 발생했습니다. 결국 400, 500 등의 응답을 받는 경우가 발생했습니다.

 

이런 경우가 발생하더라도 실제 서비스에서는 이런 문제가 나타나면 안 된다고 생각합니다. 혹시나 6MB를 넘는 요청이 발생하였더라도, 자체적인 서버 운영 등의 방법을 통해 서비스에 지장을 주지 않게 해야 합니다.

 

CDN Vary Header

캐싱 정책을 사용할 때 Vary 헤더를 사용해야만 요청 헤더마다 별도의 캐시를 사용할 수 있습니다. 폴리필 서버를 예로 들면, 제가 사용하는 브라우저와 옆 사람이 쓰는 브라우저가 다르지만, 폴리필 JS를 동일하게 받는 문제가 생깁니다. 즉, 인터넷 익스플로러가 먼저 캐싱 해버린 상태로 크롬에서 폴리필 JS를 받으면 익스플로러에서 캐시 된 폴리필 JS를 받게 되는 것입니다.

 

이러한 문제를 해결하기 위해 요청 헤더를 Vary 헤더로 설정하여 유저 에이전트가 달라지면 캐시를 별도로 사용한다고 명시적으로 세팅해야 합니다.

 

 

절망편 정리

시행착오 내용들을 정리하면, 서비스를 이중화를 하면 다양한 업체에 대해 관리해야 하는 문제가 있고, 람다를 사용할 때 Node.js의 버전을 잘 챙겨야 합니다. 이벤트성 트래픽은 캐싱이 어렵기 때문에 트래픽 비용을 잘 고려해야 하고, QueryString보다는 Path 기반의 인터페이스로 만들기를 추천합니다. 람다의 응답 최대 크기는 6MB라는 점을 기억하고 이를 초과하는 경우를 대비해야 하고, Vary 헤더를 잘 사용하여 캐싱 정책을 올바르게 만들어 사용해야 합니다.

 

 

 

마치며

지금까지 프론트엔드에 버프를 걸기 위한 7가지 마법에 대해 희망 편과 절망 편으로 나누어 알아보았습니다. 7가지 마법을 잘 활용하여 안정성 높고 개발하기 쉬운 프론트엔드 인프라를 구축하길 바랍니다. 또, 절망 편에서 소개한 시행착오 내용들도 유의하여 앞으로 만나게 될 문제점들을 이겨내는 데 도움이 되면 좋겠습니다.

 

 

요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.

좋아요

댓글

공유

공유

댓글 0
FEConf
508
명 알림 받는 중

작가 홈

FEConf
508
명 알림 받는 중
프론트엔드 컨퍼런스 FEConf 공식 계정입니다.

좋아요

댓글

스크랩

공유

공유

요즘IT가 PICK한 뉴스레터를 매주 목요일에 만나보세요

요즘IT가 PICK한 뉴스레터를
매주 목요일에 만나보세요

뉴스레터를 구독하려면 동의가 필요합니다.
https://auth.wishket.com/login