11package com .jocketdan .auth .service .user ;
22
3+ import com .jocketdan .auth .dto .EditProfileRequest ;
34import com .jocketdan .auth .dto .UserResponse ;
45import com .jocketdan .auth .entity .User ;
6+ import com .jocketdan .auth .exception .DuplicateNicknameException ;
57import com .jocketdan .auth .exception .UserNotFoundException ;
68import com .jocketdan .auth .repository .UserRepository ;
79import com .jocketdan .auth .service .auth .TokenService ;
810import lombok .RequiredArgsConstructor ;
911import lombok .extern .slf4j .Slf4j ;
12+ import org .springframework .dao .DataIntegrityViolationException ;
1013import org .springframework .security .core .userdetails .UserDetails ;
1114import org .springframework .stereotype .Service ;
1215import org .springframework .transaction .annotation .Transactional ;
1316
1417/**
15- * 기존의 복잡한 기능은 각 서비스로 분리 후,
16- * 정말 유저 관리만 초점
17- * */
18+ * 기존의 복잡한 기능은 각 서비스로 분리 후, 정말 유저 관리만 초점
19+ */
1820@ Slf4j
1921@ Service
2022@ RequiredArgsConstructor
@@ -24,28 +26,68 @@ public class UserService {
2426 private final TokenService tokenService ;
2527
2628 public UserResponse getProfileById (UserDetails userDetails ) {
27- User user = userRepository .findByEmail (userDetails .getUsername ())
28- .orElseThrow (() -> new UserNotFoundException ("사용자를 찾을 수 없습니다." ));
29+ User user = findUser (userDetails .getUsername ());
2930 return UserResponse .of (user );
3031 }
3132
33+ // @Transactional(isolation = Isolation.READ_COMMITTED)
3234 @ Transactional
33- public void changeNickname (Long userId , String newNickName ) {
34- User user = userRepository .findById (userId )
35- .orElseThrow (() -> new UserNotFoundException ("사용자를 찾을 수 없습니다." ));
36- if (userRepository .existsByNickname (newNickName )) {
37- throw new IllegalArgumentException ("이미 사용 중인 닉네임입니다." );
35+ public void changeProfile (UserDetails userDetails , EditProfileRequest request ) {
36+ User user = findUser (userDetails .getUsername ());
37+ try {
38+ if (request .getNewNickName () != null
39+ && !request .getNewNickName ().isBlank ()
40+ && !user .getNickname ().equals (request .getNewNickName ().trim ())
41+ ) {
42+ validateNickname (request .getNewNickName ()); // 검증
43+ user .changeNickname (request .getNewNickName ()); // 이후 저장
44+ }
45+
46+ if (request .getEmoji () != null && !request .getEmoji ()
47+ .isBlank ()) {
48+ validateEmoji (request .getEmoji ());
49+ user .changeEmoji (request .getEmoji ());
50+ }
51+ log .info ("회원 프로필 변경 완료: email={}" , user .getEmail ());
52+ } catch (DataIntegrityViolationException e ) {
53+ log .warn ("닉네임 중복 시도: email={}, nickname={}" ,
54+ user .getEmail (), request .getNewNickName ());
55+ throw new DuplicateNicknameException ("이미 사용 중인 닉네임입니다." );
56+ } catch (IllegalArgumentException e ){
57+ throw new IllegalArgumentException ("형식에 맞지 않습니다." );
3858 }
39- user .changeNickname (newNickName );
40- userRepository .save (user );
4159 }
4260
4361 @ Transactional
4462 public void withdrawUser (String email ) {
45- User user = userRepository .findByEmail (email )
46- .orElseThrow (() -> new UserNotFoundException ("사용자를 찾을 수 없습니다." ));
63+ User user = findUser (email );
4764 tokenService .revokeAllRefreshTokensByUserId (user .getId ());
4865 userRepository .delete (user );
4966 log .info ("회원 탈퇴 완료: email={}" , email );
5067 }
68+
69+ private User findUser (String email ) {
70+ return userRepository .findByEmail (email )
71+ .orElseThrow (() -> new UserNotFoundException ("사용자를 찾을 수 없습니다." ));
72+ }
73+
74+ private void validateEmoji (String emoji ) {
75+ if (emoji .length () > 10 ) {
76+ throw new IllegalArgumentException ("이모지는 10자 이하여야 합니다." );
77+ }
78+ }
79+
80+ private void validateNickname (String nickname ) {
81+ if (nickname == null || nickname .isBlank ()) {
82+ throw new IllegalArgumentException ("닉네임은 필수입니다." );
83+ }
84+ String trimmed = nickname .trim ();
85+ if (trimmed .length () < 2 || trimmed .length () > 20 ) {
86+ throw new IllegalArgumentException ("닉네임은 2~20자여야 합니다." );
87+ }
88+ // 특수문자 검증
89+ if (!trimmed .matches ("^[a-zA-Z0-9가-힣_]+$" )) {
90+ throw new IllegalArgumentException ("닉네임은 영문, 한글, 숫자, _만 가능합니다." );
91+ }
92+ }
5193}
0 commit comments