소개
Next.js 모바일 앱을 처음부터 만들고 싶으십니까? 이 가이드에서는 모바일을 위한 Next.js 15 프로젝트를 새로 만들고, __CAPGO_KEEP_0__ 8을 사용하여 iOS 및 Android 앱으로 패키징하는 방법을 안내합니다. Capacitor 8.
이 튜토리얼을 마치면, 시뮬레이터에서 작동하는 모바일 앱을 개발하고, 앱 스토어와 구글 플레이에 게시할 수 있습니다.
시간 소요: ~30분
제작할 프로젝트:
- Next.js 15 앱 루터 프로젝트
- 모바일 정적 내보내기 설정
- Capacitor 8에 필수 플러그인
- 네이티브 iOS 및 Android 앱
- 라이브 리로드 개발 설정
Next.js 앱이 이미 있으신가요? Next.js 앱을 모바일로 변환하는 방법 대신.
사전 요구 사항
이것들을 설치했는지 확인하세요:
- Node.js 18+ (
node --version) - Bun package manager (
curl -fsSL https://bun.sh/install | bash) - Xcode (macOS만 iOS 개발을 위해 사용합니다)
- Android Studio (Android 개발을 위해 사용합니다)
Step 1: Next.js 프로젝트 만들기
새로운 Next.js 15 프로젝트를 생성하세요:
bunx create-next-app@latest my-mobile-app
When prompted, select these options:
- TypeScript: Yes (recommended)
- ESLint: Yes
- Tailwind CSS: Yes (recommended for mobile styling)
src/directory: Yes- App Router: Yes (recommended)
- Import alias: 기본값 (
@/*)
프로젝트로 이동하세요:
cd my-mobile-app
2단계: Next.js를 정적 내보내기 위해 구성하세요.
Capacitor은 정적 HTML/JS/CSS 파일이 필요합니다. Next.js를 정적 내보내기 위해 구성하려면 next.config.ts:
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
output: 'export',
images: {
unoptimized: true,
},
// Ensure trailing slashes for proper routing in Capacitor
trailingSlash: true,
};
export default nextConfig;
이러한 설정은 왜 필요한가요?
output: 'export'— 정적 HTML이 서버가 필요하지 않도록 생성됩니다.images: { unoptimized: true }— Next.js Image Optimization이 비활성화됩니다 (서버가 필요합니다).trailingSlash: true— 네이티브 WebView에서 올바른 라우팅을 보장합니다.
3단계: 모바일 스크립트 추가
모바일 개발 스크립트로 업데이트: package.json 빌드 테스트:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"mobile": "bun run build && bunx cap sync",
"mobile:ios": "bun run mobile && bunx cap open ios",
"mobile:android": "bun run mobile && bunx cap open android"
}
}
빌드 테스트를 하면
bun run build
__CAPGO_KEEP_0__ out __CAPGO_KEEP_0__ 폴더에 정적 파일이 있습니다.
4단계: Capacitor 8을 설치하세요.
Capacitor 코어 패키지를 설치하세요:
bun add @capacitor/core
bun add -D @capacitor/cli
대부분의 모바일 앱이 필요로 하는 필수 플러그인을 설치하세요.
bun add @capacitor/app @capacitor/keyboard @capacitor/splash-screen @capacitor/status-bar @capacitor/preferences
이러한 플러그인이 무엇을 하는지 설명합니다.
- @capacitor/app — 전면/후면, 깊은 링크와 관련된 앱 라이프 사이클 이벤트
- @capacitor/keyboard — 키보드 동작을 제어합니다.
- @capacitor/splash-screen — 네이티브 스플래시 스크린을 제어합니다.
- @capacitor/status-bar — 장치 상태 바 스타일링
- @capacitor/preferences — 키-값 저장소 (localStorage와 같은 네이티브)
5단계: Capacitor 초기화
Capacitor을 프로젝트 세부 정보와 초기화하십시오:
bunx cap init "My Mobile App" com.example.mymobileapp --web-dir out
대체:
"My Mobile App"앱의 표시 이름으로com.example.mymobileapp역 도메인 표기법의 앱 ID로
이는 capacitor.config.ts. 플러그인 구성으로 업데이트하십시오:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.mymobileapp',
appName: 'My Mobile App',
webDir: 'out',
plugins: {
SplashScreen: {
launchShowDuration: 2000,
launchAutoHide: true,
androidScaleType: 'CENTER_CROP',
splashFullScreen: true,
splashImmersive: true,
},
Keyboard: {
resize: 'body',
resizeOnFullScreen: true,
},
StatusBar: {
style: 'light',
},
},
};
export default config;
6단계: 네이티브 플랫폼 추가
플랫폼 패키지를 설치하십시오:
bun add @capacitor/ios @capacitor/android
__CAPGO_KEEP_0__을 생성하세요:
bunx cap add ios
bunx cap add android
__CAPGO_KEEP_1__을 생성합니다. ios __CAPGO_KEEP_2__와 android __CAPGO_KEEP_3__에 포함된 네이티브 프로젝트가 포함된 디렉터리.
7단계: 빌드 및 실행
프로젝트를 빌드하고 네이티브 플랫폼과 동기화하세요.
bun run mobile
iOS 시뮬레이터에서 열기:
bun run mobile:ios
또는 안드로이드 에뮬레이터에서 열기:
bun run mobile:android
Xcode (iOS)에서:
- 디바이스 드롭다운에서 시뮬레이터를 선택하세요.
- Play 버튼을 클릭하거나
Cmd + R
Android Studio에서:
- Gradle 동기화가 완료될 때까지 기다려 주세요.
- 장치 드롭다운에서 에뮬레이터를 선택하세요.
- Run 버튼을 클릭하거나
Shift + F10
8단계: 라이브 리로드 설정
개발을 위해 더 빠르게 하려면, 라이브 리로드를 활성화하여 변경 사항이 즉시 장치에 나타나도록 하세요.
- 장치 IP 주소를 찾으세요:
# macOS
ipconfig getifaddr en0
# Windows
ipconfig
- 개발 Capacitor 설정을 생성하세요. 다음에 추가하세요.
capacitor.config.ts:
import type { CapacitorConfig } from '@capacitor/cli';
const devConfig: CapacitorConfig = {
appId: 'com.example.mymobileapp',
appName: 'My Mobile App',
webDir: 'out',
server: {
url: 'http://YOUR_IP_ADDRESS:3000',
cleartext: true,
},
plugins: {
// ... same plugin config
},
};
const prodConfig: CapacitorConfig = {
appId: 'com.example.mymobileapp',
appName: 'My Mobile App',
webDir: 'out',
plugins: {
// ... same plugin config
},
};
const config = process.env.NODE_ENV === 'development' ? devConfig : prodConfig;
export default config;
- 개발 서버를 시작하고 config를 네이티브로 복사하세요:
bun run dev &
NODE_ENV=development bunx cap copy
- Xcode/Android Studio에서 다시 빌드하세요.
이제 Next.js code의 편집 사항이 장치에서 즉시 리로드됩니다.
9단계: 첫 번째 모바일 화면 만들기
간단한 모바일 친화적인 홈 화면을 만들겠습니다. 업데이트 src/app/page.tsx:
'use client';
import { useEffect, useState } from 'react';
import { App } from '@capacitor/app';
import { Keyboard } from '@capacitor/keyboard';
export default function Home() {
const [appInfo, setAppInfo] = useState<{ name: string; version: string } | null>(null);
useEffect(() => {
// Get app info on mount
App.getInfo().then(setAppInfo).catch(console.error);
// Handle back button on Android
const backHandler = App.addListener('backButton', ({ canGoBack }) => {
if (!canGoBack) {
App.exitApp();
} else {
window.history.back();
}
});
// Hide keyboard when tapping outside inputs
const keyboardHandler = Keyboard.addListener('keyboardWillShow', () => {
document.body.classList.add('keyboard-open');
});
return () => {
backHandler.then(h => h.remove());
keyboardHandler.then(h => h.remove());
};
}, []);
return (
<main className="min-h-screen bg-linear-to-b from-blue-500 to-blue-700 flex flex-col items-center justify-center p-6 text-white">
<h1 className="text-4xl font-bold mb-4">My Mobile App</h1>
<p className="text-xl mb-8 text-center opacity-90">
Built with Next.js 15 + Capacitor 8
</p>
{appInfo && (
<div className="bg-white/20 rounded-lg p-4 backdrop-blur-sm">
<p className="text-sm">
{appInfo.name} v{appInfo.version}
</p>
</div>
)}
<div className="mt-12 space-y-4 w-full max-w-sm">
<button className="w-full py-4 px-6 bg-white text-blue-600 rounded-xl font-semibold text-lg shadow-lg active:scale-95 transition-transform">
Get Started
</button>
<button className="w-full py-4 px-6 bg-white/20 text-white rounded-xl font-semibold text-lg backdrop-blur-sm active:scale-95 transition-transform">
Learn More
</button>
</div>
</main>
);
}
Step 10: notch 영역 처리를 위한 안전 영역 처리 추가하기
모바일 기기는 notch, 홈 인디케이터, 상태 바를 가지고 있습니다. Tailwind를 사용하여 안전 영역 처리를 추가하세요.
수정 src/app/globals.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--sat: env(safe-area-inset-top);
--sar: env(safe-area-inset-right);
--sab: env(safe-area-inset-bottom);
--sal: env(safe-area-inset-left);
}
body {
padding-top: var(--sat);
padding-right: var(--sar);
padding-bottom: var(--sab);
padding-left: var(--sal);
}
/* Prevent text selection on mobile */
* {
-webkit-user-select: none;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
/* Allow text selection in inputs */
input, textarea {
-webkit-user-select: auto;
user-select: auto;
}
/* Keyboard handling */
.keyboard-open {
--sab: 0px;
}
프로젝트 구조
현재 프로젝트 구조는 다음과 같습니다.
my-mobile-app/
├── android/ # Android native project
├── ios/ # iOS native project
├── out/ # Static build output
├── src/
│ ├── app/
│ │ ├── globals.css
│ │ ├── layout.tsx
│ │ └── page.tsx
│ └── ...
├── capacitor.config.ts # Capacitor configuration
├── next.config.ts # Next.js configuration
├── package.json
└── ...
다음 단계
Next.js 모바일 앱이 작동하는 것을 확인했습니다. 다음 단계는 무엇인가요?:
기본 설정
- 앱 아이콘: 기본 아이콘을
ios/App/App/Assets.xcassets와android/app/src/main/res - 스플래시 화면: __CAPGO_KEEP_0__ 프로젝트에서 원시적으로 맞춤화하거나 사용
@capacitor/splash-screen__CAPGO_KEEP_0__ - Deep Links: 앱의 URL 스키마를 구성하십시오
더 많은 기능 추가
- 카메라:
bun add @capacitor/camera - 위치 정보:
bun add @capacitor/geolocation - 푸시 알림:
bun add @capacitor/push-notifications - 파일 시스템:
bun add @capacitor/filesystem
원시 UI 및 전환
Capgo 플러그인 대신 Konsta UI를 사용하지 않으면 원시 모바일 느낌을 얻으십시오:
- @capgo/capacitor-native-navigation — Liquid Glass tab bar 및 네이티브 네비게이션 바
- @capgo/capacitor-transitions — 네이티브 느낌의 페이지 전환
bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync
Tailwind safe areas를 위해 추가하세요. @capgo/tailwind-capacitor:
bun add -D tailwind-capacitor
See @capgo/capacitor-native-navigation을 사용하는 방법, @capgo/capacitor-transitions을 사용하는 방법그리고 tailwind-capacitor 리포지토리 Next.js에 대한 구체적인 설정을 위한
iOS 레이아웃 문제 해결 (뷰포트, Safe Area, 및 수평적 오버플로우)
If content looks cropped, shifted, or horizontally scrollable on iOS, adding more or tweaking the viewport tag alone usually does not fix it. Work through these checks in order. overflow-x: hidden viewport meta 태그가 올바르게 적용되어 있는지 확인하세요.
App Router
): export (app/from viewport Pages Router app/layout.tsx:
import type { Viewport } from 'next';
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
viewportFit: 'cover',
};
): viewport meta 태그를 (pages/, not pages/_app.tsxiOS safe area를 한 루트 wrapper에서만 처리하세요. _document.tsx.
Create a single app shell and apply safe area padding there — not in multiple nested components:
모든 페이지 콘텐츠를 단일 앱 셸 내에 감싸세요 — 중첩된 컴포넌트 여러 개에 적용하지 마세요.
html,
body,
#__next {
width: 100%;
min-height: 100%;
margin: 0;
padding: 0;
overflow-x: hidden;
}
* {
box-sizing: border-box;
}
.app-shell {
min-height: 100dvh;
width: 100%;
padding-top: env(safe-area-inset-top);
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
}
Wrap all page content inside .app-shell. 중복된 safe-area padding이 헤더, 모달, 레이아웃 wrapper에 있는 경우 UI가 잘려 보이거나 너무 크게 보일 수 있습니다.
With @capgo/tailwind-capacitor, __CAPGO_KEEP_0__와 같은 패딩을 표현할 수 있는 유틸리티를 사용할 수 있습니다. pt-safe pb-safe px-safe on that single shell.
Capacitor iOS contentInset 를 never first
In capacitor.config.ts, native inset이 disabled된 경우 CSS (또는 Native Navigation의 )가 safe area를 관리하도록 하세요. contentInsetMode: 'css'Mixing __CAPGO_KEEP_0__’s automatic content inset with CSS
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'out',
ios: {
contentInset: 'never',
},
};
Capacitor의 자동 콘텐츠 inset을 CSS와 혼합하는 경우 env(safe-area-inset-*) padding은 일반적으로 두 줄 간격의 원인입니다.
실제로 넘치는 요소를 찾으세요
일반적으로 원인은 요소가 사용하는 100vw, Tailwind w-screen, 고정 픽셀 너비 또는 큰 min-width.
Safari Web Inspector에서 실행:
[...document.querySelectorAll('*')]
.filter(el => el.scrollWidth > document.documentElement.clientWidth)
.map(el => ({
el,
tag: el.tagName,
class: el.className,
scrollWidth: el.scrollWidth,
clientWidth: document.documentElement.clientWidth,
}));
Tailwind와 함께 w-screen 대신 w-full 가능한 경우에만 100vw / w-screen많은 수평 방출 문제는
, duplicated safe-area padding, 또는 고정 너비 컨테이너 — viewport meta 태그 자체가 아니라.
Over-the-Air 업데이트 설정하기 Capgo 앱스토어 승인 없이 업데이트 푸시하기:
bunx @capgo/cli init
문제 해결
빌드가 “모듈을 찾을 수 없습니다”라고 실패합니다.
실행 bun install 다시 시도해 보세요.
iOS: “인증서를 찾을 수 없습니다” Xcode를 열고 Signing & Capabilities로 이동하여 개발 팀을 선택하세요.
Android: “SDK 위치를 찾을 수 없습니다”
생성 android/local.properties 와 sdk.dir=/path/to/android/sdk
장치에 나타나지 않는 변경 사항
__CAPGO_KEEP_0__를 확인하세요. live reload를 위해 IP 주소가 정확하고 개발 서버가 실행 중인지 확인하세요. bun run mobile 자원
__CAPGO_KEEP_0__ 8 문서
- Capacitor 8 Documentation
- __CAPGO_KEEP_0__ - Live 업데이트
- @Capgo/__CAPGO_KEEP_1__-native-navigation
- @capgo/capacitor-transitions
- @capgo/tailwind-capacitor
- @capgo/tailwind-capacitor
Capgo 무료 계정으로 가입하세요. 오늘 바로 시작하세요. __CAPGO_KEEP_0__
Capacitor 8을 계속 진행하는 Build a Next.js Mobile App from Scratch
__CAPGO_KEEP_0__ 사용 중이라면 Build a Next.js Mobile App from Scratch with Capacitor 8 CI/CD 자동화 계획을 위해 연결하세요. Capgo CI/CD Capgo CI/CD에서 제품 워크플로우를 위해 Capgo Native Builds Capgo Native Builds에서 제품 워크플로우를 위해 Capgo Integrations Capgo Integrations에서 제품 워크플로우를 위해 CI/CD Integration CI/CD Integration의 구현 세부 사항을 위해 GitHub 액션 통합 GitHub 액션 통합 구현 세부 사항을 위해.