메인 콘텐츠로 바로가기
Tutorial

Capacitor를 사용하여 스캐치부터 Nuxt 모바일 앱을 빌드하세요.

iOS와 Android 모바일 앱으로 변환하기 위한 Nuxt 4 프로젝트를 새로 만들고 Capacitor 8을 사용하여 모바일 앱으로 변환하는 단계별 가이드입니다. 모바일 개발을 시작하는 데 이상적입니다.

마틴 도나디우

마틴 도나디우

콘텐츠 마케터

Capacitor를 사용하여 스캐치부터 Nuxt 모바일 앱을 빌드하세요.

소개

Nuxt를 사용하여 모바일 앱을 처음부터 만들고 싶으십니까? 이 가이드는 모바일 앱을 처음부터 만들기 위해 Nuxt 4 프로젝트를 새로 만들고 모바일에서부터 설정된 프로젝트를 iOS와 Android 앱으로 패키징하는 방법을 안내합니다. Capacitor 8.

이 튜토리얼을 마치면 시뮬레이터에서 작동하는 모바일 앱을 만들 수 있으며, 개발을 계속하고 나중에는 앱 스토어와 구글 플레이에 게시할 수 있습니다.

시간 소요량: ~30분

만들어 볼 건데:

  • 새로운 Nuxt 4 프로젝트와 최신 폴더 구조
  • 모바일용 정적 생성 설정
  • Capacitor 8에 필수 플러그인
  • iOS 및 Android 네이티브 앱
  • 라이브 리로드 개발 환경

Nuxt 앱이 이미 있으신가요? Nuxt 앱을 모바일로 변환하세요. 대신.

기초 조건

이것들을 설치했는지 확인하세요:

  • Node.js 18+ ( node --version)
  • Bun package manager (curl -fsSL https://bun.sh/install | bash)
  • Xcode (macOS만 iOS 개발을 위해 사용합니다)
  • Android Studio (Android 개발을 위해 사용합니다)

Step 1: Nuxt 4 프로젝트 만들기

Nuxt 4 프로젝트를 새로 만들기 시작하세요:

bunx nuxi@latest init my-mobile-app
cd my-mobile-app
bun install

Nuxt 4 디렉토리 구조

Nuxt 4은 새로운 디렉토리 구조를 사용하며 app code이 디렉토리 내에 있습니다. app/ 디렉토리:

my-mobile-app/
  app/
    assets/
    components/
    composables/
    layouts/
    middleware/
    pages/
    plugins/
    utils/
    app.vue
  public/
  server/
  nuxt.config.ts
  package.json

이 구조는 앱과 서버 code 사이의 분리를 더 잘 제공합니다.

2단계: Nuxt를 정적 생성에 구성합니다.

Capacitor은 정적 HTML/JS/CSS 파일이 필요합니다. Nuxt를 정적 생성에 구성하여 Capacitor을 정적 HTML/JS/CSS 파일로 변환합니다. nuxt.config.ts:

export default defineNuxtConfig({
  compatibilityDate: '2025-01-15',
  devtools: { enabled: true },

  // Enable static generation
  ssr: true,
  nitro: {
    preset: 'static',
  },
});

3단계: 모바일 스크립트 추가

모바일 개발 스크립트를 업데이트하여 __CAPGO_KEEP_0__을 사용합니다. package.json 정적 생성 테스트:

{
  "scripts": {
    "dev": "nuxt dev",
    "build": "nuxt build",
    "generate": "nuxt generate",
    "preview": "nuxt preview",
    "mobile": "bun run generate && bunx cap sync",
    "mobile:ios": "bun run mobile && bunx cap open ios",
    "mobile:android": "bun run mobile && bunx cap open android"
  }
}

정적 파일이 포함된 디렉토리를 볼 수 있어야 합니다.

bun run generate

4단계: __CAPGO_KEEP_0__ 8 설치 .output/public __CAPGO_KEEP_0__ 8을 설치합니다.

Capacitor 8을 설치합니다.

Capacitor core 패키지를 설치하세요:

bun add @capacitor/core
bun add -D @capacitor/cli

__CAPGO_KEEP_0__에서 필요로 하는 기본 플러그인을 설치하세요:

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 — Native localStorage와 같은 키-값 저장소

Step 5: Capacitor을 초기화하세요

Capacitor을 초기화하여 프로젝트 세부 정보를 입력하세요:

bunx cap init "My Mobile App" com.example.mymobileapp --web-dir .output/public

대체:

  • "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: '.output/public',
  plugins: {
    SplashScreen: {
      launchShowDuration: 2000,
      launchAutoHide: true,
      androidScaleType: 'CENTER_CROP',
      splashFullScreen: true,
      splashImmersive: true,
    },
    Keyboard: {
      resize: 'body',
      resizeOnFullScreen: true,
    },
    StatusBar: {
      style: 'dark',
    },
  },
};

