Skip to content

[♻️Refactor] 자기소개서 persistence DB/JPA 전환#27

Merged
yong203 merged 2 commits into
devfrom
refactor/#24
Jun 16, 2026
Merged

[♻️Refactor] 자기소개서 persistence DB/JPA 전환#27
yong203 merged 2 commits into
devfrom
refactor/#24

Conversation

@yong203

@yong203 yong203 commented Jun 16, 2026

Copy link
Copy Markdown
Member

작업 내용

  • API-008 POST /cover-letters 공개 계약을 유지하면서 내부 persistence를 in-memory에서 DB/JPA로 전환했습니다.
  • H2 기반 DB 설정을 추가했습니다.
    • 로컬: H2 file DB
    • 테스트: H2 in-memory DB
    • Flyway는 이번 범위에서 제외
  • CoverLettercover_letters JPA entity로 전환하고 ERD 기준 주요 컬럼을 반영했습니다.
  • CoverLetterRepository를 Spring Data JPA repository로 전환하고 in-memory repository를 제거했습니다.
  • ID 생성 정책을 공통 IdGenerator/UuidIdGenerator로 정리했습니다.
  • CreateCoverLetterResponse는 내부 Instant를 API 계약대로 Asia/Seoul LocalDateTime으로 변환합니다.
  • repository/service/controller/generator 테스트를 추가 또는 갱신했습니다.
  • docs/status.md, docs/architecture.md에 DB/JPA 전환 상태를 반영했습니다.

관련 이슈

문서 반영

  • 반영한 문서:
    • docs/status.md
    • docs/architecture.md
  • 문서 반영 없음. 이유: 해당 없음

확인 결과

  • ./gradlew test
  • ./gradlew check
  • 기타: git diff --check
  • 실행하지 못함. 이유:

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 데이터베이스 기반 영속성 저장소 도입으로 애플리케이션 재시작 후에도 데이터가 유지됩니다.
  • 버그 수정

    • 타임스탬프 시간대를 Asia/Seoul로 통일하여 시간 표시 일관성을 개선했습니다.
  • Chores

    • 개발 환경 설정 및 의존성을 업데이트했습니다.

@yong203 yong203 linked an issue Jun 16, 2026 that may be closed by this pull request
9 tasks
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

CoverLetter 엔티티를 JPA @Entity로 전환하고 타임스탬프를 Instant로 교체한다. InMemoryCoverLetterRepository와 도메인 전용 CoverLetterIdGenerator/UuidCoverLetterIdGenerator를 제거하고, CoverLetterRepositoryJpaRepository를 상속하도록 변경한다. 범용 IdGenerator/UuidIdGenerator를 추가하고 H2/JPA 의존성 및 설정을 구성한다.

Changes

CoverLetter persistence DB/JPA 전환

