Skip to content

feat: 모의지원 최대 지망 수를 동적으로 관리하도록#746

Open
whqtker wants to merge 22 commits into
developfrom
feat/733-dynamic-choice-count
Open

feat: 모의지원 최대 지망 수를 동적으로 관리하도록#746
whqtker wants to merge 22 commits into
developfrom
feat/733-dynamic-choice-count

Conversation

@whqtker

@whqtker whqtker commented Jun 9, 2026

Copy link
Copy Markdown
Member

관련 이슈

작업 내용

1. 엔티티 구조 변경

  • Application 엔티티에서 firstChoice / secondChoice / thirdChoiceUnivApplyInfoId 컬럼을 제거했습니다.
  • @Embeddable 클래스 ApplicationChoice 를 추가했습니다. (잘 몰랐는데 @ElementCollection 매핑 대상 클래스는 @Embeddable이 있어야 한다고 하더라고요 ..)
  • application_choice@ElementCollection으로 매핑했습니다.
@Query("""
       SELECT DISTINCT a
       FROM Application a
       JOIN a.choices c
       WHERE c.univApplyInfoId IN :univApplyInfoIds
           AND a.verifyStatus = :status
           AND a.termId = :termId
           AND a.isDelete = false
       """)
List<Application> findAllByUnivApplyInfoIds(
        @Param("univApplyInfoIds") List<Long> univApplyInfoIds,
        @Param("status") VerifyStatus status,
        @Param("termId") long termId);
  • Application을 조회하는 과정에서, ApplicationChoice 컬렉션을 로드하기 위해 추가 쿼리가 발생할 수 있습니다(N+1 문제). 이를 방지하기 위해 @BatchSize(size = 100)를 적용했습니다.
  • HomeUniversity 엔티티에 maxChoiceCount 컬럼을 추가했습니다.
  • 모의지원 시 최대 지망 수를 초과 시 처리도 구현되었습니다.

2. DTO 구조 변경

  • 어드민에서 국내 대학 정보 추가 시 요청 DTO에 maxChoiceCount 또한 받도록 수정했습니다.
  • 모의지원 관련 DTO에서 3지망 고정 필드를 List<> 타입으로 변경했습니다.

3. 검증 로직 변경

  • 기존의 2지망이 있어야 2지망이 있어야 한다 와 같은 검증을 변경했습니다. (Validator)

4. 스키마 관련

  • 1, 2, 3지망에 대한 인덱스를 삭제했습니다.
  • 추후 데이터 마이그레이션 후 컬럼 또한 삭제할 예정입니다.

5. 테스트 코드 변경

특이 사항

리뷰 요구사항 (선택)

작업 범위가 꽤 큽니다. 엣지 케이스 위주로 봐주시면 감사하겠습니다 !

@whqtker whqtker self-assigned this Jun 9, 2026
@whqtker whqtker requested review from Gyuhyeok99 and wibaek as code owners June 9, 2026 08:49
@whqtker whqtker added the 기능 label Jun 9, 2026
@whqtker whqtker added the 최종 리뷰 최소 1명 필수 label Jun 9, 2026
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

🎯 Walkthrough

  1. 도메인 재구성: Application 엔티티의 고정 3개 선택 필드를 List choices로 통합했습니다.
  2. 홈대학 확장: HomeUniversity에 maxChoiceCount 필드를 추가하고 관련 DTO·서비스에 반영했습니다.
  3. 요청/응답 스키마: UnivApplyInfoChoiceRequest, UnivApplyInfoResponse, ApplicationsResponse 등 선택 관련 DTO가 리스트 기반으로 통일되었습니다.
  4. 검증·에러: ValidUnivApplyInfoChoiceValidator가 리스트(null/빈/중복) 기준 검증으로 변경되고 ErrorCode에 INVALID_UNIV_APPLY_INFO_CHOICE, CHOICE_COUNT_EXCEEDS_LIMIT가 추가되었습니다.
  5. 제출 흐름: ApplicationSubmissionService가 maxChoiceCount 해석, 선택 개수 검증, buildChoices 생성, 일괄 UnivApplyInfo 조회로 흐름을 재구성했습니다.
  6. 조회·분류: ApplicationRepository 쿼리가 choices 컬렉션을 JOIN하도록 바뀌고 ApplicationQueryService는 가변 maxChoiceCount로 분류합니다.
  7. SiteUser 조회: SiteUserFilterRepositoryImpl는 최신 Application의 choices를 정렬해 UnivApplyInfo 이름 매핑으로 반환하도록 변경되었습니다.
  8. DB 변경 및 테스트: 마이그레이션(V50)으로 max_choice_count 컬럼과 application_choice 테이블을 추가하고, 픽스처·빌더·테스트 케이스를 리스트 기반으로 전면 갱신했습니다.

