Skip to content

[infra] flyway 기반 DB 마이그레이션 도입 & Room 테이블에 RoomStatus 컬럼 추가#285

Merged
buzz0331 merged 6 commits intodevelopfrom
infra/#282-db-migration
Sep 1, 2025
Merged

[infra] flyway 기반 DB 마이그레이션 도입 & Room 테이블에 RoomStatus 컬럼 추가#285
buzz0331 merged 6 commits intodevelopfrom
infra/#282-db-migration

Conversation

@buzz0331
Copy link
Contributor

@buzz0331 buzz0331 commented Aug 29, 2025

#️⃣ 연관된 이슈

closes #282

📝 작업 내용

flyway를 통한 DB 마이그레이션을 도입했습니다. 밑에 내용 확인 부탁드립니다!

  1. DB 마이그레이션 도입 배경
    • 기존에는 ddl-auto 설정에 의존하여 스키마가 자동 변경되는 방식 → 운영/개발 환경 간의 스키마 차이 발생 위험.
    • Flyway를 도입하여 DB 스키마 변경을 이력 관리 + 코드 리뷰 가능한 형태로 관리.
    • 모든 스키마 변경 내역은 db/migration 디렉토리에 SQL 파일로 기록되며, flyway_schema_history 테이블을 통해 DB 적용 여부가 추적됩니다.

  2. 파일명 컨벤션
    • 규칙: V{날짜}__{변경 내용}.sql
    • 예시: V250828__Add_room_status.sql
    • 동일한 날짜에 여러 개의 변경이 필요하다면 소수점 버전을 증가시켜 작성해주세요.
    • V250828.1__Add_room_status.sql
    • V250828.2__Delete_room_status.sql

image
  1. 기존 마이그레이션 파일은 절대 수정 금지
    • Flyway는 아래와 같이 flyway_schema_history 테이블을 통해 적용된 마이그레이션을 관리합니다.
    • 이미 적용된 SQL 파일을 수정해도 Flyway는 이를 변경으로 인식하지 않기 때문에 새로운 변경사항이 있다면 반드시 새로운 버전 파일을 추가해주세요!
스크린샷 2025-08-29 오후 4 39 05
  1. 변경 단위는 최소화
    • 특정 컬럼을 추가/수정할 경우 테이블 전체를 재정의할 필요 없이 ALTER TABLE을 이용해 해당 컬럼만 변경해주세요!
스크린샷 2025-08-29 오후 4 48 14
  1. 로컬 환경 검증 절차
    • 로컬 환경의 ddl-auto 옵션을 validate로 변경하여 로컬에서도 Flyway 마이그레이션을 통해 스키마가 적용되는지 확인 가능합니다.
    • 따라서, 로컬에서 먼저 적용/테스트 후에 개발 서버에 머지 부탁드립니다!

  2. 엔티티 반영 필수
    • DB 마이그레이션 후에는 반드시 엔티티 코드에도 동일하게 반영해야 합니다!
    • (예: RoomJpaEntity에 roomStatus 필드 추가 완료)

스크린샷 2025-08-29 오후 4 44 32

📸 스크린샷

💬 리뷰 요구사항

이번 변경 사항

  • Room 테이블에 room_status 컬럼 추가 (기본값: RECRUITING, 조건부 업데이트 포함).
  • Flyway 도입 및 마이그레이션 파일 작성 컨벤션 적용.
스크린샷 2025-08-29 오후 4 40 05
  • RoomStatus 컬럼과 연동되는 API 코드 수정은 별도 PR에서 이어서 진행 예정

📌 PR 진행 시 이러한 점들을 참고해 주세요

* P1 : 꼭 반영해 주세요 (Request Changes) - 이슈가 발생하거나 취약점이 발견되는 케이스 등
* P2 : 반영을 적극적으로 고려해 주시면 좋을 것 같아요 (Comment)
* P3 : 이런 방법도 있을 것 같아요~ 등의 사소한 의견입니다 (Chore)