Layer / File(s) Summary
범용 IdGenerator 인터페이스 및 구현체 도입
src/main/java/com/daon/rewrite/global/util/IdGenerator.java, src/main/java/com/daon/rewrite/global/util/UuidIdGenerator.java, src/test/java/com/daon/rewrite/global/util/UuidIdGeneratorTest.java
도메인 전용 CoverLetterIdGenerator/UuidCoverLetterIdGenerator를 제거하고 prefix를 인자로 받는 범용 IdGenerator 인터페이스와 UuidIdGenerator 구현체(@Component)를 추가한다. UuidIdGeneratorTestprefix + "_" + UUID 형식을 검증한다.
CoverLetter JPA 엔티티 전환 및 리포지토리 교체
src/main/java/com/daon/rewrite/coverletter/entity/CoverLetter.java, src/main/java/com/daon/rewrite/coverletter/repository/CoverLetterRepository.java
CoverLetter@Entity/@Table/@Column/@Enumerated를 추가하고 타임스탬프를 LocalDateTime에서 Instant로 교체한다. 생성자 가시성을 private으로 변경하고 draft() 팩토리 시그니처를 갱신한다. CoverLetterRepositoryJpaRepository<CoverLetter, String>를 상속하도록 변경하며 InMemoryCoverLetterRepository를 삭제한다.
CoverLetterService 및 DTO 타임존 변환 갱신
src/main/java/com/daon/rewrite/coverletter/service/CoverLetterService.java, src/main/java/com/daon/rewrite/coverletter/dto/CreateCoverLetterResponse.java
CoverLetterService에서 CoverLetterIdGenerator 대신 IdGenerator를 주입하고 COVER_LETTER_ID_PREFIX("cl") 상수를 추가한다. createDraft()에서 LocalDateTime.now(clock)Instant.now(clock)으로 교체한다. CreateCoverLetterResponseAPI_ZONE(Asia/Seoul) 상수를 추가하고 from() 메서드가 InstantLocalDateTime으로 변환하도록 변경한다.
H2/JPA 의존성 및 설정 추가
build.gradle, src/main/resources/application.yaml, src/test/resources/application-test.yaml, .gitignore
build.gradlespring-boot-starter-data-jpa와 H2 런타임 의존성을 추가한다. application.yaml에 H2 파일 기반 datasource, JPA(ddl-auto: update), H2 콘솔 설정을 추가한다. application-test.yaml을 신규 생성해 H2 인메모리 datasource, JPA(ddl-auto: create-drop), H2 콘솔 비활성, OpenAI 더미 키를 구성한다. data/ 디렉터리를 .gitignore에 추가한다.
리포지토리/서비스/컨트롤러 테스트 갱신
src/test/java/com/daon/rewrite/coverletter/repository/CoverLetterRepositoryTest.java, src/test/java/com/daon/rewrite/coverletter/service/CoverLetterServiceTest.java, src/test/java/com/daon/rewrite/coverletter/controller/CoverLetterControllerTest.java
@DataJpaTest 기반 CoverLetterRepositoryTest를 추가해 flush/clearfindById 라운드트립을 검증한다. CoverLetterServiceTest@SpringBootTest로 전환하고 @MockitoBean으로 CurrentUserProvider/IdGenerator/Clock을 주입한다. CoverLetterControllerTest에서 CoverLetter 생성을 Instant.parse() 기반으로 수정하고 createdAt 검증을 특정 문자열 비교로 강화한다.
아키텍처 및 상태 문서 갱신
docs/architecture.md, docs/status.md
architecture.md에서 in-memory 기반 표현을 제거하고 DB/JPA 기반 구현으로 서술을 정리한다. status.md에서 REQ-007을 Implemented로 전환하고 Next Issue Slice Candidates를 REQ-003/REQ-004 중심으로 재구성한다.

Possibly related PRs

  • Rewrite-Team/Rewrite-BE#19: CoverLetter 도메인(엔티티/리포지토리/서비스/컨트롤러/DTO)을 in-memory 기반으로 초기 구현한 PR이며, 본 PR이 동일한 스택을 JPA 기반으로 전환한다.

Suggested labels

🔧 Chore

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 핵심 변경사항을 명확하게 요약합니다. '자기소개서 persistence DB/JPA 전환'은 주요 변경 내용을 정확히 반영합니다.
Description check ✅ Passed PR 설명이 작업 내용, 관련 이슈, 문서 반영, 확인 결과를 모두 포함하여 템플릿 요구사항을 충족합니다.
Linked Issues check ✅ Passed 모든 코드 변경사항이 #24 이슈의 완료 기준을 충족합니다. DB/JPA 전환, Repository 변환, Entity 전환, ID 생성 정책 정리, 테스트 추가, 문서 반영이 모두 구현되었고 ./gradlew test./gradlew check 통과를 확인했습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 #24 이슈의 범위 내에 있습니다. Flyway 제외, 신규 API 미포함, API-008 공개 계약 유지 등 제외 사항을 적절히 지켰습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


Comment @coderabbitai help to get the list of available commands and usage tips.

@yong203 yong203 marked this pull request as ready for review June 16, 2026 07:50
@yong203 yong203 self-assigned this Jun 16, 2026
@yong203 yong203 added the ♻️ Refactor 코드 리팩토링 label Jun 16, 2026
@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/test/java/com/daon/rewrite/global/util/UuidIdGeneratorTest.java (1)

15-16: ⚡ Quick win

UUID 형식 검증을 테스트에 추가해 주세요.

현재는 "cl_" 이후가 비어있지 않은지만 확인해서, UUID가 아닌 문자열 회귀를 놓칠 수 있습니다. suffix를 UUID.fromString(...)으로 파싱 검증하면 계약이 더 명확해집니다.