🎯 Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

📋 Suggested Reviewers

  • Gyuhyeok99
  • lsy1307
  • wibaek
  • Hexeong
  • JAEHEE25
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 제목이 주요 변경사항을 명확하게 나타냅니다. 모의지원 최대 지망 수의 동적 관리라는 핵심 기능을 간결하게 표현했습니다.
Description check ✅ Passed PR 설명이 대부분 완성되었습니다. 엔티티 구조 변경, DTO 구조 변경, 검증 로직 변경, 스키마 변경, 테스트 코드 변경을 명확히 구분하여 설명했으며, 리뷰 요구사항도 제시했습니다.
Linked Issues check ✅ Passed PR이 연결된 이슈 #744의 목표인 국내 대학별 최대 지망 수 동적 관리를 구현했습니다. HomeUniversity.maxChoiceCount 추가, Application 엔티티 구조 변경, DTO 및 검증 로직 업데이트로 요구사항을 충족합니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 최대 지망 수 동적 관리 기능과 직접 관련이 있습니다. 엔티티, DTO, 검증, 스키마, 테스트 변경이 일관되게 이 목표를 지원합니다.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/733-dynamic-choice-count

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 074b5408cb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main/resources/db/migration/V50__dynamic_choice_count.sql

@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: 7

Caution

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

⚠️ Outside diff range comments (1)
src/test/java/com/example/solidconnection/admin/university/service/AdminHomeUniversityServiceTest.java (1)

182-191: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

2) \t같은 이름 수정 성공 케이스에 maxChoiceCount 검증이 빠져 있습니다

요청에 maxChoiceCount를 넣었는데 성공 검증은 이름만 확인하고 있어, 수정 매핑 누락 회귀를 놓칠 수 있습니다. 응답(또는 DB 재조회)에서 maxChoiceCount도 함께 단언해 주세요.