Summary by CodeRabbit

  • New Features
    • 방 상태(모집중/진행중/종료) 기능 추가. 상태가 데이터베이스에 저장되며, 기존 방은 시작일·종료일 기준으로 자동 업데이트됩니다. 이로써 방 진행 상황을 더 명확하게 파악할 수 있습니다.
  • Chores
    • 데이터베이스 마이그레이션 도구(Flyway) 도입으로 스키마 변경을 안정적으로 관리합니다.
    • 방 테이블에 상태 컬럼 추가 및 초기 데이터 일괄 변환 작업 포함.

@coderabbitai
Copy link

coderabbitai bot commented Aug 29, 2025

Walkthrough

Gradle에 Flyway 의존성을 추가하고, 방 상태(RoomStatus) 필드를 도메인/엔티티/매퍼에 도입했으며, Flyway 마이그레이션 스크립트로 rooms 테이블에 room_status 열을 추가하고 기존 데이터 상태를 날짜 기준으로 갱신했습니다.

Changes

Cohort / File(s) Summary
Infra: Flyway 설정
build.gradle
Flyway 도입을 위한 flyway-core, flyway-mysql 의존성 추가.
DB Migration: room_status 컬럼 추가
src/main/resources/db/migration/V250828__Add_room_status.sql
rooms 테이블에 room_status(VARCHAR(32), NOT NULL, 기본값 RECRUITING) 추가 및 start_date/end_date 기준으로 기존 데이터 상태 업데이트.
Room 상태 모델링 및 매핑 반영
src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java, src/main/java/konkuk/thip/room/adapter/out/jpa/RoomStatus.java, src/main/java/konkuk/thip/room/adapter/out/mapper/RoomMapper.java, src/main/java/konkuk/thip/room/domain/Room.java
- JPA 엔티티에 roomStatus 필드 추가(ENUM STRING, non-null, 기본 RECRUITING), updateFrom에 전파 로직 추가.
- 새 RoomStatus enum 정의(RECRUITING, IN_PROGRESS, EXPIRED).
- 매퍼 양방향 roomStatus 매핑 추가.
- 도메인 RoomroomStatus 필드 및 기본값 설정.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Service as RoomService
  participant Mapper as RoomMapper
  participant JPA as RoomJpaRepository
  participant DB as Database

  rect rgba(200,230,255,0.3)
  note over User,DB: 생성(Recruiting 기본값)
  User->>Service: createRoom(cmd)
  Service->>Mapper: toEntity(Room{roomStatus=RECRUITING})
  Mapper-->>Service: RoomJpaEntity{roomStatus=RECRUITING}
  Service->>JPA: save(entity)
  JPA->>DB: INSERT rooms(room_status=RECRUITING)
  DB-->>JPA: OK
  JPA-->>Service: entity
  Service-->>User: Room
  end

  rect rgba(220,255,220,0.35)
  note over Service,DB: 조회/매핑 시 상태 전파
  User->>Service: getRoom(id)
  Service->>JPA: findById(id)
  JPA->>DB: SELECT * FROM rooms
  DB-->>JPA: row(room_status=IN_PROGRESS|EXPIRED|RECRUITING)
  JPA-->>Service: entity
  Service->>Mapper: toDomain(entity.roomStatus)
  Mapper-->>Service: Room{roomStatus=...}
  Service-->>User: Room
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
Flyway 기반 DB 마이그레이션 도입(#282)
초기 마이그레이션 스크립트 추가 및 적용(#282)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
방 상태 enum 추가 및 사용 도입 (src/main/java/konkuk/thip/room/adapter/out/jpa/RoomStatus.java) 이슈 #282는 Flyway 도입에 한정되어 있으며 도메인 상태 모델 추가는 범위를 초과합니다.
엔티티에 roomStatus 필드 추가 및 updateFrom 수정 (src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java) 마이그레이션 도입과 직접적인 관련이 없고 도메인 모델 확장에 해당합니다.
매퍼에 roomStatus 양방향 매핑 추가 (src/main/java/konkuk/thip/room/adapter/out/mapper/RoomMapper.java) Flyway 도입 범위를 넘어선 애플리케이션 로직 변경입니다.
도메인 RoomroomStatus 필드 및 기본값 추가 (src/main/java/konkuk/thip/room/domain/Room.java) 인프라 과업(#282)과 무관한 도메인 변경입니다.

Poem

밤하늘 깃발, 마이그레 쇼 시작!
깡충깡충, 토끼가 스키마를 삭— 정리했지.
RECRUITING, IN_PROGRESS, 그리고 만료의 박자,
테이블엔 새 칸, 코드엔 새 숨결.
플라이웨이 한 번 퍼덕, 데이터도 고개 끄덕! 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch infra/#282-db-migration

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link

github-actions bot commented Aug 29, 2025

Test Results

426 tests   426 ✅  35s ⏱️
128 suites    0 💤
128 files      0 ❌

Results for commit 1d39c20.

♻️ This comment has been updated with latest results.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/konkuk/thip/room/domain/Room.java (1)

109-111: isExpired의 의미 혼동 가능성(공통 StatusType vs RoomStatus)

현재 isExpired()는 공통 StatusType.EXPIRED를 봅니다. 비즈니스 의미의 방 만료(RoomStatus.EXPIRED)와 혼선 우려가 큽니다. 메서드 명/역할을 분리하세요.

- public boolean isExpired() {
-     return this.getStatus() == StatusType.EXPIRED;
- }
+ public boolean isEntityExpired() { // 시스템 공통 엔티티 상태
+     return this.getStatus() == StatusType.EXPIRED;
+ }
+ public boolean isRoomExpired() {   // 비즈니스 상태
+     return this.roomStatus == RoomStatus.EXPIRED;
+ }
🧹 Nitpick comments (4)
src/main/resources/db/migration/V250828__Add_room_status.sql (3)

1-4: 상태 컬럼 제약/인덱스도 함께 고려해주세요

  • 값 제약: MySQL 8.0.16+ 사용 시 CHECK 제약으로 허용값을 강제하면 데이터 무결성이 좋아집니다.
  • 조회 최적화: room_status로 조회/정렬이 많다면 보조 인덱스 추가를 권장합니다.

적용 예시(별도 버전 파일로 추가 권장):

ALTER TABLE rooms
  ADD CONSTRAINT chk_rooms_room_status
    CHECK (room_status IN ('RECRUITING','IN_PROGRESS','EXPIRED'));

CREATE INDEX idx_rooms_room_status ON rooms(room_status);

6-10: 주석과 조건 불일치

주석은 “이전(<)”이라고 되어 있지만 조건은 “<= CURDATE()”로 오늘 포함입니다. 주석 또는 조건 중 하나를 통일하세요.

- -- 2) start_date가 현재 날짜보다 "이전"이면 IN_PROGRESS로 업데이트
+ -- 2) start_date가 현재 날짜와 같거나 이전(<=)이면 IN_PROGRESS로 업데이트

6-14: 단일 UPDATE로 테이블 스캔/잠금 최소화

두 번의 UPDATE 대신 CASE 한 번으로 갱신하면 락 홀드/스캔 비용을 줄일 수 있습니다. 의미도 동일합니다(만료 우선).

-UPDATE rooms
-SET room_status = 'IN_PROGRESS'
-WHERE start_date <= CURDATE();
-
-UPDATE rooms
-SET room_status = 'EXPIRED'
-WHERE end_date < CURDATE();
+UPDATE rooms
+SET room_status = CASE
+  WHEN end_date < CURRENT_DATE THEN 'EXPIRED'
+  WHEN start_date <= CURRENT_DATE THEN 'IN_PROGRESS'
+  ELSE room_status
+END;
src/main/java/konkuk/thip/room/domain/Room.java (1)

44-45: roomStatus 필드 불변/기본값 보장

빌더 경로로 생성 시 null 가능성이 남습니다. Lombok @Builder.Default 또는 생성자에서 기본값을 강제해 불변식을 보장하세요.

- private RoomStatus roomStatus;
+ @lombok.Builder.Default
+ private RoomStatus roomStatus = RoomStatus.RECRUITING;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3153d83 and 1d39c20.

📒 Files selected for processing (6)
  • build.gradle (1 hunks)
  • src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java (2 hunks)
  • src/main/java/konkuk/thip/room/adapter/out/jpa/RoomStatus.java (1 hunks)
  • src/main/java/konkuk/thip/room/adapter/out/mapper/RoomMapper.java (2 hunks)
  • src/main/java/konkuk/thip/room/domain/Room.java (3 hunks)
  • src/main/resources/db/migration/V250828__Add_room_status.sql (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (7)
build.gradle (1)

81-85: Flyway 의존성 추가 LGTM

Spring Boot 3.5 BOM 하에서 버전 관리도 자동이라 현재 선언 방식이 깔끔합니다.

src/main/resources/db/migration/V250828__Add_room_status.sql (1)

1-14: 문제 없음: RoomJpaEntity@Table(name = "rooms")이 실제 테이블 rooms와 일치하며, start_date·end_date 컬럼도 nullable = false로 설정되어 있어 마이그레이션 스크립트 적용에 문제가 없습니다.

src/main/java/konkuk/thip/room/adapter/out/jpa/RoomStatus.java (1)

3-7: 열거형 정의 자체는 간결하고 적절합니다

값 네이밍과 직렬화(EnumType.STRING 전제) 모두 일관적입니다.

src/main/java/konkuk/thip/room/adapter/out/mapper/RoomMapper.java (1)

22-25: roomStatus 매핑 추가 LGTM

도메인↔JPA 양방향 매핑이 누락 없이 반영됐습니다. 기존 데이터는 NOT NULL+DEFAULT로 null 위험도 낮습니다.

Also applies to: 40-46

src/main/java/konkuk/thip/room/domain/Room.java (3)

68-69: 초기 기본값 설정 LGTM

새 Room 생성시 RECRUITING으로 시작하는 정책이 DB 기본값과 일치합니다.


148-152: 모집 마감 판정 로직 재검토

today.isAfter(startDate.minusDays(1))는 startDate 당일 00:00부터 “모집 마감”으로 봅니다. 기획이 “startDate 전날 23:59:59까지 모집”과 정확히 일치하는지 확인하세요.


176-181: startRoomProgress()에서 startDate 덮어쓰기 대신 상태 전이 적용

-    startDate = LocalDate.now();
+    this.roomStatus = RoomStatus.IN_PROGRESS;

RoomStatus enum에 IN_PROGRESS가 정의되어 있는지, 자정 경계에 맞춰 도메인 서비스/스케줄러에서 상태 전이 정책을 어떻게 운영할지 확인 부탁드립니다.

Comment on lines +53 to +57
@Builder.Default
@Column(name = "room_status", nullable = false)
@Enumerated(EnumType.STRING)
private RoomStatus roomStatus = RoomStatus.RECRUITING;

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

room_status 매핑은 적절. 다만 null 유입 방지(Bean Validation) 추가 필요

@Builder.Default만으로는 빌더가 명시적으로 null을 넣을 때/기본 생성자로 생성 후 세터로 null이 들어갈 때를 막지 못합니다. DB 제약(nullable=false) 위반 또는 INSERT 실패를 예방하려면 @NotNull을 붙여 조기 검증을 권장합니다.

적용 diff:

-    @Builder.Default
-    @Column(name = "room_status", nullable = false)
-    @Enumerated(EnumType.STRING)
-    private RoomStatus roomStatus = RoomStatus.RECRUITING;
+    @Builder.Default
+    @Column(name = "room_status", nullable = false)
+    @Enumerated(EnumType.STRING)
+    @NotNull
+    private RoomStatus roomStatus = RoomStatus.RECRUITING;

추가 import(변경 범위 밖):

import jakarta.validation.constraints.NotNull;

추가로, 생성 경로가 빌더가 아닌 경우를 대비해 PrePersist 가드도 고려 가능합니다(변경 범위 밖):

@PrePersist
void prePersistDefaultStatus() {
    if (roomStatus == null) roomStatus = RoomStatus.RECRUITING;
}
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java around
lines 53 to 57, the roomStatus field relies on @Builder.Default but can still
become null via explicit builder/null setters which would violate the DB
nullable=false constraint; add jakarta.validation.constraints.NotNull to the
roomStatus field (and import jakarta.validation.constraints.NotNull) to enforce
Bean Validation at the entity level, and optionally add a @PrePersist method to
set roomStatus to RoomStatus.RECRUITING if null for non-builder creation paths.

💡 Verification agent

🧩 Analysis chain

계층 의존 역전 가능성: RoomStatus의 패키지 위치 재검토

Enum이 adapter.out.jpa 패키지에 있고, 도메인 객체(Room)가 이를 직접 참조하면 도메인→인프라 의존이 생깁니다. Enum을 도메인 계층(e.g., konkuk.thip.room.domain.value.RoomStatus)으로 승격하거나, 도메인 Enum ↔ JPA Enum 매핑을 명확히 분리해 주세요.

아래 스크립트로 도메인 계층이 adapter의 RoomStatus를 import하는지 확인해 주세요:


🏁 Script executed:

#!/bin/bash
# 도메인 코드에서 adapter.out.jpa.RoomStatus 참조 여부 확인
rg -nP 'import\s+konkuk\.thip\.room\.adapter\.out\.jpa\.RoomStatus' -C2 --type java
# 프로젝트 내 RoomStatus 선언 위치 확인
rg -nP '\benum\s+RoomStatus\b' -C2 --type java

Length of output: 1028


도메인 계층이 infra(adapter) enum을 직접 참조하지 않도록 분리 필요
Room.java(도메인)에서 konkuk.thip.room.adapter.out.jpa.RoomStatus를 import(Line 7)해 도메인→인프라 의존이 발생하고 있습니다.

  • src/main/java/konkuk/thip/room/domain/value 패키지에 도메인 전용 RoomStatus enum을 선언
  • JPA 어댑터 레이어에서는 도메인 enum을 참조하고, @Enumerated 필드 매핑 시 도메인 enum ↔ JPA enum 간 변환 로직(또는 AttributeConverter)을 구현하세요.
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java around
lines 53–57, the JPA layer currently defines/uses an infra enum directly causing
domain→infra coupling; create a domain-only enum class RoomStatus in
src/main/java/konkuk/thip/room/domain/value, update the JPA entity to reference
the domain enum type (not an adapter-specific enum), and implement a conversion
layer: either add a JPA AttributeConverter that maps domain RoomStatus to its DB
representation (String) and annotate the entity field with
@Convert(converter=YourRoomStatusConverter.class) or create explicit mapping
methods between the domain enum and a JPA-specific enum; finally remove any
import of adapter enum from the domain package and ensure the entity uses the
converter so persistence uses the domain enum without introducing domain→infra
dependency.

this.endDate = room.getEndDate();
this.recruitCount = room.getRecruitCount();
this.memberCount = room.getMemberCount();
this.roomStatus = room.getRoomStatus();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

updateFrom에서 roomStatus null 덮어쓰기 방지

room.getRoomStatus()가 null이면 @column(nullable=false) 위반 가능성이 큽니다. null일 때는 필드 유지(또는 예외)하도록 가드하세요.

적용 diff:

-        this.roomStatus = room.getRoomStatus();
+        if (room.getRoomStatus() != null) {
+            this.roomStatus = room.getRoomStatus();
+        }
+        // null을 허용하지 않으려면 다음처럼 실패 빠르게도 고려:
+        // Objects.requireNonNull(room.getRoomStatus(), "roomStatus must not be null");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.roomStatus = room.getRoomStatus();
// updateFrom에서 roomStatus null 덮어쓰기 방지
if (room.getRoomStatus() != null) {
this.roomStatus = room.getRoomStatus();
}
// null을 허용하지 않으려면 다음처럼 빠르게 실패시키는 방법도 고려:
// Objects.requireNonNull(room.getRoomStatus(), "roomStatus must not be null");
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java around line
76, the updateFrom method unconditionally sets this.roomStatus =
room.getRoomStatus(), which can overwrite a non-null DB-mandated field with null
and violate @Column(nullable=false); change the assignment to check for null
first and only assign when room.getRoomStatus() != null (or alternatively throw
a ValidationException when null) so the existing roomStatus is preserved when
the incoming value is null.

Comment on lines +1 to +7
package konkuk.thip.room.adapter.out.jpa;

public enum RoomStatus {
RECRUITING,
IN_PROGRESS,
EXPIRED
}
Copy link

@coderabbitai coderabbitai bot Aug 29, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

패키지 레이어링 역참조(도메인→어댑터) 발생

Room 도메인이 adapter.out.jpa 패키지의 enum을 import합니다. 도메인이 하위 레이어를 참조하지 않도록 RoomStatus를 도메인(or common) 레이어로 승격하고, JPA 엔티티가 그 도메인 enum을 사용하도록 방향을 정리하세요.

예(이 PR 외 파일 변경 수반):

- package konkuk.thip.room.adapter.out.jpa;
+ package konkuk.thip.room.domain;

그리고 Room/RoomJpaEntity/Mapper의 import를 도메인 enum으로 교체.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
package konkuk.thip.room.adapter.out.jpa;
public enum RoomStatus {
RECRUITING,
IN_PROGRESS,
EXPIRED
}
package konkuk.thip.room.domain;
public enum RoomStatus {
RECRUITING,
IN_PROGRESS,
EXPIRED
}
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/room/adapter/out/jpa/RoomStatus.java lines 1-7, the
enum is currently placed in the adapter layer causing a domain→adapter layering
violation; move RoomStatus into the domain (or a shared common) package (e.g.,
src/main/java/konkuk/thip/room/domain/RoomStatus.java or common package), update
its package declaration accordingly, and then change all imports in Room,
RoomJpaEntity, and Mapper to reference the new domain/common enum location so
the JPA entity uses the domain enum rather than the adapter enum.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@coderabbitai enum 의존성은 유연하게 진행하기로 결정했어

Copy link

Choose a reason for hiding this comment

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

@seongjunnoh 네, 알겠습니다! enum 의존성에 대해 유연하게 접근하기로 하신 결정을 이해했어요. 실용적인 구현을 우선시하는 방향으로 진행하시는군요.

(・ω・) ♪


✏️ Learnings added
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#285
File: src/main/java/konkuk/thip/room/adapter/out/jpa/RoomStatus.java:1-7
Timestamp: 2025-08-31T05:25:14.835Z
Learning: seongjunnoh는 enum 의존성에 대해 유연한 접근을 선호하며, 도메인→어댑터 레이어 참조와 같은 아키텍처 layering 원칙보다 실용적인 구현을 우선시한다.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#113
File: src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/RecentSearchCommandPersistenceAdapter.java:38-44
Timestamp: 2025-07-30T14:05:04.945Z
Learning: seongjunnoh는 코드 최적화 제안에 대해 구체적인 기술적 근거와 효율성 차이를 이해하고 싶어하며, 성능 개선 방식에 대한 상세한 설명을 선호한다.

Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#93
File: src/main/java/konkuk/thip/room/adapter/out/persistence/RoomQueryPersistenceAdapter.java:49-114
Timestamp: 2025-07-28T16:44:31.224Z
Learning: seongjunnoh는 코드 중복 문제에 대한 리팩토링 제안을 적극적으로 수용하고 함수형 인터페이스를 활용한 해결책을 선호한다.

Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#195
File: src/main/java/konkuk/thip/feed/application/mapper/FeedQueryMapper.java:0-0
Timestamp: 2025-08-13T05:22:32.287Z
Learning: seongjunnoh는 데이터 무결성과 중복 방지에 대한 고민이 깊으며, LinkedHashSet을 활용한 중복 제거와 순서 보장을 동시에 달성하는 솔루션을 선호한다.

Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#180
File: src/main/java/konkuk/thip/room/application/service/AttendanceCheckCreateService.java:22-40
Timestamp: 2025-08-14T09:15:31.371Z
Learning: seongjunnoh는 기술적 완벽성보다 실제 비즈니스 시나리오와 사용자 행동 패턴을 우선 고려하며, 발생 가능성이 낮은 엣지 케이스보다는 실용적인 구현을 선호한다.

Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#278
File: src/main/java/konkuk/thip/common/exception/code/ErrorCode.java:210-211
Timestamp: 2025-08-24T09:40:48.595Z
Learning: seongjunnoh는 HTTP 상태 코드 선택에 대해 기술적 근거와 코드베이스 내 일관성을 중요하게 생각하며, 구체적인 사례 분석을 통한 설명을 선호한다.

Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#278
File: src/main/java/konkuk/thip/TestTokenController.java:0-0
Timestamp: 2025-08-24T09:33:52.982Z
Learning: seongjunnoh는 Spring의 ConditionalOnProperty 동작 원리를 정확히 이해하고 있으며, 보안 이슈에 대해서도 실질적인 위험성을 기준으로 판단하는 실용적 접근을 선호한다.

Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#112
File: src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepositoryImpl.java:272-272
Timestamp: 2025-07-30T10:44:34.115Z
Learning: seongjunnoh는 피드 커서 페이지네이션에서 LocalDateTime 단일 커서 방식을 선호하며, 복합 키 기반 커서보다 구현 단순성과 성능을 우선시한다.

import konkuk.thip.common.exception.InvalidStateException;
import konkuk.thip.common.entity.StatusType;
import konkuk.thip.common.exception.code.ErrorCode;
import konkuk.thip.room.adapter.out.jpa.RoomStatus;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

도메인에서 어댑터 enum import 회피 필요

도메인 레이어가 adapter 패키지를 참조하지 않도록 RoomStatus를 도메인(or common)으로 이동시킨 뒤 import를 교체하세요.

- import konkuk.thip.room.adapter.out.jpa.RoomStatus;
+ import konkuk.thip.room.domain.RoomStatus; // enum을 도메인으로 이동했다고 가정
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import konkuk.thip.room.adapter.out.jpa.RoomStatus;
// File: src/main/java/konkuk/thip/room/domain/Room.java
import konkuk.thip.room.domain.RoomStatus;
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/room/domain/Room.java around line 7, the class
currently imports the adapter enum konkuk.thip.room.adapter.out.jpa.RoomStatus
which couples the domain to the adapter layer; move RoomStatus out of the
adapter package into the domain (or a shared common package), update the enum's
package declaration accordingly, and replace the import in Room.java with the
new package path so the domain layer no longer depends on adapter code.

Comment on lines +1 to +14
-- 1) 컬럼 추가: 기본값 RECRUITING, NOT NULL
ALTER TABLE rooms
ADD COLUMN room_status VARCHAR(32) NOT NULL DEFAULT 'RECRUITING'
COMMENT 'Room 상태: RECRUITING/IN_PROGRESS/EXPIRED';

-- 2) start_date가 현재 날짜보다 "이전"이면 IN_PROGRESS로 업데이트
UPDATE rooms
SET room_status = 'IN_PROGRESS'
WHERE start_date <= CURDATE();

