From 533528e3d115b6ac3137f435eddd5604d3a064ab Mon Sep 17 00:00:00 2001 From: jbh010204 Date: Sun, 10 Aug 2025 22:35:22 +0900 Subject: [PATCH 1/3] feat: add NotBlankPhoneNumberPattern annotation for phone number validation --- .../NotBlankPhoneNumberPattern.java | 25 +++++++++++++++++++ .../global/annotation/PhoneNumberPattern.java | 3 +++ 2 files changed, 28 insertions(+) create mode 100644 src/main/java/life/mosu/mosuserver/global/annotation/NotBlankPhoneNumberPattern.java diff --git a/src/main/java/life/mosu/mosuserver/global/annotation/NotBlankPhoneNumberPattern.java b/src/main/java/life/mosu/mosuserver/global/annotation/NotBlankPhoneNumberPattern.java new file mode 100644 index 00000000..ed520e67 --- /dev/null +++ b/src/main/java/life/mosu/mosuserver/global/annotation/NotBlankPhoneNumberPattern.java @@ -0,0 +1,25 @@ +package life.mosu.mosuserver.global.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.constraints.Pattern; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Pattern( + regexp = "^01[016789]-\\d{3,4}-\\d{4}$", + message = "전화번호 형식은 010-XXXX-XXXX 이어야 합니다." +) +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = {}) +public @interface NotBlankPhoneNumberPattern { + + String message() default "전화번호 형식은 010-XXXX-XXXX 이어야 합니다."; + + Class[] groups() default {}; + + Class[] payload() default {}; +} \ No newline at end of file diff --git a/src/main/java/life/mosu/mosuserver/global/annotation/PhoneNumberPattern.java b/src/main/java/life/mosu/mosuserver/global/annotation/PhoneNumberPattern.java index d03eb5f6..64c49445 100644 --- a/src/main/java/life/mosu/mosuserver/global/annotation/PhoneNumberPattern.java +++ b/src/main/java/life/mosu/mosuserver/global/annotation/PhoneNumberPattern.java @@ -2,6 +2,7 @@ import jakarta.validation.Constraint; import jakarta.validation.Payload; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -12,6 +13,8 @@ regexp = "^01[016789]-\\d{3,4}-\\d{4}$", message = "전화번호 형식은 010-XXXX-XXXX 이어야 합니다." ) + +@NotBlank @Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {}) From 1dad3f7728ef9a8cdc2d0007624a70d4f67c1f88 Mon Sep 17 00:00:00 2001 From: jbh010204 Date: Sun, 10 Aug 2025 22:35:51 +0900 Subject: [PATCH 2/3] feat: add custom exception for invalid gender value --- .../life/mosu/mosuserver/domain/profile/entity/Gender.java | 4 +++- .../java/life/mosu/mosuserver/global/exception/ErrorCode.java | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/life/mosu/mosuserver/domain/profile/entity/Gender.java b/src/main/java/life/mosu/mosuserver/domain/profile/entity/Gender.java index 74f03bf7..2e0f9e30 100644 --- a/src/main/java/life/mosu/mosuserver/domain/profile/entity/Gender.java +++ b/src/main/java/life/mosu/mosuserver/domain/profile/entity/Gender.java @@ -1,6 +1,8 @@ package life.mosu.mosuserver.domain.profile.entity; import java.util.Arrays; +import life.mosu.mosuserver.global.exception.CustomRuntimeException; +import life.mosu.mosuserver.global.exception.ErrorCode; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -18,6 +20,6 @@ public static Gender fromName(String genderName) { .filter(g -> g.getGenderName().equals(genderName)) .findFirst() .orElseThrow( - () -> new IllegalArgumentException("Invalid gender name: " + genderName)); + () -> new CustomRuntimeException(ErrorCode.INVAILD_GENDER)); } } diff --git a/src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java b/src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java index e9918494..ef8791b1 100644 --- a/src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java +++ b/src/main/java/life/mosu/mosuserver/global/exception/ErrorCode.java @@ -44,6 +44,7 @@ public enum ErrorCode { USER_INFO_INVALID(HttpStatus.BAD_REQUEST, "유효하지 않은 사용자 정보입니다."), USER_NOT_ACCESS_FORBIDDEN(HttpStatus.BAD_REQUEST, "접근 권한이 없는 사용자입니다"), USER_SAVE_FAILED(HttpStatus.INTERNAL_SERVER_ERROR, "사용자 저장에 실패했습니다."), + INVAILD_GENDER(HttpStatus.BAD_REQUEST, "유효하지 않은 성별 값입니다."), // 신청 관련 에러 WRONG_SUBJECT_TYPE(HttpStatus.BAD_REQUEST, "잘못된 과목명 입니다."), WRONG_LUNCH_TYPE(HttpStatus.BAD_REQUEST, "잘못된 도시락명 입니다."), From 735cbf37412ded7a7ec18e3ef3ce695b3bbdb0e0 Mon Sep 17 00:00:00 2001 From: jbh010204 Date: Sun, 10 Aug 2025 23:47:19 +0900 Subject: [PATCH 3/3] feat: replace PhoneNumberPattern with NotBlankPhoneNumberPattern for phone number validation --- .../global/annotation/NotBlankPhoneNumberPattern.java | 2 ++ .../mosu/mosuserver/global/annotation/PhoneNumberPattern.java | 2 -- .../presentation/application/dto/ApplicationGuestRequest.java | 4 ++-- .../presentation/auth/dto/request/SignUpAccountRequest.java | 4 ++-- .../profile/dto/RecommenderRegistrationRequest.java | 4 ++-- .../presentation/profile/dto/SignUpProfileRequest.java | 4 ++-- .../recommendation/dto/RecommendationRequest.java | 4 ++-- .../presentation/user/dto/request/FindLoginIdRequest.java | 4 ++-- .../presentation/user/dto/request/FindPasswordRequest.java | 4 ++-- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/life/mosu/mosuserver/global/annotation/NotBlankPhoneNumberPattern.java b/src/main/java/life/mosu/mosuserver/global/annotation/NotBlankPhoneNumberPattern.java index ed520e67..166fb1bd 100644 --- a/src/main/java/life/mosu/mosuserver/global/annotation/NotBlankPhoneNumberPattern.java +++ b/src/main/java/life/mosu/mosuserver/global/annotation/NotBlankPhoneNumberPattern.java @@ -2,6 +2,7 @@ import jakarta.validation.Constraint; import jakarta.validation.Payload; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -12,6 +13,7 @@ regexp = "^01[016789]-\\d{3,4}-\\d{4}$", message = "전화번호 형식은 010-XXXX-XXXX 이어야 합니다." ) +@NotBlank @Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {}) diff --git a/src/main/java/life/mosu/mosuserver/global/annotation/PhoneNumberPattern.java b/src/main/java/life/mosu/mosuserver/global/annotation/PhoneNumberPattern.java index 64c49445..24101adb 100644 --- a/src/main/java/life/mosu/mosuserver/global/annotation/PhoneNumberPattern.java +++ b/src/main/java/life/mosu/mosuserver/global/annotation/PhoneNumberPattern.java @@ -2,7 +2,6 @@ import jakarta.validation.Constraint; import jakarta.validation.Payload; -import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -14,7 +13,6 @@ message = "전화번호 형식은 010-XXXX-XXXX 이어야 합니다." ) -@NotBlank @Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {}) diff --git a/src/main/java/life/mosu/mosuserver/presentation/application/dto/ApplicationGuestRequest.java b/src/main/java/life/mosu/mosuserver/presentation/application/dto/ApplicationGuestRequest.java index 15d66de9..64b702cc 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/application/dto/ApplicationGuestRequest.java +++ b/src/main/java/life/mosu/mosuserver/presentation/application/dto/ApplicationGuestRequest.java @@ -13,7 +13,7 @@ import life.mosu.mosuserver.domain.user.entity.AuthProvider; import life.mosu.mosuserver.domain.user.entity.UserJpaEntity; import life.mosu.mosuserver.domain.user.entity.UserRole; -import life.mosu.mosuserver.global.annotation.PhoneNumberPattern; +import life.mosu.mosuserver.global.annotation.NotBlankPhoneNumberPattern; import life.mosu.mosuserver.global.exception.CustomRuntimeException; import life.mosu.mosuserver.global.exception.ErrorCode; import life.mosu.mosuserver.presentation.common.FileRequest; @@ -27,7 +27,7 @@ public record ApplicationGuestRequest( String userName, @JsonFormat(pattern = "yyyy-MM-dd") LocalDate birth, - @PhoneNumberPattern + @NotBlankPhoneNumberPattern String phoneNumber, @NotNull ExamApplicationRequest examApplication, diff --git a/src/main/java/life/mosu/mosuserver/presentation/auth/dto/request/SignUpAccountRequest.java b/src/main/java/life/mosu/mosuserver/presentation/auth/dto/request/SignUpAccountRequest.java index 2bab8039..ba97e99e 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/auth/dto/request/SignUpAccountRequest.java +++ b/src/main/java/life/mosu/mosuserver/presentation/auth/dto/request/SignUpAccountRequest.java @@ -12,8 +12,8 @@ import life.mosu.mosuserver.domain.user.entity.UserJpaEntity; import life.mosu.mosuserver.domain.user.entity.UserRole; import life.mosu.mosuserver.global.annotation.LoginIdPattern; +import life.mosu.mosuserver.global.annotation.NotBlankPhoneNumberPattern; import life.mosu.mosuserver.global.annotation.PasswordPattern; -import life.mosu.mosuserver.global.annotation.PhoneNumberPattern; import org.springframework.security.crypto.password.PasswordEncoder; public record SignUpAccountRequest( @@ -45,7 +45,7 @@ public record SignUpAccountRequest( @Schema(description = "휴대폰 번호", example = "010-1234-5678", required = true) @NotBlank(message = "휴대폰 번호는 필수입니다.") - @PhoneNumberPattern + @NotBlankPhoneNumberPattern String phoneNumber, SignUpServiceTermRequest serviceTermRequest diff --git a/src/main/java/life/mosu/mosuserver/presentation/profile/dto/RecommenderRegistrationRequest.java b/src/main/java/life/mosu/mosuserver/presentation/profile/dto/RecommenderRegistrationRequest.java index ff2ddebe..0a790ecd 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/profile/dto/RecommenderRegistrationRequest.java +++ b/src/main/java/life/mosu/mosuserver/presentation/profile/dto/RecommenderRegistrationRequest.java @@ -1,11 +1,11 @@ package life.mosu.mosuserver.presentation.profile.dto; import io.swagger.v3.oas.annotations.media.Schema; -import life.mosu.mosuserver.global.annotation.PhoneNumberPattern; +import life.mosu.mosuserver.global.annotation.NotBlankPhoneNumberPattern; public record RecommenderRegistrationRequest( @Schema(description = "추천인 전화번호 (전화번호 형식은 010-XXXX-XXXX 이어야 합니다.)", example = "010-8765-4322") - @PhoneNumberPattern + @NotBlankPhoneNumberPattern String phoneNumber ) { diff --git a/src/main/java/life/mosu/mosuserver/presentation/profile/dto/SignUpProfileRequest.java b/src/main/java/life/mosu/mosuserver/presentation/profile/dto/SignUpProfileRequest.java index 54506198..074ea638 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/profile/dto/SignUpProfileRequest.java +++ b/src/main/java/life/mosu/mosuserver/presentation/profile/dto/SignUpProfileRequest.java @@ -9,7 +9,7 @@ import life.mosu.mosuserver.domain.profile.entity.Gender; import life.mosu.mosuserver.domain.profile.entity.Grade; import life.mosu.mosuserver.domain.profile.entity.ProfileJpaEntity; -import life.mosu.mosuserver.global.annotation.PhoneNumberPattern; +import life.mosu.mosuserver.global.annotation.NotBlankPhoneNumberPattern; @Schema(description = "프로필 등록 요청 DTO") public record SignUpProfileRequest( @@ -29,7 +29,7 @@ public record SignUpProfileRequest( @Schema(description = "휴대폰 번호", example = "010-1234-5678", required = true) @NotBlank(message = "휴대폰 번호는 필수입니다.") - @PhoneNumberPattern + @NotBlankPhoneNumberPattern String phoneNumber, @Schema(description = "이메일 주소", example = "hong@example.com") diff --git a/src/main/java/life/mosu/mosuserver/presentation/recommendation/dto/RecommendationRequest.java b/src/main/java/life/mosu/mosuserver/presentation/recommendation/dto/RecommendationRequest.java index aceb9692..21fae3ea 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/recommendation/dto/RecommendationRequest.java +++ b/src/main/java/life/mosu/mosuserver/presentation/recommendation/dto/RecommendationRequest.java @@ -2,11 +2,11 @@ import jakarta.validation.constraints.NotBlank; import life.mosu.mosuserver.domain.recommendation.RecommendationJpaEntity; -import life.mosu.mosuserver.global.annotation.PhoneNumberPattern; +import life.mosu.mosuserver.global.annotation.NotBlankPhoneNumberPattern; public record RecommendationRequest( @NotBlank String name, - @PhoneNumberPattern String phoneNumber, + @NotBlankPhoneNumberPattern String phoneNumber, @NotBlank String bank, @NotBlank String accountNumber ) { diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindLoginIdRequest.java b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindLoginIdRequest.java index 3ff2fe68..a3990ee3 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindLoginIdRequest.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindLoginIdRequest.java @@ -1,10 +1,10 @@ package life.mosu.mosuserver.presentation.user.dto.request; -import life.mosu.mosuserver.global.annotation.PhoneNumberPattern; +import life.mosu.mosuserver.global.annotation.NotBlankPhoneNumberPattern; public record FindLoginIdRequest( String name, - @PhoneNumberPattern + @NotBlankPhoneNumberPattern String phoneNumber ) { diff --git a/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindPasswordRequest.java b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindPasswordRequest.java index 95f97940..08dcd5b7 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindPasswordRequest.java +++ b/src/main/java/life/mosu/mosuserver/presentation/user/dto/request/FindPasswordRequest.java @@ -1,13 +1,13 @@ package life.mosu.mosuserver.presentation.user.dto.request; import life.mosu.mosuserver.global.annotation.LoginIdPattern; -import life.mosu.mosuserver.global.annotation.PhoneNumberPattern; +import life.mosu.mosuserver.global.annotation.NotBlankPhoneNumberPattern; public record FindPasswordRequest( String name, @LoginIdPattern String loginId, - @PhoneNumberPattern + @NotBlankPhoneNumberPattern String phoneNumber ) {