diff --git a/SossBar/src/main/java/com/sossbar/oauth2/kakao/service/KakaoLoginService.java b/SossBar/src/main/java/com/sossbar/oauth2/kakao/service/KakaoLoginService.java
index 7c05258..9c53057 100644
--- a/SossBar/src/main/java/com/sossbar/oauth2/kakao/service/KakaoLoginService.java
+++ b/SossBar/src/main/java/com/sossbar/oauth2/kakao/service/KakaoLoginService.java
@@ -104,7 +104,6 @@ public User processLogin(String code) {
).orElseGet(() ->
userRepository.save(User.builder()
.email(kakaoUserInfo.getKakaoAccount().getEmail())
- .nickname(kakaoUserInfo.getProperties().getNickname())
.profileImageUrl(
kakaoUserInfo.getKakaoAccount()
.getProfile()
diff --git a/SossBar/src/main/java/com/sossbar/user/controller/UserController.java b/SossBar/src/main/java/com/sossbar/user/controller/UserController.java
index 3e05aa2..b94c3e9 100644
--- a/SossBar/src/main/java/com/sossbar/user/controller/UserController.java
+++ b/SossBar/src/main/java/com/sossbar/user/controller/UserController.java
@@ -3,7 +3,6 @@
import com.sossbar.global.common.code.SuccessCode;
import com.sossbar.global.common.template.ApiResTemplate;
import com.sossbar.global.common.template.SwaggerApiResTemplate;
-import com.sossbar.user.dto.request.UserOnboardingReqDto;
import com.sossbar.user.dto.request.UserInfoUpdateReqDto;
import com.sossbar.user.dto.response.UserInfoResDto;
import com.sossbar.user.service.UserService;
@@ -23,35 +22,25 @@
@RequiredArgsConstructor
@RequestMapping("/api/v1/users")
@SwaggerApiResTemplate
-@Tag(name = "MyPage API", description = "내 프로필 관련 API")
+@Tag(name = "User API", description = "사용자 관련 API - MyPage")
public class UserController {
private final UserService userService;
- @Operation(summary = "사용자 정보 추가 입력", description = "카카오 로그인을 완료한 사용자가 최초 1회 추가 정보(이름, 한 줄 소개, 프로필 이미지)를 입력합니다." +
+ @Operation(summary = "사용자 정보 추가 입력", description = "카카오 로그인을 완료한 사용자가 최초 1회 추가 정보(실명, 한 줄 소개, 프로필 이미지)를 입력합니다." +
"
이미지를 빈 값으로 보낼 시 url은 null로 저장됨")
@PostMapping(value = "/onboarding", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ApiResTemplate saveUserInfo(Principal principal,
- @Valid @RequestPart("onboarding") UserOnboardingReqDto userOnboardingReqDto,
+ @Valid @RequestPart("onboarding") UserInfoUpdateReqDto userInfoUpdateReqDto,
@RequestPart(value = "profileImage", required = false) MultipartFile profileImage) {
- UserInfoResDto userInfoResDto = userService.onboarding(principal, userOnboardingReqDto, profileImage);
+ UserInfoResDto userInfoResDto = userService.onboarding(principal, userInfoUpdateReqDto, profileImage);
return ApiResTemplate.successResponse(SuccessCode.SUCCESS, userInfoResDto);
}
- @Operation(summary = "내 정보 조회", description = "로그인한 사용자가 자신의 프로필 정보를 조회합니다.")
+ @Operation(summary = "내 정보 조회", description = "로그인한 사용자가 자신의 계정 정보를 조회합니다. (본인만 조회 가능, 이메일 포함)")
@GetMapping("/profile")
public ApiResTemplate getUserInfo(Principal principal) {
UserInfoResDto userInfoResDto = userService.getUserInfo(principal);
return ApiResTemplate.successResponse(SuccessCode.GET_SUCCESS, userInfoResDto);
}
-
- @Operation(summary = "내 정보 수정", description = "로그인한 사용자가 자신의 프로필 정보를 수정합니다. (닉네임, 한 줄 소개, 프로필 이미지) " +
- "
이미지를 빈 값으로 보낼 시 기존 프로필 이미지 유지")
- @PatchMapping(value = "/profile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
- public ApiResTemplate updateUserInfo(Principal principal,
- @Valid @RequestPart("info") UserInfoUpdateReqDto userInfoUpdateReqDto,
- @RequestPart(value = "profileImage", required = false) MultipartFile profileImage) {
- UserInfoResDto userInfoResDto = userService.updateUserInfo(principal, userInfoUpdateReqDto, profileImage);
- return ApiResTemplate.successResponse(SuccessCode.UPDATE_SUCCESS, userInfoResDto);
- }
}
diff --git a/SossBar/src/main/java/com/sossbar/user/controller/UserProfileController.java b/SossBar/src/main/java/com/sossbar/user/controller/UserProfileController.java
new file mode 100644
index 0000000..b7937ce
--- /dev/null
+++ b/SossBar/src/main/java/com/sossbar/user/controller/UserProfileController.java
@@ -0,0 +1,45 @@
+package com.sossbar.user.controller;
+
+import com.sossbar.global.common.code.SuccessCode;
+import com.sossbar.global.common.template.ApiResTemplate;
+import com.sossbar.global.common.template.SwaggerApiResTemplate;
+import com.sossbar.user.dto.request.UserInfoUpdateReqDto;
+import com.sossbar.user.dto.response.UserInfoResDto;
+import com.sossbar.user.dto.response.UserProfileInfoResDto;
+import com.sossbar.user.service.UserProfileService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.security.Principal;
+
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/api/v1/users")
+@SwaggerApiResTemplate
+@Tag(name = "User Profile API", description = "사용자 프로필 관련 API")
+public class UserProfileController {
+
+ private final UserProfileService userProfileService;
+
+ @Operation(summary = "사용자 프로필 정보 조회", description = "로그인한 사용자가 userId로 사용자 프로필 정보(실명, 프로필 사진, 한 줄 소개)를 조회합니다.")
+ @GetMapping("/profile/{userId}")
+ public ApiResTemplate getUserProfile(@PathVariable("userId") Long userId) {
+ UserProfileInfoResDto userProfileInfoResDto = userProfileService.getUserProfile(userId);
+ return ApiResTemplate.successResponse(SuccessCode.GET_SUCCESS, userProfileInfoResDto);
+ }
+
+ @Operation(summary = "내 프로필 수정", description = "로그인한 사용자가 자신의 프로필 정보를 수정합니다. (실명, 한 줄 소개, 프로필 이미지)" +
+ "
이미지를 빈 값으로 보낼 시 기존 프로필 이미지 유지")
+ @PatchMapping(value = "/profile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public ApiResTemplate updateUserInfo(Principal principal,
+ @Valid @RequestPart("info") UserInfoUpdateReqDto userInfoUpdateReqDto,
+ @RequestPart(value = "profileImage", required = false) MultipartFile profileImage) {
+ UserInfoResDto userInfoResDto = userProfileService.updateUserInfo(principal, userInfoUpdateReqDto, profileImage);
+ return ApiResTemplate.successResponse(SuccessCode.UPDATE_SUCCESS, userInfoResDto);
+ }
+}
diff --git a/SossBar/src/main/java/com/sossbar/user/dto/request/UserInfoUpdateReqDto.java b/SossBar/src/main/java/com/sossbar/user/dto/request/UserInfoUpdateReqDto.java
index eb4dd1e..fd04245 100644
--- a/SossBar/src/main/java/com/sossbar/user/dto/request/UserInfoUpdateReqDto.java
+++ b/SossBar/src/main/java/com/sossbar/user/dto/request/UserInfoUpdateReqDto.java
@@ -4,11 +4,10 @@
import jakarta.validation.constraints.Size;
public record UserInfoUpdateReqDto(
- @NotBlank
- @Size(min = 2, max = 20, message = "닉네임은 2자 이상 20자 이하로 입력해 주세요.")
- String nickname,
+ @NotBlank(message = "실명만 입력해 주세요.")
+ @Size(min = 2, max = 20, message = "이름은 2자 이상 20자 이하로 입력해 주세요.")
+ String username,
- @NotBlank
@Size(max = 100, message = "한 줄 소개는 100자 이하로 입력해 주세요.")
String bio
) {
diff --git a/SossBar/src/main/java/com/sossbar/user/dto/request/UserOnboardingReqDto.java b/SossBar/src/main/java/com/sossbar/user/dto/request/UserOnboardingReqDto.java
deleted file mode 100644
index 0582289..0000000
--- a/SossBar/src/main/java/com/sossbar/user/dto/request/UserOnboardingReqDto.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.sossbar.user.dto.request;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Size;
-
-public record UserOnboardingReqDto(
- @NotBlank
- @Size(min = 2, max = 10, message = "이름은 2자 이상 10자 이하로 입력해 주세요.")
- String username,
-
- @NotBlank
- @Size(max = 100, message = "한 줄 소개는 100자 이하로 입력해 주세요.")
- String bio
-) {
-}
diff --git a/SossBar/src/main/java/com/sossbar/user/dto/response/UserInfoResDto.java b/SossBar/src/main/java/com/sossbar/user/dto/response/UserInfoResDto.java
index f8885ec..37cb1bb 100644
--- a/SossBar/src/main/java/com/sossbar/user/dto/response/UserInfoResDto.java
+++ b/SossBar/src/main/java/com/sossbar/user/dto/response/UserInfoResDto.java
@@ -8,7 +8,6 @@
public record UserInfoResDto(
Long userId,
String username,
- String nickname,
String email,
String bio,
String profileImageUrl,
@@ -18,7 +17,6 @@ public static UserInfoResDto from(User user) {
return UserInfoResDto.builder()
.userId(user.getId())
.username(user.getUsername())
- .nickname(user.getNickname())
.email(user.getEmail())
.bio(user.getBio())
.profileImageUrl(user.getProfileImageUrl())
diff --git a/SossBar/src/main/java/com/sossbar/user/dto/response/UserProfileInfoResDto.java b/SossBar/src/main/java/com/sossbar/user/dto/response/UserProfileInfoResDto.java
new file mode 100644
index 0000000..b82869b
--- /dev/null
+++ b/SossBar/src/main/java/com/sossbar/user/dto/response/UserProfileInfoResDto.java
@@ -0,0 +1,21 @@
+package com.sossbar.user.dto.response;
+
+import com.sossbar.user.entity.User;
+import lombok.Builder;
+
+@Builder
+public record UserProfileInfoResDto(
+ Long userId,
+ String username,
+ String bio,
+ String profileImageUrl
+) {
+ public static UserProfileInfoResDto from(User user) {
+ return UserProfileInfoResDto.builder()
+ .userId(user.getId())
+ .username(user.getUsername())
+ .bio(user.getBio())
+ .profileImageUrl(user.getProfileImageUrl())
+ .build();
+ }
+}
diff --git a/SossBar/src/main/java/com/sossbar/user/entity/User.java b/SossBar/src/main/java/com/sossbar/user/entity/User.java
index 0032871..75ea1e6 100644
--- a/SossBar/src/main/java/com/sossbar/user/entity/User.java
+++ b/SossBar/src/main/java/com/sossbar/user/entity/User.java
@@ -2,7 +2,6 @@
import com.sossbar.global.common.template.BaseTimeEntity;
import com.sossbar.user.dto.request.UserInfoUpdateReqDto;
-import com.sossbar.user.dto.request.UserOnboardingReqDto;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
@@ -18,7 +17,6 @@ public class User extends BaseTimeEntity {
@Column(name = "user_id")
private Long id;
private String username;
- private String nickname;
@Column(unique = true, nullable = false)
private String email;
@@ -30,9 +28,8 @@ public class User extends BaseTimeEntity {
private String refreshToken;
@Builder
- public User(String username, String nickname, String email, String bio, String profileImageUrl, UserType userType, String refreshToken) {
+ public User(String username, String email, String bio, String profileImageUrl, UserType userType, String refreshToken) {
this.username = username;
- this.nickname = nickname;
this.email = email;
this.bio = bio;
this.profileImageUrl = profileImageUrl;
@@ -40,16 +37,18 @@ public User(String username, String nickname, String email, String bio, String p
this.refreshToken = refreshToken;
}
- public void onboarding(UserOnboardingReqDto userInfoSaveReqDto, String profileImageUrl) {
- this.username = userInfoSaveReqDto.username();
- this.bio = userInfoSaveReqDto.bio();
- this.profileImageUrl = profileImageUrl;
- }
-
public void updateUserInfo(UserInfoUpdateReqDto userInfoUpdateReqDto, String profileImageUrl) {
- this.nickname = userInfoUpdateReqDto.nickname();
- this.bio = userInfoUpdateReqDto.bio();
- this.profileImageUrl = profileImageUrl;
+ if (userInfoUpdateReqDto.username() != null) {
+ this.username = userInfoUpdateReqDto.username();
+ }
+
+ if (userInfoUpdateReqDto.bio() != null) {
+ this.bio = userInfoUpdateReqDto.bio();
+ }
+
+ if (profileImageUrl != null) {
+ this.profileImageUrl = profileImageUrl;
+ }
}
public void saveRefreshToken(String refreshToken) {
diff --git a/SossBar/src/main/java/com/sossbar/user/repository/UserRepository.java b/SossBar/src/main/java/com/sossbar/user/repository/UserRepository.java
index 4863ab4..a1b3085 100644
--- a/SossBar/src/main/java/com/sossbar/user/repository/UserRepository.java
+++ b/SossBar/src/main/java/com/sossbar/user/repository/UserRepository.java
@@ -9,6 +9,4 @@
@Repository
public interface UserRepository extends JpaRepository {
Optional findByEmail(String email);
- boolean existsByNickname(String nickname);
- boolean existsByNicknameAndIdNot(String nickname, Long userId);
}
diff --git a/SossBar/src/main/java/com/sossbar/user/service/UserProfileService.java b/SossBar/src/main/java/com/sossbar/user/service/UserProfileService.java
new file mode 100644
index 0000000..ef476a6
--- /dev/null
+++ b/SossBar/src/main/java/com/sossbar/user/service/UserProfileService.java
@@ -0,0 +1,62 @@
+package com.sossbar.user.service;
+
+import com.sossbar.global.common.code.ErrorCode;
+import com.sossbar.global.common.exception.BusinessException;
+import com.sossbar.global.config.S3Service;
+import com.sossbar.user.dto.request.UserInfoUpdateReqDto;
+import com.sossbar.user.dto.response.UserInfoResDto;
+import com.sossbar.user.dto.response.UserProfileInfoResDto;
+import com.sossbar.user.entity.User;
+import com.sossbar.user.repository.UserRepository;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.security.Principal;
+
+@Service
+@RequiredArgsConstructor
+@Transactional(readOnly = true)
+public class UserProfileService {
+
+ private final UserRepository userRepository;
+ private final S3Service s3Service;
+
+ // 프로필 페이지 - 내 프로필 수정(실명, 한 줄 소개, 프로필 이미지)
+ @Transactional
+ public UserInfoResDto updateUserInfo(Principal principal, UserInfoUpdateReqDto userInfoUpdateReqDto, MultipartFile profileImage) {
+ Long id = Long.parseLong(principal.getName());
+ User user = getUserById(id);
+
+ // 프로필 이미지 수정 처리 (기존 이미지 삭제 후 새 이미지 업로드)
+ String newProfileImageUrl = user.getProfileImageUrl();
+
+ if (profileImage != null && !profileImage.isEmpty()) {
+ // 기존 이미지가 존재한다면 S3에서 삭제
+ if (newProfileImageUrl != null && !newProfileImageUrl.isBlank()) {
+ s3Service.deleteFile(newProfileImageUrl);
+ }
+ // 새 이미지 업로드
+ newProfileImageUrl = s3Service.uploadFile(profileImage, "sossbar/profile");
+ }
+
+ user.updateUserInfo(userInfoUpdateReqDto, newProfileImageUrl);
+
+ return UserInfoResDto.from(user);
+ }
+
+ // 프로필 페이지 - 사용자 프로필 조회, userId로 구분
+ public UserProfileInfoResDto getUserProfile(Long userId) {
+ User user = getUserById(userId);
+
+ return UserProfileInfoResDto.from(user);
+ }
+
+ // entity 찾는 공통 메소드
+ private User getUserById(Long userId) {
+ return userRepository.findById(userId).orElseThrow(
+ () -> new BusinessException(ErrorCode.USER_NOT_FOUND_EXCEPTION
+ , ErrorCode.USER_NOT_FOUND_EXCEPTION.getMessage() + userId));
+ }
+}
diff --git a/SossBar/src/main/java/com/sossbar/user/service/UserService.java b/SossBar/src/main/java/com/sossbar/user/service/UserService.java
index 54f5a4a..8b7abe9 100644
--- a/SossBar/src/main/java/com/sossbar/user/service/UserService.java
+++ b/SossBar/src/main/java/com/sossbar/user/service/UserService.java
@@ -3,7 +3,6 @@
import com.sossbar.global.common.code.ErrorCode;
import com.sossbar.global.common.exception.BusinessException;
import com.sossbar.global.config.S3Service;
-import com.sossbar.user.dto.request.UserOnboardingReqDto;
import com.sossbar.user.dto.request.UserInfoUpdateReqDto;
import com.sossbar.user.dto.response.UserInfoResDto;
import com.sossbar.user.entity.User;
@@ -23,9 +22,9 @@ public class UserService {
private final UserRepository userRepository;
private final S3Service s3Service;
- // 온보딩 - 사용자 추가 정보 입력 (이름, 한 줄 소개, 프로필 이미지)
+ // 온보딩 - 사용자 추가 정보 입력 (실명, 한 줄 소개, 프로필 이미지)
@Transactional
- public UserInfoResDto onboarding(Principal principal, UserOnboardingReqDto userOnboardingReqDto, MultipartFile profileImage) {
+ public UserInfoResDto onboarding(Principal principal, UserInfoUpdateReqDto userInfoUpdateReqDto, MultipartFile profileImage) {
Long id = Long.parseLong(principal.getName());
User user = getUserById(id);
@@ -43,12 +42,12 @@ public UserInfoResDto onboarding(Principal principal, UserOnboardingReqDto userO
profileImageUrl = s3Service.uploadFile(profileImage, "sossbar/profile");
}
- user.onboarding(userOnboardingReqDto, profileImageUrl);
+ user.updateUserInfo(userInfoUpdateReqDto, profileImageUrl);
return UserInfoResDto.from(user);
}
- // 마이페이지 - 내 프로필 조회
+ // 마이페이지 - 내 계정 정보 조회(실명, 이메일)
public UserInfoResDto getUserInfo(Principal principal) {
Long id = Long.parseLong(principal.getName());
User user = getUserById(id);
@@ -56,40 +55,6 @@ public UserInfoResDto getUserInfo(Principal principal) {
return UserInfoResDto.from(user);
}
- // 마이페이지 - 내 프로필 수정
- @Transactional
- public UserInfoResDto updateUserInfo(Principal principal, UserInfoUpdateReqDto userInfoUpdateReqDto, MultipartFile profileImage) {
- Long id = Long.parseLong(principal.getName());
- User user = getUserById(id);
-
- String newNickname = userInfoUpdateReqDto.nickname();
-
- // nickname 중복 체크 - 자신 제외
- if (newNickname != null &&
- userRepository.existsByNicknameAndIdNot(newNickname, user.getId())) {
- throw new BusinessException(
- ErrorCode.VALIDATION_ERROR,
- "이미 사용 중인 닉네임입니다."
- );
- }
-
- // 프로필 이미지 수정 처리 (기존 이미지 삭제 후 새 이미지 업로드)
- String newProfileImageUrl = user.getProfileImageUrl();
-
- if (profileImage != null && !profileImage.isEmpty()) {
- // 기존 이미지가 존재한다면 S3에서 삭제
- if (newProfileImageUrl != null && !newProfileImageUrl.isBlank()) {
- s3Service.deleteFile(newProfileImageUrl);
- }
- // 새 이미지 업로드
- newProfileImageUrl = s3Service.uploadFile(profileImage, "sossbar/profile");
- }
-
- user.updateUserInfo(userInfoUpdateReqDto, newProfileImageUrl);
-
- return UserInfoResDto.from(user);
- }
-
// entity 찾는 공통 메소드
private User getUserById(Long userId) {
return userRepository.findById(userId).orElseThrow(