بنقرة واحدة
feature-implementer
테크스펙 문서를 기반으로 새로운 피처를 구현하는 전체 파이프라인을 자동화합니다. 구현 → 테스트 → 수정 → 커밋까지 자동으로 수행합니다.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
테크스펙 문서를 기반으로 새로운 피처를 구현하는 전체 파이프라인을 자동화합니다. 구현 → 테스트 → 수정 → 커밋까지 자동으로 수행합니다.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
가슴속 3천원 서버 OpenAPI 스키마를 조회/확인합니다. 서버 응답·요청 모델 구조가 궁금할 때, 특정 API의 필드(예: storeType 유무)를 확인할 때, 업데이트된 스키마가 있는지 확인할 때 사용합니다. dev OpenAPI 문서(https://dev.threedollars.co.kr/api/v3/api-docs)를 받아 필요한 스키마만 추출해 답합니다.
iOS Repository 패턴 정의. Protocol + Impl 구조 및 API enum + RequestType 확장 패턴으로 네트워크 레이어를 구현합니다. async/await와 Result 타입을 사용하며, 다른 iOS 프로젝트에서도 재사용 가능합니다.
iOS MVVM 패턴의 ViewModel 구조 정의. Input/Output/Route/Config/Dependency/State 패턴으로 ViewModel을 생성합니다. Combine 기반으로 작동하며, 다른 iOS 프로젝트에서도 재사용 가능합니다.
iOS ViewModel 유저 플로우 기반 테스트 코드 자동 생성. Given-When-Then 패턴으로 Input/Output 검증 테스트를 생성합니다. XCTest와 Combine을 사용하며, 다른 iOS 프로젝트에서도 재사용 가능합니다.
| name | feature-implementer |
| description | 테크스펙 문서를 기반으로 새로운 피처를 구현하는 전체 파이프라인을 자동화합니다. 구현 → 테스트 → 수정 → 커밋까지 자동으로 수행합니다. |
테크스펙 문서를 기반으로 새로운 피처를 자동으로 구현하고 테스트합니다.
다음 형태 중 하나로 테크스펙을 제공할 수 있습니다:
/path/to/TH-XXX.md)/path/to/spec.txt)인자 없이 호출 시 대화형으로 테크스펙을 입력받습니다.
입력받은 테크스펙 확인:
피그마 URL이 제공된 경우 연결 확인:
gh auth status
GitHub 인증 확인:
gh pr list --limit 1
저장소 권한 확인:
제공된 테크스펙에서 다음 정보 추출:
정보가 부족한 경우 AskUserQuestion으로 추가 정보 요청
피그마 URL이 제공된 경우:
get_design_context 도구로 디자인 정보 가져오기노션 테크스펙에서 언급된 기존 피처나 유사 기능이 있다면:
# 예: "기여자 목록 화면과 유사하게 구현"
사용자에게 플랜 모드 진입 승인 요청
Task tool로 Explore agent 실행하여 유사 패턴 탐색:
유사 ViewModel 찾기
유사 Repository 찾기
SDU 모듈 사용 여부 확인
UI 패턴 확인
참고 파일 읽기:
구현해야 할 파일 목록 작성:
Model 추가 (있다면)
Modules/Core/Model/Sources/Domain/Response/API 추가
Modules/Core/Network/Sources/API/{Domain}Api.swiftRepository 추가
Modules/Core/Network/Sources/Repository/{Domain}Repository.swiftViewModel 생성
Modules/Feature/{Feature}/Targets/{Feature}/Sources/Domains/{Screen}/ViewController 생성
Modules/Feature/{Feature}/Targets/{Feature}/Sources/Domains/{Screen}/테스트 코드 생성 (Phase 2 추가)
App/Targets/three-dollar-in-my-pocketTests/ViewModelTests/플랜 파일에 다음 내용을 체계적으로 작성:
# Implementation Plan: {피처 이름}
## Feature Overview
### 테크스펙
- 티켓 번호: {JIRA 티켓 번호} (있는 경우)
- 피처명: {이름}
- 요구사항: {요약}
### 피그마 디자인 (if applicable)
- URL: {피그마 URL}
- 화면 구성: {요약}
## Technical Specification
### API Endpoints
- **GET** `/api/v1/{path}`: {설명}
- Request: {구조}
- Response: {구조}
### Data Models
- `{Model이름}Response`: {설명}
- 필드 1: {타입} - {설명}
- 필드 2: {타입} - {설명}
### UI Components
- {컴포넌트 1}: {설명}
- {컴포넌트 2}: {설명}
## Implementation Plan
### 1. Model 추가
**파일**: `Modules/Core/Model/Sources/Domain/Response/{Model이름}Response.swift`
```swift
public struct {Model이름}Response: Decodable {
public let field1: String
public let field2: Int
}
파일: Modules/Core/Network/Sources/API/{Domain}Api.swift
// API enum에 추가
case fetch{Feature}(input: Fetch{Feature}Input)
// RequestType 확장
var param: Encodable? {
case .fetch{Feature}(let input):
return input
}
var method: RequestMethod {
case .fetch{Feature}:
return .get
}
var header: HTTPHeaderType {
case .fetch{Feature}:
return .json
}
var path: String {
case .fetch{Feature}(let input):
return "/api/v1/{path}/\(input.id)"
}
파일: Modules/Core/Network/Sources/Repository/{Domain}Repository.swift
// Protocol에 추가
func fetch{Feature}(input: Fetch{Feature}Input) async -> Result<{Model}Response, Error>
// Impl에 추가
public func fetch{Feature}(input: Fetch{Feature}Input) async -> Result<{Model}Response, Error> {
let request = {Domain}Api.fetch{Feature}(input: input)
return await NetworkManager.shared.request(requestType: request)
}
파일: Modules/Feature/{Feature}/Targets/{Feature}/Sources/Domains/{Screen}/{Screen}ViewModel.swift
구조:
참고: ios-viewmodel-pattern skill
파일: Modules/Feature/{Feature}/Targets/{Feature}/Sources/Domains/{Screen}/{Screen}ViewController.swift
구조:
참고: CLAUDE.md의 ViewController 패턴
파일: App/Targets/three-dollar-in-my-pocketTests/ViewModelTests/{Screen}ViewModelTests.swift
테스트 케이스:
참고: ios-viewmodel-test-generator skill
서버에서 UI 데이터를 제공하는 경우:
참고: CLAUDE.md의 SDU 모듈 섹션
난이도: {낮음/중간/높음} - {이유}
#### ExitPlanMode 호출 ⚠️
**사용자에게 계획 승인 요청**
- 승인되면 구현 시작
- 거부되면 플랜 수정 또는 종료
---
### Step 4: 워크트리 설정 (자동 승인)
#### 브랜치 이름 결정
노션 테크스펙에서 JIRA 티켓 번호 추출 (예: TH-XXX) 또는 피처 이름 사용:
- JIRA 티켓이 있는 경우: `feature/TH-XXX-{간단한설명}`
- 없는 경우: `feature/{피처명}`
#### 워크트리 생성
```bash
# 저장소 루트 확인
git rev-parse --show-toplevel
# 워크트리 생성 (develop 브랜치 기반)
git worktree add -b feature/{브랜치명} ../worktree-{브랜치명} develop
# 워크트리로 이동
cd ../worktree-{브랜치명}
워크트리 디렉토리 경로: {저장소루트}/../worktree-{브랜치명}
이후 모든 작업은 워크트리 디렉토리에서 진행하므로 원본 저장소는 영향받지 않습니다.
플랜에 따라 구현 순서대로 todo 생성:
1. [pending] {Model이름}Response.swift 생성
2. [pending] {Domain}Api.swift에 API 추가
3. [pending] {Domain}Repository.swift에 메서드 추가
4. [pending] {Screen}ViewModel.swift 생성
5. [pending] {Screen}ViewController.swift 생성
6. [pending] {Screen}ViewModelTests.swift 생성
각 작업 시작 시 in_progress로 변경, 완료 시 completed로 변경
위치: Modules/Core/Model/Sources/Domain/Response/{Model이름}Response.swift
규칙:
참고: 기존 Response 파일들
위치: Modules/Core/Network/Sources/API/{Domain}Api.swift
규칙:
참고: ios-repository-pattern skill
위치: Modules/Core/Network/Sources/Repository/{Domain}Repository.swift
규칙:
참고: ios-repository-pattern skill
위치: Modules/Feature/{Feature}/Targets/{Feature}/Sources/Domains/{Screen}/{Screen}ViewModel.swift
규칙:
참고: ios-viewmodel-pattern skill
필수 import:
import Foundation
import Combine
import Common
import Log
import Model
import Networking
템플릿 활용:
위치: Modules/Feature/{Feature}/Targets/{Feature}/Sources/Domains/{Screen}/{Screen}ViewController.swift
규칙:
필수 import:
import UIKit
import Combine
import Common
import DesignSystem
import Model
import SnapKit
참고: CLAUDE.md의 ViewController 패턴, ContributorsViewController
UI 컴포넌트 생성 패턴:
private let label: UILabel = {
let label = UILabel()
label.text = "텍스트"
label.font = Fonts.semiBold.font(size: 16)
label.textColor = Colors.gray100
return label
}()
SDU 사용 시:
private let sduView = SDUCollectionView()
private lazy var dataSource = SDUDataSource(collectionView: sduView.collectionView)
// Layout 설정
sduView.setLayout(createLayout())
// 데이터 바인딩
viewModel.output.items
.receive(on: DispatchQueue.main)
.sink { [weak self] items in
self?.dataSource.reload(items)
}
.store(in: &cancellables)
위치: App/Targets/three-dollar-in-my-pocketTests/ViewModelTests/{Screen}ViewModelTests.swift
규칙:
참고: ios-viewmodel-test-generator skill
필수 import:
import XCTest
import Combine
@testable import three_dollar_in_my_pocket
템플릿 활용:
기본 테스트 케이스:
test_사용자가로드버튼을탭하면_데이터가로드된다() - 기본 데이터 로드test_네트워크에러시_에러메시지가전달된다() - 에러 처리test_닫기버튼탭시_dismiss라우팅이발생한다() - 화면 전환추가 테스트 케이스 (필요시):
테스트 파일 하단에 Mock 클래스 생성:
// MARK: - Mock Repository
final class Mock{Domain}Repository: {Domain}Repository {
var fetch{Feature}Result: Result<{Model}Response, Error>?
var lastRequestInput: Fetch{Feature}Input?
func fetch{Feature}(input: Fetch{Feature}Input) async -> Result<{Model}Response, Error> {
lastRequestInput = input
guard let result = fetch{Feature}Result else {
return .failure(NSError(domain: "Mock", code: -1))
}
return result
}
// 다른 메서드들은 기본 구현 제공
// ...
}
// MARK: - Mock LogManager
final class MockLogManager: LogManagerProtocol {
func sendPageView(screen: ScreenName, type: AnyClass) { }
func sendEvent(_ event: LogEvent) { }
}
Skill tool로 code-cleanup 호출하여 수정한 파일들의:
# code-cleanup이 실행하는 명령어들
swiftlint --fix
swiftlint lint
수정된 파일만 정리하고, 다른 파일은 건드리지 않습니다.
워크트리 디렉토리에서 실행:
make project
프로젝트 생성이 완료될 때까지 대기합니다.
xcodebuild build \
-workspace 3dollar-in-my-pocket.xcworkspace \
-scheme three-dollar-in-my-pocket-debug \
-configuration Debug \
-destination 'platform=iOS Simulator,name=iPhone 15 Pro'
빌드 결과 확인:
빌드 성공 후:
xcodebuild test \
-workspace 3dollar-in-my-pocket.xcworkspace \
-scheme three-dollar-in-my-pocket-debug \
-destination 'platform=iOS Simulator,name=iPhone 15 Pro'
테스트 결과 확인:
swiftlint lint
SwiftLint 결과 확인:
빌드 실패, 테스트 실패, SwiftLint 오류 발생 시 자동으로 수정을 시도합니다.
최대 5회 시도: 5회 이내에 해결되지 않으면 사용자에게 수동 개입 요청
에러 분석:
xcodebuild build ... 2>&1 | grep -A 5 "error:"
에러 메시지에서 다음 정보 추출:
일반적인 컴파일 에러 패턴:
Import 누락
Cannot find type 'XXX' in scope → import 추가타입 불일치
Cannot convert value of type 'X' to expected type 'Y' → 타입 캐스팅 수정메서드 미정의
Value of type 'X' has no member 'Y' → 메서드명 확인접근 제어자 문제
'X' is inaccessible due to 'internal' protection level → public 추가자동 수정:
테스트 실패 분석:
xcodebuild test ... 2>&1 | grep -A 10 "Test Case.*failed"
실패한 테스트에서 다음 정보 추출:
일반적인 테스트 실패 패턴:
Mock 데이터 불일치
비동기 처리 누락
await Task.yield() 누락 → 추가구독 누락
Mock Repository 메서드 미구현
자동 수정:
SwiftLint 오류 분석:
swiftlint lint 2>&1 | grep -E "(error|warning):"
자동 수정 가능한 오류:
swiftlint --fix
수동 수정이 필요한 오류:
line_length (라인 길이 초과)
function_body_length (메서드 길이 초과)
type_body_length (타입 길이 초과)
identifier_name (네이밍 규칙 위반)
자동 수정:
수정 시도 1 → 빌드/테스트/SwiftLint
↓ 실패
수정 시도 2 → 빌드/테스트/SwiftLint
↓ 실패
수정 시도 3 → 빌드/테스트/SwiftLint
↓ 실패
수정 시도 4 → 빌드/테스트/SwiftLint
↓ 실패
수정 시도 5 → 빌드/테스트/SwiftLint
↓ 실패
❌ 수동 개입 요청 (사용자에게 에러 내용 전달)
성공 시: Step 10 (커밋) 진행
구현 흐름에 따라 논리적으로 분리:
Model 추가 (있다면)
git add Modules/Core/Model/Sources/Domain/Response/{Model이름}Response.swift
git commit -m "{티켓번호} : {Model이름}Response 모델 추가
- {필드 설명}
- {필드 설명}
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
API 정의
git add Modules/Core/Network/Sources/API/{Domain}Api.swift
git commit -m "{티켓번호} : {Domain}Api에 fetch{Feature} API 추가
- GET /api/v1/{path}
- {설명}
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
Repository 구현
git add Modules/Core/Network/Sources/Repository/{Domain}Repository.swift
git commit -m "{티켓번호} : {Domain}Repository에 fetch{Feature} 메서드 추가
- Protocol 시그니처 추가
- Impl 구현 추가
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
ViewModel 생성
git add Modules/Feature/{Feature}/Targets/{Feature}/Sources/Domains/{Screen}/{Screen}ViewModel.swift
git commit -m "{티켓번호} : {Screen}ViewModel 생성
- Input/Output/Route/Config/Dependency/State 구조
- {주요 로직 설명}
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
테스트 코드 생성
git add App/Targets/three-dollar-in-my-pocketTests/ViewModelTests/{Screen}ViewModelTests.swift
git commit -m "{티켓번호} : {Screen}ViewModelTests 생성
- Given-When-Then 패턴 테스트
- Mock Repository 구현
- {테스트 케이스 개수}개 테스트 케이스
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
ViewController 생성
git add Modules/Feature/{Feature}/Targets/{Feature}/Sources/Domains/{Screen}/{Screen}ViewController.swift
git commit -m "{티켓번호} : {Screen}ViewController 생성
- BaseViewController 상속
- SnapKit 레이아웃
- ViewModel 바인딩
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
git commit -m "$(cat <<'EOF'
{티켓번호} : {한 줄 요약}
- 상세 설명 1
- 상세 설명 2
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
EOF
)"
모든 커밋 완료 후 한번에 push:
git push -u origin feature/{브랜치명}
중요: PR 생성은 사용자가 직접 수행합니다.
이유:
cd {원본저장소경로}
# 워크트리 제거
git worktree remove ../worktree-{브랜치명}
# 디렉토리가 남아있다면 강제 제거
git worktree remove --force ../worktree-{브랜치명} 2>/dev/null || true
rm -rf ../worktree-{브랜치명} 2>/dev/null || true
✅ {피처 이름} 구현 완료!
📋 생성된 파일: {개수}개
- {Model파일} (있다면)
- {API파일} (업데이트)
- {Repository파일} (업데이트)
- {ViewModel파일}
- {ViewController파일}
- {Tests파일}
🧪 테스트: {개수}개 테스트 케이스 통과
- {테스트 케이스 1}
- {테스트 케이스 2}
- {테스트 케이스 3}
🔧 커밋: {개수}개 (논리적 흐름으로 분리)
- {커밋1 요약}
- {커밋2 요약}
- ...
🚀 브랜치: feature/{브랜치명}
→ Push 완료: origin/feature/{브랜치명}
📌 다음 단계:
1. PR 생성 (수동):
gh pr create --base develop --title "{티켓번호} : {PR 제목}" --body "{PR 본문}"
2. PR 본문 예시:
## 구현 내용
{피처 설명}
## 주요 변경사항
- {변경사항 1}
- {변경사항 2}
## 테스트
- {테스트 항목 1}
- {테스트 항목 2}
🤖 Generated with [Claude Code](https://claude.com/claude-code)
3. PR 리뷰 요청
4. 테스트 진행
5. 머지 후 배포
✅ code-cleanup 실행 완료 ✅ 빌드 성공 (three-dollar-in-my-pocket-debug) ✅ 테스트 통과 (모든 ViewModel 테스트) ✅ SwiftLint 검증 통과 ✅ Git 커밋 완료 (4-6개 커밋) ✅ Push 완료 ✅ 워크트리 정리 완료
다음 작업들은 사용자 확인 없이 자동으로 진행됩니다:
다음 단계에서만 사용자 승인이 필요합니다:
참고: PR 생성은 자동화하지 않고 사용자가 직접 수행합니다.
/feature-implementer /path/to/TH-XXX-spec.md
/feature-implementer /path/to/spec.md https://figma.com/design/...
/feature-implementer
→ 사용자에게 테크스펙 텍스트 또는 파일 경로 입력 요청 → (선택) 피그마 디자인 URL 입력 요청 (선택사항)
ContributorsViewModel.swift: ViewModel 예시ContributorsViewController.swift: ViewController 예시StoreRepository.swift: Repository 예시StoreApi.swift: API 예시