Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
9135dbe
docs(global): AGENTS.md를 SOT로 재구성하고 CLAUDE.md import 방식 적용
ZaMan0806 May 13, 2026
75a197b
fix(global): 존재하지 않는 .geminiignore 언급 제거
ZaMan0806 May 13, 2026
8caf9b1
fix(global): AGENTS.md와 중복되는 한국어 응답 지시 제거
ZaMan0806 May 13, 2026
266070c
fix(global): 자동 로드 확인 지시를 검증 가능한 행동 지시로 변경
ZaMan0806 May 13, 2026
4c716a8
fix(global): ktlintFormat을 commit 스킬이 자동 실행하는 것처럼 쓴 부분 정정
ZaMan0806 May 13, 2026
8a067f9
fix(global): 스킬 자동 트리거와 중복되는 우선 호출 지시 제거
ZaMan0806 May 13, 2026
85bb227
fix(global): CommonApiResponse 사용 설명을 실제 동작에 맞게 정정
ZaMan0806 May 13, 2026
93c88c1
refactor(global): 모듈 설명 라인을 가독성 위해 줄바꿈
ZaMan0806 May 13, 2026
e5eeef1
fix(global): API 응답 자동 래핑 동작을 정확히 반영 (the-sdk ResponseBodyAdvice)
ZaMan0806 May 13, 2026
c08dfa4
fix(global): CONTRIBUTING.md Kotlin 버전을 실제 빌드 설정(2.3.10)에 맞춤
ZaMan0806 May 13, 2026
cc24200
refactor(global): 테스트·주석 컨벤션을 .claude/rules/로 이관
ZaMan0806 May 17, 2026
9a32871
fix(global): 모델이 이미 아는 일반 컨벤션 요약 제거
ZaMan0806 May 17, 2026
66986d1
fix(global): Commands 섹션 축약 (Build/Test/Format 제거)
ZaMan0806 May 17, 2026
f7eb910
fix(global): CLAUDE.md ktlintFormat 지시 제거
ZaMan0806 May 17, 2026
bc81e19
fix(global): rules 자동 주입과 중복되는 직접 읽기 지시 제거
ZaMan0806 May 17, 2026
6c12801
refactor(global): AGENTS.md 본문을 영어로 재작성
ZaMan0806 May 17, 2026
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
25 changes: 25 additions & 0 deletions .claude/rules/comments.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pr 코멘트 달때 규칙인가요?

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Comment Rules

Write comments only when the logic is not self-evident. Do NOT add excessive comments.

## When to write

- Non-obvious business rules or domain constraints
- Workarounds for specific bugs or framework quirks
- Hidden invariants that a future reader could not infer from the code

## When NOT to write

- Restating what well-named identifiers already convey
- Narrating step-by-step what the code does
- Marking referenced tickets, callers, or the current task (those belong in the commit/PR description)

```kotlin
// WRONG — restates the obvious
// Find student by id
val student = studentRepository.findById(id).orElseThrow { ... }

// CORRECT — surfaces a non-obvious constraint
// NEIS API returns 0 instead of null for "no allergy", so treat 0 as absent.
val allergy = response.allergyCode.takeIf { it != 0 }
```
35 changes: 35 additions & 0 deletions .claude/rules/testing.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kotest-guide 같은 스킬이 존재하는데 충돌하는 것 같습니다. 테스트 컨벤션을 rule로 정의한다면 차라리 path 프론트매터를 추가하는게 좋을 것 같습니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Testing Rules

## Framework

Use **Kotest `DescribeSpec` + MockK + JUnit 5** with the **Given-When-Then** structure.

## Naming

Test names are written in Korean. Use `describe("클래스명 클래스의")` for the top-level scope.