export default config;

Step 6: 네이티브 플랫폼 추가

플랫폼 패키지를 설치하세요:

bun add @capacitor/ios @capacitor/android

네이티브 프로젝트를 생성하세요:

bunx cap add ios
bunx cap add android

이것은 ios __CAPGO_KEEP_0__ android __CAPGO_KEEP_0__

__CAPGO_KEEP_0__

__CAPGO_KEEP_0__

bun run mobile

__CAPGO_KEEP_0__

bun run mobile:ios

__CAPGO_KEEP_0__

bun run mobile:android

__CAPGO_KEEP_0__

  1. __CAPGO_KEEP_0__
  2. __CAPGO_KEEP_0__ Cmd + R

__CAPGO_KEEP_0__

  1. __CAPGO_KEEP_0__
  2. __CAPGO_KEEP_0__
  3. Click the Run button or press Shift + F10

8단계: Live Reload 설정

개발을 더 빠르게 하려면, 장치에 즉시 나타나는 변경 사항을 위해 Live Reload를 활성화하세요.

  1. 장치의 IP 주소를 찾으세요.
# macOS
ipconfig getifaddr en0

# Windows
ipconfig
  1. 개발 Capacitor 설정을 만들고, capacitor.config.ts:
import type { CapacitorConfig } from '@capacitor/cli';

const devConfig: CapacitorConfig = {
  appId: 'com.example.mymobileapp',
  appName: 'My Mobile App',
  webDir: '.output/public',
  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: '.output/public',
  plugins: {
    // ... same plugin config
  },
};

const config = process.env.NODE_ENV === 'development' ? devConfig : prodConfig;

export default config;
  1. 개발 서버를 시작하고, 설정을 Native로 복사하세요.
bun run dev &
NODE_ENV=development bunx cap copy
  1. Xcode/Android Studio에서 다시 빌드하세요.

이제 Nuxt code의 편집 사항은 장치에서 즉시 반영됩니다.

10단계: 모바일 화면 만들기

모바일 친화적인 홈 스크린을 만들겠습니다. 설정을 app/app.vue:

<template>
  <NuxtPage />
</template>

만들기 app/pages/index.vue:

<template>
  <main
    class="min-h-screen bg-linear-to-b from-green-500 to-green-700 flex flex-col items-center justify-center p-6 text-white"
  >
    <h1 class="text-4xl font-bold mb-4">My Mobile App</h1>
    <p class="text-xl mb-8 text-center opacity-90">
      Built with Nuxt 4 + Capacitor 8
    </p>

    <div v-if="appInfo" class="bg-white/20 rounded-lg p-4 backdrop-blur-sm mb-8">
      <p class="text-sm">
        {{ appInfo.name }} v{{ appInfo.version }}
      </p>
    </div>

    <div class="space-y-4 w-full max-w-sm">
      <button
        class="w-full py-4 px-6 bg-white text-green-600 rounded-xl font-semibold text-lg shadow-lg active:scale-95 transition-transform"
        @click="handleGetStarted"
      >
        Get Started
      </button>
      <button
        class="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"
        @click="handleShare"
      >
        Share App
      </button>
    </div>
  </main>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { App } from '@capacitor/app';

const appInfo = ref<{ name: string; version: string } | null>(null);

let backButtonListener: { remove: () => void } | null = null;

onMounted(async () => {
  // Get app info
  try {
    appInfo.value = await App.getInfo();
  } catch (e) {
    // Web fallback
    appInfo.value = { name: 'My Mobile App', version: '1.0.0' };
  }

  // Handle Android back button
  backButtonListener = await App.addListener('backButton', ({ canGoBack }) => {
    if (!canGoBack) {
      App.exitApp();
    } else {
      window.history.back();
    }
  });
});

onUnmounted(() => {
  backButtonListener?.remove();
});

function handleGetStarted() {
  // Navigate to onboarding or main app
  console.log('Get started clicked');
}

async function handleShare() {
  // We'll implement this with the Share plugin later
  console.log('Share clicked');
}
</script>

10단계: Tailwind CSS 추가

For the styling to work, add Tailwind CSS to your project:

bun add tailwindcss @tailwindcss/vite

