본문으로 건너뛰기
튜토리얼

Capacitor 8을 사용하여 Nuxt 모바일 앱을 처음부터 다시 만드는 방법

Nuxt 4 프로젝트를 새로 만들고 Capacitor 8을 사용하여 iOS 및 Android 모바일 앱으로 변환하는 단계별 가이드입니다. 모바일 개발을 시작할 때 완벽한 시작점입니다.

기사 저자

마틴 도나디유

작가

Valeria

리뷰어

Jordan

편집자

Capacitor 8

소개

모바일 앱을 처음부터 시작하여 Nuxt로 만들고 싶으신가요? 이 가이드는 모바일 앱을 처음부터 시작하여 Nuxt 4 프로젝트를 구성하고, 모바일 앱을 native iOS 및 Android 앱으로 패키징하는 방법을 안내합니다. Capacitor 8.

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

소요 시간: ~30분

제작할 내용:

  • 최신 디렉토리 구조를 갖는 새로운 Nuxt 4 프로젝트
  • 모바일을 위한 정적 생성 구성
  • Capacitor 8에 필수 플러그인을 포함
  • 자연어 iOS 및 Android 앱
  • 라이브 리로드 개발 설정

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

필수 조건:

다음 설치를 확인하세요:

  • Node.js 18+ (체크하시고) node --version)
  • Bun 패키지 매니저 (curl -fsSL https://bun.sh/install | bash)
  • Xcode (macOS 전용, iOS 개발용)
  • 안드로이드 스튜디오 (Android 개발용)

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

This structure provides better separation between app and server code.

2단계: Nuxt를 정적 생성으로 구성하기

Capacitor은 정적 HTML/JS/CSS 파일이 필요합니다. Nuxt를 정적 생성을 위한 설정으로 구성하세요. nuxt.config.ts:

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

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

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

업데이트 하세요 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단계: Capacitor 8 설치하기 .output/public Capacitor의 핵심 패키지를 설치하세요:

Capacitor

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/앱 앱 라이프 사이클 이벤트 (전경/후경, 깊이 링크)
  • @capacitor/키보드 키보드 동작을 제어합니다.
  • @capacitor/스플래시 화면 자연스러운 스플래시 스크린 제어
  • @capacitor/상태바 디바이스 상태 바 스타일링
  • @capacitor/설정 키-값 저장소 (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 그리고 android 디렉터리

7단계: 빌드 및 실행

프로젝트를 빌드하고 네이티브 플랫폼과 동기화하세요:

bun run mobile

iOS 시뮬레이터에서 열기:

bun run mobile:ios

또는 Android 에뮬레이터에서 열기:

bun run mobile:android

Xcode (iOS)에서:

  1. 디바이스 드롭다운에서 시뮬레이터를 선택하세요
  2. Play 버튼을 클릭하거나 Cmd + R

Android Studio에서:

  1. Gradle 동기화가 완료될 때까지 기다리세요
  2. 디바이스 드롭다운에서 에뮬레이터를 선택하세요
  3. Run 버튼을 클릭하거나 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. 개발 서버를 시작하고 네이티브로 설정을 복사하세요.
bun run dev &
NODE_ENV=development bunx cap copy
  1. Xcode/Android Studio에서 다시 빌드하세요.

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

9단계: 첫 번째 모바일 화면 만들기

모바일 친화적인 홈 스크린을 만들겠습니다. 업데이트 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 추가

스타일링이 작동하려면 프로젝트에 Tailwind CSS를 추가하세요.

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단계: 공유 플러그인 추가

Let's implement the share button functionality:

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>

공유 플러그인을 사용하기 위해:

bun run mobile

Sync 및 Rebuild:

프로젝트 구조

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
└── ...

다음 단계

다음 단계

컨텍스트: Capgo Builder / 네이티브 클라우드 빌드 제품 페이지. 역할: 짧은 UI 레이블 또는 네비게이션 아이템. 메시지 키 `native_build_builder_credit_next` (Native Build Builder Credit Next).

  • 애플리케이션 아이콘: 기본 아이콘을 ios/App/App/Assets.xcassets and android/app/src/main/res
  • 스플래시 화면: 자연스러운 프로젝트에서 personalize 하거나 @capacitor/splash-screen config
  • 깊이 있는 링크: 앱 URL 스키마를 구성하십시오

더 많은 기능 추가:

  • 카메라: bun add @capacitor/camera
  • 위치 정보: 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

See @capgo/capacitor-자연스러운 네비게이션, @capgo/capacitor-transition, 그리고 Tailwind-capacitor 레포 Capacitor Fixing iOS Layout Issues (Viewport, Safe Area, and Horizontal Overflow)

Capacitor If content looks cropped, shifted, or horizontally scrollable on iOS, adding more

Capacitor or tweaking the viewport tag alone usually does not fix it. Work through these checks in order. overflow-x: hidden Capacitor Make sure the viewport meta tag is applied correctly

Capacitor In

In nuxt.config.tsIn app.head:

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

iOS 안전 영역을 한 번에 처리하기

단일 앱 셸을 만들고 안전 영역 패딩을 적용하세요 — 여러 중첩된 컴포넌트에서 적용하지 마세요:

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가 잘려나거나 너무 크게 보이는 문제를 일으킵니다.

Live Update @capgo/tailwind-capacitor단일 셸에서 동일한 패딩을 표현할 수 있는 유틸리티를 사용하세요. pt-safe pb-safe px-safe __CAPGO_KEEP_0__ iOS

Set Capacitor iOS contentInset In never first

In capacitor.config.ts, native inset을 사용하고 CSS (또는 Native Navigation의) contentInsetMode: 'css') safe area를 관리하도록 해주세요:

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

Capacitor의 자동 콘텐츠 inset을 CSS padding과 혼합하는 것은 일반적인 double spacing의 원인입니다. env(safe-area-inset-*) 실제로 오버플로우가 발생하는 요소를 찾으세요.

일반적인 원인은 요소가

, Tailwind 100vw, 고정 픽셀 너비, 또는 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-screenviewport meta tag 자체에서 duplicated safe-area padding, 또는 fixed-width container — viewport meta tag 자체에서 아닌 것.

Over-the-Air 업데이트

설정 Capgo 앱 스토어 재제출 없이 업데이트를 푸시하는 방법:

bunx @capgo/cli init

문제 해결

빌드가 “Cannot find module” 에러로 실패합니다. 실행 bun install 업데이트를 푸시하는 방법은 앱 스토어 재제출 없이 다음과 같습니다.

빌드가 실패합니다. iOS: “No signing identity found”

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

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

.output/public이 빈 폴더거나 없으면 변경 사항을 적용한 후에 다시 실행하세요. nitro: { preset: 'static' } 설정한 nuxt.config.ts 에서 bun run generate.

실행하세요.

Capgo으로 앱을 배달하는 속도를 더 빠르게 하려면? 무료 계정으로 가입하세요. 오늘.

Build a Nuxt Mobile App from Scratch with Capacitor 8

Build a Nuxt Mobile App from Scratch with __CAPGO_KEEP_0__ 8 Capacitor을 사용하여 CI/CD 자동화 계획을 만드는 경우 __CAPGO_KEEP_0__ CI/CD와 연결하세요. Capgo CI/CD Capgo CI/CD workflow를 위한 Capgo 네이티브 빌드 Capgo 네이티브 빌드 workflow를 위한 Capgo 통합 Capgo 통합 CI/CD 통합 __CAPGO_KEEP_0__ 액션 통합 GitHub 액션 통합 Capacitor 구현 세부 사항에 대한 GitHub 액션 통합.

Capacitor 앱에 대한 즉시 업데이트

웹-layer 버그가 활성화된 경우 Capgo을 통해修정을 배포하는 대신 앱 스토어 승인에 몇 일 기다리지 말고 배포하세요. 사용자는 배경에서 업데이트를 받으면서 네이티브 변경 사항은 일반적인 검토 경로에 남게 됩니다.

최신 뉴스

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