```kotlin
class StudentServiceImplTest : DescribeSpec({
describe("StudentServiceImpl 클래스의") {
context("execute 메서드를 호출할 때") {
it("학생을 조회한다") {
// Given
val id = 1L
every { studentRepository.findById(id) } returns Optional.of(student)

// When
val result = service.execute(id)

// Then
result.id shouldBe id
}
}
}
})
```

## Structure

- **Given**: prepare data, configure mocks (`every { } returns ...`)
- **When**: invoke the system under test
- **Then**: assert results (`shouldBe`, `shouldThrow<T>`, `verify { }`)
110 changes: 34 additions & 76 deletions AGENTS.md
Comment thread
snowykte0426 marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -2,99 +2,57 @@

## Project Overview

DataGSM is a Spring Boot REST API service providing school information (students, clubs, meals, schedules) for Gwangju Software Meister High School. The system uses Google OAuth2 authentication with JWT token and API key management.
DataGSM is a Spring Boot REST API server that exposes Gwangju Software Meister High School data (students, clubs, meals, timetable, etc.). It provides Google OAuth2 (JWT) authentication for internal clients and API-Key authentication for external public APIs.

## Tech Stack

- **Backend**: Kotlin, Spring Boot 4.0, Spring Security, Spring Data JPA
- **Database**: MySQL (main data), Redis (caching, sessions)
- **Query & Integration**: QueryDSL for complex queries, OpenFeign for external APIs
- **Serialization**: Jackson 3.0 for JSON processing
- **Testing**: Kotest + MockK + JUnit 5 (Given-When-Then style)
- **Language / Framework**: Kotlin 2.3.10, Spring Boot 4.0.3, Spring Security, Spring Data JPA
Comment thread
ZaMan0806 marked this conversation as resolved.
- **Build**: Gradle (Java 25 toolchain), multi-module
- **Database**: MySQL (main), Redis (cache, session)
- **Query / Integration**: QueryDSL, OpenFeign
- **Serialization**: Jackson 3.0
- **Testing**: Kotest (`DescribeSpec`) + MockK + JUnit 5

## Project Structure (Multi-module)
## Project Structure

```
datagsm-server/
├── datagsm-common/ # Shared library (Entity, DTO, Repository, Config, Health API)
├── datagsm-common/ # Shared Entity/DTO/Repository/Config, Health API (library module)
├── datagsm-oauth-authorization/ # OAuth2 authentication, account lifecycle (signup, password reset)
├── datagsm-oauth-userinfo/ # OAuth2 UserInfo endpoint (external clients)
├── datagsm-openapi/ # Public read-only API (students, clubs, NEIS)
└── datagsm-web/ # Web service API (user features, admin features, Excel)
├── datagsm-oauth-userinfo/ # OAuth2 UserInfo endpoint (for external clients)
├── datagsm-openapi/ # External public API (API-Key auth)
│ # Domains: student, club, project, webhook, neis
└── datagsm-web/ # Web service API (includes Excel processing)
# Domains: account, auth, application, client, student, club, project, utility
```

Each module follows: `controller/`, `service/`, `repository/`, `entity/`, `dto/`
Each module follows the `controller/service/repository/` layering with `entity/` and `dto/` packages per domain.

**Note**: `/v1/health` endpoint is provided by `HealthController` in `datagsm-common/global/controller/` and is shared across all modules.
**Key Paths**

## Commands
- The `/v1/health` endpoint is served by `HealthController` in `datagsm-common` and is shared across all runnable modules.
- Shared entities: `datagsm-common/src/main/kotlin/team/themoment/datagsm/common/domain/`
- Global exception handling: `datagsm-common/src/main/kotlin/team/themoment/datagsm/common/global/common/error/`
- API response: controllers return DTOs directly — `the-sdk`'s `ResponseBodyAdvice` automatically wraps them in `CommonApiResponse`. Use `CommonApiResponse<Nothing>` explicitly only when no data is returned (e.g. delete operations). Exception responses are wrapped by `GlobalExceptionHandler`.

