Skip to content

Commit 81ff85e

Browse files
committed
Feat: 회원 정보 수정 API 구현
1 parent 63a0083 commit 81ff85e

File tree

7 files changed

+89
-11
lines changed

7 files changed

+89
-11
lines changed

src/main/java/com/back/domain/user/controller/UserController.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package com.back.domain.user.controller;
22

3+
import com.back.domain.user.dto.UpdateUserProfileRequest;
34
import com.back.domain.user.dto.UserDetailResponse;
45
import com.back.domain.user.service.UserService;
56
import com.back.global.common.dto.RsData;
67
import com.back.global.security.CustomUserDetails;
8+
import jakarta.validation.Valid;
79
import lombok.RequiredArgsConstructor;
810
import org.springframework.http.ResponseEntity;
911
import org.springframework.security.core.annotation.AuthenticationPrincipal;
10-
import org.springframework.web.bind.annotation.GetMapping;
11-
import org.springframework.web.bind.annotation.RequestMapping;
12-
import org.springframework.web.bind.annotation.RestController;
12+
import org.springframework.web.bind.annotation.*;
1313

1414
@RestController
1515
@RequestMapping("/api/users")
@@ -28,4 +28,18 @@ public ResponseEntity<RsData<UserDetailResponse>> getMyInfo (
2828
userDetail
2929
));
3030
}
31+
32+
@PatchMapping("/me")
33+
public ResponseEntity<RsData<UserDetailResponse>> updateMyProfile(
34+
@AuthenticationPrincipal CustomUserDetails user,
35+
@Valid @RequestBody UpdateUserProfileRequest request
36+
) {
37+
UserDetailResponse updated = userService.updateUserProfile(user.getUserId(), request);
38+
return ResponseEntity
39+
.ok(RsData.success(
40+
"회원 정보를 수정했습니다.",
41+
updated
42+
)
43+
);
44+
}
3145
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.back.domain.user.dto;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.Size;
5+
6+
import java.time.LocalDate;
7+
8+
/**
9+
* 사용자 프로필 수정 요청 DTO
10+
*
11+
* @param nickname 사용자의 별명
12+
* @param profileImageUrl 사용자의 프로필 이미지 URL
13+
* @param bio 사용자의 자기소개
14+
* @param birthDate 사용자의 생년월일
15+
*/
16+
public record UpdateUserProfileRequest(
17+
@NotBlank @Size(max = 20) String nickname,
18+
String profileImageUrl,
19+
@Size(max = 255) String bio,
20+
LocalDate birthDate
21+
) {}

src/main/java/com/back/domain/user/dto/UserDetailResponse.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.back.domain.user.entity.UserProfile;
66
import com.back.domain.user.entity.UserStatus;
77

8+
import java.time.LocalDate;
89
import java.time.LocalDateTime;
910

1011
/**
@@ -61,7 +62,7 @@ public record ProfileResponse(
6162
String nickname,
6263
String profileImageUrl,
6364
String bio,
64-
LocalDateTime birthDate,
65+
LocalDate birthDate,
6566
int point
6667
) {
6768
public static ProfileResponse from(UserProfile profile) {

src/main/java/com/back/domain/user/dto/UserRegisterRequest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import jakarta.validation.constraints.Email;
44
import jakarta.validation.constraints.NotBlank;
5+
import jakarta.validation.constraints.Size;
56

67
/**
78
* 사용자 회원 가입 요청을 나타내는 DTO
@@ -15,5 +16,5 @@ public record UserRegisterRequest(
1516
@NotBlank String username,
1617
@NotBlank @Email String email,
1718
@NotBlank String password,
18-
@NotBlank String nickname
19+
@NotBlank @Size(max = 20) String nickname
1920
) {}

src/main/java/com/back/domain/user/entity/UserProfile.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import lombok.NoArgsConstructor;
88
import lombok.Setter;
99

10-
import java.time.LocalDateTime;
10+
import java.time.LocalDate;
1111

1212
@Entity
1313
@Getter
@@ -25,7 +25,7 @@ public class UserProfile extends BaseEntity {
2525

2626
private String bio;
2727

28-
private LocalDateTime birthDate;
28+
private LocalDate birthDate;
2929

3030
private int point;
3131
}

src/main/java/com/back/domain/user/repository/UserProfileRepository.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
@Repository
88
public interface UserProfileRepository extends JpaRepository<UserProfile, Long> {
99
boolean existsByNickname(String nickname);
10+
boolean existsByNicknameAndUserIdNot(String nickname, Long userId);
1011
}

src/main/java/com/back/domain/user/service/UserService.java

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package com.back.domain.user.service;
22

3+
import com.back.domain.user.dto.UpdateUserProfileRequest;
34
import com.back.domain.user.dto.UserDetailResponse;
45
import com.back.domain.user.entity.User;
6+
import com.back.domain.user.entity.UserProfile;
57
import com.back.domain.user.entity.UserStatus;
8+
import com.back.domain.user.repository.UserProfileRepository;
69
import com.back.domain.user.repository.UserRepository;
710
import com.back.global.exception.CustomException;
811
import com.back.global.exception.ErrorCode;
@@ -15,12 +18,12 @@
1518
@Transactional
1619
public class UserService {
1720
private final UserRepository userRepository;
21+
private final UserProfileRepository userProfileRepository;
1822

1923
/**
20-
* 내 정보 조회 서비스
21-
* 1. 사용자 조회
22-
* 2. 상태 검증 (DELETED, SUSPENDED)
23-
* 3. UserDetailResponse 변환 및 반환
24+
* 사용자 정보 조회 서비스
25+
* 1. 사용자 조회 및 상태 검증
26+
* 2. UserDetailResponse 변환 및 반환
2427
*/
2528
public UserDetailResponse getUserInfo(Long userId) {
2629

@@ -39,4 +42,41 @@ public UserDetailResponse getUserInfo(Long userId) {
3942
// UserDetailResponse로 변환하여 반환
4043
return UserDetailResponse.from(user);
4144
}
45+
46+
/**
47+
* 사용자 프로필 수정 서비스
48+
* 1. 사용자 조회 및 상태 검증
49+
* 2. 닉네임 중복 검사
50+
* 3. UserProfile 업데이트
51+
* 4. UserDetailResponse 변환 및 반환
52+
*/
53+
public UserDetailResponse updateUserProfile(Long userId, UpdateUserProfileRequest request) {
54+
55+
// userId로 User 조회
56+
User user = userRepository.findById(userId)
57+
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
58+
59+
// UserStatus가 DELETED, SUSPENDED면 예외 처리
60+
if (user.getUserStatus() == UserStatus.DELETED) {
61+
throw new CustomException(ErrorCode.USER_DELETED);
62+
}
63+
if (user.getUserStatus() == UserStatus.SUSPENDED) {
64+
throw new CustomException(ErrorCode.USER_SUSPENDED);
65+
}
66+
67+
// 닉네임 중복 검사 (본인 제외)
68+
if (userProfileRepository.existsByNicknameAndUserIdNot(request.nickname(), userId)) {
69+
throw new CustomException(ErrorCode.NICKNAME_DUPLICATED);
70+
}
71+
72+
// UserProfile 업데이트
73+
UserProfile profile = user.getUserProfile();
74+
profile.setNickname(request.nickname());
75+
profile.setProfileImageUrl(request.profileImageUrl());
76+
profile.setBio(request.bio());
77+
profile.setBirthDate(request.birthDate());
78+
79+
// UserDetailResponse로 변환하여 반환
80+
return UserDetailResponse.from(user);
81+
}
4282
}

0 commit comments

Comments
 (0)