Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
470 changes: 470 additions & 0 deletions .claude/hooks/tdd-notion-logger.py

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "source ~/.zshrc 2>/dev/null; python3 \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/tdd-notion-logger.py",
"timeout": 30
}
]
}
]
}
}
27 changes: 27 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"permissions": {
"allow": [
"Bash(./gradlew build:*)",
"Bash(java -version:*)",
"Bash(echo:*)",
"Bash(/usr/libexec/java_home:*)",
"Bash(JAVA_HOME=/Users/praesentia/Library/Java/JavaVirtualMachines/azul-21.0.7/Contents/Home ./gradlew build:*)",
"Bash(JAVA_HOME=/Users/praesentia/Library/Java/JavaVirtualMachines/azul-21.0.7/Contents/Home ./gradlew:*)",
"Bash(docker info:*)",
"Bash(docker context inspect:*)",
"Bash(docker run:*)",
"Bash(docker context:*)",
"Bash(JAVA_HOME=/Users/praesentia/Library/Java/JavaVirtualMachines/azul-21.0.7/Contents/Home DOCKER_HOST=unix:///Users/praesentia/.docker/run/docker.sock ./gradlew:*)",
"Bash(~/.testcontainers.properties)",
"Bash(curl:*)",
"Bash(JAVA_HOME=/Users/praesentia/Library/Java/JavaVirtualMachines/azul-21.0.7/Contents/Home TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE=/var/run/docker.sock ./gradlew:*)",
Comment on lines +7 to +17
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# .gitignore에 settings.local.json이 포함되어 있는지 확인
grep -n "settings.local.json" .gitignore || echo "settings.local.json is NOT in .gitignore"

Repository: Loopers-dev-lab/loop-pack-be-l2-vol3-java

Length of output: 125


🏁 Script executed:

#!/bin/bash

# 1. .claude 디렉토리 내용 확인
echo "=== .claude directory contents ==="
ls -la .claude/

# 2. .gitignore에서 .claude 관련 패턴 확인
echo -e "\n=== .claude patterns in .gitignore ==="
grep -E "\.claude|settings" .gitignore || echo "No .claude or settings patterns found"

# 3. settings.local.json이 git에 추적되는지 확인
echo -e "\n=== Git tracking status ==="
git ls-files | grep settings.local.json || echo "Not in git index"

# 4. .gitignore 전체 내용 (크기 확인)
echo -e "\n=== .gitignore line count ==="
wc -l .gitignore

Repository: Loopers-dev-lab/loop-pack-be-l2-vol3-java

Length of output: 601


🏁 Script executed:

#!/bin/bash

# .gitignore 전체 내용 확인
echo "=== Full .gitignore content ==="
cat -n .gitignore

# settings.json과 settings.local.json 내용 비교
echo -e "\n=== settings.json (첫 10줄) ==="
head -10 .claude/settings.json

echo -e "\n=== settings.local.json (첫 10줄) ==="
head -10 .claude/settings.local.json

# git에 커밋된 상태 확인
echo -e "\n=== Git commit history for settings.local.json ==="
git log --oneline -- .claude/settings.local.json | head -5

Repository: Loopers-dev-lab/loop-pack-be-l2-vol3-java

Length of output: 1061


.claude/settings.local.json이 개발자 머신 특화 경로와 함께 저장소에 커밋되어 있어 다른 개발자 환경에서 작동하지 않는다.

현재 이 파일은 git에 추적되고 있으며, /Users/praesentia/Library/Java/JavaVirtualMachines/azul-21.0.7 같은 하드코딩된 로컬 경로를 포함하고 있다. 다른 개발자가 리포지토리를 클론했을 때 이 설정을 적용할 수 없어 개발 환경 구성이 실패한다. .claude/settings.local.json은 개발자별 로컬 오버라이드 설정으로 설계된 것으로 보이므로 공유 저장소에 저장되어서는 안 된다.

필수 수정사항:

  1. .gitignore.claude/settings.local.json을 추가하여 향후 개인별 설정이 커밋되지 않도록 한다.
  2. 기존 커밋에서 제거하고자 하면 git rm --cached .claude/settings.local.json 실행 후 커밋한다.
  3. 환경 변수($JAVA_HOME, $DOCKER_HOST 등)를 직접 활용하거나 설정 템플릿(settings.local.json.example)을 제공하는 방식으로 변경한다.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/settings.local.json around lines 7 - 17, The file
.claude/settings.local.json contains machine-specific paths and should not be
tracked; add ".claude/settings.local.json" to .gitignore, remove the tracked
file with git rm --cached .claude/settings.local.json and commit that change,
and replace the committed content with a repository-safe alternative by creating
a template (e.g., settings.local.json.example) that documents using environment
variables like $JAVA_HOME and $DOCKER_HOST or explains how to populate local
overrides so developers copy it into their own untracked
.claude/settings.local.json.

"Bash(./gradlew:*)",
"Bash(JAVA_HOME=/Users/praesentia/Library/Java/JavaVirtualMachines/azul-21.0.7/Contents/Home DOCKER_API_VERSION=1.44 ./gradlew:*)",
"Bash(python3:*)",
"WebSearch",
"WebFetch(domain:github.com)",
"Bash(osascript:*)",
"Bash(docker:*)"
]
}
}
45 changes: 0 additions & 45 deletions .codeguide/loopers-1-week.md

