From f0ef4270a41e30dd9a6d330dafcf0734ec6c7050 Mon Sep 17 00:00:00 2001 From: sgo722 Date: Mon, 2 Feb 2026 13:08:09 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[fix]=20VALUES/VALUES=5FCODE=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20CURRENT=5FME=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=88=98=EC=A0=95=20(#397)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - VALUES를 회원가입 전용으로 변경 (usedInChat=false, chatGroupPolicy=NONE) - VALUES_CODE 신규 추가 (채팅방 전용, A_THEN_B 정책) - CURRENT_ME usedInSignup=true로 수정 - 관리자 페이지 카테고리 옵션 수정 - V22 마이그레이션 추가 Co-Authored-By: Claude Opus 4.5 --- .../codel/question/domain/QuestionCategory.kt | 21 ++++++++---- .../V22__add_values_code_category.sql | 19 +++++++++++ .../resources/templates/questionEditForm.html | 19 ++++------- .../resources/templates/questionForm.html | 5 +-- .../resources/templates/questionList.html | 5 ++- .../question/domain/QuestionCategoryTest.kt | 34 +++++++++++++++---- 6 files changed, 73 insertions(+), 30 deletions(-) create mode 100644 src/main/resources/db/migration/V22__add_values_code_category.sql diff --git a/src/main/kotlin/codel/question/domain/QuestionCategory.kt b/src/main/kotlin/codel/question/domain/QuestionCategory.kt index d9a7a8c..76a59a7 100644 --- a/src/main/kotlin/codel/question/domain/QuestionCategory.kt +++ b/src/main/kotlin/codel/question/domain/QuestionCategory.kt @@ -15,14 +15,14 @@ enum class QuestionCategory( @Schema(description = "채팅방 그룹 정책") val chatGroupPolicy: GroupPolicy ) { - // 회원가입 + 채팅방 양쪽 사용 - @Schema(description = "가치관 관련 질문 (회원가입 + 채팅방)") + // 회원가입 전용 + @Schema(description = "가치관 관련 질문 (회원가입 전용)") VALUES( displayName = "가치관", description = "인생 가치관·성향", usedInSignup = true, - usedInChat = true, - chatGroupPolicy = GroupPolicy.A_THEN_B + usedInChat = false, + chatGroupPolicy = GroupPolicy.NONE ), // 회원가입 전용 @@ -35,11 +35,11 @@ enum class QuestionCategory( chatGroupPolicy = GroupPolicy.NONE ), - @Schema(description = "현재 상태 관련 질문 (레거시)") + @Schema(description = "현재 상태 관련 질문") CURRENT_ME( displayName = "요즘 나", description = "최근 상태·몰입한 것", - usedInSignup = false, + usedInSignup = true, usedInChat = false, chatGroupPolicy = GroupPolicy.NONE ), @@ -81,6 +81,15 @@ enum class QuestionCategory( ), // 채팅방 전용 + @Schema(description = "가치관 코드 - 가치관으로 서로의 성격 코드 알아가기") + VALUES_CODE( + displayName = "가치관 코드", + description = "가치관으로 서로의 성격 코드 알아가기", + usedInSignup = false, + usedInChat = true, + chatGroupPolicy = GroupPolicy.A_THEN_B + ), + @Schema(description = "텐션업 코드 - 가벼운 선택 질문") TENSION_UP( displayName = "텐션업 코드", diff --git a/src/main/resources/db/migration/V22__add_values_code_category.sql b/src/main/resources/db/migration/V22__add_values_code_category.sql new file mode 100644 index 0000000..19539fe --- /dev/null +++ b/src/main/resources/db/migration/V22__add_values_code_category.sql @@ -0,0 +1,19 @@ +-- VALUES_CODE 카테고리 추가 (채팅방 전용 가치관 코드) +-- Issue: #397 + +-- category ENUM에 VALUES_CODE 추가 +ALTER TABLE question +MODIFY COLUMN category +ENUM( + 'VALUES', + 'VALUES_CODE', + 'FAVORITE', + 'CURRENT_ME', + 'DATE', + 'MEMORY', + 'WANT_TALK', + 'BALANCE_ONE', + 'IF', + 'TENSION_UP', + 'SECRET' +) NOT NULL; diff --git a/src/main/resources/templates/questionEditForm.html b/src/main/resources/templates/questionEditForm.html index 5165a18..ed8cf28 100644 --- a/src/main/resources/templates/questionEditForm.html +++ b/src/main/resources/templates/questionEditForm.html @@ -167,7 +167,7 @@

질문 수정

// 용도별 카테고리 옵션 const categoryOptions = { chatroom: [ - { value: 'VALUES', label: '가치관 코드' }, + { value: 'VALUES_CODE', label: '가치관 코드' }, { value: 'TENSION_UP', label: '텐션업 코드' }, { value: 'IF', label: '만약에 코드' }, { value: 'SECRET', label: '비밀 코드 (19+)' } @@ -175,6 +175,7 @@

질문 수정

profile: [ { value: 'VALUES', label: '가치관' }, { value: 'FAVORITE', label: 'favorite' }, + { value: 'CURRENT_ME', label: '요즘 나' }, { value: 'DATE', label: '데이트' }, { value: 'MEMORY', label: '추억' }, { value: 'WANT_TALK', label: '이런대화해보고싶어' } @@ -183,18 +184,20 @@

질문 수정

// 카테고리별 용도 매핑 const categoryToPurpose = { - 'VALUES': 'both', // 양쪽 모두 가능 + 'VALUES': 'profile', + 'VALUES_CODE': 'chatroom', 'TENSION_UP': 'chatroom', 'IF': 'chatroom', 'SECRET': 'chatroom', 'FAVORITE': 'profile', + 'CURRENT_ME': 'profile', 'DATE': 'profile', 'MEMORY': 'profile', 'WANT_TALK': 'profile' }; // 회원가입 전용 카테고리 (그룹 자동 RANDOM) - const signupOnlyCategories = ['FAVORITE', 'DATE', 'MEMORY', 'WANT_TALK']; + const signupOnlyCategories = ['FAVORITE', 'CURRENT_ME', 'DATE', 'MEMORY', 'WANT_TALK']; const purposeSelect = document.getElementById('purpose'); const categorySelect = document.getElementById('category'); @@ -251,15 +254,7 @@

질문 수정

// 기존 카테고리로 용도 결정 const purpose = categoryToPurpose[currentCategory]; - if (purpose === 'both') { - // VALUES는 채팅방 용도로 기본 설정 (채팅방에서 사용되는 경우가 더 흔함) - // 그룹이 RANDOM이면 profile, 아니면 chatroom으로 추정 - if (currentGroup === 'RANDOM') { - purposeSelect.value = 'profile'; - } else { - purposeSelect.value = 'chatroom'; - } - } else if (purpose === 'chatroom') { + if (purpose === 'chatroom') { purposeSelect.value = 'chatroom'; } else { purposeSelect.value = 'profile'; diff --git a/src/main/resources/templates/questionForm.html b/src/main/resources/templates/questionForm.html index 6eed7c3..776292a 100644 --- a/src/main/resources/templates/questionForm.html +++ b/src/main/resources/templates/questionForm.html @@ -151,7 +151,7 @@

새 질문 등록

// 용도별 카테고리 옵션 const categoryOptions = { chatroom: [ - { value: 'VALUES', label: '가치관 코드' }, + { value: 'VALUES_CODE', label: '가치관 코드' }, { value: 'TENSION_UP', label: '텐션업 코드' }, { value: 'IF', label: '만약에 코드' }, { value: 'SECRET', label: '비밀 코드 (19+)' } @@ -159,6 +159,7 @@

새 질문 등록

profile: [ { value: 'VALUES', label: '가치관' }, { value: 'FAVORITE', label: 'favorite' }, + { value: 'CURRENT_ME', label: '요즘 나' }, { value: 'DATE', label: '데이트' }, { value: 'MEMORY', label: '추억' }, { value: 'WANT_TALK', label: '이런대화해보고싶어' } @@ -166,7 +167,7 @@

새 질문 등록

}; // 회원가입 전용 카테고리 (그룹 자동 RANDOM) - const signupOnlyCategories = ['FAVORITE', 'DATE', 'MEMORY', 'WANT_TALK']; + const signupOnlyCategories = ['FAVORITE', 'CURRENT_ME', 'DATE', 'MEMORY', 'WANT_TALK']; const purposeSelect = document.getElementById('purpose'); const categorySelect = document.getElementById('category'); diff --git a/src/main/resources/templates/questionList.html b/src/main/resources/templates/questionList.html index d3abb51..03a8732 100644 --- a/src/main/resources/templates/questionList.html +++ b/src/main/resources/templates/questionList.html @@ -194,7 +194,7 @@

질문 관리

// 용도별 카테고리 옵션 const categoryOptions = { chatroom: [ - { value: 'VALUES', label: '가치관 코드' }, + { value: 'VALUES_CODE', label: '가치관 코드' }, { value: 'TENSION_UP', label: '텐션업 코드' }, { value: 'IF', label: '만약에 코드' }, { value: 'SECRET', label: '비밀 코드 (19+)' } @@ -202,6 +202,7 @@

질문 관리

profile: [ { value: 'VALUES', label: '가치관' }, { value: 'FAVORITE', label: 'favorite' }, + { value: 'CURRENT_ME', label: '요즘 나' }, { value: 'DATE', label: '데이트' }, { value: 'MEMORY', label: '추억' }, { value: 'WANT_TALK', label: '이런대화해보고싶어' } @@ -225,8 +226,6 @@

질문 관리

html += ''; categoryOptions.profile.forEach(opt => { - // VALUES는 이미 chatroom에서 추가했으므로 profile에서는 생략 - if (opt.value === 'VALUES') return; const selected = selectedCategory === opt.value ? ' selected' : ''; html += ``; }); diff --git a/src/test/kotlin/codel/question/domain/QuestionCategoryTest.kt b/src/test/kotlin/codel/question/domain/QuestionCategoryTest.kt index b35fbd6..1994d76 100644 --- a/src/test/kotlin/codel/question/domain/QuestionCategoryTest.kt +++ b/src/test/kotlin/codel/question/domain/QuestionCategoryTest.kt @@ -11,17 +11,32 @@ class QuestionCategoryTest { @DisplayName("카테고리 용도 테스트") inner class CategoryUsageTest { - @DisplayName("VALUES는 회원가입과 채팅방 양쪽에서 사용된다") + @DisplayName("VALUES는 회원가입에서만 사용된다") @Test - fun values_used_in_both() { + fun values_used_in_signup_only() { // given val category = QuestionCategory.VALUES // then assertTrue(category.usedInSignup) - assertTrue(category.usedInChat) + assertFalse(category.usedInChat) assertTrue(category.isSignupCategory()) + assertFalse(category.isChatCategory()) + assertEquals(GroupPolicy.NONE, category.chatGroupPolicy) + } + + @DisplayName("VALUES_CODE는 채팅방에서만 사용된다") + @Test + fun values_code_used_in_chat_only() { + // given + val category = QuestionCategory.VALUES_CODE + + // then + assertFalse(category.usedInSignup) + assertTrue(category.usedInChat) + assertFalse(category.isSignupCategory()) assertTrue(category.isChatCategory()) + assertEquals(GroupPolicy.A_THEN_B, category.chatGroupPolicy) } @DisplayName("FAVORITE은 회원가입에서만 사용된다") @@ -77,11 +92,11 @@ class QuestionCategoryTest { @DisplayName("그룹 정책 테스트") inner class GroupPolicyTest { - @DisplayName("VALUES는 A_THEN_B 그룹 정책을 사용한다") + @DisplayName("VALUES_CODE는 A_THEN_B 그룹 정책을 사용한다") @Test - fun values_has_a_then_b_policy() { + fun values_code_has_a_then_b_policy() { // given - val category = QuestionCategory.VALUES + val category = QuestionCategory.VALUES_CODE // then assertEquals(GroupPolicy.A_THEN_B, category.chatGroupPolicy) @@ -122,7 +137,9 @@ class QuestionCategoryTest { fun signup_only_categories_have_none_policy() { // given val signupOnlyCategories = listOf( + QuestionCategory.VALUES, QuestionCategory.FAVORITE, + QuestionCategory.CURRENT_ME, QuestionCategory.DATE, QuestionCategory.MEMORY, QuestionCategory.WANT_TALK @@ -149,9 +166,11 @@ class QuestionCategoryTest { // then assertTrue(signupCategories.contains(QuestionCategory.VALUES)) assertTrue(signupCategories.contains(QuestionCategory.FAVORITE)) + assertTrue(signupCategories.contains(QuestionCategory.CURRENT_ME)) assertTrue(signupCategories.contains(QuestionCategory.DATE)) assertTrue(signupCategories.contains(QuestionCategory.MEMORY)) assertTrue(signupCategories.contains(QuestionCategory.WANT_TALK)) + assertFalse(signupCategories.contains(QuestionCategory.VALUES_CODE)) assertFalse(signupCategories.contains(QuestionCategory.TENSION_UP)) assertFalse(signupCategories.contains(QuestionCategory.IF)) assertFalse(signupCategories.contains(QuestionCategory.SECRET)) @@ -164,10 +183,11 @@ class QuestionCategoryTest { val chatCategories = QuestionCategory.getChatCategories() // then - assertTrue(chatCategories.contains(QuestionCategory.VALUES)) + assertTrue(chatCategories.contains(QuestionCategory.VALUES_CODE)) assertTrue(chatCategories.contains(QuestionCategory.TENSION_UP)) assertTrue(chatCategories.contains(QuestionCategory.IF)) assertTrue(chatCategories.contains(QuestionCategory.SECRET)) + assertFalse(chatCategories.contains(QuestionCategory.VALUES)) assertFalse(chatCategories.contains(QuestionCategory.FAVORITE)) assertFalse(chatCategories.contains(QuestionCategory.DATE)) } From 0842edd355881f0c5d3527e648dcb14d868b9c31 Mon Sep 17 00:00:00 2001 From: sgo722 Date: Mon, 2 Feb 2026 18:08:52 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[fix]=20QuestionServiceRecommendationTest?= =?UTF-8?q?=20VALUES=20=E2=86=92=20VALUES=5FCODE=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.5 --- .../question/business/QuestionServiceRecommendationTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/kotlin/codel/question/business/QuestionServiceRecommendationTest.kt b/src/test/kotlin/codel/question/business/QuestionServiceRecommendationTest.kt index b87dd64..748d0de 100644 --- a/src/test/kotlin/codel/question/business/QuestionServiceRecommendationTest.kt +++ b/src/test/kotlin/codel/question/business/QuestionServiceRecommendationTest.kt @@ -53,7 +53,7 @@ class QuestionServiceRecommendationTest { fun recommend_from_group_a_when_available() { // given val chatRoomId = 1L - val category = QuestionCategory.VALUES + val category = QuestionCategory.VALUES_CODE val groupAQuestions = listOf( createQuestion(1L, category, QuestionGroup.A), createQuestion(2L, category, QuestionGroup.A) @@ -82,7 +82,7 @@ class QuestionServiceRecommendationTest { fun recommend_from_group_b_when_group_a_exhausted() { // given val chatRoomId = 1L - val category = QuestionCategory.VALUES + val category = QuestionCategory.VALUES_CODE val groupBQuestions = listOf( createQuestion(3L, category, QuestionGroup.B), createQuestion(4L, category, QuestionGroup.B) @@ -110,7 +110,7 @@ class QuestionServiceRecommendationTest { fun return_exhausted_when_all_groups_exhausted() { // given val chatRoomId = 1L - val category = QuestionCategory.VALUES + val category = QuestionCategory.VALUES_CODE `when`(questionJpaRepository.findUnusedQuestionsByChatRoomAndCategoryAndGroup( chatRoomId, category, QuestionGroup.A