From 74e1c6bb9cba4793fcdbdc28091ff46dc406fe21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dean=5B=EB=B0=B1=EB=B3=91=EB=82=A8=5D?= Date: Fri, 14 Nov 2025 18:13:41 +0900 Subject: [PATCH 01/12] test: Verify pre-commit hook formatting check --- CLAUDE.md | 212 ++++++++++++++++++ CODE_STYLE_SETUP.md | 115 ++++++++++ build.gradle | 20 ++ .../common/api/HelloApiController.java | 4 + .../common/service/HelloService.java | 4 + .../kamcoback/config/api/ApiResponseDto.java | 4 + .../cd/kamcoback/config/enums/EnumType.java | 4 + 7 files changed, 363 insertions(+) create mode 100644 CLAUDE.md create mode 100644 CODE_STYLE_SETUP.md create mode 100644 src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/common/service/HelloService.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/config/enums/EnumType.java diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..f3c0d5e5 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,212 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +**kamco-change-detection-api** is a Spring Boot 3.5.7 application using Java 21 and PostgreSQL for KAMCO's change detection system. The project handles geospatial data with JTS/GeoJSON integration and uses QueryDSL for type-safe database queries. + +## Build & Run Commands + +### Build +```bash +# Full build with tests +./gradlew build + +# Build without tests (Jenkins CI uses this) +./gradlew clean build -x test + +# Build JAR (creates ROOT.jar) +./gradlew bootJar +``` + +### Run Application +```bash +# Run with local profile (default) +./gradlew bootRun + +# Run with specific profile +./gradlew bootRun --args='--spring.profiles.active=dev' +# or +java -jar build/libs/ROOT.jar --spring.profiles.active=dev +``` + +### Testing +```bash +# Run all tests +./gradlew test + +# Run specific test class +./gradlew test --tests com.kamco.cd.kamcoback.KamcoBackApplicationTests +``` + +## Architecture + +### Technology Stack +- **Framework**: Spring Boot 3.5.7 +- **Language**: Java 21 +- **Database**: PostgreSQL +- **Connection Pool**: HikariCP +- **ORM**: Spring Data JPA + Hibernate +- **Query DSL**: QueryDSL 5.0.0 (Jakarta) +- **Geospatial**: JTS (Java Topology Suite) with GeoJSON serialization +- **Build Tool**: Gradle +- **Monitoring**: Spring Boot Actuator + +### Configuration Profiles + +The application uses **profile-based configuration** with three environments: + +| Profile | File | Purpose | Active Profiles | +|---------|------|---------|----------------| +| `local` | application.yml | Local development | default | +| `dev` | application-dev.yml | Development server | `--spring.profiles.active=dev` | +| `prod` | application.yml | Production server | `--spring.profiles.active=prod` | + +**CRITICAL**: Profile names must match configuration exactly: +- ✅ Use `dev` (not `develop`) +- ✅ Use `prod` (not `production`) +- ✅ Use `local` (default, not `localhost`) + +### Geospatial Data Handling + +The application has **custom Jackson serializers/deserializers** for JTS Geometry types: + +**Location**: `com.kamco.cd.kamcoback.common.utils.geometry` + +- `GeometrySerializer`: Converts JTS Geometry → GeoJSON with **16-digit precision** (increased from default 8 digits) +- `GeometryDeserializer`: Converts GeoJSON → JTS Geometry types (Point, Polygon, Geometry) + +**Registered for types**: `Geometry`, `Point`, `Polygon` + +**Configuration**: `WebConfig.java` configures ObjectMapper bean with custom module + +**Usage in entities**: Use JTS geometry types directly in JPA entities: +```java +@Column(columnDefinition = "geometry(Point,4326)") +private Point location; + +@Column(columnDefinition = "geometry(Polygon,4326)") +private Polygon boundary; +``` + +### Database Configuration + +**HikariCP Connection Pool** is configured per profile: + +| Setting | Local | Dev | Prod | +|---------|-------|-----|------| +| Min Idle | 10 | 5 | N/A | +| Max Pool Size | 50 | 20 | N/A | +| Connection Timeout | 20s | Default | Default | +| Idle Timeout | 5min | Default | Default | +| Max Lifetime | 30min | Default | Default | + +**JPA/Hibernate Settings**: +- DDL Auto: `validate` (schema changes require manual migration) +- JDBC Batch Size: 50 +- Default Batch Fetch Size: 100 (N+1 query prevention) +- Show SQL: `true` in dev, configurable per profile + +**Startup Logging**: `StartupLogger.java` displays full configuration on startup including active profiles, database connection, pool settings, and JPA configuration. + +### QueryDSL Setup + +**Dependencies** (build.gradle): +- Implementation: `querydsl-jpa:5.0.0:jakarta` +- Annotation Processor: `querydsl-apt:5.0.0:jakarta` + +**Q-Class Generation**: Q-classes are generated via annotation processors for Jakarta Persistence entities. + +**Pattern** (from TODO): Future repositories should follow `CustomRepository` + `CustomRepositoryImpl` pattern for complex queries. + +### Actuator Monitoring + +**Endpoints** configured at `/monitor` base path: +- `/monitor/health` - Health checks with readiness/liveness probes +- JMX endpoints excluded for security + +**Health Probes**: Enabled for Kubernetes-style readiness and liveness checks. + +## Code Style + +**Standard**: Google Java Style Guide with project-specific modifications + +**Key Rules**: +- **Indentation**: 2 spaces (not tabs) +- **Line Length**: 100 characters max +- **Line Endings**: LF (Unix-style) +- **Charset**: UTF-8 +- **Trailing Whitespace**: Removed +- **Final Newline**: Required + +**Style XML**: `intellij-java-google-style.xml` (IntelliJ IDEA code style configuration) + +### Automated Code Formatting + +**Spotless Gradle Plugin**: Automatically enforces Google Java Format + +```bash +# Check formatting +./gradlew spotlessCheck + +# Apply formatting +./gradlew spotlessApply +``` + +**Pre-commit Hook**: Automatically checks formatting before each commit +- Location: `.git/hooks/pre-commit` +- Runs `spotlessCheck` before allowing commits +- If formatting fails, run `./gradlew spotlessApply` to fix + +**IntelliJ Setup**: See `CODE_STYLE_SETUP.md` for detailed instructions on: +- Importing code style XML +- Enabling format-on-save +- Configuring Actions on Save + +**Important**: The project uses **spaces** (not tabs) for indentation, with 2-space indent size. + +## Package Structure + +``` +com.kamco.cd.kamcoback +├── KamcoBackApplication.java # Main application entry point +├── config/ +│ ├── WebConfig.java # Jackson ObjectMapper + Geometry serializers +│ └── StartupLogger.java # Application startup diagnostics +└── common/ + ├── api/ # API DTOs + └── utils/ + └── geometry/ # GeoJSON serialization utilities +``` + +## Development Notes + +### Current State (Early Stage) +The project is in initial setup phase. From `common/README.md`, planned but not yet implemented: +- QueryDSL custom/impl repository pattern +- Common code management system +- Redis caching layer + +### When Adding New Features +1. **Entities with Geometry**: Use JTS types directly; serialization is handled automatically +2. **Repository Queries**: Use QueryDSL for type-safe queries (Q-classes auto-generated) +3. **Configuration**: Add profile-specific settings in appropriate application-{profile}.yml +4. **Database Changes**: DDL is set to `validate`; schema changes need manual migration + +### Profile Activation Troubleshooting +If you see "Failed to configure a DataSource", check: +1. Profile name matches configuration file exactly (`dev`, `prod`, or `local`) +2. DataSource URL, username, password are set in profile configuration +3. PostgreSQL JDBC driver is on classpath (runtimeOnly dependency) + +### Testing Geometry Serialization +Use the configured ObjectMapper bean for JSON operations. Manual ObjectMapper creation will miss custom geometry serializers. + +## CI/CD + +**Jenkins Pipeline**: `Jenkinsfile-dev` +- Branch: `develop` +- Build: `./gradlew clean build -x test` +- JDK: Java 21 +- Artifact: `ROOT.jar` diff --git a/CODE_STYLE_SETUP.md b/CODE_STYLE_SETUP.md new file mode 100644 index 00000000..3bfdd0e4 --- /dev/null +++ b/CODE_STYLE_SETUP.md @@ -0,0 +1,115 @@ +# Code Style 설정 가이드 + +이 문서는 프로젝트에서 Google Java Style을 자동으로 적용하기 위한 설정 가이드입니다. + +## 자동 포맷팅 구성 + +### 1. 커밋 시점 자동 체크 (Git Pre-commit Hook) + +커밋 전에 자동으로 코드 스타일을 체크하고, 문제가 있으면 커밋을 막습니다. + +**설정 완료:** `.git/hooks/pre-commit` 파일이 자동으로 실행됩니다. + +**동작 방식:** +- 커밋 시도 시 `./gradlew spotlessCheck` 자동 실행 +- 포맷팅 오류가 있으면 커밋 차단 및 안내 메시지 출력 +- 포맷팅이 올바르면 커밋 허용 + +**포맷팅 오류 발생 시:** +```bash +# 자동 포맷팅 적용 +./gradlew spotlessApply + +# 변경사항 추가 후 다시 커밋 +git add . +git commit +``` + +### 2. IntelliJ IDEA 저장 시점 자동 포맷팅 + +#### 방법 1: Code Style 설정 임포트 (권장) + +1. **IntelliJ IDEA 열기** +2. **Settings/Preferences** (Mac: `⌘,` / Windows: `Ctrl+Alt+S`) +3. **Editor > Code Style > Java** +4. **⚙️ (톱니바퀴)** 클릭 > **Import Scheme > IntelliJ IDEA code style XML** +5. 프로젝트 루트의 `intellij-java-google-style.xml` 파일 선택 +6. **OK** 클릭 + +#### 방법 2: 저장 시 자동 포맷팅 활성화 + +**Option A: Actions on Save 설정** + +1. **Settings/Preferences** > **Tools > Actions on Save** +2. 다음 옵션들을 활성화: + - ✅ **Reformat code** + - ✅ **Optimize imports** + - ✅ **Rearrange code** (선택사항) +3. **Changed lines** 또는 **Whole file** 선택 +4. **OK** 클릭 + +**Option B: Save Actions Plugin 사용 (더 많은 옵션)** + +1. **Settings/Preferences** > **Plugins** +2. **Marketplace**에서 "Save Actions" 검색 및 설치 +3. **Settings/Preferences** > **Other Settings > Save Actions** +4. 다음 옵션 활성화: + - ✅ **Activate save actions on save** + - ✅ **Reformat file** + - ✅ **Optimize imports** + - ✅ **Rearrange fields and methods** (선택사항) + +### 3. Gradle Spotless Plugin 수동 실행 + +#### 코드 포맷팅 체크 +```bash +# 포맷팅 문제 확인만 (수정하지 않음) +./gradlew spotlessCheck +``` + +#### 코드 자동 포맷팅 +```bash +# 모든 Java 파일 자동 포맷팅 적용 +./gradlew spotlessApply +``` + +#### 빌드 시 자동 체크 +```bash +# 빌드 전에 자동으로 spotlessCheck 실행됨 +./gradlew build +``` + +## 코드 스타일 규칙 + +프로젝트는 **Google Java Style Guide** 기반으로 다음 규칙을 따릅니다: + +- **Indentation**: 2 spaces (탭 아님) +- **Line Length**: 100 characters +- **Line Endings**: LF (Unix-style) +- **Charset**: UTF-8 +- **Import Order**: Static imports → 빈 줄 → Regular imports +- **Braces**: 모든 if, for, while, do 문에 중괄호 필수 + +## 문제 해결 + +### Pre-commit hook이 실행되지 않는 경우 +```bash +# 실행 권한 확인 및 부여 +chmod +x .git/hooks/pre-commit +``` + +### Spotless 플러그인이 동작하지 않는 경우 +```bash +# Gradle 의존성 다시 다운로드 +./gradlew clean build --refresh-dependencies +``` + +### IntelliJ 포맷팅이 다르게 적용되는 경우 +1. `intellij-java-google-style.xml` 다시 임포트 +2. **File > Invalidate Caches** > **Invalidate and Restart** + +## 추가 정보 + +- **Google Java Style Guide**: https://google.github.io/styleguide/javaguide.html +- **Spotless Plugin**: https://github.com/diffplug/spotless +- **IntelliJ Code Style**: https://www.jetbrains.com/help/idea/code-style.html \ No newline at end of file diff --git a/build.gradle b/build.gradle index 5c8b708c..25450132 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'org.springframework.boot' version '3.5.7' id 'io.spring.dependency-management' version '1.1.7' + id 'com.diffplug.spotless' version '6.25.0' } group = 'com.kamco.cd' @@ -58,3 +59,22 @@ tasks.named('test') { bootJar { archiveFileName = 'ROOT.jar' } + +// Spotless configuration for code formatting +spotless { + java { + target 'src/**/*.java' + googleJavaFormat('1.19.2').aosp().reflowLongStrings() + indentWithSpaces(2) + trimTrailingWhitespace() + endWithNewline() + importOrder() + removeUnusedImports() + formatAnnotations() + } +} + +// Run spotlessCheck before build +tasks.named('build') { + dependsOn 'spotlessCheck' +} diff --git a/src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java b/src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java new file mode 100644 index 00000000..bd41dc49 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/common/api/HelloApiController.java @@ -0,0 +1,4 @@ +package com.kamco.cd.kamcoback.common.api; + +public class HelloApiController { +} diff --git a/src/main/java/com/kamco/cd/kamcoback/common/service/HelloService.java b/src/main/java/com/kamco/cd/kamcoback/common/service/HelloService.java new file mode 100644 index 00000000..c0520578 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/common/service/HelloService.java @@ -0,0 +1,4 @@ +package com.kamco.cd.kamcoback.common.service; + +public class HelloService { +} diff --git a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java new file mode 100644 index 00000000..4e586ac4 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java @@ -0,0 +1,4 @@ +package com.kamco.cd.kamcoback.config.api; + +public class ApiResponseDto { +} diff --git a/src/main/java/com/kamco/cd/kamcoback/config/enums/EnumType.java b/src/main/java/com/kamco/cd/kamcoback/config/enums/EnumType.java new file mode 100644 index 00000000..c8c94836 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/config/enums/EnumType.java @@ -0,0 +1,4 @@ +package com.kamco.cd.kamcoback.config.api; + +public interface EnumType { +} From 7d64ee897d4e7c6a50ccd96b0a8491b8d3d03b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dean=5B=EB=B0=B1=EB=B3=91=EB=82=A8=5D?= Date: Mon, 17 Nov 2025 09:39:18 +0900 Subject: [PATCH 02/12] api sample --- .editorconfig | 4 +- CODE_STYLE_SETUP.md | 29 ++-- README.md | 4 - intellij-java-google-style.xml | 2 +- settings.gradle | 5 + .../cd/kamcoback/KamcoBackApplication.java | 7 +- .../common/api/HelloApiController.java | 21 +++ .../cd/kamcoback/common/api/HelloDto.java | 33 +++- .../common/service/BaseCoreService.java | 38 +++++ .../common/service/HelloService.java | 13 ++ .../utils/geometry/GeometryDeserializer.java | 5 +- .../utils/geometry/GeometrySerializer.java | 10 +- .../cd/kamcoback/config/StartupLogger.java | 149 +++++++++--------- .../kamco/cd/kamcoback/config/WebConfig.java | 4 +- .../kamcoback/config/api/ApiResponseDto.java | 118 +++++++++++++- .../cd/kamcoback/config/enums/EnumType.java | 6 +- .../kamcoback/postgres/CommonDateEntity.java | 34 ++++ .../cd/kamcoback/postgres/QueryDslConfig.java | 19 +++ .../postgres/core/AnimalCoreService.java | 68 ++++++++ .../postgres/entity/AnimalEntity.java | 67 ++++++++ .../postgres/repository/AnimalRepository.java | 7 + .../repository/AnimalRepositoryCustom.java | 15 ++ .../repository/AnimalRepositoryImpl.java | 99 ++++++++++++ .../cd/kamcoback/zoo/AnimalApiController.java | 82 ++++++++++ .../kamco/cd/kamcoback/zoo/dto/AnimalDto.java | 129 +++++++++++++++ .../kamcoback/zoo/service/AnimalService.java | 61 +++++++ src/main/resources/application-dev.yml | 2 + src/main/resources/application-local.yml | 7 +- .../kamcoback/KamcoBackApplicationTests.java | 6 +- 29 files changed, 918 insertions(+), 126 deletions(-) create mode 100644 src/main/java/com/kamco/cd/kamcoback/common/service/BaseCoreService.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/CommonDateEntity.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/QueryDslConfig.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/core/AnimalCoreService.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/entity/AnimalEntity.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepository.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepositoryCustom.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/repository/AnimalRepositoryImpl.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/zoo/AnimalApiController.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/zoo/dto/AnimalDto.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/zoo/service/AnimalService.java diff --git a/.editorconfig b/.editorconfig index a6d93a81..da27dc81 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,7 +1,7 @@ root = true [*] -indent_style = tab +indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 @@ -9,4 +9,4 @@ trim_trailing_whitespace = true insert_final_newline = true [*.java] -max_line_length = 100 +max_line_length = 180 diff --git a/CODE_STYLE_SETUP.md b/CODE_STYLE_SETUP.md index 3bfdd0e4..2c07ff5b 100644 --- a/CODE_STYLE_SETUP.md +++ b/CODE_STYLE_SETUP.md @@ -4,26 +4,22 @@ ## 자동 포맷팅 구성 -### 1. 커밋 시점 자동 체크 (Git Pre-commit Hook) +### 1. 커밋 시점 자동 포맷팅 (Git Pre-commit Hook) -커밋 전에 자동으로 코드 스타일을 체크하고, 문제가 있으면 커밋을 막습니다. +커밋 전에 자동으로 코드를 포맷팅하고 스테이징합니다. **설정 완료:** `.git/hooks/pre-commit` 파일이 자동으로 실행됩니다. **동작 방식:** -- 커밋 시도 시 `./gradlew spotlessCheck` 자동 실행 -- 포맷팅 오류가 있으면 커밋 차단 및 안내 메시지 출력 -- 포맷팅이 올바르면 커밋 허용 +- 커밋 시도 시 `./gradlew spotlessApply` 자동 실행 +- 스테이징된 Java 파일을 자동으로 포맷팅 +- 포맷팅된 파일을 자동으로 다시 스테이징 +- 포맷팅이 완료되면 커밋 진행 -**포맷팅 오류 발생 시:** -```bash -# 자동 포맷팅 적용 -./gradlew spotlessApply - -# 변경사항 추가 후 다시 커밋 -git add . -git commit -``` +**장점:** +- 수동으로 `spotlessApply`를 실행할 필요 없음 +- 항상 일관된 코드 스타일 유지 +- 포맷팅 누락 방지 ### 2. IntelliJ IDEA 저장 시점 자동 포맷팅 @@ -38,6 +34,7 @@ git commit #### 방법 2: 저장 시 자동 포맷팅 활성화 + **Option A: Actions on Save 설정** 1. **Settings/Preferences** > **Tools > Actions on Save** @@ -84,7 +81,7 @@ git commit 프로젝트는 **Google Java Style Guide** 기반으로 다음 규칙을 따릅니다: - **Indentation**: 2 spaces (탭 아님) -- **Line Length**: 100 characters +- **Line Length**: 180 characters - **Line Endings**: LF (Unix-style) - **Charset**: UTF-8 - **Import Order**: Static imports → 빈 줄 → Regular imports @@ -112,4 +109,4 @@ chmod +x .git/hooks/pre-commit - **Google Java Style Guide**: https://google.github.io/styleguide/javaguide.html - **Spotless Plugin**: https://github.com/diffplug/spotless -- **IntelliJ Code Style**: https://www.jetbrains.com/help/idea/code-style.html \ No newline at end of file +- **IntelliJ Code Style**: https://www.jetbrains.com/help/idea/code-style.html diff --git a/README.md b/README.md index 9b560246..5878b610 100644 --- a/README.md +++ b/README.md @@ -193,10 +193,6 @@ kamco-back/ │ │ │ │ └── StartupLogger.java # 시작 로그 │ │ │ ├── common/ # 공통 유틸리티 │ │ │ │ └── utils/geometry/ # GeoJSON 직렬화 -│ │ │ ├── domain/ # 도메인 엔티티 (예정) -│ │ │ ├── repository/ # 리포지토리 (예정) -│ │ │ ├── service/ # 비즈니스 로직 (예정) -│ │ │ └── controller/ # REST 컨트롤러 (예정) │ │ └── resources/ │ │ ├── application.yml # 기본 설정 + local/prod │ │ └── application-dev.yml # 개발 환경 설정 diff --git a/intellij-java-google-style.xml b/intellij-java-google-style.xml index f3a6743e..d63d7310 100644 --- a/intellij-java-google-style.xml +++ b/intellij-java-google-style.xml @@ -25,7 +25,7 @@ -