From f1e72d4912dd22fb5933de479a0bac4e40946118 Mon Sep 17 00:00:00 2001 From: leedy5521 Date: Mon, 16 Feb 2026 18:53:07 +0900 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=ED=8C=A8=ED=84=B4=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/DuplicatedIdCheckRequest.java | 12 +-- .../controller/MemberControllerTest.java | 86 +++++++++++++++++-- 2 files changed, 87 insertions(+), 11 deletions(-) diff --git a/clokey-api/src/main/java/org/clokey/domain/member/dto/request/DuplicatedIdCheckRequest.java b/clokey-api/src/main/java/org/clokey/domain/member/dto/request/DuplicatedIdCheckRequest.java index 5760cb71..44751b3a 100644 --- a/clokey-api/src/main/java/org/clokey/domain/member/dto/request/DuplicatedIdCheckRequest.java +++ b/clokey-api/src/main/java/org/clokey/domain/member/dto/request/DuplicatedIdCheckRequest.java @@ -1,13 +1,15 @@ package org.clokey.domain.member.dto.request; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; public record DuplicatedIdCheckRequest( - @NotNull(message = "닉네임은 비워둘 수 없습니다.") + @NotBlank(message = "닉네임은 비워둘 수 없습니다.") + @Size(max = 20, message = "닉네임은 20자 이하여야 합니다.") @Pattern( - regexp = "^[a-z0-9._]+$", - message = "닉네임은 영어 소문자, 숫자, 언더바(_), 점(.)만 허용됩니다.") - @Schema(description = "중복을 확인할 닉네임", example = "clokey11") + regexp = "^[a-z가-힣._]+$", + message = "닉네임은 영어 소문자, 한글, 언더바(_), 점(.)만 허용됩니다.") + @Schema(description = "중복을 확인할 닉네임", example = "clokey.홍길동") String nickname) {} diff --git a/clokey-api/src/test/java/org/clokey/domain/member/controller/MemberControllerTest.java b/clokey-api/src/test/java/org/clokey/domain/member/controller/MemberControllerTest.java index fd34a6e3..3ef9e68d 100644 --- a/clokey-api/src/test/java/org/clokey/domain/member/controller/MemberControllerTest.java +++ b/clokey-api/src/test/java/org/clokey/domain/member/controller/MemberControllerTest.java @@ -1,5 +1,6 @@ package org.clokey.domain.member.controller; +import static org.hamcrest.Matchers.containsString; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.willDoNothing; @@ -94,7 +95,9 @@ class 프로필_수정_요청_시 { .andExpect(jsonPath("$.isSuccess").value(false)) .andExpect(jsonPath("$.code").value("COMMON400")) .andExpect(jsonPath("$.message").value("잘못된 요청입니다.")) - .andExpect(jsonPath("$.result.nickname").value("닉네임은 비워둘 수 없습니다.")); + .andExpect( + jsonPath("$.result.nickname") + .value(containsString("닉네임은 비워둘 수 없습니다."))); } @ParameterizedTest @@ -121,7 +124,9 @@ class 프로필_수정_요청_시 { .andExpect(jsonPath("$.isSuccess").value(false)) .andExpect(jsonPath("$.code").value("COMMON400")) .andExpect(jsonPath("$.message").value("잘못된 요청입니다.")) - .andExpect(jsonPath("$.result.nickname").value("닉네임은 비워둘 수 없습니다.")); + .andExpect( + jsonPath("$.result.nickname") + .value(containsString("닉네임은 비워둘 수 없습니다."))); } @Test @@ -157,7 +162,7 @@ class 아이디_중복확인_요청_시 { @Test void 유효한_요청이면_중복_여부를_반환한다() throws Exception { // given - DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest("test_clokey_id"); + DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest("clokey.홍길동"); DuplicatedIdCheckResponse response = new DuplicatedIdCheckResponse(true); given(memberService.checkDuplicateNickname(request)).willReturn(response); @@ -197,9 +202,34 @@ class 아이디_중복확인_요청_시 { .andExpect(jsonPath("$.result.nickname").value("닉네임은 비워둘 수 없습니다.")); } - // 허용 종류 : 영문(소문자) , 숫자, 언더바(_), 점(.) @ParameterizedTest - @ValueSource(strings = {"clokey clokey", "CLOKEY", "클로키", "clokey-user", "clokey,,user^^"}) + @NullAndEmptySource + @ValueSource(strings = {" "}) + void 닉네임이_비어있으면_예외가_발생한다(String nickname) throws Exception { + // given + DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest(nickname); + + // when + ResultActions perform = + mockMvc.perform( + post("/users/check-duplicate-nickname") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))); + + // then + perform.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.isSuccess").value(false)) + .andExpect(jsonPath("$.code").value("COMMON400")) + .andExpect(jsonPath("$.message").value("잘못된 요청입니다.")) + .andExpect( + jsonPath("$.result.nickname") + .value(containsString("닉네임은 비워둘 수 없습니다."))); + } + + // 허용 종류 : 영어 소문자, 한글, 언더바(_), 점(.) + @ParameterizedTest + @ValueSource( + strings = {"clokey clokey", "CLOKEY", "clokey-user", "clokey,,user^^", "clokey1"}) void 닉네임_제약조건을_위배하면_예외가_발생한다(String nickname) throws Exception { // given DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest(nickname); @@ -218,7 +248,51 @@ class 아이디_중복확인_요청_시 { .andExpect(jsonPath("$.message").value("잘못된 요청입니다.")) .andExpect( jsonPath("$.result.nickname") - .value("닉네임은 영어 소문자, 숫자, 언더바(_), 점(.)만 허용됩니다.")); + .value("닉네임은 영어 소문자, 한글, 언더바(_), 점(.)만 허용됩니다.")); + } + + @Test + void 닉네임이_20자를_초과하면_예외가_발생한다() throws Exception { + // given + DuplicatedIdCheckRequest request = + new DuplicatedIdCheckRequest("abcdefghijklmnopqrstu"); + + // when + ResultActions perform = + mockMvc.perform( + post("/users/check-duplicate-nickname") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))); + + // then + perform.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.isSuccess").value(false)) + .andExpect(jsonPath("$.code").value("COMMON400")) + .andExpect(jsonPath("$.message").value("잘못된 요청입니다.")) + .andExpect(jsonPath("$.result.nickname").value("닉네임은 20자 이하여야 합니다.")); + } + + @ParameterizedTest + @ValueSource(strings = {"clokey", "홍길동", "clokey.홍길동", "abc_def"}) + void 닉네임_제약조건을_만족하면_중복_여부를_반환한다(String nickname) throws Exception { + // given + DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest(nickname); + DuplicatedIdCheckResponse response = new DuplicatedIdCheckResponse(false); + given(memberService.checkDuplicateNickname(request)).willReturn(response); + + // when + ResultActions perform = + mockMvc.perform( + post("/users/check-duplicate-nickname") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))); + + // then + perform.andExpect(status().isOk()) + .andExpect(jsonPath("$.isSuccess").value(true)) + .andExpect(jsonPath("$.code").value("COMMON200")) + .andExpect(jsonPath("$.message").value("성공입니다.")) + .andExpect(jsonPath("$.result.duplicated").value(false)); } } From d8e811601780c3c1590998595f34a6a0a93f1528 Mon Sep 17 00:00:00 2001 From: leedy5521 Date: Mon, 16 Feb 2026 19:10:10 +0900 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20DuplicatedNicknameCheckRequest?= =?UTF-8?q?=EB=A1=9Crecord=EB=AA=85=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= =?UTF-8?q?=ED=95=98=EA=B3=A0=20=EA=B4=80=EB=A0=A8=20=EC=B0=B8=EC=A1=B0=20?= =?UTF-8?q?=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EB=AA=A8?= =?UTF-8?q?=EB=91=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 4 ++-- ...java => DuplicatedNicknameCheckRequest.java} | 2 +- .../domain/member/service/MemberService.java | 4 ++-- .../member/service/MemberServiceImpl.java | 5 +++-- .../member/controller/MemberControllerTest.java | 17 +++++++++-------- .../member/service/MemberServiceTest.java | 7 ++++--- 6 files changed, 21 insertions(+), 18 deletions(-) rename clokey-api/src/main/java/org/clokey/domain/member/dto/request/{DuplicatedIdCheckRequest.java => DuplicatedNicknameCheckRequest.java} (94%) diff --git a/clokey-api/src/main/java/org/clokey/domain/member/controller/MemberController.java b/clokey-api/src/main/java/org/clokey/domain/member/controller/MemberController.java index 32226907..9918fdfd 100644 --- a/clokey-api/src/main/java/org/clokey/domain/member/controller/MemberController.java +++ b/clokey-api/src/main/java/org/clokey/domain/member/controller/MemberController.java @@ -6,7 +6,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.clokey.code.GlobalBaseSuccessCode; -import org.clokey.domain.member.dto.request.DuplicatedIdCheckRequest; +import org.clokey.domain.member.dto.request.DuplicatedNicknameCheckRequest; import org.clokey.domain.member.dto.request.ProfileUpdateRequest; import org.clokey.domain.member.dto.response.*; import org.clokey.domain.member.service.MemberService; @@ -42,7 +42,7 @@ public BaseResponse updateProfile(@Valid @RequestBody ProfileUpdateRequest summary = "닉네임 중복확인", description = "닉네임 중복을 확인합니다.") public BaseResponse checkDuplicateNickname( - @Valid @RequestBody DuplicatedIdCheckRequest request) { + @Valid @RequestBody DuplicatedNicknameCheckRequest request) { DuplicatedIdCheckResponse response = memberService.checkDuplicateNickname(request); return BaseResponse.onSuccess(GlobalBaseSuccessCode.OK, response); diff --git a/clokey-api/src/main/java/org/clokey/domain/member/dto/request/DuplicatedIdCheckRequest.java b/clokey-api/src/main/java/org/clokey/domain/member/dto/request/DuplicatedNicknameCheckRequest.java similarity index 94% rename from clokey-api/src/main/java/org/clokey/domain/member/dto/request/DuplicatedIdCheckRequest.java rename to clokey-api/src/main/java/org/clokey/domain/member/dto/request/DuplicatedNicknameCheckRequest.java index 44751b3a..5c6f3a7d 100644 --- a/clokey-api/src/main/java/org/clokey/domain/member/dto/request/DuplicatedIdCheckRequest.java +++ b/clokey-api/src/main/java/org/clokey/domain/member/dto/request/DuplicatedNicknameCheckRequest.java @@ -5,7 +5,7 @@ import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; -public record DuplicatedIdCheckRequest( +public record DuplicatedNicknameCheckRequest( @NotBlank(message = "닉네임은 비워둘 수 없습니다.") @Size(max = 20, message = "닉네임은 20자 이하여야 합니다.") @Pattern( diff --git a/clokey-api/src/main/java/org/clokey/domain/member/service/MemberService.java b/clokey-api/src/main/java/org/clokey/domain/member/service/MemberService.java index ed55ddab..2d57148b 100644 --- a/clokey-api/src/main/java/org/clokey/domain/member/service/MemberService.java +++ b/clokey-api/src/main/java/org/clokey/domain/member/service/MemberService.java @@ -1,6 +1,6 @@ package org.clokey.domain.member.service; -import org.clokey.domain.member.dto.request.DuplicatedIdCheckRequest; +import org.clokey.domain.member.dto.request.DuplicatedNicknameCheckRequest; import org.clokey.domain.member.dto.request.ProfileUpdateRequest; import org.clokey.domain.member.dto.response.*; import org.clokey.global.paging.SortDirection; @@ -10,7 +10,7 @@ public interface MemberService { void updateProfile(ProfileUpdateRequest request); - DuplicatedIdCheckResponse checkDuplicateNickname(DuplicatedIdCheckRequest request); + DuplicatedIdCheckResponse checkDuplicateNickname(DuplicatedNicknameCheckRequest request); void toggleFollow(Long userId); diff --git a/clokey-api/src/main/java/org/clokey/domain/member/service/MemberServiceImpl.java b/clokey-api/src/main/java/org/clokey/domain/member/service/MemberServiceImpl.java index 1fa39c04..27825525 100644 --- a/clokey-api/src/main/java/org/clokey/domain/member/service/MemberServiceImpl.java +++ b/clokey-api/src/main/java/org/clokey/domain/member/service/MemberServiceImpl.java @@ -4,7 +4,7 @@ import java.util.Optional; import lombok.RequiredArgsConstructor; import org.clokey.domain.history.repository.HistoryRepository; -import org.clokey.domain.member.dto.request.DuplicatedIdCheckRequest; +import org.clokey.domain.member.dto.request.DuplicatedNicknameCheckRequest; import org.clokey.domain.member.dto.request.ProfileUpdateRequest; import org.clokey.domain.member.dto.response.*; import org.clokey.domain.member.event.NewFollowerEvent; @@ -70,7 +70,8 @@ public void updateProfile(ProfileUpdateRequest request) { } @Override - public DuplicatedIdCheckResponse checkDuplicateNickname(DuplicatedIdCheckRequest request) { + public DuplicatedIdCheckResponse checkDuplicateNickname( + DuplicatedNicknameCheckRequest request) { final Member currentMember = memberUtil.getCurrentMember(); boolean duplicated = diff --git a/clokey-api/src/test/java/org/clokey/domain/member/controller/MemberControllerTest.java b/clokey-api/src/test/java/org/clokey/domain/member/controller/MemberControllerTest.java index 3ef9e68d..4df72cc4 100644 --- a/clokey-api/src/test/java/org/clokey/domain/member/controller/MemberControllerTest.java +++ b/clokey-api/src/test/java/org/clokey/domain/member/controller/MemberControllerTest.java @@ -10,7 +10,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; -import org.clokey.domain.member.dto.request.DuplicatedIdCheckRequest; +import org.clokey.domain.member.dto.request.DuplicatedNicknameCheckRequest; import org.clokey.domain.member.dto.request.ProfileUpdateRequest; import org.clokey.domain.member.dto.response.*; import org.clokey.domain.member.service.MemberService; @@ -162,7 +162,8 @@ class 아이디_중복확인_요청_시 { @Test void 유효한_요청이면_중복_여부를_반환한다() throws Exception { // given - DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest("clokey.홍길동"); + DuplicatedNicknameCheckRequest request = + new DuplicatedNicknameCheckRequest("clokey.홍길동"); DuplicatedIdCheckResponse response = new DuplicatedIdCheckResponse(true); given(memberService.checkDuplicateNickname(request)).willReturn(response); @@ -185,7 +186,7 @@ class 아이디_중복확인_요청_시 { @Test void 닉네임이_null이면_예외가_발생한다() throws Exception { // given - DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest(null); + DuplicatedNicknameCheckRequest request = new DuplicatedNicknameCheckRequest(null); // when ResultActions perform = @@ -207,7 +208,7 @@ class 아이디_중복확인_요청_시 { @ValueSource(strings = {" "}) void 닉네임이_비어있으면_예외가_발생한다(String nickname) throws Exception { // given - DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest(nickname); + DuplicatedNicknameCheckRequest request = new DuplicatedNicknameCheckRequest(nickname); // when ResultActions perform = @@ -232,7 +233,7 @@ class 아이디_중복확인_요청_시 { strings = {"clokey clokey", "CLOKEY", "clokey-user", "clokey,,user^^", "clokey1"}) void 닉네임_제약조건을_위배하면_예외가_발생한다(String nickname) throws Exception { // given - DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest(nickname); + DuplicatedNicknameCheckRequest request = new DuplicatedNicknameCheckRequest(nickname); // when ResultActions perform = @@ -254,8 +255,8 @@ class 아이디_중복확인_요청_시 { @Test void 닉네임이_20자를_초과하면_예외가_발생한다() throws Exception { // given - DuplicatedIdCheckRequest request = - new DuplicatedIdCheckRequest("abcdefghijklmnopqrstu"); + DuplicatedNicknameCheckRequest request = + new DuplicatedNicknameCheckRequest("abcdefghijklmnopqrstu"); // when ResultActions perform = @@ -276,7 +277,7 @@ class 아이디_중복확인_요청_시 { @ValueSource(strings = {"clokey", "홍길동", "clokey.홍길동", "abc_def"}) void 닉네임_제약조건을_만족하면_중복_여부를_반환한다(String nickname) throws Exception { // given - DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest(nickname); + DuplicatedNicknameCheckRequest request = new DuplicatedNicknameCheckRequest(nickname); DuplicatedIdCheckResponse response = new DuplicatedIdCheckResponse(false); given(memberService.checkDuplicateNickname(request)).willReturn(response); diff --git a/clokey-api/src/test/java/org/clokey/domain/member/service/MemberServiceTest.java b/clokey-api/src/test/java/org/clokey/domain/member/service/MemberServiceTest.java index c6f22465..5fdedf9e 100644 --- a/clokey-api/src/test/java/org/clokey/domain/member/service/MemberServiceTest.java +++ b/clokey-api/src/test/java/org/clokey/domain/member/service/MemberServiceTest.java @@ -7,7 +7,7 @@ import java.util.Optional; import org.clokey.IntegrationTest; import org.clokey.TransactionUtil; -import org.clokey.domain.member.dto.request.DuplicatedIdCheckRequest; +import org.clokey.domain.member.dto.request.DuplicatedNicknameCheckRequest; import org.clokey.domain.member.dto.request.ProfileUpdateRequest; import org.clokey.domain.member.dto.response.BlockedMemberResponse; import org.clokey.domain.member.dto.response.FollowMemberResponse; @@ -135,7 +135,7 @@ void setUp() { @ValueSource(strings = {"testNickname1", "distinctId1", "distinctId2"}) void 현재_닉네임_또는_중복되지_않는_닉네임을_입력하면_false를_반환한다(String nickname) { // given - DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest(nickname); + DuplicatedNicknameCheckRequest request = new DuplicatedNicknameCheckRequest(nickname); // when& then assertThat(memberService.checkDuplicateNickname(request).duplicated()).isFalse(); @@ -144,7 +144,8 @@ void setUp() { @Test void 중복되는_닉네임을_입력한_경우_true를_반환한다() { // given - DuplicatedIdCheckRequest request = new DuplicatedIdCheckRequest("testNickname2"); + DuplicatedNicknameCheckRequest request = + new DuplicatedNicknameCheckRequest("testNickname2"); // when& then assertThat(memberService.checkDuplicateNickname(request).duplicated()).isTrue();