This file was deleted.

42 changes: 3 additions & 39 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,40 +1,4 @@
HELP.md
.gradle
.DS_Store
.idea/
build/
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

build/ 패턴 범위를 다시 제한하는 편이 안전하다.

현재 build/는 저장소 전역의 모든 build 디렉터리를 무시한다. 운영 관점에서는 src/main/**/build 또는 src/test/**/build 같은 정상 소스 경로가 생겼을 때 git status에 나타나지 않아 코드 누락 상태로 배포·CI가 진행될 수 있어 추적이 어렵다. 루트/모듈 산출물만 제외하려는 의도라면 기존 예외 패턴을 유지하거나, 필요한 위치만 명시적으로 무시하는 방식으로 범위를 좁히는 편이 안전하다.

수정 예시
 .DS_Store
 .idea/
 build/
 .gradle/
+!**/src/main/**/build/
+!**/src/test/**/build/

추가 테스트로는 src/main/java/.../build/Example.java 같은 경로에 더미 파일을 만든 뒤 git check-ignore -v <path> 결과가 무시되지 않는지 확인하는 테스트를 권장한다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.gitignore at line 3, .gitignore currently ignores any directory named
"build" across the repo which is too broad; update the ignore rules to scope to
the repository root and/or explicit module outputs by replacing the global
"build/" pattern with a root-anchored pattern such as "/build/" and/or explicit
module output paths (e.g., "module-name/build/" or "*/target/build/" as
appropriate) and retain or add negate rules if you need to allow specific source
build folders; after editing, verify with git check-ignore -v <path> (e.g.,
src/main/.../build/Example.java) to confirm those source paths are no longer
ignored.

!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

### VS Code ###
.vscode/

### Kotlin ###
.kotlin
.gradle/
152 changes: 152 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Multi-module Spring Boot 3.4.4 / Java 21 template project with clean architecture. The actual codebase is in `loop-pack-be-l2-vol3-java/`.

## Build & Test Commands

```bash
# Build
./gradlew build

# Run all tests
./gradlew test

# Run single test class
./gradlew test --tests "ExampleV1ApiE2ETest"

# Run tests matching pattern
./gradlew test --tests "*ModelTest"

# Generate coverage report
./gradlew jacocoTestReport
```

## Local Development Infrastructure

```bash
# Start MySQL, Redis (master/replica), Kafka
docker-compose -f ./docker/infra-compose.yml up

# Start Prometheus + Grafana (localhost:3000, admin/admin)
docker-compose -f ./docker/monitoring-compose.yml up
```

## Module Structure

```
loop-pack-be-l2-vol3-java/
├── apps/ # Executable Spring Boot applications
│ ├── commerce-api # REST API service
│ ├── commerce-batch # Batch processing
│ └── commerce-streamer # Kafka event streaming
├── modules/ # Reusable configuration modules
│ ├── jpa # JPA + QueryDSL config
│ ├── redis # Redis cache config
│ └── kafka # Kafka config
└── supports/ # Add-on utilities
├── jackson # JSON serialization
├── logging # Structured logging
└── monitoring # Prometheus/Grafana metrics
```

## Architecture Layers (per app)

- `interfaces/api/` - REST Controllers + DTOs (request/response records)
- `application/` - Facades/Use Cases (business orchestration)
- `domain/` - Business logic, entities, domain services
- `infrastructure/` - JPA repositories, external integrations

