이번 튜토리얼에서는 먼저 다음을 사용하여 새로운 웹 앱을 만드는 것부터 시작합니다. Quasar그 후, Capacitor를 사용하여 이를 모바일 앱으로 전환하는 방법을 알아봅니다. 모바일에서 앱을 더 멋지게 만들고 싶다면 말이죠.
Capacitor를 사용하면 React Native처럼 완전히 새로운 앱 개발 방식을 배우거나 복잡한 과정을 거칠 필요 없이, 기존 Quasar 웹 앱을 모바일 앱으로 바꿀 수 있습니다.
이 튜토리얼에서는 새로운 Quasar 앱을 만드는 것부터 시작하여, Capacitor를 활용해 네이티브 모바일 앱의 세계로 나아가는 과정을 안내합니다. 또한, Capgo 를 사용하여 단 몇 초 만에 앱으로 live update를 전송하는 방법도 배웁니다.
Capacitor 소개
CapacitorJS는 정말 혁신적입니다! 어떤 웹 프로젝트에도 손쉽게 통합할 수 있으며, 애플리케이션을 네이티브 webview로 감싸 Xcode 및 Android Studio 프로젝트를 자동으로 생성해 줍니다. 또한, 플러그인을 통해 JS bridge로 카메라와 같은 네이티브 디바이스 기능에 접근할 수 있습니다.
Capacitor를 사용하면 복잡한 설정이나 어려운 학습 과정 없이도 환상적인 네이티브 모바일 앱을 만들 수 있습니다. 가벼운 API와 간결한 기능 덕분에 프로젝트에 통합하기 매우 쉽습니다. Capacitor를 통해 완벽하게 작동하는 네이티브 앱을 얼마나 쉽게 구현할 수 있는지 직접 경험해 보세요!
Quasar 앱 준비하기
새로운 Quasar 앱을 생성하려면 다음 명령어를 실행하세요:
npm init quasar

“App with Quasar CLI” 옵션을 선택한 다음 “Quasar v2”를 선택하세요.
네이티브 모바일 앱을 만들려면 export 가 필요합니다. 따라서 프로젝트의 package.json Quasar 프로젝트를 빌드하고 복사하는 데 사용할 수 있습니다:
{
"scripts": {
// ...
"build": "quasar build"
}
}
명령어를 실행한 후 generate, 다음과 같은 새로운 dist 폴더가 프로젝트 루트에 생성됩니다.
이 폴더는 나중에 Capacitor에서 사용되지만, 지금은 올바르게 설정해야 합니다.
Quasar 앱에 Capacitor 추가하기
웹 앱을 네이티브 모바일 컨테이너로 패키징하려면 몇 가지 초기 단계를 거쳐야 하지만, 그 이후에는 단 하나의 sync 명령어만 실행하면 됩니다.
먼저, Capacitor CLI 개발 의존성(development dependency)으로 추가한 뒤 프로젝트 내에서 설정을 진행합니다. 설정 중 이름과 bundle ID에 대한 기본값을 사용하려면 “enter”를 누르면 됩니다.
다음으로 core 패키지와 iOS 및 Android 플랫폼용 관련 패키지를 설치해야 합니다.
마지막으로 플랫폼을 추가하면, Capacitor가 프로젝트 루트에 각 플랫폼별 폴더를 생성합니다:
# Install the Capacitor CLI locally
npm install -D @capacitor/cli
# Initialize Capacitor in your Quasar project
npx cap init
# Install the required packages
npm install @capacitor/core @capacitor/ios @capacitor/android
# Add the native platforms
npx cap add ios
npx cap add android