- Build: `./gradlew build`
- Test: `./gradlew test`
- Format: `./gradlew ktlintFormat`
- Run: `./gradlew :<module>:bootRun`
## Runnable Modules

## Coding Conventions
Modules launched via `./gradlew :<module>:bootRun`: `datagsm-oauth-authorization`, `datagsm-oauth-userinfo`, `datagsm-openapi`, `datagsm-web`. (`datagsm-common` is a library module and is not run directly.)

Comment thread
snowykte0426 marked this conversation as resolved.
Comment on lines +38 to 41

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gradle 사용법을 재차 알려줄 필요는 없을 것 같습니다

### Kotlin Style
## Detailed Rules (`.claude/rules/`)

- Prefer `val` over `var`. Use `var` only when reassignment is strictly required.
- Always use constructor injection — never `@Autowired` field injection.
- Use Kotlin null-safety features (`?.`, `?:`) instead of `!!`.
- Do NOT add excessive comments — only where logic is not self-evident.
The following rule files are auto-loaded when working on related code:

### DTO Annotations

- Jackson: always use `@field:` target — never `@param:` (e.g., `@field:JsonProperty("user_name")`)
- Swagger/OpenAPI:
- Request DTOs (`*ReqDto`): use `@param:Schema`
- Response DTOs (`*ResDto`): use `@field:Schema`

### API Conventions

- 1–2 query params: use `@RequestParam`; 3+ or with validation: use `@ModelAttribute` + DTO
- `@RequestBody` variable: `reqDto`; `@ModelAttribute` query: `queryReq`
- `@Transactional` must be at **method level only** — never class level
- Read operations: `@Transactional(readOnly = true)` / Write operations: `@Transactional`
- Use `CommonApiResponse` wrapper for all API responses

### Logging

- English only — verb-led sentences
- SLF4J `{}` placeholder only — no Kotlin string interpolation, no colon separators
- Correct: `logger().info("Deleted {} expired API keys", deletedCount)`
- Wrong: `logger().error("에러 발생: $message")` or `logger().error("Failed: {}", msg)`

### Exception Handling

- Use `ExpectedException` directly — do NOT subclass it
- Message: Korean (합쇼체) + period, no dynamic data (IDs, names, variables)
- Correct: `ExpectedException("학생을 찾을 수 없습니다.", HttpStatus.NOT_FOUND)`
- Wrong: `ExpectedException("학생 ID: $id 없음", HttpStatus.NOT_FOUND)`

### Commit Conventions

Format: `type(scope): 설명`

- Types: `add` / `update` / `fix` / `refactor` / `ci/cd` / `docs` / `test` / `merge`
- Scope: domain name (`auth`, `student`, `club`, `application`, etc.) — NOT module names
- Cross-cutting only: `global`, `ci/cd`, or module names (`web`, `openapi`, `oauth`)
- Description: Korean, no period

## Key Practices

### JPA
Comment thread
snowykte0426 marked this conversation as resolved.
- Avoid N+1 problems — use Fetch Join or `@EntityGraph`
- Use `@Transactional(readOnly = true)` for read operations

### Testing
- Write Kotest tests for business logic
- Use Kotest `DescribeSpec` with `describe/context/it` blocks
- Use MockK for mocking; Given-When-Then structure inside `it` blocks
- Test names in Korean: `describe("클래스명 클래스의")`, `describe("메서드명 메서드는")`
- `kotlin-style.md` — `val/var`, constructor injection, null safety
- `dto-annotations.md` — Jackson/Swagger `@field:` vs `@param:` targets
- `api-conventions.md` — `@RequestParam` vs `@ModelAttribute`, DTO naming, `@Transactional` placement
- `logging.md` — English only, SLF4J `{}` placeholder, no colon separators
- `exception.md` — `ExpectedException` usage and message format
- `testing.md` — Kotest `DescribeSpec` + MockK + Given-When-Then structure
- `comments.md` — when to write comments (only for non-obvious logic)
- `commit-conventions.md` — commit `type(scope): description` rules (scope = domain name)