제안 패치
 import org.junit.jupiter.api.Test;
+import java.util.UUID;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@
     void generateReturnsPrefixAndUuid() {
         String id = idGenerator.generate("cl");
 
         assertThat(id).startsWith("cl_");
-        assertThat(id.substring("cl_".length())).isNotBlank();
+        String uuidPart = id.substring("cl_".length());
+        assertThat(uuidPart).isNotBlank();
+        assertThat(UUID.fromString(uuidPart)).isNotNull();
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/java/com/daon/rewrite/global/util/UuidIdGeneratorTest.java` around
lines 15 - 16, The test in UuidIdGeneratorTest is only checking that the suffix
after "cl_" is not blank, but not validating that it is actually a valid UUID
format. Replace or supplement the current isNotBlank() assertion with a call to
UUID.fromString() to parse the suffix extracted from
id.substring("cl_".length()). This will ensure the generated ID truly conforms
to the expected "cl_" prefix followed by a valid UUID, rather than just any
non-empty string.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/resources/application.yaml`:
- Around line 19-22: The H2 console is currently enabled in the default profile
(application.yaml), which is a security risk as it exposes direct database
access. Change the enabled property under h2.console in application.yaml from
true to false to secure the default environment. Then create a new profile file
application-local.yaml specifically for local development and configure the
h2.console settings there with enabled set to true and path set to /h2-console,
ensuring the console is only available in local development environments and not
in production.

---

Nitpick comments:
In `@src/test/java/com/daon/rewrite/global/util/UuidIdGeneratorTest.java`:
- Around line 15-16: The test in UuidIdGeneratorTest is only checking that the
suffix after "cl_" is not blank, but not validating that it is actually a valid
UUID format. Replace or supplement the current isNotBlank() assertion with a
call to UUID.fromString() to parse the suffix extracted from
id.substring("cl_".length()). This will ensure the generated ID truly conforms
to the expected "cl_" prefix followed by a valid UUID, rather than just any
non-empty string.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: bcdbca26-bdbf-42b7-933c-9263df885b73

📥 Commits

Reviewing files that changed from the base of the PR and between 3b10a61 and 477842e.

📒 Files selected for processing (19)
  • .gitignore
  • build.gradle
  • docs/architecture.md
  • docs/status.md
  • src/main/java/com/daon/rewrite/coverletter/dto/CreateCoverLetterResponse.java
  • src/main/java/com/daon/rewrite/coverletter/entity/CoverLetter.java
  • src/main/java/com/daon/rewrite/coverletter/repository/CoverLetterRepository.java
  • src/main/java/com/daon/rewrite/coverletter/repository/InMemoryCoverLetterRepository.java
  • src/main/java/com/daon/rewrite/coverletter/service/CoverLetterIdGenerator.java
  • src/main/java/com/daon/rewrite/coverletter/service/CoverLetterService.java
  • src/main/java/com/daon/rewrite/coverletter/service/UuidCoverLetterIdGenerator.java
  • src/main/java/com/daon/rewrite/global/util/IdGenerator.java
  • src/main/java/com/daon/rewrite/global/util/UuidIdGenerator.java
  • src/main/resources/application.yaml
  • src/test/java/com/daon/rewrite/coverletter/controller/CoverLetterControllerTest.java
  • src/test/java/com/daon/rewrite/coverletter/repository/CoverLetterRepositoryTest.java
  • src/test/java/com/daon/rewrite/coverletter/service/CoverLetterServiceTest.java
  • src/test/java/com/daon/rewrite/global/util/UuidIdGeneratorTest.java
  • src/test/resources/application-test.yaml
💤 Files with no reviewable changes (3)
  • src/main/java/com/daon/rewrite/coverletter/service/UuidCoverLetterIdGenerator.java
  • src/main/java/com/daon/rewrite/coverletter/repository/InMemoryCoverLetterRepository.java
  • src/main/java/com/daon/rewrite/coverletter/service/CoverLetterIdGenerator.java

Comment thread src/main/resources/application.yaml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

♻️ Refactor 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[♻️Refactor] 자기소개서 persistence DB/JPA 전환

1 participant