클라이언트 SIProject2025.03 – 2025.06
Chatly — 맞춤형 언어학습 모바일 앱·어드민
React Native·Expo 앱에서 WebView PASS 인증과 재사용 가능한 API·데이터 변환 구조를 설계
역할 React Native 앱 및 웹 연동 구조 개발
Key Result
웹 기반 본인인증을 모바일 앱에 안정적으로 연결하고 크로스 플랫폼 데이터 구조 정리
React NativeExpoNext.jsTypeScript
핵심 요약
MBTI 기반 맞춤형 학습 콘텐츠를 제공하는 언어학습 모바일 앱·어드민에서, WebView를 인증 브리지로 삼아 웹 기반 PASS 인증을 네이티브 앱에 안전하게 연결하고, API·Form 변환 레이어로 서버·UI 변경이 서로에게 번지지 않게 했습니다.
프로젝트 배경
MBTI 기반 맞춤형 학습 콘텐츠·퀴즈·학습 기록/분석을 제공하는 언어학습 모바일 앱(React Native·Expo)과 콘텐츠 운영 어드민(Next.js) 프로젝트입니다. 저는 네이티브 앱과 웹 연동 구조를 맡았습니다.
담당 범위
- React Native·Expo 기반 iOS/Android 앱 개발
- WebView·deep linking·secure storage 등 모바일 연동
- PASS 본인인증 연동 구조
- httpOnly Cookie 인증 상태 동기화 · 웹↔네이티브 메시지 브리지(햅틱·공유)
- API Fetcher 및 데이터 변환 유틸
- 콘텐츠 유형별 렌더링 및 최적화
문제 정의
- 웹 전용 인증을 네이티브에서 못 쓰는 문제 — PASS 본인인증은 웹 기반이라 React Native 앱에서 그대로 호출할 수 없었고, 앱·WebView·서버 사이에서 인증 결과를 위·변조 없이 전달해야 했습니다.
- 인증 상태의 위치 — 토큰을 앱 저장소에 그대로 두면 탈취 위험이 커집니다. 인증의 신뢰 원천을 어디에 둘지 결정해야 했습니다.
- DTO와 화면의 강결합 — API DTO를 화면 Form이 직접 쓰면, 서버 스펙이 바뀔 때마다 UI가 흔들리고 반대로 UI 요구가 DTO를 오염시킵니다.
- HTTP 라이브러리 종속 — 특정 HTTP 라이브러리 호출이 기능 코드 전체에 퍼지면 교체·정책 변경 비용이 커집니다.
기술적 의사결정
1. WebView를 인증 브리지로 사용
- 배경 — 웹 PASS 인증을 앱 흐름에 잇되, 앱이 인증 결과를 임의로 신뢰하지 않게 해야 했습니다.
- 선택 — PASS 인증은 WebView에서 수행하고, 인증 결과는 Next.js API Route에서 서버 검증한 뒤
postMessage로 앱에 전달했습니다. 앱은 검증된 결과만 받아 후속 화면 이동을 처리하도록 역할을 나눴습니다. - 트레이드오프 — 네이티브 SDK로 직접 연동하는 방법도 있었지만, 웹·앱 양쪽에서 재사용하고 검증 책임을 서버에 모으기 위해 WebView 브리지를 택했습니다.
2. 인증 신뢰 원천을 서버에 유지
- 배경 — 토큰을 앱이 들고 있으면 노출 표면이 늘어납니다.
- 선택 — httpOnly Cookie로 인증 상태를 동기화해 토큰을 클라이언트에 노출하지 않고, 인증의 Source of Truth를 서버에 뒀습니다.
3. 웹↔네이티브 메시지 프로토콜 표준화
- 배경 — 브리지 메시지가 규칙 없이 오가면 이벤트 종류가 늘수록 파싱이 취약해집니다.
- 선택 —
eventType::payload형식으로 메시지 프로토콜을 표준화하고, HapticManager로 iOS/Android 햅틱 차이를 흡수해 플랫폼별 분기를 한곳에 모았습니다.
4. API 호출부 추상화 + DTO ↔ Form 분리
- 배경 — HTTP 라이브러리 종속과 DTO-Form 강결합이 변경을 서로에게 전파시켰습니다.
- 선택 — 커스텀 Fetcher 인터페이스로 토큰 주입·에러 처리·로깅을 기능 로직과 분리하고,
form ↔ request ↔ response변환 레이어를 두어 UI와 서버 스펙의 변경 영향을 끊었습니다. - 트레이드오프 — 변환 레이어는 보일러플레이트를 늘리지만, 서버·UI가 독립적으로 진화하는 값을 다룰 때는 결합을 끊는 편이 유지보수에 유리하다고 판단했습니다.
결과
- 웹 기반 PASS 인증을 모바일 앱에 안정적으로 연결 · 검증 책임을 서버로 집중
- httpOnly Cookie로 토큰 노출 없이 인증 상태 동기화
eventType::payload브리지 표준화 · HapticManager로 플랫폼 햅틱 차이 흡수- 커스텀 Fetcher로 HTTP 관심사와 기능 로직 분리, DTO ↔ Form 변환 레이어로 서버·UI 변경 영향 축소