This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Kokomen Payment (꼬꼬면 결제) is a multi-module Spring Boot payment system implementing Tosspayments integration. The project uses Java 17, Spring Boot 3.4.5, MySQL, Redis, and follows a domain-driven design with layered architecture.
- api: External-facing REST API module with authentication and member services
- internal: Internal payment processing module with Tosspayments integration
- domain: Core domain entities and repositories (JPA/Hibernate)
- common: Shared configurations (Redis, logging)
- external: External API clients (Tosspayments)
# Run all tests
./gradlew test
# Build entire project
./gradlew clean build
# Build specific module
./gradlew :api:build
./gradlew :internal:build
# Run tests for specific module
./gradlew :api:test
./gradlew :internal:test# Start API service locally (includes MySQL & Redis)
cd api && ./run-local-api.sh
# Start Internal service locally
cd internal && ./run-local-internal.sh
# Start test MySQL container
cd domain && ./run-test-mysql.sh
# Start test Redis container
cd common && ./run-test-redis.shDomain-first organization followed by layered architecture:
domain/
├── controller/
├── service/
├── repository/
├── domain/
└── dto/
global/
├── config/
├── exception/
└── infrastructure/
- Integration tests preferred: Uses real beans with MySQL test containers (not H2)
- DatabaseCleaner pattern: Tests use
MySQLDatabaseCleanerinstead of@Transactionalfor proper isolation - Base test classes:
BaseTestfor services,BaseControllerTestfor controllers with MockMvc - Test naming: Korean method names without
@DisplayName
- PaymentFacadeService: Orchestrates payment confirmation flow
- TosspaymentsTransactionService: Manages transactional operations
- TosspaymentsPaymentService: Handles payment entity operations
- TosspaymentsClient: External API communication with Tosspayments
Custom exceptions with HTTP status mapping:
BadRequestException(400)UnauthorizedException(401)ForbiddenException(403)
Global exception handler in GlobalExceptionHandler class.
- Always use Spring Data's
Pageablefor pagination - Controller methods receive
Pageableas parameter with@PageableDefaultannotation - Example:
@PageableDefault(size = 10) Pageable pageable - Service methods accept
Pageabledirectly without decomposing into page/size - Repository methods use
Pageablefor database queries
- Based on Woowacourse Java Style Guide (Google Java Style variant)
- Indentation: 4 spaces
- Column limit: 120 characters (general), 160 (maximum)
- Line wrapping: +8 spaces for continuation lines
- Records/Controllers: One parameter per line
- Annotated methods or >160 chars: One per line
- Regular methods: No line breaks
- Methods: action + domain format (e.g.,
saveMember()) - Read vs Find:
readthrows exception if not found,findreturns Optional/empty - No
get-prefix except for actual getters - No
notin validation methods - No
finalin method parameters
- Use for constructors, getters/setters
- Spring annotations before Lombok annotations
- Domain entities override
toString()
- DTO → Entity: Conversion methods are placed in DTO classes (e.g.,
dto.toEntity()) - Entity → DTO: Conversion methods are also placed in DTO classes as static factory methods or in service layer
- DTOs are responsible for transformation logic to keep entities clean
- Example:
ConfirmRequest.toTosspaymentsPayment()in DTO class
- @Transactional always on methods, not classes
- Place
@Transactional(readOnly = true)on read-only service methods - Place
@Transactionalon write service methods - Never put @Transactional at class level
- Test methods named in Korean
- No
@DisplayNameannotations - Given-When-Then structure
- Test data initialized in given section (no data.sql)
Location: domain/src/main/resources/db/migration/
Naming: V{version}__{description}.sql
- ENUM columns: Always use MySQL ENUM type instead of VARCHAR for enum fields
- Example:
ALTER TABLE table_name ADD COLUMN status ENUM('ACTIVE', 'INACTIVE') NOT NULL - This ensures type safety at the database level and reduces storage size
- Example:
MySQL 8.4.5 containers for testing (port 13308)
Configuration in domain/test.yml
Follow Angular commit message convention:
- feat: A new feature for the user
- fix: A bug fix
- docs: Documentation changes
- style: Changes that don't affect code meaning (formatting, etc.)
- refactor: Code changes that neither fix bugs nor add features
- test: Adding or updating tests
- chore: Changes to build process, tools, dependencies
Format: <type>: <description>
Example: feat: 결제 기능 개발
- No wildcard imports in Java files
- MDC logging context must be preserved across threads
- Security: Never log or commit secrets/keys
- Git commits: Never commit unless explicitly requested
- Documentation: Don't create README/docs unless requested
- Testing: Always verify with existing test commands before suggesting new ones