업데이트 nuxt.config.ts:

import tailwindcss from '@tailwindcss/vite';

export default defineNuxtConfig({
  compatibilityDate: '2025-01-15',
  devtools: { enabled: true },

  ssr: true,
  nitro: {
    preset: 'static',
  },

  css: ['~/assets/css/main.css'],

  vite: {
    plugins: [tailwindcss()],
  },
});

만들기 app/assets/css/main.css:

@import 'tailwindcss';

: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;
}

11단계: 공유 플러그인을 추가하세요

공유 버튼 기능을 구현하세요:

bun add @capacitor/share

업데이트 app/pages/index.vue 공유 플러그인을 사용하기 위해:

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { App } from '@capacitor/app';
import { Share } from '@capacitor/share';

// ... existing code ...

async function handleShare() {
  try {
    await Share.share({
      title: 'Check out this app!',
      text: 'Built with Nuxt 4 and Capacitor 8',
      url: 'https://capacitorjs.com',
      dialogTitle: 'Share with friends',
    });
  } catch (e) {
    console.log('Share cancelled or failed:', e);
  }
}
</script>

Sync and rebuild:

bun run mobile

프로젝트 구조

현재 프로젝트 구조는 다음과 같습니다.

my-mobile-app/
├── android/                  # Android native project
├── ios/                      # iOS native project
├── .output/
│   └── public/              # Static build output
├── app/
│   ├── assets/
│   │   └── css/
│   │       └── main.css
│   ├── pages/
│   │   └── index.vue
│   └── app.vue
├── capacitor.config.ts       # Capacitor configuration
├── nuxt.config.ts            # Nuxt configuration
├── package.json
└── ...

다음 단계

현재 Nuxt 모바일 앱이 작동하고 있습니다. 다음 단계는?

__CAPGO_KEEP_0__

  • 앱 아이콘: __CAPGO_KEEP_1__ ios/App/App/Assets.xcassets __CAPGO_KEEP_2__ android/app/src/main/res
  • __CAPGO_KEEP_3__ @capacitor/splash-screen __CAPGO_KEEP_4__
  • __CAPGO_KEEP_5__ __CAPGO_KEEP_6__

__CAPGO_KEEP_7__

  • __CAPGO_KEEP_8__ bun add @capacitor/camera
  • __CAPGO_KEEP_9__ bun add @capacitor/geolocation
  • 푸시 알림: bun add @capacitor/push-notifications 또는 @capgo/capacitor-firebase-messaging iOS와 Android용 Firebase Cloud Messaging에 대해
  • 파일 시스템: bun add @capacitor/filesystem

자연스러운 UI와 전환

Capgo 플러그인을 사용하여 Konsta UI 대신 네이티브 모바일 느낌을 얻으세요:

bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync

Tailwind safe areas를 위해 추가하세요 @capgo/tailwind-capacitor:

bun add -D tailwind-capacitor

보기 Capgo를 사용하여 @capgo/capacitor-native-navigation, Capgo를 사용하여 @capgo/capacitor-transitionstailwind-capacitor 저장소 Nuxt에 대한 특정 설정을위한

iOS 레이아웃 문제를 해결하는 방법

iOS에서 콘텐츠가 잘려나거나-shifted 또는 가로 스크롤이 가능하다면, viewport 태그를 더 추가하거나 조정하는 것만으로는 문제를 해결할 수 없습니다. 이러한 체크를 순서대로 진행하세요. overflow-x: hidden viewport meta 태그가 올바르게 적용되었는지 확인하세요

In

In nuxt.config.ts, 뷰포트를 설정하세요. app.head:

export default defineNuxtConfig({
  app: {
    head: {
      meta: [
        {
          name: 'viewport',
          content: 'width=device-width, initial-scale=1, viewport-fit=cover',
        },
      ],
    },
  },
});

iOS 안전 영역을 하나의 루트 wrapper에서 처리하세요.

싱글 앱 셸을 생성하고 안전 영역 패딩을 적용하세요 — 여러 중첩된 컴포넌트에 적용하지 마세요:

html,
body,
#__nuxt {
  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);
}

모든 페이지 콘텐츠를 내부에 감싸세요. .app-shell헤더, 모달, 레이아웃 wrapper에 중복된 안전 영역 패딩이 있는 경우 UI가 잘린 것처럼 보거나 너무 크게 보입니다.

그것과 동일한 패딩을 표현하기 위해 @capgo/tailwind-capacitor, utilities를 사용하세요. pt-safe pb-safe px-safe 싱글 셸에 적용하세요.

