요즘IT
위시켓
AIDP - AX
Rise ERP
콘텐츠프로덕트 밸리
요즘 작가들컬렉션물어봐
놀이터
콘텐츠
프로덕트 밸리
요즘 작가들
컬렉션
물어봐
놀이터
새로 나온
인기
개발
AI
IT서비스
기획
디자인
비즈니스
프로덕트
커리어
트렌드
스타트업
서비스 전체보기
위시켓요즘ITAIDP - AXRise ERP
고객 문의
02-6925-4867
10:00-18:00주말·공휴일 제외
yozm_help@wishket.com
요즘IT
요즘IT 소개작가 지원
기타 문의
콘텐츠 제안하기광고 상품 보기
요즘IT 슬랙봇크롬 확장 프로그램
이용약관
개인정보 처리방침
청소년보호정책
㈜위시켓
대표이사 : 박우범
서울특별시 강남구 테헤란로 211 3층 ㈜위시켓
사업자등록번호 : 209-81-57303
통신판매업신고 : 제2018-서울강남-02337 호
직업정보제공사업 신고번호 : J1200020180019
제호 : 요즘IT
발행인 : 박우범
편집인 : 노희선
청소년보호책임자 : 박우범
인터넷신문등록번호 : 서울,아54129
등록일 : 2022년 01월 23일
발행일 : 2021년 01월 10일
© 2013 Wishket Corp.
로그인
요즘IT 소개
콘텐츠 제안하기
광고 상품 보기
개발

Next.js 모바일 웹을 일주일 만에 앱으로 바꾼 방법 ①

핸디
7분
3시간 전
201
에디터가 직접 고른 실무 인사이트 매주 목요일에 만나요.
newsletter_profile0명 뉴스레터 구독 중

서서히 유저를 끌어모으던 웹 서비스가 있었습니다. Next.js로 잘 돌아가던 B2B 서비스였죠. 모바일 웹에서도 핵심 플로우는 이미 잘 동작하고 있었습니다. 그런데 VOC를 살펴보다가 고민에 빠졌습니다. 알림을 보지 못해서 계약이 불발되었다는 내용이었습니다. 웹에서는 항상 보이는 헤더의 알림창이 서비스를 벗어나면, 더이상 쉽게 볼 수 없는 정보가 됐습니다. 그래서 앱을 만드는 것에 대해 고민하기 시작했죠.

 

앱을 만드는 건 생각보다 많은 시간이 걸립니다. 하지만 이미 잘 정리된 모바일 웹이 있으니, 이걸 기반으로 AI에게 시키면 잘 만들어주지 않을까?라는 생각을 하게 된 거죠. 결론부터 미리 말하자면, 생각보다 더 잘 만들어줬습니다. 이 글의 제목처럼 일주일 만에 POC수준 이상의 앱을 만들었고, 지금은 QA를 거치는 중입니다.

 

그래서 이번 글에서는 모바일 웹을 앱으로 바꾸는 과정에서 부딪힌 이슈와, 이를 위해 어떤 워크플로우를 도입했고, 어떻게 기술 스택을 선정했는지에 대한 얘기를 풀어보고자 합니다.

 

시대를 역행하는 기술 스택

최근에 Shopify 엔지니어링 블로그의 “Native is now the future of mobile at Shopify”를 읽었습니다. 한 줄로 말하면, Shopify가 앱을 React Native에서 Swift와 Kotlin 네이티브로 되돌린다는 내용입니다.

 

흥미로운 지점은 “RN(React Native)이 실패해서”가 아니라는 데 있습니다. 글에서도 2020년 RN 올인은 매우 성공적이었다고 말합니다. 기능을 한 번만 만들고, 모바일 배경이 없는 개발자도 기여할 수 있게 하고, 플랫폼 간 패리티 추격에 덜 매달리게 해 주었다는 거죠. 그런데 코딩 에이전트(LLM)가 좋아지면서, 같은 기능을 두 번 만드는 비용이라는 가정이 흔들렸다고 합니다. 에이전트가 iOS를 보고 Android를 구현하거나, 그 반대를 할 수 있고, 공유 스펙·테스트·리뷰로 패리티 유지비가 예전만큼 무겁지 않다는 실험이 나왔다는 이야기입니다. 그래서 플랫폼에 더 가까운 네이티브가, 지금 Shopify 규모에서는 다시 합리적이 되었다는 결론으로 갑니다.

 