이제 Quasar 프로젝트에서 새로 생성된 ios 및 android 폴더들을 확인할 수 있습니다.
이것들은 실제 Native 프로젝트입니다!
나중에 Android 프로젝트에 접근하려면 반드시 Android Studio를 설치해야 합니다. iOS의 경우 Mac이 필요하며 다음을 설치해야 합니다: iOS 프로파일링.
또한, 프로젝트 내에서 다음 capacitor.config.ts 파일을 찾을 수 있습니다. 이 파일에는 동기화 과정에서 사용되는 핵심 Capacitor 설정이 포함되어 있습니다. 주의 깊게 확인해야 할 부분은 바로 webDir 항목이며, 이는 빌드 명령의 결과물을 가리켜야 합니다. 현재 설정은 정확하지 않습니다.
이를 수정하려면 capacitor.config.json 파일을 열고 다음을 업데이트하세요. webDir:
{
"appId": "com.example.app",
"appName": "my-app",
"webDir": "dist"
}
다음 명령어를 실행하여 테스트해 볼 수 있습니다:
npm run generate
npx cap sync
첫 번째 명령은 npm run generate Quasar 프로젝트를 빌드하고 정적 빌드 파일을 복사하며, 두 번째 명령은 npx cap sync 모든 웹 code를 네이티브 플랫폼의 적절한 위치로 동기화하여 앱에서 표시할 수 있게 합니다.
또한, sync 명령어로 인해 native 플랫폼이 업데이트되거나 플러그인이 설치될 수 있으므로, 새로운 항목을 설치할 때 Capacitor 플러그인 다음 명령을 실행할 차례입니다: npx cap sync 다시.
어느새 모든 과정이 끝났습니다. 이제 기기에서 앱을 확인해 봅시다!
네이티브 앱 빌드 및 배포
iOS 앱을 개발하려면 다음이 필요합니다. iOS 프로파일링 설치되었으며, Android 앱의 경우 다음이 필요합니다. Android Studio 설치해야 합니다. 또한 앱을 스토어에 배포하려면 iOS용 Apple Developer Program과 Android용 Google Play Console에 등록해야 합니다.
네이티브 모바일 개발이 처음이라면, Capacitor CLI를 사용하여 두 네이티브 프로젝트를 간편하게 열 수 있습니다:
npx cap open ios
npx cap open android
네이티브 프로젝트 설정이 완료되었다면, 연결된 기기에 앱을 배포하는 것은 매우 간단합니다. Android Studio에서는 모든 준비가 완료될 때까지 기다리기만 하면 별도의 설정 변경 없이 연결된 기기에 앱을 배포할 수 있습니다. 예시는 다음과 같습니다:

Xcode에서는 시뮬레이터가 아닌 실제 기기에 앱을 배포하려면 서명 계정(signing account)을 설정해야 합니다. 처음이라면 Xcode의 안내에 따라 진행할 수 있습니다(단, Developer Program에 등록되어 있어야 합니다). 설정이 완료되면 상단에서 연결된 기기를 선택한 후, 실행 버튼을 눌러 앱을 구동할 수 있습니다. 예시는 다음과 같습니다:

축하합니다! Quasar 웹 앱을 모바일 기기에 성공적으로 배포했습니다. 예시는 다음과 같습니다:
잠깐만요, 개발 중에는 이보다 더 빠른 방법이 있습니다...
Capgo Live Update
Capgo Live Update는 개발자가 기존의 App Store 심사 과정을 거치지 않고도 모바일 앱에 업데이트를 배포할 수 있게 해주는 서비스입니다. 이를 통해 App Store의 리뷰를 기다릴 필요 없이 버그를 빠르게 수정하거나 앱에 작은 업데이트를 즉시 적용할 수 있습니다.
Quasar 앱에 Capgo를 통합하면 실시간 Live Update 기능을 손쉽게 활용할 수 있습니다. 이 가이드를 통해 Capgo Live Update를 통합하고 구현하여 끊김 없는 업데이트를 제공하는 방법을 단계별로 알아보세요.
Capgo 대시보드 가입 및 접속:
이제 가입을 완료하고 첫 번째 버전을 upload할 API 키를 발급받을 차례입니다! 먼저 Capgo 계정을 생성하세요.
Capgo SDK 설치:
터미널에서 Capacitor 앱의 루트 디렉토리로 이동한 뒤 다음 명령어를 실행하세요:
npm i @capgo/capacitor-updater && npx cap sync Capacitor 앱에 플러그인을 설치합니다.
그 다음, CodePush를 대체할 code를 앱에 추가합니다:
import { CapacitorUpdater } from '@capgo/capacitor-updater'
CapacitorUpdater.notifyAppReady()
이 과정을 통해 네이티브 플러그인에 설치가 성공했음을 알립니다.
Capgo CLOUD 로그인:
먼저, all apikey 계정에 있는 CLI로 로그인하려면:
`npx @capgo/cli@latest login YOU_KEY`
첫 번째 앱 추가하기:
CLI을(를) 사용하여 Capgo Cloud에 앱을 먼저 생성해 보세요.
npx @capgo/cli@latest app add
이 명령은 Capacitor 설정 파일에 정의된 모든 변수를 사용하여 앱을 생성합니다.
첫 번째 버전 업로드:
다음 명령을 실행하여 code를 빌드하고 Capgo로 전송하세요:
npx @capgo/cli@latest bundle upload`
기본적으로 버전 이름은 package.json 파일에 명시된 이름을 따릅니다.
체크인 Capgo 빌드가 있으면.
다음 앱으로 직접 테스트할 수도 있습니다: 모바일 샌드박스 앱.
채널 기본값 설정:
앱을 Capgo에 전송한 후, 앱이 Capgo로부터 업데이트를 받을 수 있도록 채널을 기본값으로 설정해야 합니다.
npx @capgo/cli@latest channel set production -s default
업데이트 검증을 위한 앱 설정:
메인 JavaScript 파일에 이 설정을 추가하세요.
import { CapacitorUpdater } from '@capgo/capacitor-updater'
CapacitorUpdater.notifyAppReady()
그 다음 npm run build && npx cap copy 를 실행하여 앱을 업데이트하세요.
Live Update 받기:
Deploy로부터 live update를 받으려면 앱을 실제 기기나 에뮬레이터에서 실행해야 합니다. 가장 간단한 방법은 다음 명령어를 사용하여 컴퓨터에 연결된 기기나 에뮬레이터에서 로컬 앱을 실행하는 것입니다.
npx cap run [ios | android]
앱을 실행한 뒤 백그라운드로 보냈다가 다시 열어보세요. 로그에서 앱이 업데이트를 완료한 것을 확인할 수 있습니다.
축하합니다! 🎉 첫 번째 Live Update 배포에 성공하셨습니다. 이것은 Live Updates로 할 수 있는 일의 시작일 뿐입니다. 더 자세한 내용은 전체 Live Updates 문서.
Capacitor 플러그인 사용법
이전에 여러 번 언급했던 Capacitor 플러그인을 실제로 어떻게 사용하는지 살펴보겠습니다. 먼저 다음 명령어를 실행하여 간단한 플러그인을 설치할 수 있습니다:
npm i @capacitor/share
별거 없지만 플러그인 공유하기, 하지만 여전히 네이티브 공유 다이얼로그가 나타납니다! 이제 패키지를 import하고 해당 메서드를 호출하기만 하면 됩니다. share() 앱에서 함수를 호출하기만 하면 됩니다. 그럼 pages/index.vue 파일을 이렇게 수정해 봅시다:
<template>
<div>
<h1>Welcome to Quasar and Capacitor!</h1>
<button @click="share">Share now!</button>
</div>
</template>
<script setup lang="ts">
import { Share } from '@capacitor/share';
async function share() {
await Share.share({
title: 'Open Youtube',
text: 'Check new video on youtube',
url: 'https://www.youtube.com',
dialogTitle: 'Share with friends'
});
}
</script>
앞서 말했듯이, 새 플러그인을 설치할 때는 sync 작업을 수행한 뒤 기기에 앱을 다시 배포해야 합니다. 이렇게 하려면 다음 명령어를 실행하세요:
npx cap sync
버튼을 누르면 멋진 네이티브 공유 다이얼로그가 실제로 뜨는 걸 확인할 수 있습니다!
다음으로, Capgo 내비게이션과 트랜지션으로 iOS와 Android에서 앱을 더 네이티브하게 느끼게 하고, 가로 오버플로우나 세이프 에어리어가 잘리는 흔한 iOS 레이아웃 문제도 해결할 수 있습니다.
Capgo Native Navigation and Transitions로 만드는 네이티브한 UI
저는 수년간 Ionic 크로스 플랫폼 앱을 빌드할 때 사용하지만, 이미 사용 중인 환경이 있다면 Quasar와 통합하는 방식은 다소 불안정하며 그만한 가치가 없는 경우가 많습니다. Tailwind CSS.
Quasar + Capacitor 앱에서 네이티브 모바일 느낌을 구현하려면, Konsta UI 같은 웹 전용 UI 키트 대신 Capgo 플러그인을 사용하세요:
- @capgo/capacitor-native-navigation — 네이티브 navbar, iOS의 Liquid Glass tab bar, Android의 블러 처리된 tab bar 스타일을 제공합니다. Quasar router는 라우트 상태를 유지하고, 플러그인은 네이티브 chrome을 제어합니다.
- @capgo/capacitor-transitions — Ionic UI 없이 WebView 레이어에서 Ionic 스타일 페이지 전환과 iOS edge swipe-back을 제공합니다.
둘 다 설치하세요:
npm add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
npmx cap sync
웹 콘텐츠가 native bar를 침범하지 않도록 CSS inset 모드로 native navigation을 설정하세요:
import { NativeNavigation } from '@capgo/capacitor-native-navigation';
await NativeNavigation.configure({
contentInsetMode: 'css',
animationDuration: 360,
glass: {
effect: 'liquidGlass',
},
});
Liquid Glass tab bar를 렌더링합니다 (iOS는 시스템이 렌더링하고, Android는 블러 처리된 WebView 배경을 사용합니다):
await NativeNavigation.setTabbar({
selectedId: 'home',
labelVisibilityMode: 'labeled',
icons: true,
colors: { dynamic: true },
tabs: [
{ id: 'home', title: 'Home', icon: { svg: '...' } },
{ id: 'settings', title: 'Settings', icon: { svg: '...' } },
],
});
await NativeNavigation.addListener('tabSelect', ({ id }) => {
router.push(`/${id}`);
});
앱 shell에 native page transitions를 추가하세요:
<script setup>
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import '@capgo/capacitor-transitions';
import { initTransitions, setDirection, setupRouterOutlet } from '@capgo/capacitor-transitions/vue';
initTransitions({ platform: 'auto' });
const router = useRouter();
const outletRef = ref(null);
onMounted(() => {
if (outletRef.value) {
setupRouterOutlet(outletRef.value, { platform: 'auto', swipeGesture: 'auto' });
}
});
const openSettings = () => {
setDirection('forward');
router.push('/settings');
};
</script>
<template>
<cap-router-outlet ref="outletRef">
<router-view />
</cap-router-outlet>
</template>
라우팅된 페이지를 cap-router-outlet, cap-page, 그리고 cap-content로 감싸고, 호출하세요 setDirection('forward') 또는 setDirection('back') 이동하기 전에. 네이티브 네비게이션이 해당 영역을 담당할 때는 웹 헤더나 푸터를 중복해서 만들지 마세요.
전체 가이드 보기: @capgo/capacitor-native-navigation 사용하기 및 @capgo/capacitor-transitions 사용하기.
Tailwind로 safe area 처리하기
Tailwind CSS에서 디바이스 safe area에는 다음을 사용하세요: @capgo/tailwind-capacitor (다음으로 게시됨: tailwind-capacitor npm). 다음을 제공합니다: safe-areas 유틸리티와 기타 Capacitor 친화적인 Tailwind 플러그인:
npm add -D tailwind-capacitor
다음에서 src/css/app.scss:
@import 'tailwindcss';
@plugin "@capgo/tailwind-capacitor/platform";
@plugin "@capgo/tailwind-capacitor/safe-areas";
다음과 같은 유틸리티를 사용하세요: pt-safe, pb-safe, 그리고 px-safe 여기저기 흩뿌리는 대신 env(safe-area-inset-*) 수동으로 작업할 필요가 없습니다. 이 프로젝트는 활발히 개발 중이며, Quasar 설정에 필요한 게 빠져 있다면, GitHub에 PR을 올려주세요..
iOS 레이아웃 이슈 해결 (Viewport, Safe Area, 가로 오버플로우)
iOS에서 콘텐츠가 잘리거나, 밀리거나, 가로 스크롤이 생긴다면, 더 추가하거나 overflow-x: hidden viewport 태그를 조정하는 것만으로는 보통 해결되지 않습니다. 다음 점검을 순서대로 진행하세요.
viewport meta 태그가 올바르게 적용되었는지 확인하세요
다음에서 index.html (또는 사용 중인 Quasar HTML 템플릿)의 viewport meta 태그를 설정하세요. <head>:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
iOS safe area는 루트 래퍼 한 곳에서만 처리하세요
단일 앱 셸을 생성하고 그곳에 safe area 패딩을 적용하세요. 여러 중첩된 컴포넌트에 각각 적용하지 마세요:
html,
body,
#q-app {
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. 헤더, 모달, 레이아웃 래퍼에 safe-area 패딩이 중복되면 UI가 잘리거나 너무 커 보일 수 있습니다.
사용하면 @capgo/tailwind-capacitor, 다음과 같은 유틸리티로 동일한 패딩을 표현할 수 있습니다. pt-safe pb-safe px-safe 해당 단일 셸에서.
Capacitor iOS를 설정하세요 contentInset 대상 never 먼저
다음에서 capacitor.config.ts, native inset을 비활성화하는 편이 좋고 CSS(또는 Native Navigation의 contentInsetMode: 'css')가 safe area를 제어하도록 하세요:
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'dist/spa',
ios: {
contentInset: 'never',
},
};
Capacitor의 자동 content inset과 CSS env(safe-area-inset-*) padding을 함께 쓰면 이중 여백이 생기는 흔한 원인입니다.
실제로 overflow되는 요소를 찾으세요
흔한 원인은 다음을 사용하는 요소입니다: 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중복된 safe-area 패딩이나 고정 너비 컨테이너 때문이며, viewport meta tag 자체 때문은 아닙니다.
마치며
Capacitor는 기존 웹 프로젝트를 기반으로 네이티브 앱을 빌드하는 데 탁월한 선택지이며, code를 공유하고 일관된 UI를 유지하는 간단한 방법을 제공합니다.
그리고 여기에 Capgo를 더하면 앱에 라이브 업데이트를 추가하기가 훨씬 쉬워지며, 사용자가 항상 최신 기능과 버그 수정을 이용할 수 있도록 보장합니다.
Next.js 앱에 Capgo를 추가하는 방법이 궁금하다면 다음 아티클을 확인해 보세요:
Quasar와 Capacitor를 활용한 Live Update 기반 모바일 앱 제작하기 시리즈의 다음 단계입니다.
사용 중이라면 Live Updates, Quasar, Capacitor로 모바일 앱 만들기 네이티브 플러그인 작업을 계획하려면, 이를 다음 항목과 연결하세요: Capgo 플러그인 디렉토리 Capgo Plugin Directory의 제품 워크플로우에 맞춰, Capgo의 Capacitor 플러그인 Capgo의 Capacitor 플러그인 구현 상세 내용에 대해서는, 플러그인 추가 또는 업데이트 플러그인 추가 또는 업데이트의 구현 세부 사항은, Ionic Enterprise 플러그인 대안 Ionic Enterprise 플러그인 대안의 제품 워크플로우와, Capgo Native Build Capgo Native Builds의 제품 워크플로우를 위해.