Set Capacitor iOS contentInset 안전 영역을 never 첫 번째로

In __CAPGO_KEEP_0__에서 Native Navigation의 CSS (또는 Native Navigation의)가 Safe Area를 제어하도록 하세요. capacitor.config.ts__CAPGO_KEEP_0__의 자동 콘텐츠 인셋과 CSS의 패딩을 혼합하는 것은 두 배의 간격이 발생하는 일반적인 원인입니다. contentInsetMode: 'css'실제로 넘치는 요소를 찾으세요.

const config: CapacitorConfig = {
  appId: 'com.example.myapp',
  appName: 'my-app',
  webDir: '.output/public',
  ios: {
    contentInset: 'never',
  },
};

Mixing Capacitor’s automatic content inset with CSS env(safe-area-inset-*) Safari Web Inspector에서 실행하세요:

Tailwind의 경우 __CAPGO_KEEP_0__를 __CAPGO_KEEP_0__로 대체하세요.

__CAPGO_KEEP_0__는 Native Navigation의 CSS (또는 Native Navigation의)가 Safe Area를 제어하도록 하세요. 100vw__CAPGO_KEEP_0__의 자동 콘텐츠 인셋과 CSS의 패딩을 혼합하는 것은 두 배의 간격이 발생하는 일반적인 원인입니다. w-screen실제로 넘치는 요소를 찾으세요. min-width.

일반적으로 원인은 Tailwind, 고정 픽셀 너비 또는 큰 요소가 사용되는 요소입니다.

[...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,
  }));

Safari Web Inspector에서 실행하세요: w-screen Tailwind의 경우 __CAPGO_KEEP_0__를 __CAPGO_KEEP_0__로 대체하세요. w-full __CAPGO_KEEP_0__ 100vw / w-screen가급적이면 여러 가지 수평 방향의 오버플로우 문제는

, 중복된 safe-area 패딩 또는 고정 너비 컨테이너에서 발생합니다 — viewport meta 태그 자체에서 발생하지 않습니다.

Over-the-Air Updates Capgo __CAPGO_KEEP_0__

bunx @capgo/cli init

앱 스토어 재제출 없이 업데이트를 푸시하기 위해:

Troubleshooting 빌드가 'Cannot find module' 오류와 함께 실패합니다. bun install Run

그리고 다시 시도해 보세요. iOS: 'No signing identity found' 오류가 발생합니다.

안드로이드: “SDK 위치를 찾을 수 없음” 만들기 android/local.propertiessdk.dir=/path/to/android/sdk

장치에 나타나지 않는 변경 사항 변경 사항이 나타나지 않으면, 변경 사항을 적용한 후 다시 실행하세요. 라이브 리로드를 위해 IP 주소가 정확하고 개발 서버가 실행 중인지 확인하세요. bun run mobile .output/public이 비어 있거나 누락된 경우

만들기nitro: { preset: 'static' } 설정하고 nuxt.config.ts 리소스 bun run generate.

__CAPGO_KEEP_0__ 8 문서

Capgo으로 앱을 배달하기 위해 더 빠르게 업데이트를 제공하는 방법을 알아보세요 — __CAPGO_KEEP_0__ 무료 계정으로 가입하세요 오늘.

Nuxt 모바일 앱을 처음부터 만들기 위해 Capacitor 8을 계속하세요

__CAPGO_KEEP_0__을 사용하는 경우 Nuxt 모바일 앱을 처음부터 만들기 위해 Capacitor 8을 계속하세요 CI/CD 자동화 계획을 만들기 위해 연결하세요 Capgo CI/CD 제품 워크플로우에서 Capgo CI/CD를 위해 Capgo Native Builds 제품 워크플로우에서 Capgo Native Builds를 위해 Capgo Integrations 제품 워크플로우에서 Capgo Integrations를 위해 CI/CD 통합 CI/CD 통합 구현 세부 사항에서 GitHub Actions Integration 구현 세부 사항에서 GitHub Actions Integration

Capacitor 앱에 대한 실시간 업데이트

Capgo 앱의 버그가 생겼을 때, 앱 스토어 승인까지 며칠 기다리지 않고, Capgo를 통해 바로 수정을 배포하세요. 사용자는 배경에서 업데이트를 받으면서, 네이티브 변경은 일반적인 검토 경로를 유지합니다.

시작하기

블로그에서 최신 소식

Capgo는 전문적인 모바일 앱을 만들기 위해 필요한 최고의 통찰력을 제공합니다.