Comment thread
snowykte0426 marked this conversation as resolved.
## Notes

- This project uses Java 25 for Gradle builds
- Always check `.gitignore` and `.geminiignore` when suggesting file changes
- When analyzing code, consider the multi-module structure
- Always check `.gitignore` before proposing file changes.
- When analyzing code, consider the multi-module structure and inter-module dependencies (`datagsm-common` is the base for every runnable module).
56 changes: 3 additions & 53 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,5 @@
## Project Overview
@AGENTS.md

School information API server for Gwangju Software Meister High School (students, clubs, meals, schedules)
## Claude Code Specific

## Module Structure

- datagsm-common: Shared Entity/DTO/Repository, Health API
- datagsm-oauth-authorization: OAuth2 authentication, account lifecycle (signup, password reset)
- datagsm-oauth-userinfo: OAuth2 UserInfo endpoint (external clients)
- datagsm-openapi: Public read-only API (students, clubs, NEIS integration)
- datagsm-web: Web service API (user features, admin features, Excel processing)

**Note**: `/v1/health` endpoint is provided by `HealthController` in `datagsm-common` module and is shared across all modules.

## Commands

- Build: `./gradlew build`
- Test: `./gradlew test`
- Format: `./gradlew ktlintFormat`
- Run: `./gradlew :<module>:bootRun` (modules: `datagsm-oauth-authorization`, `datagsm-openapi`, `datagsm-oauth-userinfo`, `datagsm-web`)

## Tech Stack

Kotlin, Spring Boot 4.0, Spring Data JPA, QueryDSL, Redis, MySQL

## Coding Rules

- Controller → Service → Repository pattern
- Use constructor injection
- Test: Kotest + MockK (Given-When-Then)
- Do NOT add excessive comments - only add comments where logic is not self-evident

Detailed rules are split into `.claude/rules/`:
- `dto-annotations.md` — `@field:` vs `@param:` rules for Jackson and Swagger
- `logging.md` — English-only, SLF4J `{}` placeholders, no colon separators
- `exception.md` — `ExpectedException` usage and message format
- `kotlin-style.md` — `val/var`, constructor injection, null safety
- `api-conventions.md` — `@RequestParam` vs `@ModelAttribute`, DTO naming, `@Transactional` placement
- `commit-conventions.md` — commit type/scope rules

## Context Compaction Rules

Priority order when compressing conversation history:
1. Project Overview (module structure)
2. Common Mistakes section
3. DTO Annotations rules
4. Commit/PR conventions
5. Tech Stack
6. Reduce: Commands, Key Paths

## Key Paths

- Common Entity: `datagsm-common/src/main/kotlin/.../domain/`
- Exception Handler: `datagsm-common/.../global/common/error/`
- API Response: Use `CommonApiResponse` wrapper
- `.claude/rules/`의 세부 규칙은 Claude Code가 작업 컨텍스트에 맞춰 자동 로드합니다. 자동 로드된 규칙과 충돌하는 코드를 발견하면 단순 수정에 그치지 말고 규칙 파일에 누락된 항목이 있는지 점검하고 보완을 제안하세요.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사용자 상호작용 규칙에 따른다고 하셨는데 사실 이해가 되지 않습니다. 해당 내용도 한국어로 유지할 이유가 있을까요

2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ DataGSM 프로젝트에 기여해주셔서 감사합니다! 이 문서는 프로
프로젝트 개발을 위해 다음 환경이 필요합니다:

- **JDK**: Java 25 (Temurin 권장)
- **Kotlin**: 2.3.0 (자동 설정)
- **Kotlin**: 2.3.10 (자동 설정)
- **Gradle**: 최신 버전 (래퍼 사용)
- **Docker & Docker Compose**: 로컬 개발용
- **MySQL**: 8.0
Expand Down