토스는 어떻게 광고 속에 게임을 넣었을까
토스가 광고 시스템을 자체 구축하면서 서드파티 SDK 대신 국제 광고 표준 MRAID를 직접 구현해 플레이어블 광고(앱 설치 전 게임 체험)를 지원한 과정이다. mraid.js 브릿지, 5중 렌더링 완료 신호, 보안 중심 설계, 앱 심사 없는 즉시 배포를 동시에 달성했다.
요약 이어보기카카오웹툰 검색창에서 "포커스 시 커서를 제일 뒤로" 요구사항을 구현하면서 HTMLInputElement.setSelectionRange()의 타이밍 이슈와 setTimeout(fn, 0)의 이벤트 루프 동작을 실전에서 학습한 경험을 담은 글이다. 단순해 보이는 UX 하나가 브라우저 이벤트 처리 순서 이해를 요구하는 사례다.
핵심 포인트 - setSelectionRange(start, end)는 input 커서 위치 제어에 사용하며, start===end이면 커서만 이동 (선택 없음) - focus 이벤트와 브라우저 기본 클릭 커서 위치 지정의 실행 순서 충돌이 핵심 문제 - mouseup 이벤트로 교체하면 키보드 포커스 대응 불가 + 특정 위치 커서 지정 불가 side effect 발생 - setTimeout(fn, 0)으로 콜백을 마이크로태스크 큐 이후로 밀어 브라우저 기본 동작 완료 후 커서 이동 - 0ms delay여도 최소 4ms 지연이 발생하며, 이것이 이벤트 처리 순서 역전을 가능하게 함 - scrollLeft도 함께 설정해야 input 내 스크롤 위치가 커서와 동기화됨
상세 정리 - setSelectionRange(selStart, selEnd, selectionDirection?) 시그니처: 0-based index - 값이 length보다 크면 자동으로 끝 위치로 처리 → maxLength를 넘겨도 안전 - 지원 input type: text, search, URL, tel, password. number/range 등에서 호출하면 예외 발생 - 첫 구현: focus 이벤트에서 setSelectionRange(maxLength, maxLength) → 스크롤은 이동하나 커서는 클릭 위치에 남음 - 원인: 브라우저가 클릭 위치로 커서를 재설정하는 기본 동작이 focus 콜백 이후에 실행됨 - mouseup 교체 시도: 마우스 손가락을 떼는 시점에 커서 강제 이동 → 키보드 포커스 미동작 - mouseup의 치명적 부작용: 사용자가 특정 위치 클릭해도 커서가 항상 끝으로 고정됨 - setTimeout(fn, 0) 적용: 0초여도 이벤트 루프 다음 틱으로 콜백이 밀림 - console.log 실행 순서 실험: setTimeout(fn, 0) 내부 로그가 외부 로그보다 나중에 출력 - 이유: 태스크 큐에 등록되어 현재 실행 컨텍스트 완료 후 실행, 최소 4ms delay 보장 - 최종 코드: focus 이벤트 + setTimeout 0ms + setSelectionRange(maxLength, maxLength) + scrollLeft - scrollLeft 계산: font-size 22px 기준, 한글 약 30px로 추산 → maxLength * 30
왜 읽나: focus 이벤트와 브라우저 기본 동작의 실행 순서 문제를 setTimeout(fn, 0)으로 해결하는 이벤트 루프 실전 사례로, DOM API를 다루는 개발자라면 한 번쯤 마주칠 패턴이다.
토스가 광고 시스템을 자체 구축하면서 서드파티 SDK 대신 국제 광고 표준 MRAID를 직접 구현해 플레이어블 광고(앱 설치 전 게임 체험)를 지원한 과정이다. mraid.js 브릿지, 5중 렌더링 완료 신호, 보안 중심 설계, 앱 심사 없는 즉시 배포를 동시에 달성했다.
요약 이어보기채널톡 고객용 SDK에서 boot→shutdown→boot 연속 호출 시 사이드 이펙트가 중첩되는 타이밍 버그를 RxJS 기반 구조 개편으로 해결한 사례다. 비동기 흐름 직렬화에 RxJS, 동기적 상태 관리에 Zustand를 도입해 타이밍 비결정성을 구조 수준에서 제거했다.
요약 이어보기여기어때 항공 서비스 프론트엔드가 웹과 앱 웹뷰 두 환경에서 동일한 함수 호출로 동작하는 앱 브릿지 추상화 레이어를 설계한 과정을 다룬다. iOS·안드로이드 규약 차이와 "웹에 존재하지 않는 브릿지를 어떻게 호출하나"라는 문제를 단일 추상화 층으로 해결한 구현 사례다.
요약 이어보기