11package com .ururulab .ururu .seller .service ;
22
3+ import com .ururulab .ururu .global .exception .BusinessException ;
4+ import com .ururulab .ururu .global .exception .error .ErrorCode ;
35import com .ururulab .ururu .global .util .MaskingUtils ;
46import com .ururulab .ururu .seller .dto .request .SellerSignupRequest ;
57import com .ururulab .ururu .seller .dto .response .SellerAvailabilityResponse ;
@@ -32,31 +34,25 @@ public class SellerService {
3234 */
3335 @ Transactional
3436 public SellerResponse signup (final SellerSignupRequest request ) {
37+ // null 체크 강화
38+ if (request == null ) {
39+ log .error ("판매자 회원가입 요청이 null입니다." );
40+ throw new BusinessException (ErrorCode .INVALID_ARGUMENT , "회원가입 요청은 null일 수 없습니다." );
41+ }
42+
3543 log .info ("판매자 회원가입 시작: {}" , MaskingUtils .maskEmail (request .email ()));
3644
37- // 이메일 정규화 (소문자 변환)
38- final String normalizedEmail = request .email (). toLowerCase (). trim ( );
45+ // 이메일 정규화
46+ final String normalizedEmail = normalizeEmail ( request .email ());
3947
4048 // 트랜잭션 범위 내에서 중복 체크 (1차 방어)
4149 validateSignupRequest (request , normalizedEmail );
4250
4351 // 비밀번호 암호화
44- final String encodedPassword = passwordEncoder . encode (request .password ());
52+ final String encodedPassword = encodePassword (request .password ());
4553
46- // 판매자 엔티티 생성
47- final Seller seller = Seller .of (
48- request .name (),
49- request .businessName (),
50- request .ownerName (),
51- request .businessNumber (),
52- normalizedEmail ,
53- encodedPassword ,
54- request .phone (),
55- request .image (),
56- request .address1 (),
57- request .address2 (),
58- request .mailOrderNumber ()
59- );
54+ // 정규화된 데이터로 판매자 엔티티 생성
55+ final Seller seller = createSellerEntity (request , normalizedEmail , encodedPassword );
6056
6157 try {
6258 // 저장 (DB UNIQUE 제약조건이 2차 방어선)
@@ -70,9 +66,131 @@ public SellerResponse signup(final SellerSignupRequest request) {
7066 } catch (DataIntegrityViolationException e ) {
7167 // DB 레벨에서 중복 감지 (동시성 환경에서 최종 방어선)
7268 log .warn ("DB 중복 제약조건 위반: {}" , e .getMessage ());
73- throw new com .ururulab .ururu .global .exception .BusinessException (
74- com .ururulab .ururu .global .exception .error .ErrorCode .DUPLICATE_EMAIL );
69+ throw new BusinessException (ErrorCode .DUPLICATE_EMAIL );
70+ }
71+ }
72+
73+ /**
74+ * 이메일 정규화
75+ */
76+ private String normalizeEmail (final String email ) {
77+ if (email == null || email .isBlank ()) {
78+ throw new BusinessException (ErrorCode .INVALID_ARGUMENT , "이메일은 필수입니다." );
79+ }
80+ return email .toLowerCase ().trim ();
81+ }
82+
83+ /**
84+ * 비밀번호 암호화
85+ */
86+ private String encodePassword (final String password ) {
87+ if (password == null || password .isBlank ()) {
88+ throw new BusinessException (ErrorCode .INVALID_ARGUMENT , "비밀번호는 필수입니다." );
89+ }
90+ return passwordEncoder .encode (password );
91+ }
92+
93+ /**
94+ * 판매자 엔티티 생성
95+ */
96+ private Seller createSellerEntity (final SellerSignupRequest request , final String normalizedEmail , final String encodedPassword ) {
97+ // 통신판매업 번호 정규화
98+ final String normalizedMailOrderNumber = normalizeField (request .mailOrderNumber ());
99+
100+ // 사업자명 정규화
101+ final String normalizedBusinessName = normalizeField (request .businessName ());
102+
103+ // 대표자명 정규화
104+ final String normalizedOwnerName = normalizeField (request .ownerName ());
105+
106+ // 전화번호 정규화
107+ final String normalizedPhone = normalizeField (request .phone ());
108+
109+ // 주소 정규화 (앞뒤 공백만 제거, 중간 공백 유지)
110+ final String normalizedAddress1 = normalizeField (request .address1 ());
111+ final String normalizedAddress2 = normalizeField (request .address2 ());
112+
113+ return Seller .of (
114+ request .name (),
115+ normalizedBusinessName ,
116+ normalizedOwnerName ,
117+ request .businessNumber (),
118+ normalizedEmail ,
119+ encodedPassword ,
120+ normalizedPhone ,
121+ request .image (),
122+ normalizedAddress1 ,
123+ normalizedAddress2 ,
124+ normalizedMailOrderNumber
125+ );
126+ }
127+
128+ /**
129+ * 필드 정규화 (null 체크 포함)
130+ */
131+ private String normalizeField (final String field ) {
132+ return field != null ? field .trim () : null ;
133+ }
134+
135+ //회원가입 요청 유효성 검증
136+ private void validateSignupRequest (final SellerSignupRequest request , final String normalizedEmail ) {
137+ // 필수 필드 검증
138+ validateRequiredFields (request );
139+
140+ // 이메일 중복 체크
141+ if (!sellerRepository .isEmailAvailable (normalizedEmail )) {
142+ log .warn ("이메일 중복: {}" , MaskingUtils .maskEmail (normalizedEmail ));
143+ throw new BusinessException (ErrorCode .DUPLICATE_EMAIL );
144+ }
145+
146+ // 사업자등록번호 정규화 후 중복 체크
147+ final String normalizedBusinessNumber = normalizeBusinessNumber (request .businessNumber ());
148+ if (!sellerRepository .isBusinessNumberAvailable (normalizedBusinessNumber )) {
149+ log .warn ("사업자등록번호 중복: {}" , MaskingUtils .maskBusinessNumber (normalizedBusinessNumber ));
150+ throw new BusinessException (ErrorCode .DUPLICATE_BUSINESS_NUMBER );
151+ }
152+
153+ // 브랜드명 정규화 후 중복 체크
154+ final String normalizedName = normalizeName (request .name ());
155+ if (!sellerRepository .isNameAvailable (normalizedName )) {
156+ log .warn ("브랜드명 중복: {}" , normalizedName );
157+ throw new BusinessException (ErrorCode .DUPLICATE_BRAND_NAME );
158+ }
159+ }
160+
161+ /**
162+ * 필수 필드 검증
163+ */
164+ private void validateRequiredFields (final SellerSignupRequest request ) {
165+ if (request .name () == null || request .name ().isBlank ()) {
166+ throw new BusinessException (ErrorCode .INVALID_ARGUMENT , "브랜드명은 필수입니다." );
167+ }
168+ if (request .businessNumber () == null || request .businessNumber ().isBlank ()) {
169+ throw new BusinessException (ErrorCode .INVALID_ARGUMENT , "사업자등록번호는 필수입니다." );
170+ }
171+ if (request .password () == null || request .password ().isBlank ()) {
172+ throw new BusinessException (ErrorCode .INVALID_ARGUMENT , "비밀번호는 필수입니다." );
173+ }
174+ }
175+
176+ /**
177+ * 사업자등록번호 정규화
178+ */
179+ private String normalizeBusinessNumber (final String businessNumber ) {
180+ if (businessNumber == null || businessNumber .isBlank ()) {
181+ throw new BusinessException (ErrorCode .INVALID_ARGUMENT , "사업자등록번호는 필수입니다." );
182+ }
183+ return businessNumber .trim ();
184+ }
185+
186+ /**
187+ * 브랜드명 정규화
188+ */
189+ private String normalizeName (final String name ) {
190+ if (name == null || name .isBlank ()) {
191+ throw new BusinessException (ErrorCode .INVALID_ARGUMENT , "브랜드명은 필수입니다." );
75192 }
193+ return name .trim ();
76194 }
77195
78196 /**
@@ -121,31 +239,6 @@ public SellerResponse getSellerProfile(final Long sellerId) {
121239 return SellerResponse .from (seller );
122240 }
123241
124-
125- //회원가입 요청 유효성 검증
126- private void validateSignupRequest (final SellerSignupRequest request , final String normalizedEmail ) {
127- // 이메일 중복 체크
128- if (!sellerRepository .isEmailAvailable (normalizedEmail )) {
129- log .warn ("이메일 중복: {}" , MaskingUtils .maskEmail (normalizedEmail ));
130- throw new com .ururulab .ururu .global .exception .BusinessException (
131- com .ururulab .ururu .global .exception .error .ErrorCode .DUPLICATE_EMAIL );
132- }
133-
134- // 사업자등록번호 중복 체크
135- if (!sellerRepository .isBusinessNumberAvailable (request .businessNumber ())) {
136- log .warn ("사업자등록번호 중복: {}" , MaskingUtils .maskBusinessNumber (request .businessNumber ()));
137- throw new com .ururulab .ururu .global .exception .BusinessException (
138- com .ururulab .ururu .global .exception .error .ErrorCode .DUPLICATE_BUSINESS_NUMBER );
139- }
140-
141- // 브랜드명 중복 체크
142- if (!sellerRepository .isNameAvailable (request .name ())) {
143- log .warn ("브랜드명 중복: {}" , request .name ());
144- throw new com .ururulab .ururu .global .exception .BusinessException (
145- com .ururulab .ururu .global .exception .error .ErrorCode .DUPLICATE_BRAND_NAME );
146- }
147- }
148-
149242 /**
150243 * 이메일로 판매자 조회
151244 *
@@ -156,14 +249,12 @@ private void validateSignupRequest(final SellerSignupRequest request, final Stri
156249 public Seller findByEmail (final String email ) {
157250 final String normalizedEmail = email .toLowerCase ().trim ();
158251 return sellerRepository .findByEmail (normalizedEmail )
159- .orElseThrow (() -> new com .ururulab .ururu .global .exception .BusinessException (
160- com .ururulab .ururu .global .exception .error .ErrorCode .SELLER_NOT_FOUND ));
252+ .orElseThrow (() -> new BusinessException (ErrorCode .SELLER_NOT_FOUND ));
161253 }
162254
163255 // 활성 판매자 조회
164256 private Seller findActiveSellerById (final Long sellerId ) {
165257 return sellerRepository .findActiveSeller (sellerId )
166- .orElseThrow (() -> new com .ururulab .ururu .global .exception .BusinessException (
167- com .ururulab .ururu .global .exception .error .ErrorCode .SELLER_NOT_FOUND , sellerId ));
258+ .orElseThrow (() -> new BusinessException (ErrorCode .SELLER_NOT_FOUND , sellerId ));
168259 }
169260}
0 commit comments