watchOS 앱 만들기
이 플러그인의 설치 단계와 전체 마크다운 가이드가 포함된 설정 프롬프트를 복사하세요.
이 가이드는 다음 과정을 안내합니다: watchOS companion app을 처음부터 만드는 방법입니다. Xcode 프로젝트 설정, CapgoWatchSDK 통합, SwiftUI를 이용한 watch app 빌드 과정을 포함합니다.
대상: Wear OS의 경우, Wear OS 앱 만들기 를 사용하세요.
사전 요구사항
“사전 준비 사항” 섹션시작하기 전에 다음 사항을 확인하세요:
- Xcode 15 이상 (Mac App Store에서 다운로드)
- macOS Sonoma 이상 (최신 watchOS SDK용)
- 기존 Capacitor iOS 프로젝트 (실행)
npx cap add ios(아직 안 했다면) - Apple Developer 계정 (개발용으로는 무료 계정도 가능)
프로젝트 구조 개요
“프로젝트 구조 개요” 섹션이 가이드를 마치면 프로젝트 구조는 다음과 같습니다:
디렉토리ios/
디렉토리App/
디렉토리App/ (메인 iOS 앱)
- …
- App.xcodeproj
- App.xcworkspace (프로젝트를 열 때 사용)
- Podfile
디렉토리MyWatch/ (새 watch app)
디렉토리MyWatch/ (watch app 소스)
- MyWatchApp.swift
- ContentView.swift
디렉토리Assets.xcassets/
- …
- MyWatch.xcodeproj
1단계: Xcode에서 iOS 프로젝트 열기
“1단계: Xcode에서 iOS 프로젝트 열기” 섹션- Capacitor 프로젝트의 다음 경로로 이동하세요
ios/App폴더 - 열기
App.xcworkspace(아님.xcodeproj)을(를) 더블 클릭하여 - Xcode의 프로젝트 인덱싱이 완료될 때까지 기다리세요
2단계: watchOS Target 추가
“2단계: watchOS Target 추가” 섹션-
Xcode에서 다음 경로로 이동하세요: 파일 → New → Target…
-
템플릿 선택 창에서:
- 선택 watchOS 상단 탭
- 선택 앱
- 클릭 다음
-
watch app을 설정하세요:
- 제품 이름:
MyWatch(또는 원하는 이름) - 팀: Apple Developer 팀을 선택하세요
- Organization Identifier: iOS 앱과 일치해야 합니다 (예:
app.capgo) - Bundle Identifier: 자동으로 생성됩니다 (예:
app.capgo.myapp.watchkitapp) - 언어Swift
- 사용자 인터페이스SwiftUI
- Watch App 유형: App (기존 iOS App용 App 아님)
- 체크 해제 알림 Scene 포함하기 (필요하지 않은 경우)
- 체크 해제 Complication 포함하기 (필요하지 않은 경우)
- 제품 이름:
-
클릭 완료
-
“Activate ‘MyWatch’ scheme?” 프롬프트가 뜨면, 다음을 클릭하세요 Activate
3단계: Watch App 설정 구성
“3단계: Watch App 설정 구성” 섹션-
Project Navigator(왼쪽 사이드바)에서 프로젝트(상단의 파란색 아이콘)를 선택하세요
-
targets 목록에서 watch target(예: “MyWatch”)을 선택하세요
-
다음으로 이동하세요: General 탭:
- 표시 이름: 앱 아이콘 아래에 표시될 이름 (예: “My App”)
- Bundle Identifier: 다음으로 끝나야 합니다
.watchkitapp - 버전: iOS 앱 버전과 일치해야 함
- 빌드: iOS 앱 빌드 번호와 일치시키세요
-
다음으로 이동: Signing & Capabilities 탭:
- 활성화 Signing 자동 관리
- 다음 항목을 선택하세요: 팀
- Xcode가 프로비저닝 프로파일을 자동으로 생성합니다
-
설정 배포 정보:
- 최소 배포 버전: watchOS 9.0 이상
4단계: Swift Package Manager로 CapgoWatchSDK 추가
“4단계: Swift Package Manager로 CapgoWatchSDK 추가” 섹션CapgoWatchSDK는 바로 사용할 수 있는 WatchConnector 통신용 class를 제공합니다.
-
Xcode에서 다음 경로로 이동하세요: 파일 → 패키지 의존성 추가…
-
검색 필드에 다음을 입력하세요:
https://github.com/Cap-go/capacitor-watch.git -
Enter를 누르고 Xcode가 패키지를 가져올 때까지 기다리세요
-
패키지 설정:
- 의존성 규칙: “Up to Next Major Version” (“8.0.0” 기준)
- 클릭 패키지 추가
-
추가할 제품을 선택하세요:
- 주의 사항: 다음 항목만 선택하세요
CapgoWatchSDK - 반드시 다음 항목에 추가되었는지 확인하세요: watch 타겟 (예: “MyWatch”), iOS 앱이 아닙니다
- 클릭 패키지 추가
- 주의 사항: 다음 항목만 선택하세요
5단계: Watch 앱 구현
“5단계: Watch 앱 구현” 섹션이제 code watch 앱을 만들어 보겠습니다. 자동 생성된 파일들을 다음 코드로 교체하세요:
5.1 앱 엔트리 포인트 생성
“5.1 앱 엔트리 포인트 생성” 섹션편집 MyWatch/MyWatchApp.swift:
import SwiftUIimport CapgoWatchSDK
@mainstruct MyWatchApp: App { init() { // Activate WatchConnectivity when app launches WatchConnector.shared.activate() }
var body: some Scene { WindowGroup { ContentView() } }}5.2 메인 뷰 생성하기
“5.2 메인 뷰 생성하기” 섹션편집 MyWatch/ContentView.swift:
import SwiftUIimport CapgoWatchSDK
struct ContentView: View { // Observe the WatchConnector for automatic UI updates @ObservedObject var connector = WatchConnector.shared
// Local state @State private var messageText = "" @State private var statusMessage = "Ready"
var body: some View { ScrollView { VStack(spacing: 16) { // Connection Status ConnectionStatusView(connector: connector)
Divider()
// Message Input TextField("Message", text: $messageText) .textFieldStyle(.roundedBorder)
// Send Buttons HStack { Button("Send") { sendMessage() } .disabled(!connector.isReachable || messageText.isEmpty)
Button("Request") { sendWithReply() } .disabled(!connector.isReachable || messageText.isEmpty) }
Divider()
// Status Text(statusMessage) .font(.caption) .foregroundColor(.secondary)
// Last Received Message if !connector.lastMessage.isEmpty { VStack(alignment: .leading) { Text("Last Message:") .font(.caption) .foregroundColor(.secondary) Text(formatMessage(connector.lastMessage)) .font(.caption2) } .frame(maxWidth: .infinity, alignment: .leading) } } .padding() } }
private func sendMessage() { connector.sendMessage(["text": messageText, "timestamp": Date().timeIntervalSince1970]) statusMessage = "Message sent" messageText = "" }
private func sendWithReply() { connector.sendMessage(["text": messageText, "needsReply": true]) { reply in DispatchQueue.main.async { statusMessage = "Reply: \(formatMessage(reply))" } } messageText = "" }
private func formatMessage(_ message: [String: Any]) -> String { message.map { "\($0.key): \($0.value)" }.joined(separator: ", ") }}
// Separate view for connection statusstruct ConnectionStatusView: View { @ObservedObject var connector: WatchConnector
var body: some View { HStack { Circle() .fill(connector.isReachable ? Color.green : Color.red) .frame(width: 12, height: 12)
Text(connector.isReachable ? "Connected" : "Disconnected") .font(.headline)
Spacer()
if connector.isActivated { Image(systemName: "checkmark.circle.fill") .foregroundColor(.green) } } }}
#Preview { ContentView()}6단계: WatchConnectivity를 위한 iOS 앱 설정
“6단계: WatchConnectivity를 위한 iOS 앱 설정” 섹션iOS 앱에도 WatchConnectivity 권한이 필요합니다.
-
Project Navigator에서 프로젝트를 선택하세요
-
다음 항목을 선택하세요: iOS App 타겟 (watch 타겟이 아님)
-
다음으로 이동: Signing & Capabilities 탭
-
클릭 + 권한 추가
-
검색하여 추가 WatchConnectivity (사용 가능한 경우) 또는 자동으로 추가될 수 있습니다
-
Capacitor 플러그인이 iOS 쪽을 자동으로 처리하지만, Info.plist에 다음 항목이 있는지 확인하세요:
<key>WKCompanionAppBundleIdentifier</key><string>app.capgo.myapp.watchkitapp</string>
7단계: 빌드 및 실행
“7단계: 빌드 및 실행” 섹션시뮬레이터에서 실행
“시뮬레이터에서 실행” 섹션-
Scheme selector(Xcode 창 상단)에서 watch scheme을 선택하세요
-
watch 시뮬레이터 선택:
- Scheme 옆의 디바이스 선택기를 클릭하세요
- Apple Watch 시뮬레이터를 선택하세요 (예: “Apple Watch Series 9 (45mm)”)
-
Members 섹션에서 실행 버튼(▶️)을 클릭하거나
Cmd + R -
iPhone과 Apple Watch가 포함된 iOS Simulator가 실행됩니다
실제 기기에서 실행
“실제 기기에서 실행” 섹션-
USB로 iPhone을 연결하세요
-
Apple Watch가 해당 iPhone과 페어링되어 있는지 확인하세요
-
Watch 스킴을 선택하세요
-
기기 목록에서 실제 Apple Watch를 선택하세요
-
클릭 실행
-
처음 사용 시: 두 기기 모두에서 컴퓨터를 신뢰해야 할 수도 있습니다
8단계: 통신 테스트
“8단계: 통신 테스트” 섹션iPhone (Capacitor)에서 Watch로
“iPhone (Capacitor)에서 Watch로” 섹션Capacitor 앱에서:
import { CapgoWatch } from '@capgo/capacitor-watch';
// Check connectionconst info = await CapgoWatch.getInfo();console.log('Watch reachable:', info.isReachable);
// Send a messageif (info.isReachable) { await CapgoWatch.sendMessage({ data: { action: 'update', value: 'Hello from iPhone!' } });}Watch에서 iPhone으로
“Watch에서 iPhone으로” 섹션watch 앱은 다음을 사용합니다 WatchConnector:
// Send message (fire and forget)WatchConnector.shared.sendMessage(["action": "buttonTapped"])
// Send message with replyWatchConnector.shared.sendMessage(["request": "getData"]) { reply in print("Got reply: \(reply)")}iPhone에서 메시지 처리하기
“iPhone에서 메시지 처리하기” 섹션// Listen for messages from watchawait CapgoWatch.addListener('messageReceived', (event) => { console.log('Message from watch:', event.message); // { action: 'buttonTapped' }});
// Handle messages that need a replyawait CapgoWatch.addListener('messageReceivedWithReply', async (event) => { console.log('Request from watch:', event.message);
// Send reply back await CapgoWatch.replyToMessage({ callbackId: event.callbackId, data: { status: 'success', items: ['item1', 'item2'] } });});고급: 더 세밀한 제어를 위한 Custom Delegate
“Advanced: Custom Delegate for More Control” 섹션더 세밀한 제어가 필요한 경우, 다음을 구현하세요: WatchConnectorDelegate:
import SwiftUIimport CapgoWatchSDK
class WatchHandler: WatchConnectorDelegate { func didReceiveMessage(_ message: [String: Any]) { print("Received: \(message)") // Handle incoming message }
func didReceiveMessageWithReply(_ message: [String: Any], replyHandler: @escaping ([String: Any]) -> Void) { print("Received request: \(message)") // Process and send reply replyHandler(["status": "processed"]) }
func didReceiveApplicationContext(_ context: [String: Any]) { print("Context updated: \(context)") }
func didReceiveUserInfo(_ userInfo: [String: Any]) { print("User info received: \(userInfo)") }
func reachabilityDidChange(_ isReachable: Bool) { print("Reachability changed: \(isReachable)") }
func activationDidComplete(with state: WCSessionActivationState) { print("Activation completed: \(state.rawValue)") }}
// In your app setup:let handler = WatchHandler()WatchConnector.shared.delegate = handlerWatchConnector.shared.activate()문제 해결
“문제 해결” 섹션Watch에 Watch App이 나타나지 않을 때
“Watch App Not Appearing on Watch” 섹션- Bundle ID가 올바르게 연결되었는지 확인하세요 (watch app bundle ID는 iOS app bundle ID에
.watchkitapp) - 두 앱 모두 동일한 팀으로 서명되었는지 확인하세요
- 실제 기기에서: iPhone에서 Watch 앱 실행 → My Watch → 앱을 찾아 스크롤 → 토글 ON
메시지가 수신되지 않을 때
“메시지를 수신할 수 없음” 섹션- 양쪽 앱의 WCSession 활성화 여부 확인
- 체크 항목
isReachable메시지를 보내기 전에 - 메시지 전달을 보장하려면 다음을 사용하세요
transferUserInfo를 전달하고sendMessage - 상대 기기에서 메시지를 보내기 전에 리스너가 등록되었는지 확인하세요
“Session Not Activated” 에러
“Session Not Activated” 에러 섹션- 호출하세요
WatchConnector.shared.activate()앱 생명주기 초기 단계에 - iOS에서는 플러그인이 자동으로 활성화됩니다. 플러그인이 import 되었는지 확인하세요
- iOS target에 WatchConnectivity capability가 추가되었는지 확인하세요
CapgoWatchSDK 빌드 에러
“CapgoWatchSDK 빌드 오류” 섹션- 패키지가 다음 항목에 추가되었는지 확인하세요: watch 대상(iOS target이 아님)
- 빌드 폴더 정리: Product → Clean Build Folder (Cmd + Shift + K)
- 패키지 캐시 초기화: File → Packages → Reset Package Caches
Simulator 관련 이슈
“Simulator Issues” 섹션- 시뮬레이터를 초기화하세요: 설정 → 모든 콘텐츠 및 설정 지우기
- iOS와 watchOS 시뮬레이터가 호환되는 버전인지 확인하세요
- 통신이 작동하려면 두 시뮬레이터가 모두 실행 중이어야 합니다
다음 단계
“다음 단계” 섹션- Wear OS 앱 만들기 Android watch의 경우
- API 레퍼런스 - 완전한 API 문서
- 통신 패턴 - 각 메서드별 사용 시점
- 예제 앱 - 전체 동작 예제
watchOS App 만들기 다음 단계
“Creating a watchOS App” 단계 이후 계속하기 섹션사용 중이라면 watchOS 앱 만들기 네이티브 플러그인 작업을 계획하려면, 이를 다음 항목과 연결하세요: @capgo/capacitor-watch 사용하기 @capgo/capacitor-watch 사용 시 네이티브 기능 구현을 위해, Capgo 플러그인 디렉토리 Capgo Plugin Directory의 제품 워크플로우에 맞춰, Capgo의 Capacitor 플러그인 Capgo의 Capacitor 플러그인 구현 상세 내용에 대해서는, 플러그인 추가 또는 업데이트 플러그인 추가 또는 업데이트 구현 상세 내용에 대해서는, Ionic Enterprise 플러그인 대안 Ionic Enterprise 플러그인 대안의 제품 워크플로우에 대해서는.