docs(commit-policy): 커밋 정책 스킬과 검증 절차를 정비한다

This commit is contained in:
Yu Sung
2026-02-25 14:58:12 +09:00
parent b796f6d9c5
commit aaffd08cb5
6 changed files with 299 additions and 17 deletions

174
AGENTS.md
View File

@@ -1,18 +1,160 @@
질문에 대한 답변과 설명은 한국어로 한다.
# AGENTS.md
`SodaLive` 저장소에서 작업하는 에이전트 실행 가이드다.
## Quality Assurance Guidelines
## 커뮤니케이션 규칙
- **"질문에 대한 답변과 설명은 한국어로 한다."**
- 사용자에게 전달하는 설명, 진행 상황, 결과 보고는 한국어로 작성한다.
- 코드 식별자, 파일 경로, 명령어는 원문(영문) 그대로 유지한다.
### Commit Standards
1. Write in Korean.
2. Use the present tense in the subject line (e.g., "Add feature" not "Added feature").
3. Keep the subject line to 50 characters or less.
4. Add a blank line between the subject and body.
5. Keep the body to 72 characters or less per line.
6. Within a paragraph, only break lines when the text exceeds 72 characters.
7. Describe changes to public API features and do not include implementation details such as package-private code.
8. Do not mention test code in commit messages.
9. Do not use any prefix (such as "fix:", "update:", "docs:", "feat:", etc.) in the subject line.
10. Do not start the subject line with a lowercase letter unless the first word is a function name or another identifier that is conventionally lowercase and there is a clear, justifiable reason for the exception. Otherwise, always start with an uppercase letter.
11. Do not include tool advertisements, branding, or promotional content in commit messages.
12. Use separate git commands to stage files before committing.
13. Always validate commits using `work/scripts/check-commit-message-rules.sh` and fix until validation passes.
## 저장소 범위
- 앱 소스: `SodaLive/Sources/**`
- 프로젝트/스킴: `SodaLive.xcodeproj`, `SodaLive.xcworkspace`
- 의존성 설정: `Podfile`, `Podfile.lock`
- 운영 스크립트: `work/scripts/**`
- 생성/외부 결과물: `Pods/**`, `generated/**`, `build/**`
- 작업 계획 문서: `docs/**`
### 수정 우선순위
- 기능 변경은 `SodaLive/Sources/**`에서 해결한다.
- 프로젝트 설정 변경은 필요한 경우에만 수행한다.
- `Pods/**`, `generated/**`는 직접 수정하지 않는다.
- `build/**`는 빌드 산출물로 간주하며 수정 대상이 아니다.
## 빌드/테스트/검증 명령
아래 명령은 현재 저장소에서 확인된 공식 진입점이다.
### 1) 의존성 설치
- `pod install`
- 근거: `Podfile`에 CocoaPods 타깃(`SodaLive`, `SodaLive-dev`) 정의.
### 2) 스킴/타깃 확인
- `xcodebuild -workspace "SodaLive.xcworkspace" -list`
- 근거: 공유 스킴 `SodaLive`, `SodaLive-dev` 존재.
### 3) 빌드
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build`
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`
### 4) 테스트(전체)
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test`
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test`
### 5) 단일 테스트 실행
- 일반 형식(테스트 타깃이 있는 경우):
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -only-testing:"SodaLiveTests/TestClass/testMethod" test`
- **현재 주의사항**:
- `SodaLive.xcodeproj/project.pbxproj` 기준으로 앱 타깃 중심 구성이고 테스트 번들 타깃이 확인되지 않는다.
- 따라서 현재 상태에서는 단일 테스트 지정이 실질적으로 동작하지 않을 수 있다.
### 6) 린트/포맷
- 저장소에 공식 `swiftlint`/`swiftformat` 실행 스크립트는 확인되지 않았다.
- `generated/*.generated.swift``swiftlint:disable all` 주석은 존재하나, 이는 생성 코드 보호 목적이다.
- 린트 도구를 도입/추가하면 본 문서 명령 섹션을 즉시 갱신한다.
## 코드 스타일 가이드
### 아키텍처/레이어
- 기본 흐름은 `View -> ViewModel -> Repository -> Api(TargetType)`를 따른다.
- API는 `enum ...Api: TargetType`, 저장소는 `final class ...Repository` 형태를 우선 사용한다.
- 상태 모델은 `struct`/`enum` 중심으로 두고, 화면 상태는 `ObservableObject`에서 관리한다.
### 임포트 규칙
- 시스템 프레임워크(`Foundation`, `SwiftUI`, `Combine`)를 먼저 배치한다.
- 서드파티(`Moya`, `CombineMoya`, SDK들)는 이후 배치한다.
- import 그룹 사이에는 한 줄 공백으로 의미 단위를 분리한다.
### 포맷/구조
- 들여쓰기는 4칸 스페이스를 사용한다.
- 프로퍼티 선언, 비즈니스 로직, 헬퍼 메서드는 공백 줄로 구획한다.
- 클로저 체인은 줄바꿈해 가독성을 유지한다.
### 타입/상태 관리
- ViewModel은 `final class ...: ObservableObject` 패턴을 우선한다.
- View가 소유하는 객체는 `@StateObject`, 외부 주입 객체는 `@ObservedObject`를 사용한다.
- 네트워크 반환은 `AnyPublisher<Response, MoyaError>` 패턴을 기본으로 따른다.
### 네이밍 규칙
- 타입명은 PascalCase (`HomeViewModel`, `UserRepository`, `UserApi`).
- 변수/함수는 camelCase (`errorMessage`, `getMemberInfo`).
- 역할을 이름에 반영한다 (`*View`, `*ViewModel`, `*Repository`, `*Api`, `*Request`, `*Response`).
### 비동기/Combine 규칙
- 비동기 처리는 Combine의 `sink`, `receiveValue`, `.store(in: &subscription)` 패턴을 따른다.
- `sink` 완료 블록에서 `.failure`를 반드시 처리한다.
- 클로저 캡처는 상황에 맞게 `[weak self]` 또는 `[unowned self]`를 선택한다.
### 에러 처리 규칙
- 사용자 노출 오류는 `errorMessage`와 팝업 플래그(`isShowPopup`)로 일관되게 처리한다.
- JSON 파싱은 `do/catch + JSONDecoder` 패턴을 따른다.
- **신규 코드에서 빈 `catch`는 금지**하고, 최소한 로깅 또는 명시적 무시 사유를 남긴다.
### 로깅 규칙
- 디버그 로그는 `DEBUG_LOG`, 오류 로그는 `ERROR_LOG`를 사용한다.
- `print`는 임시 디버깅 목적 외 신규 코드에서 지양한다.
### 네트워크/헤더 규칙
- 공통 Moya 플러그인(`AuthPlugin`, `AcceptLanguagePlugin`) 흐름을 유지한다.
- 언어 헤더는 `LanguageHeaderProvider.current`를 기준으로 사용한다.
### 문자열/다국어
- 신규 사용자 노출 문자열은 가능하면 `I18n` 경로를 우선 사용한다.
- 다국어 기능 수정 시 `Settings/Language` 모듈과 `Accept-Language` 헤더 흐름을 함께 점검한다.
### 주석/문서화
- 자명한 코드에는 주석을 남기지 않는다.
- 복잡한 분기, 외부 제약, 부작용이 있는 로직에만 주석을 추가한다.
## Cursor/Copilot 규칙 반영
- 아래 파일 존재 여부를 확인해 AGENTS와 함께 유지한다.
- `.cursor/rules/**`
- `.cursorrules`
- `.github/copilot-instructions.md`
- 현재 저장소에서는 위 파일들이 확인되지 않았다.
- 추후 파일이 추가되면 AGENTS.md에 요약 규칙을 동기화한다.
- 충돌 우선순위 기본값:
- 범위가 더 구체적인 규칙이 우선한다(경로 특화 > 저장소 전역).
- Cursor: `.cursor/rules/**` > `.cursorrules` > `AGENTS.md`
- Copilot: `.github/instructions/**`(존재 시) > `.github/copilot-instructions.md` > `AGENTS.md`
## 커밋 메시지 규칙 (표준 Conventional Commits)
- 커밋 상세 가이드/절차는 `.opencode/skills/commit-policy/SKILL.md`를 단일 기준으로 사용한다.
- 커밋 작업 시작 시 `skill` 도구로 `commit-policy`를 먼저 로드한다.
- 기본 형식은 `<type>(scope): <description>`를 사용한다.
- `type`은 소문자(`feat`, `fix`, `chore`, `docs`, `refactor`, `test`)를 사용한다.
- 제목(description)은 한글로 작성하고, 명령형/간결한 현재형으로 작성한다.
- 이슈 참조 footer는 `Refs: #123` 또는 `Refs: #123, #456` 형식을 사용한다.
### 커밋 메시지 검증 절차
- `git commit` 직후 `work/scripts/check-commit-message-rules.sh`를 실행해 규칙 준수 여부를 확인한다.
- 스크립트 결과가 `[FAIL]`이면 커밋 메시지를 수정한 뒤 다시 검증한다.
## 작업 절차 체크리스트
- 변경 전: 유사 기능 코드를 먼저 찾아 네이밍/예외/응답 패턴을 맞춘다.
- 변경 중: 공개 API 스키마를 임의 변경하지 말고 작은 단위로 안전하게 수정한다.
- 변경 후: 영향 범위 파일에 대해 빌드/테스트/로그/다국어 키를 점검한다.
- 커밋 직후: `commit-policy` 스킬을 로드하고 메시지 검증 스크립트를 실행한다.
## 작업 계획 문서 규칙 (docs)
- 모든 작업 시작 전에 `docs` 폴더 아래 계획 문서를 먼저 생성하고, 해당 문서를 기준으로 구현한다.
- 계획 문서 파일명은 `[날짜]_구현할내용한글.md` 형식을 사용한다.
- 날짜는 `YYYYMMDD` 8자리 숫자를 사용한다.
- 구현 항목은 기능/작업 단위 체크박스(`- [ ]`)로 작성하고 완료 즉시 `- [x]`로 갱신한다.
- 작업 도중 범위가 변경되면 계획 문서 체크리스트를 먼저 업데이트한 뒤 구현한다.
- 결과 보고 시 문서 하단에 검증 기록(무엇/왜/어떻게, 실행 명령, 결과)을 한국어로 남긴다.
- 후속 수정이 발생해도 기존 검증 기록은 삭제/덮어쓰기 없이 누적한다.
## 문서 유지보수 규칙
- 불확실한 규칙은 추측으로 채우지 말고 근거 파일 경로를 먼저 확인한다.
- 에이전트 안내 문구는 한국어 중심으로 유지한다.
- 명령/경로/타깃명이 바뀌면 본 문서를 즉시 업데이트한다.
## 에이전트 동작 원칙
- 추측하지 말고 근거 파일을 읽고 결정한다.
- 기존 관례를 깨는 변경은 이유가 명확할 때만 수행한다.
- 불필요한 리팩터링 확장은 피하고 요청 범위를 우선 충족한다.
- 결과 보고 시 무엇을, 왜, 어떻게 검증했는지 한국어로 간단히 남긴다.
## 설정/보안 유의사항
- 토큰/키/개인정보를 코드/로그/문서에 하드코딩하지 않는다.
- 인증 관련 헤더/토큰 처리 로직(`AuthPlugin`, `UserDefaultsKey.token`) 수정 시 회귀 위험을 함께 점검한다.
- 외부 SDK 키 변경 시 빌드 설정과 런타임 초기화 지점을 함께 검토한다.