9.3 KiB
9.3 KiB
AGENTS.md
SodaLive 저장소에서 작업하는 에이전트 실행 가이드다.
커뮤니케이션 규칙
- "질문에 대한 답변과 설명은 한국어로 한다."
- 이 저장소에서 사용자에게 전달하는 설명, 진행 상황, 결과 보고는 한국어로 작성한다.
- 코드 식별자, 경로, 명령어는 원문(영문) 그대로 유지한다.
저장소 범위
- Android Gradle 프로젝트이며
settings.gradle기준 모듈은:app단일 구성이다. - 모든 명령은 저장소 루트에서 실행한다.
- 추측하지 말고 근거 파일(
settings.gradle,build.gradle,app/build.gradle, 소스 코드)을 읽고 결정한다. - 요청 범위를 우선 충족하고, 변경은 작고 안전하게 유지한다.
빌드 / 린트 / 테스트 명령
기본 실행 형태:
./gradlew <task>
빌드:
./gradlew clean
./gradlew :app:assembleDebug
./gradlew :app:assembleRelease
./gradlew :app:build
./gradlew :app:check
린트/포맷:
./gradlew :app:lint
./gradlew :app:lintDebug
./gradlew :app:lintRelease
./gradlew :app:ktlintCheck
./gradlew :app:ktlintFormat
테스트:
./gradlew :app:test
./gradlew :app:testDebugUnitTest
./gradlew :app:testReleaseUnitTest
./gradlew :app:connectedDebugAndroidTest
주의:
:app:connectedDebugAndroidTest는 기기/에뮬레이터 연결이 필요하다.app/build.gradle에lint { checkReleaseBuilds false }가 있어 릴리스 린트는:app:lintRelease를 명시 실행해야 한다.- 현재
app/src/androidTest에는 테스트 소스가 없으므로 계측 테스트 명령은 신규 테스트 추가 시 사용한다.
1) 단일 테스트 실행 (중요)
로컬 단위 테스트(app/src/test)는 --tests 필터를 사용한다.
클래스 단위:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.chat.talk.room.ChatRepositoryTest"
메서드 단위:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.chat.talk.room.ChatRepositoryTest.enterChatRoom inserts messages and returns response"
패턴 매칭 예시:
./gradlew :app:testDebugUnitTest --tests "*TimeUtilsTest*"
참고:
- Kotlin backtick 테스트명은 공백이 포함될 수 있으므로 전체 문자열을 인용한다.
- 메서드 매칭이 불안정하면 클래스 단위로 먼저 실행한다.
2) 계측 테스트 클래스/메서드 타깃 실행
Gradle 인자 방식:
./gradlew :app:connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=kr.co.vividnext.sodalive.SomeInstrumentedTest
./gradlew :app:connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=kr.co.vividnext.sodalive.SomeInstrumentedTest#someMethod
ADB 대안:
adb shell am instrument -w -e class kr.co.vividnext.sodalive.SomeInstrumentedTest#someMethod <test_package>/<runner>
코드 스타일 가이드
1) 포맷/기본 규칙
.editorconfig기준을 준수한다.- 인덴트: 공백 4칸, 줄바꿈: LF, 최대 라인 길이: 130.
- 파일 끝 개행 유지, trailing whitespace 제거.
- Kotlin/KTS에서
import-orderingktlint 규칙은 비활성화되어 있으므로 기존 파일 정렬 스타일을 우선 따른다.
2) import 규칙
- 신규 코드에서는 와일드카드 import(
*)를 기본적으로 지양한다. - 사용하지 않는 import를 남기지 않는다.
- import alias(
as)는 필요한 경우(이름 충돌 회피) 최소 범위로만 사용한다. - 기존 파일에 와일드카드/alias가 있으면 대규모 정렬 리팩터링 없이 주변 스타일에 맞춘다.
3) 네이밍/레이어
- UI:
*Activity,*Fragment, dialog/sheet suffix - 상태/도메인:
*ViewModel(주로BaseViewModel상속) - 데이터 계층:
*Repository, Retrofit*Api - DTO:
data class+*Request,*Responsesuffix - 레이어 흐름:
Api->Repository->ViewModel->Activity/Fragment - DI는
app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt의 Koin 구성을 따른다.
4) 타입/계약/에러 처리
- nullability와 제네릭 타입을 의미가 바뀌지 않게 유지한다.
- 공개 API/스키마/리소스 계약은 요청 없이 변경하지 않는다.
- 응답 처리 시 기존
ApiResponse<T>와 Rx 타입(Single,Flowable)을 우선 재사용한다. - 빈
catch블록을 새로 추가하지 않는다. - 예외를 조용히 삼키지 않고 로그/주석/대체 흐름 중 하나를 남긴다.
5) 테스트 관례
- 단위 테스트는
app/src/test에 위치하며 클래스명은*Test를 사용한다. - 기본 스택은 JUnit4 + MockK/Mockito다.
- 테스트 추가 시 단일 실행 명령 예시도 본 문서에 갱신한다.
커밋 메시지 규칙 (표준 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 스키마를 임의 변경하지 말고 작은 단위로 안전하게 수정한다.
- 변경 후: 최소 단일 테스트(
--tests) 또는./gradlew :app:test를 실행하고 필요 시./gradlew :app:ktlintCheck를 수행한다. - 커밋 전/후:
commit-policy스킬을 먼저 로드하고,git commit직전과 직후에work/scripts/check-commit-message-rules.sh를 실행해 커밋 메시지 규칙 준수 여부를 확인한다.
작업 계획 문서 규칙 (docs)
- 모든 작업 시작 전에
docs폴더 아래 계획 문서를 먼저 생성하고, 해당 문서를 기준으로 구현한다. - 계획 문서 파일명은
[날짜]_구현할내용한글.md형식을 사용한다. - 날짜는
YYYYMMDD8자리 숫자를 사용한다. - 구현 항목은 기능/작업 단위 체크박스(
- [ ])로 작성하고 완료 즉시- [x]로 갱신한다. - 작업 도중 범위가 변경되면 계획 문서 체크리스트를 먼저 업데이트한 뒤 구현한다.
- 결과 보고 시 문서 하단에 검증 기록(무엇/왜/어떻게, 실행 명령, 결과)을 한국어로 남긴다.
- 후속 수정이 발생해도 기존 검증 기록은 삭제/덮어쓰기 없이 누적한다.
Cursor/Copilot 규칙 반영 현황
- 확인 경로:
.cursor/rules/**,.cursorrules,.github/copilot-instructions.md - 현재 저장소에는 위 파일이 존재하지 않는다.
- 추후 규칙 파일이 추가되면 본 문서에 즉시 반영한다.
문서 유지보수 규칙
build.gradle/app/build.gradle/settings.gradle변경 시 실행 명령 섹션을 함께 갱신한다.- 테스트 클래스 추가/이동 시 단일 테스트 실행 예시를 최신 상태로 유지한다.
.editorconfig변경 시 포맷 규칙 섹션을 동기화한다.- 문서 변경 후 최소 한 번
./gradlew tasks --all로 명령 유효성을 확인한다. - 불확실한 규칙은 추측으로 채우지 말고 근거 파일 경로를 먼저 확인한다.
- 에이전트 안내 문구는 한국어 중심으로 유지한다.
에이전트 동작 원칙
- 추측하지 말고 근거 파일을 읽고 결정한다.
- 기존 관례를 깨는 변경은 이유가 명확할 때만 수행한다.
- 불필요한 리팩터링 확장은 피하고 요청 범위를 우선 충족한다.
- 결과 보고 시 무엇을, 왜, 어떻게 검증했는지 한국어로 간단히 남긴다.
설정/보안 유의사항
local.properties, 키스토어(*.jks,*.keystore,*.p12,*.pem,*.key)는 생성/수정 여부와 관계없이 커밋하지 않는다.app/src/debug/google-services.json,app/src/release/google-services.json은 민감 구성으로 취급하고 외부 공유/로그 출력 금지한다.app/build.gradle의buildConfigField값(토큰/앱키/시크릿 유사 값)은 신규 하드코딩을 추가하지 않는다.BuildConfig값(키/토큰/URL)을 로그, Toast, 크래시 메시지에 직접 노출하지 않는다.- 네트워크 로깅은
AppDI.kt패턴을 유지한다(디버그만 BODY, 릴리스는 NONE). - 서명/배포 설정(Crashlytics, Google Services, Proguard, signing)은 요청 없이 변경하지 않는다.
AndroidManifest.xml권한은 민감 영역이므로 신규 추가/확장은 사유와 영향도를 확인한 뒤 반영한다.applicationId,namespace, OAuth Client ID, 딥링크 호스트는 요청 없이 변경하지 않는다.- 문서/이슈/PR 본문에 비밀값을 남기지 말고 필요 시 마스킹(
***) 처리한다. - Git 작업은 비파괴 명령을 기본으로 사용하고, 강제 푸시/히스토리 재작성은 명시 요청이 있을 때만 수행한다.