-- 3) end_date가 현재 날짜보다 "이전"이면 EXPIRED로 업데이트
UPDATE rooms
SET room_status = 'EXPIRED'
WHERE end_date < CURDATE(); No newline at end of file
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

테스트(H2) 환경 호환성 주의

이 스크립트는 MySQL 전용 문법(CURDATE, COMMENT)을 사용합니다. H2에서 Flyway가 실행되면 실패할 수 있습니다. 파일을 MySQL 전용으로 분기(.mysql.sql)하거나 테스트 프로필에서 Flyway 적용을 비활성/분리하세요.

예:

  • 파일명: V250828__Add_room_status.mysql.sql 로 변경
  • (선택) H2 전용 스크립트: V250828__Add_room_status.h2.sql
🤖 Prompt for AI Agents
In src/main/resources/db/migration/V250828__Add_room_status.sql around lines
1-14: the migration uses MySQL-specific syntax (CURDATE(), COMMENT) which will
fail on H2 during tests; fix by making the migration MySQL-only (rename to
V250828__Add_room_status.mysql.sql) and either add a separate H2-compatible
migration (e.g., V250828__Add_room_status.h2.sql) with equivalent logic using H2
functions or disable/apply Flyway migrations differently under the test profile
so H2 does not try to run the MySQL script.

