From c3eae5c719eed58e975d1df85ed62b83376ceed4 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Mon, 21 Sep 2026 21:47:20 +0900 Subject: [PATCH] =?UTF-8?q?[Chore]=20=ED=9B=88=EC=9E=A5=20=EC=84=A4?= =?UTF-8?q?=EB=AA=85=EA=B3=BC=20=EB=AF=B8=EC=85=98=20=EC=A0=9C=EB=AA=A9?= =?UTF-8?q?=EC=9D=98=20=ED=95=9C=EA=B8=80=20=EC=88=98=EB=A5=BC=20=EC=88=AB?= =?UTF-8?q?=EC=9E=90=EB=A1=9C=20=EB=B0=94=EA=BE=BC=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 훈장 설명 12개를 숫자로 바꾸고 말투를 담백하게 고친다. 새벽반과 올빼미는 판정 시간(SolveScan 의 05~08시, 00~03시)을 설명에 적는다 - 미션 제목 6개는 V47 마이그레이션의 UPDATE 로 바꾼다. V30, V33 을 고치면 이미 적용된 환경에서 Flyway 체크섬이 어긋난다 - 테스트 시드가 V47 까지 읽게 하고, 옛 문구를 비교하던 테스트를 새 문구로 맞춘다 Closes #341 --- .../achievement/entity/Achievement.java | 24 +++++++++---------- .../folder/repository/FolderRepository.java | 4 ++-- .../V47__use_digits_in_mission_titles.sql | 15 ++++++++++++ .../controller/AchievementControllerTest.java | 2 +- .../service/AchievementServiceTest.java | 2 +- .../mission/MissionSeedMigrationTest.java | 18 +++++++++----- .../controller/MissionControllerTest.java | 2 +- .../service/MissionClaimHistoryTest.java | 2 +- .../support/MissionDefinitionSeeder.java | 3 ++- 9 files changed, 47 insertions(+), 25 deletions(-) create mode 100644 src/main/resources/db/migration/V47__use_digits_in_mission_titles.sql diff --git a/src/main/java/com/aisip/OnO/backend/achievement/entity/Achievement.java b/src/main/java/com/aisip/OnO/backend/achievement/entity/Achievement.java index ae065d64..8879dea2 100644 --- a/src/main/java/com/aisip/OnO/backend/achievement/entity/Achievement.java +++ b/src/main/java/com/aisip/OnO/backend/achievement/entity/Achievement.java @@ -26,40 +26,40 @@ @Getter public enum Achievement { - FIRST_STEP("first_step", "첫 걸음", "오답노트를 처음 적었어요", + FIRST_STEP("first_step", "첫 걸음", "오답노트를 처음 작성했어요", 1, false, AchievementStats::problemCount), - ARCHIVIST("archivist", "기록광", "오답노트를 백 개나 모았어요", + ARCHIVIST("archivist", "기록광", "오답노트를 100개 작성했어요", 100, true, AchievementStats::problemCount), - PERSISTENCE("persistence", "집념", "한 문제를 다섯 번 다시 봤어요", + PERSISTENCE("persistence", "집념", "한 문제를 5번 복습했어요", 5, true, AchievementStats::maxSolveCountOnOneProblem), - PHOENIX("phoenix", "불사조", "틀렸던 문제를 기어이 맞혔어요", + PHOENIX("phoenix", "불사조", "틀렸던 문제를 다시 풀어 맞혔어요", 1, false, AchievementStats::comebackCount), - DAWN_CLASS("dawn_class", "새벽반", "해 뜨기 전에 열 번 공부했어요", + DAWN_CLASS("dawn_class", "새벽반", "새벽 5~8시에 10번 복습했어요", 10, true, AchievementStats::dawnSolveCount), - NIGHT_OWL("night_owl", "올빼미", "밤이 깊어도 열 번 공부했어요", + NIGHT_OWL("night_owl", "올빼미", "밤 12~3시에 10번 복습했어요", 10, true, AchievementStats::nightSolveCount), - PERFECT_MONTH("perfect_month", "개근", "서른 날을 하루도 안 빼먹었어요", + PERFECT_MONTH("perfect_month", "개근", "30일 연속 출석했어요", 30, true, AchievementStats::longestLoginStreak), - FLAWLESS("flawless", "무결점", "열 번을 내리 맞혔어요", + FLAWLESS("flawless", "무결점", "10번 연속으로 맞혔어요", 10, true, AchievementStats::longestCorrectStreak), - ORGANIZER("organizer", "정리의 신", "폴더를 열 개나 만들어 정리했어요", + ORGANIZER("organizer", "정리의 신", "폴더를 10개 만들었어요", 10, true, AchievementStats::folderCount), - REVIEWER("reviewer", "회고왕", "복습하고 쉰 번을 되돌아봤어요", + REVIEWER("reviewer", "회고왕", "복습 회고를 50번 남겼어요", 50, true, AchievementStats::reflectionCount), - COMPANION("companion", "동행", "같이 공부할 사람을 찾았어요", + COMPANION("companion", "동행", "스터디룸에 처음 참여했어요", 1, true, AchievementStats::studyRoomCount), - CHEERLEADER("cheerleader", "응원단장", "백 번을 응원했어요", + CHEERLEADER("cheerleader", "응원단장", "응원을 100번 보냈어요", 100, true, AchievementStats::reactionCount); /** diff --git a/src/main/java/com/aisip/OnO/backend/folder/repository/FolderRepository.java b/src/main/java/com/aisip/OnO/backend/folder/repository/FolderRepository.java index 389c6fb8..9833a277 100644 --- a/src/main/java/com/aisip/OnO/backend/folder/repository/FolderRepository.java +++ b/src/main/java/com/aisip/OnO/backend/folder/repository/FolderRepository.java @@ -79,8 +79,8 @@ public interface FolderRepository extends JpaRepository, FolderRep * 훈장 '정리의 신' 판정용. 루트 폴더는 빼고 센다. * *

