Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions UMCApp/Core/Network/Sources/Auth/KeychainTokenStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ import Security
/// - **Accessibility**: `kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly` ์‚ฌ์šฉ
/// (๋””๋ฐ”์ด์Šค ์ž ๊ธˆ ํ•ด์ œ ํ›„ ์ ‘๊ทผ ๊ฐ€๋Šฅ, ๋ฐฑ์—…ยท๋™๊ธฐํ™” ์•ˆ ๋จ)
/// - **๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ**: ์ฒซ ์กฐํšŒ ์‹œ Keychain์—์„œ ๋กœ๋“œ ํ›„ ์บ์‹ฑ
/// - **Access group**: ์ฟผ๋ฆฌ์— access group์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ €์žฅ์€ entitlement์˜
/// ์ฒซ ๊ทธ๋ฃน(`$(AppIdentifierPrefix)com.umc.product.shared`)์—, ์กฐํšŒ๋Š” ์•ฑ์ด ๊ฐ€์ง„
/// ๋ชจ๋“  ๊ทธ๋ฃน์„ ๋Œ€์ƒ์œผ๋กœ ์ด๋ค„์ง„๋‹ค
/// - **์‚ญ์ œ ๋ฒ”์œ„**: `clear()` ์—ญ์‹œ access group์„ ์ง€์ •ํ•˜์ง€ ์•Š์•„ ์•ฑ์ด ๊ฐ€์ง„ ๋ชจ๋“  ๊ทธ๋ฃน์—์„œ
/// ๋™์ผ ํ‚ค๋ฅผ ํ•จ๊ป˜ ์ œ๊ฑฐํ•œ๋‹ค
public actor KeychainTokenStore: TokenStore {

// MARK: - Property
Expand Down
8 changes: 8 additions & 0 deletions UMCApp/UMCApp.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,13 @@
<array>
<string>group.com.umc.product.widget</string>
</array>
<!-- ๋ฐฐ์—ด ์ฒซ ํ•ญ๋ชฉ์ด SecItemAdd ์˜ ๊ธฐ๋ณธ access group ์ด๋ฏ€๋กœ ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๋ฉด -->
<!-- ํ† ํฐ ์ €์žฅ ์œ„์น˜๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค. ๊ณต์œ  ๊ทธ๋ฃน๋ช…์€ watch ํƒ€๊ฒŸ๊ณผ ๋™์ผํ•˜๊ฒŒ ์œ ์ง€ํ•œ๋‹ค -->
<!-- (์œ„์ ฏ์€ Keychain ์„ ์“ฐ์ง€ ์•Š์•„ ์ด ํ‚ค๊ฐ€ ์—†๋‹ค). -->
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.umc.product.shared</string>
<string>$(AppIdentifierPrefix)com.umc.product</string>
</array>
</dict>
</plist>
1 change: 1 addition & 0 deletions UMCApp/UMCWatchApp/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ProjectDescriptionHelpers
let project = watchAppProject(
name: "UMCWatchApp",
bundleId: "com.umc.product.watchkitapp",
entitlements: .file(path: "UMCWatchApp.entitlements"),
dependencies: [
.project(target: "CoreWatchConnectivity", path: .relativeToRoot("Core/WatchConnectivity")),
]
Expand Down
13 changes: 13 additions & 0 deletions UMCApp/UMCWatchApp/UMCWatchApp.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- ๋ฐฐ์—ด ์ฒซ ํ•ญ๋ชฉ์ด SecItemAdd ์˜ ๊ธฐ๋ณธ access group ์ด๋ฏ€๋กœ ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๋ฉด -->
<!-- ํ† ํฐ ์ €์žฅ ์œ„์น˜๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค. ๊ณต์œ  ๊ทธ๋ฃน๋ช…์€ iOS ์•ฑ ํƒ€๊ฒŸ๊ณผ ๋™์ผํ•˜๊ฒŒ ์œ ์ง€ํ•œ๋‹ค. -->
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.umc.product.shared</string>
<string>$(AppIdentifierPrefix)com.umc.product.watchkitapp</string>
</array>
</dict>
</plist>
35 changes: 35 additions & 0 deletions docs/claude/build-and-modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,38 @@ featureProject(
- **Product Type**: ๋ชจ๋“  ๋ชจ๋“ˆ `.staticFramework`
- **Bundle ID**: Core โ†’ `dev.umc.core.*` / Feature โ†’ `dev.umc.feature.*.*`
- **Workspace**: glob(`Core/*`, `Features/*`) + `UMCAppWidget`, `UMCWatchApp` ๋ช…์‹œ ํฌํ•จ

### ๊ณต์œ  Keychain Access Group

iOS ์•ฑ๊ณผ watchOS ์•ฑ์€ ๋กœ๊ทธ์ธ ํ† ํฐ์šฉ ๊ณต์œ  ๊ทธ๋ฃน `$(AppIdentifierPrefix)com.umc.product.shared` ๋ฅผ
`keychain-access-groups` entitlement ์˜ **์ฒซ ํ•ญ๋ชฉ**์œผ๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ํŒ€ ID(`8B8B4462NV`)๋ฅผ ๋ฌธ์ž์—ด๋กœ
๋ฐ•์ง€ ์•Š๊ณ  `$(AppIdentifierPrefix)` ๋ฅผ ์“ฐ๋Š” ๊ฒƒ์ด ๋ ˆํฌ ๊ด€๋ก€์ž…๋‹ˆ๋‹ค
(`UMCApp/Core/Network/Tests/CoreNetworkTests.entitlements` ๋™์ผ).

| ํƒ€๊ฒŸ | entitlements ํŒŒ์ผ | ๋ฐฐ์„  ์œ„์น˜ |
|------|------------------|----------|
| iOS ์•ฑ | `UMCApp/UMCApp.entitlements:27-31` | `UMCApp/Project.swift:85` |
| watchOS ์•ฑ | `UMCApp/UMCWatchApp/UMCWatchApp.entitlements:7-11` | `UMCApp/UMCWatchApp/Project.swift:7` |

- **๋ฐฐ์—ด ์ˆœ์„œ๊ฐ€ ๊ณ„์•ฝ์ด๋‹ค.** `kSecAttrAccessGroup` ์„ ์ง€์ •ํ•˜์ง€ ์•Š์€ `SecItemAdd` ๋Š” ๋ฐฐ์—ด **์ฒซ ํ•ญ๋ชฉ**์—
์ €์žฅํ•œ๋‹ค. `UMCApp/Core/Network/Sources/Auth/KeychainTokenStore.swift` ๋Š” ์ €์žฅ(104-110ํ–‰) ยท
์กฐํšŒ(120-126ํ–‰) ยท ์‚ญ์ œ(141-145ํ–‰) ์ฟผ๋ฆฌ ์–ด๋””์—๋„ access group ์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ด ๊ธฐ๋ณธ๊ฐ’ ๊ทœ์น™์—
์ „์ ์œผ๋กœ ์˜์กดํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ๊ณต์œ  ๊ทธ๋ฃน์ด ์ฒซ ๋ฒˆ์งธ๋‹ค.
- **๋‘ ๋ฒˆ์งธ ํ•ญ๋ชฉ(๊ฐ ํƒ€๊ฒŸ ์ž๊ธฐ App ID ๊ทธ๋ฃน)์€ ์•ˆ์ „์žฅ์น˜๋‹ค.** ๊ฒ€์ƒ‰ยท์‚ญ์ œ๋Š” access group ๋ฏธ์ง€์ • ์‹œ ์•ฑ์ด ๊ฐ€์ง„
๋ชจ๋“  ๊ทธ๋ฃน์„ ๋Œ€์ƒ์œผ๋กœ ํ•˜๋ฏ€๋กœ, ๊ธฐ์กด ๋ฐฐํฌํŒ์ด ๊ธฐ๋ณธ ๊ทธ๋ฃน(`$(AppIdentifierPrefix)com.umc.product`)์— ์ €์žฅํ•ด ๋‘”
ํ† ํฐ์ด ๊ณ„์† ์ฝํžŒ๋‹ค. ์ด ์ค„์„ ๋นผ๋ฉด ์—…๋ฐ์ดํŠธ ์ฆ‰์‹œ ์ „ ์‚ฌ์šฉ์ž ๊ฐ•์ œ ๋กœ๊ทธ์•„์›ƒ์ด๋‹ค.
- **์›Œ์น˜๋Š” ๋ฐฐ์„ ๊นŒ์ง€ ํ™•์ธํ•œ๋‹ค.** `watchAppProject(entitlements: .file(path: "UMCWatchApp.entitlements"))` ๋กœ
์ธ์ž๋ฅผ ๋„˜๊ฒจ์•ผ ์‹ค์ œ๋กœ ์ ์šฉ๋œ๋‹ค. ํŒŒ์ผ๋งŒ ๋งŒ๋“ค๊ณ  ์ธ์ž๋ฅผ ์•ˆ ๋„˜๊ธฐ๋ฉด ๋ฌดํšจ๋‹ค โ€” #1147 ์œ ์‹ค์ด ์ •ํ™•ํžˆ ์ด ํ˜•ํƒœ์˜€๋‹ค.
- **watchOS ๋Š” keychain ์„ ๊ณต์œ ํ•˜์ง€ ์•Š๋Š”๋‹ค.** Apple Watch ๋Š” ์ž์ฒด keychain ์„ ๊ฐ€์ง„ ๋ณ„๊ฐœ ๊ธฐ๊ธฐ๋ผ access
group ์„ ๋งž์ถฐ๋„ ์›Œ์น˜๊ฐ€ iPhone ์˜ ํ•ญ๋ชฉ์„ ์ฝ์ง€ ๋ชปํ•œ๋‹ค. access group ์€ ๋™์ผ ๊ธฐ๊ธฐ ๋‚ด ๋™์ผ ํŒ€ ์„œ๋ช… ํƒ€๊ฒŸ
(์•ฑยทํ™•์žฅ) ๊ฐ„ ๊ณต์œ  ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค. ์›Œ์น˜ ํ† ํฐ์€ WatchConnectivity ๋กœ iPhoneโ†’Watch ์ „์†ก ํ›„ ์›Œ์น˜ ์ž์ฒด
keychain ์— ์ €์žฅํ•˜๋Š” ๊ฒฝ๋กœ์ด๋ฉฐ #1210/#1211 ๋ฒ”์œ„๋‹ค. ๋˜ํ•œ `KeychainTokenStore` ๋Š”
`kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly`(109ํ–‰)๋ผ iCloud Keychain ๋™๊ธฐํ™” ๋Œ€์ƒ๋„ ์•„๋‹ˆ๋‹ค.
- **์„œ๋ช… ์ฃผ์˜**: ๋‘ App ID(`com.umc.product` ยท `com.umc.product.watchkitapp`)์— Keychain Sharing
capability ๊ฐ€ ์—†์œผ๋ฉด ์‹ค๊ธฐ๊ธฐ/์•„์นด์ด๋ธŒ ์„œ๋ช… ๋‹จ๊ณ„์—์„œ ์‹คํŒจํ•˜๊ณ , ๋Ÿฐํƒ€์ž„ ์ฆ์ƒ์€ `SecItemAdd` ์˜
`errSecMissingEntitlement(-34018)` ๋‹ค.

> **์œ ์‹ค ์ด๋ ฅ**: PR #627(`744ad80b`)์ด ๊ณต์œ  ๊ทธ๋ฃน(`$(AppIdentifierPrefix)dev.umc.shared`)์„ ์ถ”๊ฐ€ํ–ˆ์œผ๋‚˜,
> #1147(`a68f93c2`) ๋ฒˆ๋“ค ID ์ •๋ ฌ ์ปค๋ฐ‹์ด "๋ฏธ์‚ฌ์šฉ keychain-access-groups ์ œ๊ฑฐ" ์‚ฌ์œ ๋กœ iOSยทwatch ์–‘์ชฝ์—์„œ
> ๊ฑท์–ด๋ƒˆ๋‹ค(์›Œ์น˜ entitlements ๋Š” ํŒŒ์ผ์งธ ์‚ญ์ œ). ์ด๋ฏธ **๋‘ ๋ฒˆ ์œ ์‹ค๋œ** entitlement ๋‹ค โ€” "๋ฏธ์‚ฌ์šฉ"์œผ๋กœ ๋ณด์—ฌ๋„
> ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š”๋‹ค.
Loading