## Key Conventions

### Entity Design
All entities extend `BaseEntity` (`modules/jpa/.../domain/BaseEntity.java`):
- Auto-managed: `id`, `createdAt`, `updatedAt`, `deletedAt`
- Soft-delete via idempotent `delete()` / `restore()` methods
- Override `guard()` for validation (called on PrePersist/PreUpdate)

### Error Handling
Use `CoreException` with `ErrorType` enum:
```java
throw new CoreException(ErrorType.NOT_FOUND);
throw new CoreException(ErrorType.BAD_REQUEST, "Custom message");
```
Available: `BAD_REQUEST`, `NOT_FOUND`, `CONFLICT`, `INTERNAL_ERROR`

### API Response Format
All responses wrapped in `ApiResponse<T>`:
```json
{
"meta": { "result": "SUCCESS|FAIL", "errorCode": null, "message": null },
"data": { ... }
}
```

### DTO Pattern
Use Java records with nested response classes and static `from()` factories:
```java
public class ExampleV1Dto {
public record ExampleResponse(Long id, String name) {
public static ExampleResponse from(ExampleModel model) { ... }
}
}
```

## Testing Strategy

Three test tiers with naming conventions:
1. **Unit tests** (`*ModelTest`) - Domain logic, no Spring context
2. **Integration tests** (`*IntegrationTest`) - `@SpringBootTest`, uses `DatabaseCleanUp.truncateAllTables()` in `@AfterEach`
3. **E2E tests** (`*E2ETest`) - `@SpringBootTest(webEnvironment=RANDOM_PORT)`, uses `TestRestTemplate`

Test configuration:
- Profile: `spring.profiles.active=test`
- Timezone: `Asia/Seoul`
- TestContainers for MySQL and Redis

## Tech Stack

- Java 21, Spring Boot 3.4.4, Spring Cloud 2024.0.1
- MySQL 8.0 + JPA + QueryDSL
- Redis 7.0 (master-replica), Kafka 3.5.1 (KRaft mode)
- JUnit 5, Mockito, SpringMockK, Instancio, TestContainers

## 개발 규칙
### 진행 Workflow - 증강 코딩
- **대원칙** : 방향성 및 주요 의사 결정은 개발자에게 제안만 할 수 있으며, 최종 승인된 사항을 기반으로 작업을 수행.
- **중간 결과 보고** : AI 가 반복적인 동작을 하거나, 요청하지 않은 기능을 구현, 테스트 삭제를 임의로 진행할 경우 개발자가 개입.
- **설계 주도권 유지** : AI 가 임의판단을 하지 않고, 방향성에 대한 제안 등을 진행할 수 있으나 개발자의 승인을 받은 후 수행.

### 개발 Workflow - TDD (Red > Green > Refactor)
- 모든 테스트는 given-when-then 원칙으로 작성할 것
#### 1. Red Phase : 실패하는 테스트 먼저 작성
- 요구사항을 만족하는 기능 테스트 케이스 작성
- 테스트 예시
#### 2. Green Phase : 테스트를 통과하는 코드 작성
- Red Phase 의 테스트가 모두 통과할 수 있는 코드 작성
- 오버엔지니어링 금지
#### 3. Refactor Phase : 불필요한 코드 제거 및 품질 개선
- 불필요한 private 함수 지양, 객체지향적 코드 작성
- unused import 제거
- 성능 최적화
- 모든 테스트 케이스가 통과해야 함
- ## 주의사항
### 1. Never Do
- 실제 동작하지 않는 코드, 불필요한 Mock 데이터를 이요한 구현을 하지 말 것
- null-safety 하지 않게 코드 작성하지 말 것 (Java 의 경우, Optional 을 활용할 것)
- println 코드 남기지 말 것

### 2. Recommendation
- 실제 API 를 호출해 확인하는 E2E 테스트 코드 작성
- 재사용 가능한 객체 설계
- 성능 최적화에 대한 대안 및 제안
- 개발 완료된 API 의 경우, `.http/**.http` 에 분류해 작성

### 3. Priority
1. 실제 동작하는 해결책만 고려
2. null-safety, thread-safety 고려
3. 테스트 가능한 구조로 설계
4. 기존 코드 패턴 분석 후 일관성 유지
Loading