🤖 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/example/solidconnection/admin/university/service/AdminHomeUniversityServiceTest.java`
around lines 182 - 191, The test method 같은_이름으로_수정하면_성공한다 in
AdminHomeUniversityServiceTest is only asserting the name was updated but
ignores maxChoiceCount; update the assertion to also verify maxChoiceCount was
changed (either assert response.maxChoiceCount() equals the request value 3 or
reload the entity from the repository and assert
homeUniversity.getMaxChoiceCount() == 3) so the AdminHomeUniversityUpdateRequest
-> adminHomeUniversityService.updateHomeUniversity mapping for maxChoiceCount is
covered.
🧹 Nitpick comments (1)
src/main/java/com/example/solidconnection/application/domain/ApplicationChoice.java (1)

7-24: ⚡ Quick win

equals()hashCode() 구현을 권장합니다.

  1. 현재 상태

    • @Embeddable 클래스에 equals()/hashCode()가 없습니다.
  2. 잠재적 문제

    • Hibernate는 @ElementCollection의 변경 감지 시 equals()를 사용합니다.
    • 기본 Object identity 비교로 인해 의도치 않은 dirty checking 동작이 발생할 수 있습니다.
    • 컬렉션 내 요소 비교 및 제거 시 예상과 다르게 동작할 수 있습니다.
♻️ equals/hashCode 구현 제안
 `@Embeddable`
 `@Getter`
 public class ApplicationChoice {

     `@Column`(name = "choice_order", nullable = false)
     private int choiceOrder;

     `@Column`(name = "univ_apply_info_id", nullable = false)
     private long univApplyInfoId;

     protected ApplicationChoice() {
     }

     public ApplicationChoice(int choiceOrder, long univApplyInfoId) {
         this.choiceOrder = choiceOrder;
         this.univApplyInfoId = univApplyInfoId;
     }
+
+    `@Override`
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ApplicationChoice that = (ApplicationChoice) o;
+        return choiceOrder == that.choiceOrder && univApplyInfoId == that.univApplyInfoId;
+    }
+
+    `@Override`
+    public int hashCode() {
+        return Objects.hash(choiceOrder, univApplyInfoId);
+    }
 }

java.util.Objects import 추가가 필요합니다.

🤖 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/main/java/com/example/solidconnection/application/domain/ApplicationChoice.java`
around lines 7 - 24, Implement proper equality for the embeddable
ApplicationChoice by adding equals(Object) and hashCode() that base equality on
the fields choiceOrder and univApplyInfoId (use java.util.Objects for null-safe
comparison / hashing); update ApplicationChoice to include these methods so
Hibernate’s ElementCollection dirty-checking and collection operations work
correctly—add the import java.util.Objects and implement equals to check
instance/type then compare choiceOrder and univApplyInfoId, and implement
hashCode to return Objects.hash(choiceOrder, univApplyInfoId).
🤖 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/java/com/example/solidconnection/application/dto/UnivApplyInfoResponse.java`:
- Around line 17-20: The mapping for choiceNames in UnivApplyInfoResponse can
insert nulls because nameById.get(choice.getUnivApplyInfoId()) may return null;
update the logic that builds choiceNames (the stream using
ApplicationChoice::getChoiceOrder and ApplicationChoice::getUnivApplyInfoId) to
defensively handle missing keys—either filter out choices with no name, replace
nulls with a sensible default (e.g., empty string or "Unknown"), or throw a
clear exception when data invariants are violated; ensure the chosen behavior is
applied consistently and documented in UnivApplyInfoResponse construction.

In
`@src/main/java/com/example/solidconnection/siteuser/repository/custom/SiteUserFilterRepositoryImpl.java`:
- Around line 350-358: The current collect into Map<Long,String> using
tuples.stream().collect(Collectors.toMap(...)) will NPE if
t.get(univApplyInfo.koreanName) is null and may produce nulls in the resulting
choiceNames when nameById lacks an entry; update the collection logic to
defensively handle null values by supplying a non-null value or merge function
to Collectors.toMap (use t.get(univApplyInfo.koreanName) == null ? "" :
thatValue or similar) and then when building choiceNames from univApplyInfoIds
map missing IDs to a safe default (e.g., empty string) or filter them out so
choiceNames contains no nulls; reference the tuples stream, univApplyInfo.id,
univApplyInfo.koreanName, nameById map and univApplyInfoIds when applying the
fix.

In
`@src/main/java/com/example/solidconnection/university/domain/HomeUniversity.java`:
- Around line 28-34: HomeUniversity의 maxChoiceCount가 0 또는 음수가 들어갈 수 있어 도메인 검증을
추가해야 합니다; HomeUniversity 클래스의 생성자와 update(String name, int maxChoiceCount) 메서드에서
maxChoiceCount <= 0일 경우 IllegalArgumentException(또는 도메인 전용 예외)을 던지도록 검증을 추가하고,
메시지는 "maxChoiceCount must be >= 1"처럼 명확히 표현하세요; 또한 필드 선언부나 JPA 엔티티
제약(annotation)만으로는 부족하므로 비즈니스 요구(최소 1)를 반영하는 검증 로직을 생성자와 update 메서드에 중복 없이 호출되는
private validateMaxChoiceCount(int) 같은 헬퍼 메서드로 분리해 재사용하세요.

In `@src/main/resources/db/migration/V50__dynamic_choice_count.sql`:
- Around line 4-12: Add a foreign key constraint on
application_choice.univ_apply_info_id referencing univ_apply_info(id) to enforce
referential integrity (e.g., name it fk_app_choice_univ_apply_info) and also
create an index on application_choice.univ_apply_info_id to improve lookup
performance; update the CREATE TABLE or add ALTER TABLE / CREATE INDEX
statements that reference the application_choice table and the univ_apply_info
id column accordingly.

In
`@src/test/java/com/example/solidconnection/application/fixture/ApplicationFixtureBuilder.java`:
- Around line 66-73: The ApplicationFixtureBuilder currently constructs
Application with a hard-coded max choice count of 1, which prevents tests from
exercising multi-choice scenarios; update the builder to accept and store a
configurable maxChoiceCount parameter (exposed on the builder's
API/constructor), replace the literal 1 in the Application(...) call with that
stored maxChoiceCount, and update any builder creation sites/tests to pass the
desired maxChoiceCount so fixtures can create 2+ choice applications when needed
(reference ApplicationFixtureBuilder and the Application(...) constructor call
and the maxChoiceCount builder field).

In
`@src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java`:
- Around line 127-131: The test in ApplicationQueryServiceTest currently uses
assertThat(response.choices().get(0)).containsAll(...), which only checks for
presence and can miss extra/unexpected entries; update the assertion to assert
strict equality regardless of order by replacing containsAll with
containsExactlyInAnyOrder so that ApplicantsResponse.of(...) entries must match
exactly (use response.choices().get(0) and the same ApplicantsResponse.of(...)
expected values).

In
`@src/test/java/com/example/solidconnection/university/fixture/HomeUniversityFixtureBuilder.java`:
- Around line 31-33: The create() method in HomeUniversityFixtureBuilder
currently reuses an existing HomeUniversity found by name via
homeUniversityRepository.findByName(name) without verifying maxChoiceCount,
causing tests requesting a different maxChoiceCount to get the wrong fixture;
update create() so that after finding an existing HomeUniversity you compare its
getMaxChoiceCount() to the builder's maxChoiceCount and if they differ set the
new value on the entity and persist it (e.g., call
homeUniversityRepository.save(existing) or an update method), otherwise return
the existing entity; reference HomeUniversityFixtureBuilder.create,
homeUniversityRepository.findByName, HomeUniversity.getMaxChoiceCount(), and
homeUniversityRepository.save() when making the change.

---

Outside diff comments:
In
`@src/test/java/com/example/solidconnection/admin/university/service/AdminHomeUniversityServiceTest.java`:
- Around line 182-191: The test method 같은_이름으로_수정하면_성공한다 in
AdminHomeUniversityServiceTest is only asserting the name was updated but
ignores maxChoiceCount; update the assertion to also verify maxChoiceCount was
changed (either assert response.maxChoiceCount() equals the request value 3 or
reload the entity from the repository and assert
homeUniversity.getMaxChoiceCount() == 3) so the AdminHomeUniversityUpdateRequest
-> adminHomeUniversityService.updateHomeUniversity mapping for maxChoiceCount is
covered.

---

Nitpick comments:
In
`@src/main/java/com/example/solidconnection/application/domain/ApplicationChoice.java`:
- Around line 7-24: Implement proper equality for the embeddable
ApplicationChoice by adding equals(Object) and hashCode() that base equality on
the fields choiceOrder and univApplyInfoId (use java.util.Objects for null-safe
comparison / hashing); update ApplicationChoice to include these methods so
Hibernate’s ElementCollection dirty-checking and collection operations work
correctly—add the import java.util.Objects and implement equals to check
instance/type then compare choiceOrder and univApplyInfoId, and implement
hashCode to return Objects.hash(choiceOrder, univApplyInfoId).
🪄 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: 9303249c-c45a-4c36-8c1e-356aff3eeb78

📥 Commits

Reviewing files that changed from the base of the PR and between 022bde6 and 074b540.

📒 Files selected for processing (27)
  • src/main/java/com/example/solidconnection/admin/dto/UnivApplyInfoResponse.java
  • src/main/java/com/example/solidconnection/admin/university/dto/AdminHomeUniversityCreateRequest.java
  • src/main/java/com/example/solidconnection/admin/university/dto/AdminHomeUniversityResponse.java
  • src/main/java/com/example/solidconnection/admin/university/dto/AdminHomeUniversityUpdateRequest.java
  • src/main/java/com/example/solidconnection/admin/university/service/AdminHomeUniversityService.java
  • src/main/java/com/example/solidconnection/application/domain/Application.java
  • src/main/java/com/example/solidconnection/application/domain/ApplicationChoice.java
  • src/main/java/com/example/solidconnection/application/dto/ApplicationsResponse.java
  • src/main/java/com/example/solidconnection/application/dto/UnivApplyInfoChoiceRequest.java
  • src/main/java/com/example/solidconnection/application/dto/UnivApplyInfoResponse.java
  • src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java
  • src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java
  • src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java
  • src/main/java/com/example/solidconnection/common/exception/ErrorCode.java
  • src/main/java/com/example/solidconnection/siteuser/repository/custom/SiteUserFilterRepositoryImpl.java
  • src/main/java/com/example/solidconnection/university/domain/HomeUniversity.java
  • src/main/java/com/example/solidconnection/university/dto/validation/ValidUnivApplyInfoChoiceValidator.java
  • src/main/resources/db/migration/V50__dynamic_choice_count.sql
  • src/test/java/com/example/solidconnection/admin/service/AdminUserServiceTest.java
  • src/test/java/com/example/solidconnection/admin/university/service/AdminHomeUniversityServiceTest.java
  • src/test/java/com/example/solidconnection/application/fixture/ApplicationFixture.java
  • src/test/java/com/example/solidconnection/application/fixture/ApplicationFixtureBuilder.java
  • src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java
  • src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java
  • src/test/java/com/example/solidconnection/university/dto/validation/ValidUnivApplyInfoChoiceValidatorTest.java
  • src/test/java/com/example/solidconnection/university/fixture/HomeUniversityFixture.java
  • src/test/java/com/example/solidconnection/university/fixture/HomeUniversityFixtureBuilder.java

Comment thread src/main/resources/db/migration/V50__dynamic_choice_count.sql
@whqtker whqtker changed the title feat: 최대 지망 수를 동적으로 관리하도록 feat: 모의지원 최대 지망 수를 동적으로 관리하도록 Jun 9, 2026
whqtker added 5 commits June 10, 2026 09:29
- 저장 전에 검증하여 잘못된 id가 DB에 삽입되는 경우 방지
- 중복 조회 제거
- 최대 1지망 지원 가능
- 응답의 개수를 정확히 판별하기 위해

@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.

Caution

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

⚠️ Outside diff range comments (2)
src/main/resources/db/migration/V50__dynamic_choice_count.sql (2)

5-17: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

2. 동일 지원서의 중복 지망을 DB가 막지 못합니다.

현재 PK가 (application_id, choice_order)라서 같은 univ_apply_info_id를 다른 순번으로 여러 번 넣을 수 있습니다. 이번 변경에서 중복 지망을 invalid로 보는 계약이라면, 스키마에도 (application_id, univ_apply_info_id) 유니크 제약을 같이 두는 편이 안전합니다.

🤖 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/main/resources/db/migration/V50__dynamic_choice_count.sql` around lines 5
- 17, The schema allows the same univ_apply_info_id to be added multiple times
for one application because the PK is (application_id, choice_order); add a
unique constraint on (application_id, univ_apply_info_id) to prevent duplicate
choices. Modify the application_choice table definition to include a UNIQUE
constraint (or create a unique index) named e.g. ux_app_choice_app_univ
(referencing table application_choice and columns application_id and
univ_apply_info_id) so the DB enforces uniqueness at insert/update.