Shop 앱은 AI를 도우미로 두고, 약 12주 만에 네이티브로 재구축해 스토어에 올렸다는 대목도 인상적이었습니다. Helix 같은 체크포인트 루프로 “한 방에 네이티브 번역”이 아니라, 작은 단위로 검증하며 옮긴다는 점도요. 이 글을 읽고 나면, 2026년에 React Native를 고르는 일이 어쩐지 시대를 역행하는 선택처럼 느껴질 수 있습니다. 큰 회사들이 다시 네이티브로 가는 타이밍에, 저는 Expo 기반 RN으로 POC를 시작했으니까요.

 

그럼에도 저는 RN을 골랐습니다. Shopify의 결론을 부정해서가 아니라, 전제가 달랐기 때문입니다.

 

Shopify는 여러 대형 앱과 수백 명의 엔지니어, 이미 쌓인 RN 자산과 네이티브 전환을 감당할 조직이 있습니다. 저는 사실상 1인에 가까운 프론트엔드로, 이미 돌아가는 Next.js 웹과 같은 제품 언어를 최대한 공유해야 했습니다. Swift와 Kotlin을 동시에 새로 배우고, 웹까지 세 갈래로 의미를 맞추는 일은 일주일 POC의 목표가 아니었습니다.

 

제가 원한 공유는 단순히 UI에만 국한되지 않고, 가입 스키마, 에러 카피, API 훅, 폼 검증처럼 의미의 코드베이스를 웹과 앱이 같이 쓰는 쪽이었습니다. React 문법을 아는 상태에서 RN(Expo)으로 가면, AI 에이전트에게도 “웹 모바일 화면을 보고 앱 화면을 조립해”라는 지시가 통합니다. 같은 훅, 같은 zod, 같은 도메인 단어를 유지한 채 화면 단위로 옮길 수 있었죠. 네이티브 두 플랫폼을 AI가 잘 옮겨 준다는 Shopify의 논리와는 결이 다르지만, 이미 있는 React 웹을 SoT(Single source of Truth)로 삼아 한 사람이 개발해야 하는 상황에서는 RN이 훨씬 저에겐 합리적인 선택이었습니다.

 

 

모노레포를 먼저 깐 이유

이전에 AI 에이전트에게도 “웹 모바일 화면을 보고 앱 화면을 조립해”라는 지시가 통하게 하려면 웹 모바일 화면에 대한 충분한 컨텍스트를 제공할 수 있어야합니다. 그래서 기존 프로젝트를 모노레포로 옮기는 작업을 먼저 시작했습니다.

 

