토스는 어떻게 광고 속에 게임을 넣었을까
토스가 광고 시스템을 자체 구축하면서 서드파티 SDK 대신 국제 광고 표준 MRAID를 직접 구현해 플레이어블 광고(앱 설치 전 게임 체험)를 지원한 과정이다. mraid.js 브릿지, 5중 렌더링 완료 신호, 보안 중심 설계, 앱 심사 없는 즉시 배포를 동시에 달성했다.
요약 이어보기카카오웹툰 팀이 웹에서 다크모드를 지원하면서 겪은 시행착오와 최종 채택한 방법을 정리한 글이다. CSS 미디어 쿼리 방식의 한계를 설명하고, 앱 웹뷰 환경을 포함한 실용적인 해결책을 제시한다.
핵심 포인트 - prefers-color-scheme 미디어 쿼리는 시스템 다크모드만 따라가서 앱 내 웹뷰 동기화 불가 - 구버전 Android 미지원, 사용자 직접 선택 기능 구현 어려움 등 미디어 쿼리 방식의 현실적 한계 - 추천 방법: body 태그에 .dark 클래스 부여 + JavaScript DOM 조작으로 런타임 제어 - localStorage로 사용자 선택 저장해 새로고침 후에도 유지 - 앱 웹뷰는 네이티브 앱과 postMessage/JSBridge로 다크모드 상태 동기화 - CSS 변수(--color-*)로 색상 토큰화해 .dark 클래스 하나로 전체 테마 전환
상세 정리 - prefers-color-scheme의 한계: 시스템 설정 의존, 앱 웹뷰에서 OS 설정과 앱 설정 불일치 발생 - 구버전 Android 브라우저 미지원으로 사용자 일부가 항상 라이트모드만 보는 문제 - 미디어 쿼리로는 사용자가 앱 내에서 다크/라이트 직접 선택하는 UX 구현 어렵거나 복잡 - 해결책: JavaScript로 document.body.classList.toggle('dark') 방식 채택 - CSS: :root 에 --bg, --text 등 변수 정의 → .dark 클래스 내에서 변수 재정의 - localStorage 키에 사용자 선택 저장 → 페이지 로드 시 즉시 적용해 FOUC 방지 - 앱 웹뷰 동기화: 앱이 window.postMessage로 다크모드 상태 전달 → 웹에서 클래스 적용 - 반대로 웹에서 선택 변경 시 앱에 postMessage로 통보해 네이티브 UI도 동기화 - 초기 로드 시 깜빡임(FOUC) 방지: <head> 인라인 스크립트로 클래스를 즉시 설정 - SSR 환경(Next.js)에서는 서버 렌더링 시 기본값 적용 후 클라이언트 hydration 시 로컬 설정 반영 - 다크모드 아이콘·이미지: CSS filter: invert() 또는 별도 다크 버전 에셋 사용 검토
왜 읽나: 미디어 쿼리로 다크모드를 구현했다가 앱 웹뷰 동기화 문제에 부딪힌 개발자, 또는 처음부터 제대로 된 다크모드 아키텍처를 설계하려는 개발자에게 실전 경험 기반의 해답을 제공한다.
토스가 광고 시스템을 자체 구축하면서 서드파티 SDK 대신 국제 광고 표준 MRAID를 직접 구현해 플레이어블 광고(앱 설치 전 게임 체험)를 지원한 과정이다. mraid.js 브릿지, 5중 렌더링 완료 신호, 보안 중심 설계, 앱 심사 없는 즉시 배포를 동시에 달성했다.
요약 이어보기채널톡 고객용 SDK에서 boot→shutdown→boot 연속 호출 시 사이드 이펙트가 중첩되는 타이밍 버그를 RxJS 기반 구조 개편으로 해결한 사례다. 비동기 흐름 직렬화에 RxJS, 동기적 상태 관리에 Zustand를 도입해 타이밍 비결정성을 구조 수준에서 제거했다.
요약 이어보기여기어때 항공 서비스 프론트엔드가 웹과 앱 웹뷰 두 환경에서 동일한 함수 호출로 동작하는 앱 브릿지 추상화 레이어를 설계한 과정을 다룬다. iOS·안드로이드 규약 차이와 "웹에 존재하지 않는 브릿지를 어떻게 호출하나"라는 문제를 단일 추상화 층으로 해결한 구현 사례다.
요약 이어보기