# Vercel이 v0의 iOS 앱을 개발한 방법

> Clean Markdown view of GeekNews topic #24992. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=24992](https://news.hada.io/topic?id=24992)
- GeekNews Markdown: [https://news.hada.io/topic/24992.md](https://news.hada.io/topic/24992.md)
- Type: news
- Author: [neo](https://news.hada.io/@neo)
- Published: 2025-12-11T10:01:02+09:00
- Updated: 2025-12-11T10:01:02+09:00
- Original source: [vercel.com](https://vercel.com/blog/how-we-built-the-v0-ios-app)
- Points: 22
- Comments: 0

## Summary

Vercel은 첫 모바일 앱 **v0 for iOS**를 개발하며 웹 중심 조직임에도 **Apple Design Award급 네이티브 경험**을 목표로 삼았습니다. 수십 가지 스택을 실험한 끝에 **React Native + Expo** 조합을 선택했고, 메모처럼 아이디어를 적으면 AI가 결과물을 생성하는 **채팅 기반 제작 경험**을 정교하게 구현했습니다. 채팅 인터랙션은 LegendList·Reanimated·Keyboard Controller를 조합해 키보드 높이와 스크롤 변화를 부드럽게 처리하며, 웹과 네이티브가 **타입·API 레이어를 공유**하는 구조로 동일한 Platform API를 활용합니다.

## Topic Body

- 웹 중심 회사인 Vercel이 **Apple Design Award급 네이티브 경험**을 목표로 여러 기술 스택과 UI 패턴을 실험한 끝에 **React Native + Expo** 조합으로 완성  
- 핵심은 메모처럼 아이디어를 적으면 백그라운드에서 만들어지는 **AI 채팅 기반 제작 경험**으로, 메시지 애니메이션·스크롤·키보드·Liquid Glass 컴포저까지 세밀하게 설계해 **iOS 네이티브 수준의 채팅 인터랙션**을 구현  
- 채팅 구현에서는 **LegendList, Reanimated, react-native-keyboard-controller**를 기반으로 한 컨텍스트·훅 조합, `blankSize`와 `contentInset` 계산, composer 높이 연동 등으로 **동적 높이와 키보드 변화**를 부드럽게 처리  
- 코드 구조는 웹과 네이티브 간에 **타입·비즈니스 로직·API 레이어**를 공유하고, Zod 기반 **OpenAPI 스키마 → Hey API → Tanstack Query** 흐름으로 v0 웹과 **v0 Platform API** 고객이 같은 엔드포인트를 쓰도록 설계한 점이 특징  
  
---  
### v0 iOS 앱 개요와 목표  
  
- Vercel은 자사 첫 모바일 앱인 **v0 for iOS**를 출시하며, 웹 중심 회사임에도 **Apple Design Award**를 목표로 한 **고품질 네이티브 경험**을 만드는 것을 목표로 잡았음  
  - iOS 앱 출시 전까지는 웹에 집중해 왔기 때문에, **완전한 네이티브 앱 개발은 새로운 영역**이었음  
  - 이를 위해 공개 베타 이전에 **여러 다른 기술 스택과 UI 패턴**을 적용한 수십 가지 버전을 실험함  
- 레퍼런스로는 **Apple Notes, iMessage**처럼 **아이폰의 언어를 잘 쓰는 앱들**에서 영감을 받아, 홈 화면의 다른 앱들 사이에서 자리를 차지할 수 있을 수준의 완성도를 요구했음  
  - 특정 프레임워크에 고정되지 않고, **여러 스택을 실제로 구현·비교**한 후 결론을 내렸다고 설명함  
- 여러 실험 끝에 최종적으로 **React Native + Expo**를 선택했고, 결과적으로 **네이티브 앱처럼 느껴진다**는 개발자들의 피드백이 많이 들어와 이를 계기로 상세 기술 구조를 공개함  
  
### v0 채팅 경험의 방향  
  
- v0 iOS는 “컴퓨터에서 떨어져 있을 때 떠오른 **아이디어를 바로 실행 가능한 것**으로 만드는 도구”를 목표로, **메모 앱의 다음 세대**라는 위치를 지향  
  - 웹과 같은 **모바일 IDE**나 전체 기능을 옮기는 것보다, **이동 중 AI로 무언가를 만들 수 있는 간단하고 즐거운 경험**을 우선함  
- 이 경험의 중심은 **채팅 인터페이스**이며, 이에 대해 다음과 같은 요구사항을 정리  
  - 새 메시지는 **부드럽게 애니메이션**으로 나타날 것  
  - 새 사용자 메시지는 **화면 상단까지 스크롤**되어 보일 것  
  - 어시스턴트 메시지는 스트리밍되면서 **계단식 페이드 인(스트리밍 + 지연)** 으로 표시될 것  
  - 입력창(컴포저)은 **Liquid Glass** 스타일로 떠 있으며, 스크롤 가능한 콘텐츠 위에 떠 있을 것  
  - 기존 채팅을 여는 경우 **마지막 메시지까지 스크롤된 상태**로 시작할 것  
  - 키보드 동작은 **자연스럽고 네이티브에 가깝게** 느껴질 것  
  - 텍스트 입력은 **이미지·파일 붙여넣기**와 **팬 제스처 포커스/블러**를 지원할 것  
  - **Markdown 렌더링**은 빠르면서 **동적 컴포넌트**도 지원할 것  
- 모바일에서의 AI 채팅 UI 패턴은 많지만, **AI 코드 생성용 모바일 패턴**은 부재했기 때문에 **새 패턴을 직접 설계**해야 했고, 기준에 맞추기 위해 상당한 작업·테스트·조율이 필요했음  
  
### 컴포저블 채팅 구조 설계  
  
- 채팅 요구사항을 만족시키기 위해, 채팅 코드는 **기능별로 조합 가능(composable)** 하게 설계함  
  - 이를 위해 채팅 전체를 감싸는 **여러 Context Provider**를 만든 후, 메시지 리스트를 이 안에 두는 구조를 사용  
- 채팅 구현에는 다음과 같은 **오픈소스 라이브러리**를 사용함  
  - **LegendList**: 고성능 리스트 렌더링  
  - **React Native Reanimated**: 애니메이션과 공유 값(shared value)  
  - **react-native-keyboard-controller**: 키보드 상태 제어 및 이벤트 핸들링  
- 각 메시지 렌더링은 `item.role`에 따라 **user / assistant / optimistic-placeholder**로 분기해, 역할별로 다른 컴포넌트를 사용함  
  
### 메시지 애니메이션 구현  
- 첫 사용자 메시지는 **Reanimated 공유값(shared value)** 을 이용해 부드럽게 페이드 인  
  - `useFirstMessageAnimation` 훅이 메시지 높이·화면 높이·키보드 높이를 계산해 **translateY와 opacity**를 제어  
- 첫 번째 어시스턴트 메시지는 사용자 메시지 애니메이션 완료 후 **지연 페이드 인**  
- 기존 채팅에서는 `scrollToEnd()`와 **contentInset 조정**으로 새 메시지를 화면 상단에 자연스럽게 배치  
  
### 스크롤 및 키보드 제어  
- 채팅 경험의 품질은 **키보드 동작의 자연스러움**에 크게 의존하며, React Native에서 **네이티브에 가까운 키보드 감각**을 만드는 작업은 상당히 까다로웠음  
- iOS 버전별 차이로 인해 **키보드 동작 불안정** 문제가 발생,  
  `react-native-keyboard-controller` 유지관리자와 협력해 **버그 수정 및 성능 개선**  
- `useKeyboardAwareMessageList` 훅으로 키보드 열림·닫힘·드래그 이벤트를 세밀하게 제어  
- 기존 채팅 열기 시 **자동 스크롤 위치 조정**을 위해 `scrollToEnd`를 여러 번 호출하여 **동적 높이 문제 해결**  
  
### Liquid Glass Floating Composer와 입력창 개선  
- iMessage의 **Liquid Glass 효과**를 적용해 **반투명·부유형 입력창** 구현  
  - `KeyboardStickyView`와 `composerHeight` 공유값으로 스크롤뷰 `contentInset`을 실시간 조정  
- 입력창 높이 변화 시 자동 스크롤을 유지하기 위해 `useScrollWhenComposerSizeUpdates` 훅 사용  
- 기본 `TextInput`의 스크롤 바운스·지표 노출 문제를 해결하기 위해 **RCTUITextView 네이티브 패치 적용**  
  - 스와이프 제스처로 키보드 포커스 가능하도록 개선  
  
### 이미지 붙여넣기 및 스트리밍 콘텐츠 페이드 인  
- **Expo 모듈**을 통해 `UIPasteboard` 이벤트를 감지, 텍스트·이미지·파일 붙여넣기 지원  
- **FadeInStaggeredIfStreaming** 컴포넌트를 사용해 **AI 응답 텍스트의 단어 단위 페이드 인** 구현  
  - 애니메이션 풀(pool) 관리로 **동시 애니메이션 개수 제한 및 성능 최적화**  
  - 이미 본 콘텐츠는 `DisableFadeProvider`로 재애니메이션 방지  
  
### 웹과 네이티브 간 코드 공유와 Platform API  
- 웹과 모바일 간 **타입·헬퍼 함수 공유**, UI·상태 관리는 분리  
- **Zod 기반 타입 안전 API 프레임워크** 구축, OpenAPI 스펙을 자동 생성  
  - 모바일 앱은 **Hey API + Tanstack Query**로 API 호출  
- 이 구조를 기반으로 **v0 Platform API**를 공개, 동일한 엔드포인트를 외부 개발자에게 제공  
  
### 스타일링 및 네이티브 컴포넌트  
- **react-native-unistyles**로 테마 관리, Context 접근 없이 빠른 스타일링 지원  
- **Zeego**를 통해 iOS 네이티브 `UIMenu` 기반 메뉴 구현  
- iOS 26에서 발생한 **Alert 위치 오류**를 수정하고 React Native에 **패치 업스트림 기여**  
- **모달(formSheet)** 관련 드래그·플리커링 문제를 수정, Callstack·Meta·Expo와 협력해 **React Native 0.82에 반영**  
  
### 앞으로의 계획과 커뮤니티 협업  
- **React Native + Expo 조합**으로 첫 앱을 완성한 후, **향후 프로젝트도 동일 스택 유지 예정**. 현재 스택에 만족하고 있음  
- Vercel은 **야심찬 제품을 높은 수준으로 구현**하는 데 집중하고 있으며,  
  - 웹·네이티브 개발자가 같은 수준의 제품을 만들 수 있도록 **내부에서 구축한 노하우를 오픈소스로 공개**할 계획이라고 밝힘  
  - 특히 **AI 채팅 앱용 오픈소스 라이브러리**를 베타 테스트할 커뮤니티를 모집하고 있으며, React Native 개선에 계속 기여할 것

## Comments



_No public comments on this page._
