145 lines
8.1 KiB
Markdown
145 lines
8.1 KiB
Markdown
# AGENTS.md
|
|
|
|
## 문서 목적
|
|
- 이 문서는 `/Users/klaus/Develop/sodalive/Server/sodalive` 저장소에서 작업하는 에이전트용 실행 가이드다.
|
|
- 목표는 "추측 최소화 + 기존 패턴 준수 + 검증 우선"이다.
|
|
- 이 문서의 규칙은 코드/테스트/문서 변경 모두에 적용한다.
|
|
|
|
## 커뮤니케이션 규칙
|
|
- **"질문에 대한 답변과 설명은 한국어로 한다."**
|
|
- 이 저장소에서 사용자에게 전달하는 설명, 진행 상황, 결과 보고는 한국어로 작성한다.
|
|
- 코드 식별자, 경로, 명령어는 원문(영문) 그대로 유지한다.
|
|
|
|
## 프로젝트 개요
|
|
- 빌드 도구: Gradle Wrapper (`./gradlew`)
|
|
- 언어/런타임: Kotlin + Java 17
|
|
- 프레임워크: Spring Boot 2.7.14
|
|
- 주요 플러그인: `org.jlleitschuh.gradle.ktlint`
|
|
- 단일 루트 프로젝트: `settings.gradle.kts`의 `rootProject.name = "sodalive"`
|
|
|
|
## 실행 명령어 (Build/Lint/Test)
|
|
아래 명령은 저장소 루트(`/Users/klaus/Develop/sodalive/Server/sodalive`)에서 실행한다.
|
|
|
|
```bash
|
|
./gradlew tasks --all
|
|
./gradlew bootRun
|
|
./gradlew build
|
|
./gradlew clean build
|
|
./gradlew test
|
|
./gradlew check
|
|
./gradlew ktlintCheck
|
|
./gradlew ktlintFormat
|
|
```
|
|
|
|
## 코드 스타일 규칙
|
|
|
|
### 1) 포맷/기본 규칙
|
|
- `.editorconfig` 기준을 준수한다.
|
|
- 인덴트: 공백 4칸.
|
|
- 줄바꿈: LF.
|
|
- 최대 라인 길이: 130.
|
|
- 파일 끝 개행 유지, trailing whitespace 제거.
|
|
|
|
### 2) import 규칙
|
|
- 와일드카드 import(`*`)를 사용하지 않는다.
|
|
- 사용하지 않는 import를 남기지 않는다.
|
|
- import alias(`as`)는 현재 코드베이스에서 사용 사례가 없으므로 지양한다.
|
|
- 기존 파일의 import 정렬/그룹 스타일을 그대로 맞춘다.
|
|
|
|
### 3) 네이밍 규칙
|
|
- 클래스/인터페이스/enum: PascalCase.
|
|
- 함수/변수/파라미터: camelCase.
|
|
- 상수: UPPER_SNAKE_CASE (`companion object` 내부 `const val`).
|
|
- Request/Response DTO는 `...Request`, `...Response` 접미사를 유지한다.
|
|
- 서비스/컨트롤러/리포지토리 명명은 역할 접미사(`Service`, `Controller`, `Repository`)를 유지한다.
|
|
|
|
### 4) 타입/널 처리
|
|
- Kotlin 타입 시스템을 활용하고 nullable(`?`)를 명시한다.
|
|
- 불필요한 `Any`/약한 타입을 피하고 구체 타입을 우선한다.
|
|
- 기존 코드에서 `!!` 사용이 많지만, 신규 코드는 가능한 안전 호출/가드절/명시적 예외로 대체를 우선 고려한다.
|
|
|
|
### 5) API/응답 규칙
|
|
- API 응답은 `ApiResponse.ok(...)`, `ApiResponse.error(...)` 패턴을 따른다.
|
|
- 컨트롤러는 도메인 예외를 직접 포맷하지 말고 `SodaException`을 던진다.
|
|
- 인증 사용자 필요 시 `@AuthenticationPrincipal(... ) member: Member?` 패턴 + null 가드절을 사용한다.
|
|
|
|
### 6) 예외 처리 규칙
|
|
- 비즈니스 예외는 `SodaException(messageKey = "...")` 우선 사용.
|
|
- 사용자 노출 문구는 하드코딩보다 `messageKey` 기반 i18n을 우선한다.
|
|
- 공통 예외 변환은 `SodaExceptionHandler`에서 수행하므로, 개별 컨트롤러에서 중복 처리하지 않는다.
|
|
- 예외를 삼키는 빈 `catch` 블록을 금지한다.
|
|
|
|
### 7) 트랜잭션 규칙
|
|
- 서비스 계층에서 `@Transactional`을 사용한다.
|
|
- 조회 위주 메서드는 `@Transactional(readOnly = true)`를 우선한다.
|
|
- 쓰기 로직은 메서드 단위 `@Transactional`로 경계를 명확히 한다.
|
|
|
|
### 8) 비동기/동시성 규칙
|
|
- 비동기 처리는 Kotlin Coroutines 패턴을 따른다.
|
|
- `CoroutineScope(Dispatchers.IO)` + `launch` + 예외 처리 패턴을 일관되게 유지한다.
|
|
- 생명주기 종료 시 scope 정리(`@PreDestroy`) 패턴을 참고한다.
|
|
|
|
### 9) 의존성 주입
|
|
- 생성자 주입(primary constructor + `private val`)을 기본으로 사용한다.
|
|
- 필드 주입보다 명시적 생성자 주입을 우선한다.
|
|
|
|
## 테스트 스타일 규칙
|
|
- 테스트 프레임워크: JUnit 5 (`useJUnitPlatform()`)
|
|
- 목킹: Mockito 사용 패턴 존재 (`Mockito.mock`, ``Mockito.`when`(...)``)
|
|
- 검증: `assertEquals`, `assertThrows` 패턴 준수.
|
|
- 테스트 이름은 의도가 드러나는 영어 문장형(`should...`)을 유지한다.
|
|
|
|
## 설정/보안 유의사항
|
|
- `application.yml`은 다수의 `${ENV_VAR}`를 사용한다.
|
|
- 비밀값(API Key, Secret, Token, DB 비밀번호)을 코드/문서/로그에 평문으로 남기지 않는다.
|
|
- 환경변수/시크릿 파일은 커밋 대상에서 제외한다.
|
|
|
|
## Cursor/Copilot 규칙 반영
|
|
`/.cursorrules`, `/.cursor/rules/`, `/.github/copilot-instructions.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`를 실행해 규칙 준수 여부를 확인한다.
|
|
- `git commit` 실행 직후에도 `work/scripts/check-commit-message-rules.sh`를 다시 실행해 최종 메시지를 재검증한다.
|
|
- 스크립트 결과가 `[FAIL]`이면 커밋 메시지를 규칙에 맞게 수정한 뒤 다시 검증한다.
|
|
|
|
## 작업 절차 체크리스트
|
|
- 변경 전: 유사 기능 코드를 먼저 찾아 네이밍/예외/응답 패턴을 맞춘다.
|
|
- 변경 중: 공개 API 스키마를 임의 변경하지 말고, 작은 단위로 안전하게 수정한다.
|
|
- 변경 후: 최소 단일 테스트 또는 `./gradlew test`를 실행하고, 필요 시 `./gradlew ktlintCheck`를 수행한다.
|
|
- 커밋 전/후: `commit-policy` 스킬을 먼저 로드하고, `git commit` 직전과 직후에 `work/scripts/check-commit-message-rules.sh`를 실행해 커밋 메시지 규칙 준수 여부를 확인한다.
|
|
|
|
## 작업 계획 문서 규칙 (docs)
|
|
- 모든 작업 시작 전에 `docs` 폴더 아래에 계획 문서를 먼저 생성하고, 해당 문서를 기준으로 구현을 진행한다.
|
|
- 계획 문서 파일명은 `[날짜]_구현할내용한글.md` 형식을 사용한다.
|
|
- 날짜는 `YYYYMMDD` 8자리 숫자를 사용한다.
|
|
- 파일명 예시: `20260101_구글계정으로로그인.md`
|
|
- 구현 항목은 기능/작업 단위로 분리해 체크박스(`- [ ]`) 목록으로 작성한다.
|
|
- 구현 완료 시마다 체크박스를 `- [x]`로 갱신하고, 각 항목이 정상 구현되었는지 확인한다.
|
|
- 작업 도중 범위가 변경되면 계획 문서의 체크박스 항목을 먼저 업데이트한 뒤 구현을 진행한다.
|
|
- 모든 구현이 끝난 후 결과 보고 시 계획 문서 맨 아래에 무엇을, 왜, 어떻게 검증했는지 한국어로 간단히 기록한다.
|
|
|
|
## 문서 유지보수 규칙
|
|
- `build.gradle.kts` 변경 시 실행 명령 섹션을 함께 갱신한다.
|
|
- 테스트 클래스 추가/이동 시 단일 테스트 실행 예시를 최신 상태로 유지한다.
|
|
- `.editorconfig` 변경 시 포맷 규칙 섹션을 동기화한다.
|
|
- Cursor/Copilot 규칙 파일이 생기면 해당 내용을 이 문서에 반영한다.
|
|
- 문서 변경 후 최소 한 번 `./gradlew tasks --all`로 명령 유효성을 확인한다.
|
|
- 불확실한 규칙은 추측으로 채우지 말고 근거 파일 경로를 먼저 확인한다.
|
|
- 에이전트 안내 문구는 한국어 중심으로 유지한다.
|
|
- 커밋 규칙 예시는 팀 컨벤션 변경 시 즉시 업데이트한다.
|
|
|
|
## 에이전트 동작 원칙
|
|
- 추측하지 말고, 근거 파일을 읽고 결정한다.
|
|
- 기존 관례를 깨는 변경은 이유가 명확할 때만 수행한다.
|
|
- 불필요한 리팩터링 확장은 피하고 요청 범위를 우선 충족한다.
|
|
- 결과 보고 시 무엇을, 왜, 어떻게 검증했는지 한국어로 간단히 남긴다.
|