본문 바로가기
💻 뚝딱뚝딱/북북클럽

[개발일지 #004] 회원 정보 수정 API 구현

by 뚜루리 2025. 4. 22.
728x90
320x100

🎯 오늘의 목표

  • 회원정보수정 구현

⚙️ 진행한 작업

  1. 회원정보수정 구현

🛠️ 개발내용

📌  회원서비스 수정 (UserService.java)

package ddururi.bookbookclub.domain.user.service;


import ddururi.bookbookclub.global.exception.DuplicateNicknameException;
import ddururi.bookbookclub.domain.user.dto.UserLoginRequest;
import ddururi.bookbookclub.domain.user.dto.UserResponse;
import ddururi.bookbookclub.domain.user.dto.UserSignupRequest;
import ddururi.bookbookclub.domain.user.dto.UserUpdateRequest;
import ddururi.bookbookclub.domain.user.entity.User;
import ddururi.bookbookclub.domain.user.repository.UserRepository;
import ddururi.bookbookclub.global.exception.DuplicateEmailException;
import ddururi.bookbookclub.global.exception.UserNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;
    private final BCryptPasswordEncoder passwordEncoder;
	
    //생략//

    // 회원정보 수정
    @Transactional
    public void updateProfile(Long userId, UserUpdateRequest request) {
        User user = userRepository.findById(userId)
                .orElseThrow(UserNotFoundException::new);

        // 닉네임이 바뀌었을 때만 중복 검사를 수행
        if (!user.getNickname().equals(request.getNickname())) {
            validateDuplicateNickname(request.getNickname());
        }

        user.setNickname(request.getNickname());
        user.setBio(request.getBio());
        // save 호출 안 해도 됨 → JPA가 변경감지로 UPDATE 수행
    }
}

닉네임 중복 체크 로직을 추가하였음.

 

 

📌  회원컨트롤러 추가 (UserController.java)

package ddururi.bookbookclub.domain.user.controller;

import ddururi.bookbookclub.domain.user.dto.*;
import ddururi.bookbookclub.domain.user.service.UserService;
import ddururi.bookbookclub.global.common.ApiResponse;
import ddururi.bookbookclub.global.jwt.JwtUtil;
import ddururi.bookbookclub.global.security.CustomUserDetails;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/users")
public class UserController {

    private final UserService userService;
    private final JwtUtil jwtUtil;

    //생략//

    @PutMapping("/me")
    public ResponseEntity<ApiResponse<Void>> updateMyInfo(
            @AuthenticationPrincipal CustomUserDetails userDetails,
            @Valid @RequestBody UserUpdateRequest request
    ) {
        userService.updateProfile(userDetails.getUser().getId(), request);
        return ResponseEntity.ok(ApiResponse.success(null, "회원 정보가 수정되었습니다."));
    }

}

 

 

📌  회원수정 관련 DTO 추가 (UserUpdateRequest.java)

package ddururi.bookbookclub.domain.user.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class UserUpdateRequest {

    @NotBlank(message = "닉네임은 비워둘 수 없습니다.")
    private String nickname;

    @Size(max = 500, message = "자기소개는 500자 이내로 입력해주세요.")
    private String bio;
}

 

 

[Postman을 통한 테스트]

 

 

PUT /api/users/me
Headers:
Authorization: Bearer {JWT 토큰}
Content-Type: application/json

{ "nickname": "새닉네임", "bio": "자기소개 수정" }
728x90
320x100