토스는 어떻게 광고 속에 게임을 넣었을까
토스가 광고 시스템을 자체 구축하면서 서드파티 SDK 대신 국제 광고 표준 MRAID를 직접 구현해 플레이어블 광고(앱 설치 전 게임 체험)를 지원한 과정이다. mraid.js 브릿지, 5중 렌더링 완료 신호, 보안 중심 설계, 앱 심사 없는 즉시 배포를 동시에 달성했다.
요약 이어보기Canvas API로 이미지 픽셀 데이터를 순회해 고유 색상 목록을 추출하는 컴포넌트를 만들면서 메인 스레드 블로킹 문제를 Web Worker 다중화로 해결하는 과정을 다룬다. Web Worker의 동작 원리부터 멀티 워커 데이터 분할 전략, 실측 성능 비교까지 실용적으로 설명한다.
핵심 포인트 - 문제 정의: Canvas로 이미지 픽셀 데이터(498*498*4=992,016개 값)를 메인 스레드에서 순회하면 동기 실행으로 UI가 블로킹되어 다른 스크립트 실행 지연 - Web Worker 개념: 메인 스레드와 분리된 백그라운드 스레드에서 스크립트를 실행하는 기술. postMessage/onmessage로 양방향 데이터 교환하며 객체 참조는 공유 안 됨(복사) - 다중 워커 전략: ImageData 배열을 maxWorkers 수로 균등 분할해 각 워커에 slice로 청크 전달 → 병렬 처리 - 성능 측정 결과: 캔버스 크기별 메인 스레드(단일) vs 워커 다중화 실행 시간 비교. 500x500: 142.90ms, 1000x1000: 486.80ms, 1500x1500: 1016.70ms (메인 스레드 기준) - ImageData 구조: data 필드는 Uint8ClampedArray로 [R,G,B,A,R,G,B,A,...] 형태. 4바이트씩 묶어 RGBA 색상 문자열로 변환 후 Set에 추가
상세 정리 - Canvas API 3단계: 이미지 그리기 → getImageData()로 데이터 획득 → 픽셀 데이터(Uint8ClampedArray) 조회 - 메인 스레드 코드: for(let i=0; i<imageData.length; i+=4) { mainSet.add(rgba) } — 단순하지만 UI 블로킹 유발 - 워커 코드: postMessage로 슬라이스 받아 동일한 for 루프 실행 후 colorSet을 postMessage로 반환 - new Worker("./worker.ts")로 워커 생성, maxWorkers 개수만큼 생성해 병렬 처리 - 데이터 분할 시 imageData.byteLength / maxWorkers로 청크 크기 계산, cursor 이동으로 슬라이스 - 워커에서 반환된 Set들을 메인 스레드에서 합산해 최종 고유 색상 목록 생성 - Web Worker는 DOM 접근 불가, Canvas ImageData처럼 순수 연산 작업에 적합 - 워커 개수가 무조건 많을수록 좋지 않음 — 스레드 생성·통신 오버헤드와 트레이드오프
왜 읽나: 실제 UI 컴포넌트 개발 과정에서 Web Worker를 도입해 메인 스레드 블로킹을 해소하는 방법을 Canvas 이미지 처리 예제와 실측 데이터로 구체적으로 이해할 수 있다.
토스가 광고 시스템을 자체 구축하면서 서드파티 SDK 대신 국제 광고 표준 MRAID를 직접 구현해 플레이어블 광고(앱 설치 전 게임 체험)를 지원한 과정이다. mraid.js 브릿지, 5중 렌더링 완료 신호, 보안 중심 설계, 앱 심사 없는 즉시 배포를 동시에 달성했다.
요약 이어보기채널톡 고객용 SDK에서 boot→shutdown→boot 연속 호출 시 사이드 이펙트가 중첩되는 타이밍 버그를 RxJS 기반 구조 개편으로 해결한 사례다. 비동기 흐름 직렬화에 RxJS, 동기적 상태 관리에 Zustand를 도입해 타이밍 비결정성을 구조 수준에서 제거했다.
요약 이어보기여기어때 항공 서비스 프론트엔드가 웹과 앱 웹뷰 두 환경에서 동일한 함수 호출로 동작하는 앱 브릿지 추상화 레이어를 설계한 과정을 다룬다. iOS·안드로이드 규약 차이와 "웹에 존재하지 않는 브릿지를 어떻게 호출하나"라는 문제를 단일 추상화 층으로 해결한 구현 사례다.
요약 이어보기