Copy link
Collaborator

@seongjunnoh seongjunnoh left a comment

Choose a reason for hiding this comment

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

제 로컬 yml 에서 ddl-auto 값을 validate로 수정하고, flyway 관련 설정값을 주입하니 flyway_schema_history 테이블이 정상적으로 생기고, room table 의 구조가 정상적으로 수정된 것을 확인했습니다!
추후에 soft delete 적용대상이 아닌 테이블에 대해서 status 필드를 제거하는 리펙토링을 진행할때에도 DB 구조 수정이 필요한데, 이때 유용하게 사용할 수 있을 것 같네요!! 고생하셨습니다!

Comment on lines +3 to +7
public enum RoomStatus {
RECRUITING,
IN_PROGRESS,
EXPIRED
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

굳굳

Copy link
Member

Choose a reason for hiding this comment

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

굳굳


private int memberCount;

private RoomStatus roomStatus;
Copy link
Collaborator

Choose a reason for hiding this comment

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

좋습니다! 도메인 entity 도 그냥 enum 자체를 의존하는게 더 나을 것 같습니다!!

현재 도메인 entity 에서 String 타입으로 enum을 의존하는 코드들도 수정하는게 좋을듯 하네요
언제하죠 하하

Copy link
Member

Choose a reason for hiding this comment

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

ㅜㅜ

Copy link
Member

@hd0rable hd0rable left a comment

Choose a reason for hiding this comment

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

너무 수고하셨습니다!!
로컬에서 적용잘되는것도 확인했습니다!
이제 방 상태만을 나타내는 칼럼이 추가되었으니 기존에 StatusType에서 방만료를 나타내는 상태인 EXPIRED는 없애는게 어떨까요??

Comment on lines +3 to +7
public enum RoomStatus {
RECRUITING,
IN_PROGRESS,
EXPIRED
}
Copy link
Member

Choose a reason for hiding this comment

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

굳굳


private int memberCount;

private RoomStatus roomStatus;
Copy link
Member

Choose a reason for hiding this comment

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

ㅜㅜ

.endDate(endDate)
.recruitCount(recruitCount)
.memberCount(1) // 처음 Room 생성 시 방장 1명
.roomStatus(RoomStatus.RECRUITING) // 처음 Room 생성 시 -> 모집중
Copy link
Member

Choose a reason for hiding this comment

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

좋네여 LGTM

@buzz0331
Copy link
Contributor Author

너무 수고하셨습니다!! 로컬에서 적용잘되는것도 확인했습니다! 이제 방 상태만을 나타내는 칼럼이 추가되었으니 기존에 StatusType에서 방만료를 나타내는 상태인 EXPIRED는 없애는게 어떨까요??

현재 StatusType의 EXPIRED로 방 만료조건을 검증하는 서비스 로직이 존재하는 것 같아서 다음 pr에서 종합적으로 방 만료조건을 변경해서 올려보겠습니다!

@buzz0331 buzz0331 merged commit d551a2e into develop Sep 1, 2025
4 of 6 checks passed
@buzz0331 buzz0331 deleted the infra/#282-db-migration branch September 1, 2025 07:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[THIP2025-325] [infra] DB 마이그레이션 도입

3 participants