From 8b6fc287d4b049aec1f8a19a5e4b44cd2d7eab62 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Sat, 2 Aug 2025 23:52:48 +0900 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20=EC=9E=A5=EB=A5=B4=20max=203?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/application/dto/request/UserSignUpRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/seeat/server/domain/user/application/dto/request/UserSignUpRequest.java b/src/main/java/com/seeat/server/domain/user/application/dto/request/UserSignUpRequest.java index abd764f8..165407bc 100644 --- a/src/main/java/com/seeat/server/domain/user/application/dto/request/UserSignUpRequest.java +++ b/src/main/java/com/seeat/server/domain/user/application/dto/request/UserSignUpRequest.java @@ -38,7 +38,7 @@ public class UserSignUpRequest { * 좋아하는 영화 장르 */ @NotNull(message = "좋아하는 영화 장르는 필수입니다.") - @Size(min = 1, message = "최소 하나 이상의 장르가 필요합니다.") + @Size(min = 1, max = 3, message = "1개~3개 사이의 장르가 필요합니다.") @Schema(description = "유저가 선호하는 영화 장르", example = "[\"ACTION\", \"COMEDY\",\"SF\"]") private List genres; From 377f494a114301528c050894576277103dedbd9b Mon Sep 17 00:00:00 2001 From: soo0711 Date: Sun, 3 Aug 2025 00:18:25 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EC=95=84=EC=9D=B4=EB=94=94=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=ED=99=95=EC=9D=B8=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/UserNicknameResponse.java | 24 +++++++++++++++++++ .../user/application/service/UserService.java | 13 ++++++++++ .../user/application/usecase/UserUseCase.java | 4 ++++ .../domain/repository/UserRepository.java | 2 ++ .../user/presentation/UserController.java | 10 ++++++++ .../swagger/UserControllerSpec.java | 18 +++++++++++--- .../security/config/RequestMatcherHolder.java | 1 + 7 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/seeat/server/domain/user/application/dto/response/UserNicknameResponse.java diff --git a/src/main/java/com/seeat/server/domain/user/application/dto/response/UserNicknameResponse.java b/src/main/java/com/seeat/server/domain/user/application/dto/response/UserNicknameResponse.java new file mode 100644 index 00000000..067f95de --- /dev/null +++ b/src/main/java/com/seeat/server/domain/user/application/dto/response/UserNicknameResponse.java @@ -0,0 +1,24 @@ +package com.seeat.server.domain.user.application.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; + +@Builder +@Schema(name = "[응답][유저] 유저 닉네임 중복 확인 Response",description = "유저 닉네임 중복 확인에 대한 DTO 입니다.") +public record UserNicknameResponse( + @Schema(description = "중복 여부", example = "false") + boolean duplicated, + @Schema(description = "결과 메시지", example = "사용 가능한 닉네임입니다.") + String message +) { + + // 정적 팩토리 메소드 + public static UserNicknameResponse from(boolean duplicated){ + return UserNicknameResponse.builder() + .duplicated(duplicated) + .message(duplicated + ? "닉네임이 사용 중입니다. 다른 닉네임을 사용해주세요." + : "닉네임 사용 가능합니다.") + .build(); + } +} diff --git a/src/main/java/com/seeat/server/domain/user/application/service/UserService.java b/src/main/java/com/seeat/server/domain/user/application/service/UserService.java index 6ef9fd46..296be455 100644 --- a/src/main/java/com/seeat/server/domain/user/application/service/UserService.java +++ b/src/main/java/com/seeat/server/domain/user/application/service/UserService.java @@ -3,6 +3,7 @@ import com.seeat.server.domain.theater.domain.entity.Auditorium; import com.seeat.server.domain.theater.domain.repository.AuditoriumRepository; import com.seeat.server.domain.user.application.dto.request.UserSignUpRequest; +import com.seeat.server.domain.user.application.dto.response.UserNicknameResponse; import com.seeat.server.domain.user.application.usecase.UserUseCase; import com.seeat.server.domain.user.domain.entity.User; import com.seeat.server.domain.user.domain.entity.UserAuditorium; @@ -55,6 +56,18 @@ public Optional getUserByEmail(String email) { return repository.findByEmail(email); } + /** + * 닉네임 중복 확인 로직 + * + * @param nickname 사용할 닉네임 + * @return true, false + */ + @Override + public UserNicknameResponse isNicknameDuplicated (String nickname){ + return UserNicknameResponse.from(repository.existsByNickname(nickname)); + } + + /** * 가입한 소셜 종류와 소셜 ID으로 최초 로그인인지 확인 로직 * diff --git a/src/main/java/com/seeat/server/domain/user/application/usecase/UserUseCase.java b/src/main/java/com/seeat/server/domain/user/application/usecase/UserUseCase.java index ccda7cc9..6643b4e3 100644 --- a/src/main/java/com/seeat/server/domain/user/application/usecase/UserUseCase.java +++ b/src/main/java/com/seeat/server/domain/user/application/usecase/UserUseCase.java @@ -1,6 +1,7 @@ package com.seeat.server.domain.user.application.usecase; import com.seeat.server.domain.user.application.dto.request.UserSignUpRequest; +import com.seeat.server.domain.user.application.dto.response.UserNicknameResponse; import com.seeat.server.domain.user.domain.entity.User; import com.seeat.server.domain.user.domain.entity.UserSocial; import com.seeat.server.security.oauth2.application.dto.TempUserInfo; @@ -15,6 +16,9 @@ public interface UserUseCase { // 이메일 중복 확인 Optional getUserByEmail(String email); + // 닉네임 중복 확인 + UserNicknameResponse isNicknameDuplicated(String nickname); + // 소셜ID, 소셜로 유저 가입유무확인 Optional getUserBySocialAndSocialId(UserSocial social, String socialId); diff --git a/src/main/java/com/seeat/server/domain/user/domain/repository/UserRepository.java b/src/main/java/com/seeat/server/domain/user/domain/repository/UserRepository.java index 5fcb9b40..ec3385ef 100644 --- a/src/main/java/com/seeat/server/domain/user/domain/repository/UserRepository.java +++ b/src/main/java/com/seeat/server/domain/user/domain/repository/UserRepository.java @@ -16,6 +16,8 @@ public interface UserRepository extends JpaRepository { Optional findByEmail(String email); + Boolean existsByNickname(String nickname); + Optional findByIdAndIsDeleteFalse(Long userId); List findAllByIsDeleteTrueAndUpdatedAtBefore(LocalDateTime cutoffDate); diff --git a/src/main/java/com/seeat/server/domain/user/presentation/UserController.java b/src/main/java/com/seeat/server/domain/user/presentation/UserController.java index da96d5b9..7e15af42 100644 --- a/src/main/java/com/seeat/server/domain/user/presentation/UserController.java +++ b/src/main/java/com/seeat/server/domain/user/presentation/UserController.java @@ -1,6 +1,7 @@ package com.seeat.server.domain.user.presentation; +import com.seeat.server.domain.user.application.dto.response.UserNicknameResponse; import com.seeat.server.domain.user.application.usecase.UserUseCase; import com.seeat.server.domain.user.application.dto.request.UserSignUpRequest; import com.seeat.server.domain.user.domain.entity.UserRole; @@ -53,6 +54,15 @@ public ApiResponse userSignUp( return ApiResponse.created(); } + @GetMapping + public ApiResponse userDuplicateNickname(@RequestParam String nickname){ + + UserNicknameResponse response = userService.isNicknameDuplicated(nickname); + + return ApiResponse.ok(response); + } + + /** * 로그아웃시 refreshToekn 쿠키, redis 삭제 * diff --git a/src/main/java/com/seeat/server/domain/user/presentation/swagger/UserControllerSpec.java b/src/main/java/com/seeat/server/domain/user/presentation/swagger/UserControllerSpec.java index 4aafb824..2d46fd33 100644 --- a/src/main/java/com/seeat/server/domain/user/presentation/swagger/UserControllerSpec.java +++ b/src/main/java/com/seeat/server/domain/user/presentation/swagger/UserControllerSpec.java @@ -1,15 +1,14 @@ package com.seeat.server.domain.user.presentation.swagger; import com.seeat.server.domain.user.application.dto.request.UserSignUpRequest; +import com.seeat.server.domain.user.application.dto.response.UserNicknameResponse; import com.seeat.server.global.response.ApiResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.*; import java.io.IOException; @@ -33,6 +32,19 @@ ApiResponse userSignUp( @RequestHeader String tempUserKey ) throws IOException; + /** + * 사용자 닉네임 중복확인 API + * + * @param nickname 사용할 닉네임 + * @return true(중복), false(사용가능) + */ + @GetMapping + @Operation( + summary = "닉네임 중복 확인", + description = "true면 닉네임 중복, false면 닉네임 사용 가능한 닉네임 중복 확인 기능입니다." + ) + ApiResponse userDuplicateNickname(@RequestParam String nickname); + /** * 로그아웃 API * diff --git a/src/main/java/com/seeat/server/security/config/RequestMatcherHolder.java b/src/main/java/com/seeat/server/security/config/RequestMatcherHolder.java index 61d06bdb..77c04026 100644 --- a/src/main/java/com/seeat/server/security/config/RequestMatcherHolder.java +++ b/src/main/java/com/seeat/server/security/config/RequestMatcherHolder.java @@ -30,6 +30,7 @@ public class RequestMatcherHolder { // 유저 관련 new RequestInfo(POST, "/api/v1/users", null), + new RequestInfo(GET, "/api/v1/users", null), new RequestInfo(POST, "/api/v1/users/logout", USER), new RequestInfo(POST, "/api/v1/users/dev/long-token", null), From c6beabdd782c6efa3f9206d741a42dc22f0a5997 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Mon, 4 Aug 2025 02:07:47 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=EC=A4=91=EB=B3=B5=EC=8B=9C=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/UserNicknameResponse.java | 4 +--- .../domain/user/application/service/UserService.java | 10 ++++++++++ .../com/seeat/server/global/response/ErrorCode.java | 3 +++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/seeat/server/domain/user/application/dto/response/UserNicknameResponse.java b/src/main/java/com/seeat/server/domain/user/application/dto/response/UserNicknameResponse.java index 067f95de..62b95382 100644 --- a/src/main/java/com/seeat/server/domain/user/application/dto/response/UserNicknameResponse.java +++ b/src/main/java/com/seeat/server/domain/user/application/dto/response/UserNicknameResponse.java @@ -16,9 +16,7 @@ public record UserNicknameResponse( public static UserNicknameResponse from(boolean duplicated){ return UserNicknameResponse.builder() .duplicated(duplicated) - .message(duplicated - ? "닉네임이 사용 중입니다. 다른 닉네임을 사용해주세요." - : "닉네임 사용 가능합니다.") + .message("닉네임 사용 가능합니다.") .build(); } } diff --git a/src/main/java/com/seeat/server/domain/user/application/service/UserService.java b/src/main/java/com/seeat/server/domain/user/application/service/UserService.java index 296be455..7d115e1d 100644 --- a/src/main/java/com/seeat/server/domain/user/application/service/UserService.java +++ b/src/main/java/com/seeat/server/domain/user/application/service/UserService.java @@ -11,6 +11,7 @@ import com.seeat.server.domain.user.domain.repository.UserAuditoriumRepository; import com.seeat.server.domain.user.domain.repository.UserRepository; import com.seeat.server.domain.image.application.usecase.ImageUseCase; +import com.seeat.server.global.response.CustomException; import com.seeat.server.global.response.ErrorCode; import com.seeat.server.global.service.RedisService; import com.seeat.server.global.util.JwtConstants; @@ -64,6 +65,15 @@ public Optional getUserByEmail(String email) { */ @Override public UserNicknameResponse isNicknameDuplicated (String nickname){ + + Boolean response = repository.existsByNickname(nickname); + + // 중복이면 에러처리 + if (response){ + + throw new CustomException(ErrorCode.DUPLICATED_NICKNAME, null); + } + return UserNicknameResponse.from(repository.existsByNickname(nickname)); } diff --git a/src/main/java/com/seeat/server/global/response/ErrorCode.java b/src/main/java/com/seeat/server/global/response/ErrorCode.java index 2af638a3..057e10e0 100644 --- a/src/main/java/com/seeat/server/global/response/ErrorCode.java +++ b/src/main/java/com/seeat/server/global/response/ErrorCode.java @@ -83,6 +83,9 @@ public enum ErrorCode { /** 최초 로그인 추가 정보 필요 */ FIRST_LOGIN(1200, HttpStatus.NOT_FOUND, "최초 로그인유저이기에 추가정보기입이 필요합니다."), + /** 중복 확인 **/ + DUPLICATED_NICKNAME(1300,HttpStatus.CONFLICT, "이미 사용 중인 닉네임입니다."), + // ======================== // 2000~2999 : 영화관 관련 에러 // ========================