pile·
프론트엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

항공 프론트엔드 구축기 (1/10): 웹, 모바일웹, 웹뷰를 코드 한 벌로

여기어때 항공 서비스 리뉴얼을 계기로 서비스웹개발팀과 웹뷰개발팀이 합쳐진 후, 웹·모바일웹·앱 웹뷰를 코드 한 벌로 운영하기로 결정한 과정과 그 설계 철학을 다룬다. "로직만 공유하고 화면은 따로"라는 절충안이 결국 두 벌 코드베이스로 귀결되는 이유를 밝히고, 단일 코드가 성립하기 위한 세 가지 조건을 제시한다.

핵심 포인트
  • "로직만 공유하고 화면은 따로" 방식은 드롭다운 상태, 뒤로가기 히스토리, 라우팅이 결국 각자 생겨 두 벌 코드베이스가 되고 서로 눈치를 봐야 하는 상태가 된다.
  • 한 벌이 성립하려면 세 조건이 필요하다: 소수 인원의 빠른 프레임 구성, Vue2 공용 컴포넌트 포팅 가능성, 환경 분기를 숨기는 DX 우선 설계.
  • 목표는 "차이를 없애는 것"이 아니라 "분기가 싸게 되는 것"이다. 감출 수 있는 건 감추고, 감출 수 없는 건 한 줄로 갈리게 했다.
  • 모노레포(pnpm workspace:*)로 라이브러리 변경이 서비스 화면에 즉시 반영되게 해 개발 루프에서 배포를 걷어냈다.
  • 최종적으로 국내선·해외선 양쪽 라우트 트리는 두 벌이지만, 페이지 구현 파일의 diff는 함수 이름 한 줄만 다르다.
상세 정리
  • 배경: Vue2 기반 웹뷰 전용 항공 서비스를 리뉴얼하면서 웹과 웹뷰를 어떻게 공유할지 결정해야 했다. 두 팀이 합친 후 처음 맡은 신규 서비스라 구조 결정에 여유가 없었다.
  • 3안 검토: 1안(각각 만들기) — 같은 화면을 두 번 만들고 고칠 때마다 두 곳 수정. 2안(로직만 공유) — 절충안처럼 보이지만 상태·라우팅·히스토리가 섞이면서 결국 두 벌이 되고 공유 층의 눈치까지 봐야 한다. 3안(한 벌) 채택.
  • 병목 위험: 앱 브릿지가 고유 규약이라 소수만 안다면 그 사람이 병목이 된다. 브릿지 코드·가이드 문서·스토리북으로 "아는 것을 제 바깥에 옮겨 두는" 방식으로 완화했다.
  • 한 벌 성립 조건 1: 소수 인원이 먼저 프레임을 빠르게 구성. 사공이 많으면 출발이 늦어진다.
  • 한 벌 성립 조건 2: Vue2 공용 컴포넌트를 포팅할 수 있어야 한다. Vue 전용 UI 라이브러리를 안 쓰고 Tailwind로 통일돼 있었기에 가능했다.
  • 한 벌 성립 조건 3: DX 우선. 환경 차이는 라이브러리가 감싸고, 그 위에서 개발자는 로직에만 집중. "넉넉하지 않은 일정일수록 환경에 쓰는 시간이 곧 품질 손실"이라는 판단.
  • 새로 만든 것들: 공용 컴포넌트(포팅)에 더해 환경 추상화·뒤로가기 제어·레이아웃·인증 네 가지가 "한 벌로 가기로 해서 새로 필요해진 것들"이었다.
  • 모노레포 구성: apps/flight(서비스), packages/core(공용 컴포넌트·훅·브릿지), packages/web-ui(도메인 컴포넌트). workspace:*로 라이브러리 파일 저장 즉시 서비스에 반영된다.
  • 결과: 라우트 트리는 (web)/와 (native)/ 두 벌이지만, 대부분 페이지의 diff는 함수 이름 한 줄이고 실질적 차이는 레이아웃 파일에 집중됐다.
왜 읽나웹과 웹뷰를 단일 코드베이스로 운영하는 구조를 설계하려는 팀에게, "로직만 공유"가 왜 결국 두 벌이 되는지와 한 벌 구조가 성립하기 위한 조건을 명확히 제시한다.
여기어때 (GC컴퍼니)
여기어때 (GC컴퍼니) 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 프론트엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    항공 프론트엔드 구축기 (7/10): 창구를 하나만 두었습니다

    여기어때 항공 서비스 프론트엔드가 웹과 앱 웹뷰 두 환경에서 동일한 함수 호출로 동작하는 앱 브릿지 추상화 레이어를 설계한 과정을 다룬다. iOS·안드로이드 규약 차이와 "웹에 존재하지 않는 브릿지를 어떻게 호출하나"라는 문제를 단일 추상화 층으로 해결한 구현 사례다.

    요약 이어보기
    #react#typescript#webview+2