5-20: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

1. 기존 지원서의 지망 데이터 이관 단계가 빠져 있습니다.

Application 저장 모델을 application_choice로 전환하는데, 이 마이그레이션에는 기존 first/second/third 지망 값을 새 테이블로 옮기는 단계가 없습니다. 지금 상태로 배포하면 기존 지원서는 choices가 비어 있는 것으로 읽혀서 조회/분류 결과가 깨질 가능성이 큽니다. 최소한 백필 SQL을 같은 릴리스에 포함하거나, 엔티티 전환 전후를 분리한 2단계 배포로 가야 합니다.

🤖 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/main/resources/db/migration/V50__dynamic_choice_count.sql` around lines 5
- 20, The migration creates a new application_choice table but omits backfilling
existing first/second/third choice columns, so existing Application rows will
lose choices; add steps to migrate data from
application.first_choice_university_info_for_apply_id,
application.second_choice_university_info_for_apply_id and
application.third_choice_university_info_for_apply_id into application_choice
(INSERT INTO application_choice (application_id, choice_order,
univ_apply_info_id) SELECT id, 1/2/3, <column> FROM application WHERE <column>
IS NOT NULL) before dropping or changing those columns, or split this into two
migrations (1: add table and backfill, 2: remove old columns) to ensure no data
loss and consistent reads; reference the application_choice table and the
columns
first_choice_university_info_for_apply_id/second_choice_university_info_for_apply_id/third_choice_university_info_for_apply_id
and the application primary key to implement the backfill and ordering.
🤖 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.

Outside diff comments:
In `@src/main/resources/db/migration/V50__dynamic_choice_count.sql`:
- Around line 5-17: The schema allows the same univ_apply_info_id to be added
multiple times for one application because the PK is (application_id,
choice_order); add a unique constraint on (application_id, univ_apply_info_id)
to prevent duplicate choices. Modify the application_choice table definition to
include a UNIQUE constraint (or create a unique index) named e.g.
ux_app_choice_app_univ (referencing table application_choice and columns
application_id and univ_apply_info_id) so the DB enforces uniqueness at
insert/update.
- Around line 5-20: The migration creates a new application_choice table but
omits backfilling existing first/second/third choice columns, so existing
Application rows will lose choices; add steps to migrate data from
application.first_choice_university_info_for_apply_id,
application.second_choice_university_info_for_apply_id and
application.third_choice_university_info_for_apply_id into application_choice
(INSERT INTO application_choice (application_id, choice_order,
univ_apply_info_id) SELECT id, 1/2/3, <column> FROM application WHERE <column>
IS NOT NULL) before dropping or changing those columns, or split this into two
migrations (1: add table and backfill, 2: remove old columns) to ensure no data
loss and consistent reads; reference the application_choice table and the
columns
first_choice_university_info_for_apply_id/second_choice_university_info_for_apply_id/third_choice_university_info_for_apply_id
and the application primary key to implement the backfill and ordering.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 818d8abc-33fd-4589-8a06-f66ff8b8d3e8

📥 Commits

Reviewing files that changed from the base of the PR and between 074b540 and bf5cbfa.

📒 Files selected for processing (6)
  • src/main/java/com/example/solidconnection/application/domain/Application.java
  • src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java
  • src/main/resources/data.sql
  • src/main/resources/db/migration/V50__dynamic_choice_count.sql
  • src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java
  • src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java
  • src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java
  • src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java
  • src/main/java/com/example/solidconnection/application/domain/Application.java

@sukangpunch sukangpunch left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

전반적으로 고정 3지망 구조에서 동적 지망 수로 잘 전환되었습니다. 아래 몇 가지 개선 포인트를 남깁니다.

@Service
public class ApplicationQueryService {

private static final int DEFAULT_MAX_CHOICE_COUNT = 3;

@sukangpunch sukangpunch Jun 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ApplicationQueryService와 ApplicationSubmissionService 동일하게 선언되어 있습니다. 나중에 기본 지망 수 정책이 바뀔 때 한쪽만 수정되는 버그가 생길 수 있어요.


public HomeUniversity 인하대학교(int maxChoiceCount) {
return homeUniversityFixtureBuilder.homeUniversity()
.name("인하대학교_" + maxChoiceCount + "지망")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

"인하대학교_2지망"처럼 숫자가 포함된 대학명이 생성되면 테스트 실패 메시지에서 맥락 파악이 어려울 수 있습니다. 이름 대신 별도 픽스처 메서드를 두거나, 아예 다른 가상의 대학명을 사용하는 편이 명확합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

기능 최종 리뷰 최소 1명 필수

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 국내 대학별로 최대 지망 수를 동적으로 관리한다.

2 participants