전체적인 구조는 다음과 같은데요. pnpm workspace로 apps/*와 packages/*를 나눴습니다.

 

apps 내부에는 “web”, “admin”, “mobile” 이렇게 3개의 프로젝트가 있고, packages 아래 이미지처럼 생겼습니다.

 

패키지 표: @chulgang/api·utils·assets·tokens·ui·ui-native 각각의 역할을 설명한 모노레포 구조
packages의 이름과 역할 <출처: 작가> 

 

이렇게 앱과 패키지를 나눈 세세한 이유는 없습니다. 단지 공유가능한 단위를 패키지로 옮기다보니, 이렇게 점점 생기고 있을 뿐입니다. 만약 추가로 옮겨야 하는 것들이 있다면 패키지에 추가하면 됩니다. 지금 떠오르는 후보는 Grafana, Sentry처럼 에러 로깅 시스템을 패키지화하면 좋지 않나라는 생각이 드네요.

 

하나의 패키지로 웹이랑 앱은 무리다

패키지 표를 보면 UI의 핵심이 되는 축이 세 개로 보입니다. @chulgang/ui, @chulgang/ui-native, @chulgang/tokens입니다. 특히 ui와 ui-native로 나뉘어 있는 것을 눈여겨봐 주셨으면 합니다.

 

저는 웹과 앱을 한 레포에 두더라도, UI를 억지로 하나의 패키지로 묶으면 오히려 비용이 커질 거라고 생각했습니다. 하나의 패키지로 웹이랑 앱을 다 커버하는 일은 무리에 가깝다는 쪽이었습니다.

 

처음 구상할 때는 당연히 욕심이 났습니다. 웹도 앱도 React를 쓰니, 컴포넌트 패키지 하나로 웹과 앱을 다 커버하면 좋겠다고요. 그런데 기존 웹에서 쓰던 shadcn/ui 쪽을 다시 보니, 웹에서만 자연스러운 로직이 상당히 많이 들어가 있었습니다. DOM 이벤트, 포커스 트랩, Radix 포털, asChild같은 패턴이요. 그대로 RN에 끌고 가기엔 “공유”보다 “예외 분기”가 먼저 쌓일 것 같았습니다.

 

그래서 역할을 이렇게 나눴습니다.

 

  • @chulgang/ui : 웹과 어드민용. shadcn/ui 계열로, Radix primitive와 Tailwind(DOM)로 이루어져 있습니다.
  • @chulgang/ui-native : 모바일(Expo)용. React Native Reusables 계열로, rn-primitives와 NativeWind로 이루어져 있습니다.
  • @chulgang/tokens : ui와 ui-native가 함께 쓰는 색,타이포,간격의 이름표입니다. colors / typography / spacing, 그리고 theme CSS 진입점이 여기에 있습니다.

 

구현체는 둘로 두되, 부르는 이름은 맞추려 했습니다.

 

예를 들면, @chulgang/ui/button, @chulgang/ui-native/button 이렇게 되었습니다.

 

@chulgang/ui button 코드 발췌: Radix Slot과 cva로 작성한 웹용 버튼 variants 정의
웹용 버튼 <출처: 작가> 

 

@chulgang/ui-native button 코드 발췌: React Native Pressable과 cva로 작성한 앱용 버튼 variants 정의
앱용 버튼 <출처: 작가> 

 

@chulgang/tokens 코드 발췌: colors·typography·spacing을 상수로 정의해 웹과 앱이 공유하는 토큰
공유하는 토큰 <출처: 작가> 

 

그리고 실제로 구현된 모습을 보면, 다음처럼 구현되어 있습니다.

 

웹용 Button과 앱용 NativeButton을 동일한 props로 호출하는 대칭적인 사용 예시 코드
실제 Button 사용 예시 <출처: 작가> 

 

지금은 ui/button과 ui-native/button이 함께 있기 때문에 as NativeButton으로 되어있지만, 실제 코드로 보면 둘다 <Button>으로 동일하게 사용합니다.

 

지금 단계까지는 여기까지 왔습니다. 저는 추후에 각 버튼에서 사용하는 button variant도 패키지화를 시켜야 할지 고민하고 있습니다. 다만 컴포넌트가 분리되어있는데, 스타일만 통일해야 할까?라는 고민이 있어서, 지금은 그냥 두고 있습니다.

 

 

화면 단위로 올리는 워크플로

기술 스택을 선정하고 패키지를 만든 뒤에, 드디어 화면을 만들기 시작했습니다. 다만 앱 전체를 한번에 만들기 보다는 화면 단위로 하나씩 만들기로 결정하고 메인 페이지부터 만들기 시작했습니다.

 

당연히 AI 에이전트를 시켜서 만들었고, 다음과 같이 진행했습니다.

 

  • 피그마화면, 모바일 웹 화면 스크린샷을 AI에게 공유한다.
  • 같은 화면과 기능 단위로 모바일 앱을 개발해달라고 요청한다
  • 구현이 완료되면 화면과 기능을 점검한다.

 

이게 계속 반복되다가, 반복이면 스킬로 만들어 알아서 돌려야겠다는 생각이 들었는데요. 그 결과가 mobile-design-sync 입니다.

 

스킬 mobile-design-sync를 만든 이유

한 줄로 이 스킬을 설명하면, Figma 링크 하나로 모바일 웹을 먼저 맞추고 그 다음 앱을 맞추며, 결과를 스크린샷으로 남기는 end-to-end 워크플로입니다. 사람이 매 슬라이드마다 추가적인 명령과 컨텍스트를 전달하지 않아도 되게 스킬을 만든 것입니다.

 

mobile-design-sync 스킬 실행 명령어와 Figma 모바일 웹 디자인 링크
실제 사용 예시 <출처: 작가> 

 

이 스킬이 실행되면 다음처럼 워크플로가 진행됩니다.

 

  • 피그마 링크를 보고 피그마 MCP가 해당 노드의 스크린샷을 찍어옵니다.
  • 스크린샷을 보고 연관된 컴포넌트를 식별하고, Playwright MCP를 통해 해당 컴포넌트로 이동하고 스크린샷을 찍어옵니다.
  • 노드의 스크린샷과 컴포넌트의 스크린샷을 비교하여 수정할 내용을 선정합니다.
  • 수정을 한뒤에 변경된 스크린샷을 찍어옵니다.
  • 마크다운 문서로 만들어 유저의 최종 확인을 기다립니다.

 

다음은 실제 정리된 마크다운 문서를 공유하면서 결과를 살펴보겠습니다.

 

작업 메타데이터: 토픽·날짜·Figma 섹션·대상 폴드와 1단계 웹, 2단계 앱 동기화 완료 상태를 적은 Goal
해당 작업에 대한 메타데이터와 Goal <출처: 작가> 

 

Code changes 표: 1단계 apps/web과 2단계 apps/mobile에서 각각 수정한 파일 경로와 변경 내용 목록
모바일 웹과 모바일 앱의 파일 식별과 변경사항 도출 <출처: 작가> 

 

Logic 표: 웹 SoT의 훅·상수·로직과 앱에서 대응하는 함수·동일 여부를 나란히 비교
모바일 웹과 모바일 앱의 기능을 동기화하기 위한 로직 추출 <출처: 작가> 

 

Figma 시안과 모바일 웹 이전·이후 화면 3단 비교: 출강EO 클래스 이력 목록 UI가 시안에 맞게 정리됨
1단계 피그마 모바일 웹 싱크 <출처: 작가> 

 

Figma 시안과 모바일 앱 이전·이후 화면 3단 비교: 견적 등록 취소 카드 UI와 견적 상세보기 버튼이 추가됨
2단계 모바일 웹 - 모바일 앱 싱크 <출처: 작가> 

 

저는 특히 2단계에서 큰 희열을 느꼈습니다. 앱 이전에는 단순히 피그마 전체 스크린샷을 주고, 만들때 AI가 초벌로 만들어준 작업이고, 앱 이후가 해당 스킬을 통해 싱크한 결과물입니다.

 

실제로 보면 피그마와 최종 결과물이 약간 다른 부분이 있는데요. 이게 중간 피그마 업데이트가 되지 않아, 모바일 웹이 최신 결과물이고 피그마가 Outdated된 파일이기 때문입니다. 하지만 말씀드렸다시피 웹이 SSOT(Single Source of Truth)이기 때문에, 모바일 웹을 기준으로 앱을 만든 것을 확인할 수 있습니다.

 

 

마치며

이렇게 스킬을 만들고 개발자는 최종 마크다운으로 결과만 확인 후, PR을 Merge하는 반복적이지만 지루한 과정의 연속이었습니다. 그 결과 크게는 3일 동안 어마무시한 라인을 수정하면서 완성하게 되었습니다.

 

9월9일부터 11일까지 커밋 히트맵과 일별 코드 수정 라인 수(74,398·66,289·77,571줄) 카드 3장
9월 9일 ~ 9월 11일 라인 수정량 <출처: 작가> 

 

Cursor 사용량 그래프: 9월 8일부터 13일 사이 누적 토큰 사용량이 급격히 치솟는 구간을 빨간 박스로 표시
토큰 사용량 그래프 <출처: 작가> 

 

또 AI 에이전트를 사용하면서 처음으로 모든 토큰을 리셋된지 3일 만에 전부 다 쓰게 되었습니다. 저는 결제일이 7일인데, 11일날 토큰을 전부 다 사용했다는 알림이 오더라고요. 그런데도 계속 가능했던 이유는 커서 또한 다 쓰게 되면 100불짜리 추가 크레딧을 주기 때문입니다.

 

그럼 최종 결과는 어떻게 되었을까요? 앱 출시까지 바로 완료했을까요? 아쉽게도 결론적으로는 실패했습니다.

 

그 이유는 크게 3가지였습니다.

  • 모바일 웹과 모바일 앱은 본질적으로 UI/UX 프로세스가 다르다. 디자인만 맞춘다고 끝이 아니다.
  • 실제 로직이 어긋난 부분이 생각보다 너무 많이 발견됐다.
  • 모바일 앱에서 지원할수 있는 기본 기능에 대한 추가 개발이 필요하다. (ex.푸시 알림, 패스키)

 

여기에 각 픽셀이나 토큰 단위의 싱크도 추가로 필요했고, 데스크탑 웹과 모바일 웹의 반응형 디자인의 차이까지 생각보다 여러 추가 수정사항이 계속해서 나왔던 탓입니다. 이번 편에서는 여기까지로 마무리짓고, 다음 편에서는 이러한 역경을 이겨낸 최종 출시까지의 여정을 다뤄보겠습니다. “앱 출시까지 2주면 된다”를 실제로 테스트해 본 최종 후기로 돌아올게요.


현재 FDE로 일하시거나, 최근 1년 내 일하셨던 분들은

“국내 FDE 현황 조사 2026” 참여하고, 리포트 & 네이버페이 포인트 받아가세요!

 

ⓒ요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.