{@code FolderService.initializeDefaultFoldersIfAbsent} 가 가입 시점에 루트 폴더와 기본 하위 - * 폴더를 자동으로 만든다. 전부 세면 아무것도 안 한 사람이 2/10 에서 시작해 "폴더를 열 개나 만들어 - * 정리했어요" 라는 말과 안 맞는다. + * 폴더를 자동으로 만든다. 전부 세면 아무것도 안 한 사람이 2/10 에서 시작해 "폴더를 10개 + * 만들었어요" 라는 말과 안 맞는다. * *

기본 하위 폴더까지 빼지 않는 이유는 그쪽은 이름으로만 거를 수 있기 때문이다. 사용자가 이름을 * 바꾸는 순간 판정이 달라진다. 루트는 {@code parentFolder IS NULL} 이라는 구조로 걸러져 이름과 무관하다. diff --git a/src/main/resources/db/migration/V47__use_digits_in_mission_titles.sql b/src/main/resources/db/migration/V47__use_digits_in_mission_titles.sql new file mode 100644 index 00000000..9a9432b8 --- /dev/null +++ b/src/main/resources/db/migration/V47__use_digits_in_mission_titles.sql @@ -0,0 +1,15 @@ +-- 미션 제목의 수를 한글 수사에서 숫자로 바꾼다. +-- +-- V33 은 제목을 한글 수사로 통일했는데, 앱 QA 에서 수는 숫자로 적기로 했다(이슈 #341). +-- 설명은 V33 에서 이미 숫자라 제목만 고친다. code 와 목표값은 그대로라 진행도와 보상은 바뀌지 않는다. +-- +-- V30, V33 을 고치지 않는 이유는 V33 과 같다. 이미 적용된 환경에서 Flyway 체크섬이 어긋난다. +-- 열 권의 노트 -> 오답노트 10개 (무엇을 열 개 하라는 건지 설명을 봐야 읽혔다) +-- 세 번의 완주 -> 복습 세트 3번 완주 (무엇의 완주인지 분명해진다) + +UPDATE mission_definition SET title = '3문제만' WHERE code = 'DAILY_REVIEW_3'; +UPDATE mission_definition SET title = '3문제 맞히기' WHERE code = 'DAILY_CORRECT_3'; +UPDATE mission_definition SET title = '5일 접속하기' WHERE code = 'WEEKLY_ATTEND_5'; +UPDATE mission_definition SET title = '오답노트 10개' WHERE code = 'WEEKLY_NOTE_10'; +UPDATE mission_definition SET title = '30문제 복습' WHERE code = 'WEEKLY_REVIEW_30'; +UPDATE mission_definition SET title = '복습 세트 3번 완주' WHERE code = 'WEEKLY_SET_3'; diff --git a/src/test/java/com/aisip/OnO/backend/achievement/controller/AchievementControllerTest.java b/src/test/java/com/aisip/OnO/backend/achievement/controller/AchievementControllerTest.java index a7944d10..10f9b4d1 100644 --- a/src/test/java/com/aisip/OnO/backend/achievement/controller/AchievementControllerTest.java +++ b/src/test/java/com/aisip/OnO/backend/achievement/controller/AchievementControllerTest.java @@ -30,7 +30,7 @@ void returnsAllTwelveInOrder() throws Exception { "first_step", "archivist", "persistence", "phoenix", "dawn_class", "night_owl", "perfect_month", "flawless", "organizer", "reviewer", "companion", "cheerleader"))) .andExpect(jsonPath("$.data.achievements[0].nameKo").value("첫 걸음")) - .andExpect(jsonPath("$.data.achievements[0].descriptionKo").value("오답노트를 처음 적었어요")) + .andExpect(jsonPath("$.data.achievements[0].descriptionKo").value("오답노트를 처음 작성했어요")) .andExpect(jsonPath("$.data.achievements[0].imageUrl").value("assets/Medal/first_step.png")) .andExpect(jsonPath("$.data.achievements[0].earned").value(false)) .andExpect(jsonPath("$.data.achievements[0].earnedAt").doesNotExist()) diff --git a/src/test/java/com/aisip/OnO/backend/achievement/service/AchievementServiceTest.java b/src/test/java/com/aisip/OnO/backend/achievement/service/AchievementServiceTest.java index 0543cd2c..2a5bd497 100644 --- a/src/test/java/com/aisip/OnO/backend/achievement/service/AchievementServiceTest.java +++ b/src/test/java/com/aisip/OnO/backend/achievement/service/AchievementServiceTest.java @@ -179,7 +179,7 @@ void defaultFoldersDoNotInflateProgress() { folderService.initializeDefaultFoldersIfAbsent(user.getId()); assertThat(itemOf(user, "organizer").current()) - .as("아무것도 안 한 사람이 2/10 에서 시작하면 '폴더를 열 개나 만들어 정리했어요' 와 안 맞는다") + .as("아무것도 안 한 사람이 2/10 에서 시작하면 '폴더를 10개 만들었어요' 와 안 맞는다") .isLessThanOrEqualTo(1L); } diff --git a/src/test/java/com/aisip/OnO/backend/mission/MissionSeedMigrationTest.java b/src/test/java/com/aisip/OnO/backend/mission/MissionSeedMigrationTest.java index 722b1c99..b96d66ff 100644 --- a/src/test/java/com/aisip/OnO/backend/mission/MissionSeedMigrationTest.java +++ b/src/test/java/com/aisip/OnO/backend/mission/MissionSeedMigrationTest.java @@ -36,6 +36,7 @@ class MissionSeedMigrationTest extends MissionSystemTestSupport { private static final String CLAIMED_INDEX_MIGRATION = "db/migration/V31__add_mission_progress_claimed_index.sql"; private static final String REWARD_SNAPSHOT_MIGRATION = "db/migration/V32__add_mission_progress_reward_snapshot.sql"; private static final String WORDING_MIGRATION = "db/migration/V33__refine_mission_definition_wording.sql"; + private static final String DIGIT_TITLE_MIGRATION = "db/migration/V47__use_digits_in_mission_titles.sql"; @Autowired private MissionDefinitionSeeder missionDefinitionSeeder; @@ -125,10 +126,12 @@ SELECT COUNT(*) @DisplayName("문구 수정은 V30 을 고치지 않고 새 마이그레이션의 UPDATE 로 얹는다") void wordingIsAppliedAsUpdate() { // V30 을 고치면 이미 적용된 환경에서 Flyway 체크섬이 어긋나 앱이 뜨지 않는다. - String wording = statementsOf(WORDING_MIGRATION); + for (String migration : List.of(WORDING_MIGRATION, DIGIT_TITLE_MIGRATION)) { + String wording = statementsOf(migration); - assertThat(wording).contains("UPDATE MISSION_DEFINITION"); - assertThat(wording).doesNotContain("INSERT INTO"); + assertThat(wording).as(migration).contains("UPDATE MISSION_DEFINITION"); + assertThat(wording).as(migration).doesNotContain("INSERT INTO"); + } } @Test @@ -145,10 +148,13 @@ void appliesRefinedWording() { assertThat(definitionOf("WEEKLY_REVIEW_30").getDescription()).isEqualTo("오답 30문제 복습하기"); assertThat(definitionOf("WEEKLY_SET_3").getDescription()).isEqualTo("복습 세트 3개 끝내기"); - assertThat(definitionOf("DAILY_CORRECT_3").getTitle()).isEqualTo("세 문제 맞히기"); + assertThat(definitionOf("DAILY_REVIEW_3").getTitle()).isEqualTo("3문제만"); + assertThat(definitionOf("DAILY_CORRECT_3").getTitle()).isEqualTo("3문제 맞히기"); assertThat(definitionOf("DAILY_PRACTICE_SET").getTitle()).isEqualTo("복습 세트 완주"); - assertThat(definitionOf("WEEKLY_ATTEND_5").getTitle()).isEqualTo("닷새 접속하기"); - assertThat(definitionOf("WEEKLY_REVIEW_30").getTitle()).isEqualTo("서른 문제 복습"); + assertThat(definitionOf("WEEKLY_ATTEND_5").getTitle()).isEqualTo("5일 접속하기"); + assertThat(definitionOf("WEEKLY_NOTE_10").getTitle()).isEqualTo("오답노트 10개"); + assertThat(definitionOf("WEEKLY_REVIEW_30").getTitle()).isEqualTo("30문제 복습"); + assertThat(definitionOf("WEEKLY_SET_3").getTitle()).isEqualTo("복습 세트 3번 완주"); } @Test diff --git a/src/test/java/com/aisip/OnO/backend/mission/controller/MissionControllerTest.java b/src/test/java/com/aisip/OnO/backend/mission/controller/MissionControllerTest.java index f1d452b5..cb6d127b 100644 --- a/src/test/java/com/aisip/OnO/backend/mission/controller/MissionControllerTest.java +++ b/src/test/java/com/aisip/OnO/backend/mission/controller/MissionControllerTest.java @@ -145,7 +145,7 @@ void getClaimHistory() throws Exception { .andExpect(jsonPath("$.data.totalClaimedCount").value(1)) .andExpect(jsonPath("$.data.content[0].progressId").value(progressId)) .andExpect(jsonPath("$.data.content[0].code").value(WEEKLY_NOTE_10)) - .andExpect(jsonPath("$.data.content[0].title").value("열 권의 노트")) + .andExpect(jsonPath("$.data.content[0].title").value("오답노트 10개")) .andExpect(jsonPath("$.data.content[0].iconKey").value("note_write")) .andExpect(jsonPath("$.data.content[0].category").value("WEEKLY")) .andExpect(jsonPath("$.data.content[0].periodKey").value("2020-W36")) diff --git a/src/test/java/com/aisip/OnO/backend/mission/service/MissionClaimHistoryTest.java b/src/test/java/com/aisip/OnO/backend/mission/service/MissionClaimHistoryTest.java index fcdecb80..f49fcab8 100644 --- a/src/test/java/com/aisip/OnO/backend/mission/service/MissionClaimHistoryTest.java +++ b/src/test/java/com/aisip/OnO/backend/mission/service/MissionClaimHistoryTest.java @@ -62,7 +62,7 @@ void carriesMissionDetail() { assertThat(item.progressId()).isEqualTo(progressId); assertThat(item.code()).isEqualTo(WEEKLY_NOTE_10); - assertThat(item.title()).isEqualTo("열 권의 노트"); + assertThat(item.title()).isEqualTo("오답노트 10개"); assertThat(item.iconKey()).isEqualTo("note_write"); assertThat(item.category().name()).isEqualTo("WEEKLY"); assertThat(item.periodKey()).isEqualTo("2020-W36"); diff --git a/src/test/java/com/aisip/OnO/backend/mission/support/MissionDefinitionSeeder.java b/src/test/java/com/aisip/OnO/backend/mission/support/MissionDefinitionSeeder.java index 4b40213f..cb13c790 100644 --- a/src/test/java/com/aisip/OnO/backend/mission/support/MissionDefinitionSeeder.java +++ b/src/test/java/com/aisip/OnO/backend/mission/support/MissionDefinitionSeeder.java @@ -38,7 +38,8 @@ public class MissionDefinitionSeeder { */ private static final List MIGRATION_PATHS = List.of( "db/migration/V30__seed_mission_definitions.sql", - "db/migration/V33__refine_mission_definition_wording.sql" + "db/migration/V33__refine_mission_definition_wording.sql", + "db/migration/V47__use_digits_in_mission_titles.sql" ); @PersistenceContext