
지난번 포스트에 이어서 유저 정보를 생성하는 회원가입 API를 구현해보자.
User Domain 및 User(JPA)Repository, UserDetailService 를 구현한 상태이다.
유저 생성 API에서 사용하는 DTO 객체이다.
@Data
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserRegisterRequest {
@NotBlank(message = "이메일은 필수입니다.")
@Pattern(regexp = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
message = "유효하지 않은 이메일 형식입니다.")
private String email;
@NotBlank(message = "비밀번호를 입력해주세요")
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,30}$",
message = "비밀번호는 8~30 자리이면서 1개 이상의 알파벳, 숫자, 특수문자를 포함해야합니다.")
private String password;
@NotBlank(message = "닉네임은 필수입니다.") // 없을 시 랜덤으로 지정.
private String nickname;
}
Validation:
✨@NotBlank: 요청 value가 null, '', ' ' 인지 검사한다. ✅
✨@NotEmpty: 요청 value가 null, '' 인지 검사한다.
✨@NotNull: 요청 value가 null인지 검사한다.
CRUD Repository를 상속받은 UserRepository의 save() 함수로 User Domain에 저장한다.
@RequiredArgsConstructor
@Service
public class UserRegisterService {
private final UserRepository userRepository;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
public Long save(UserRegisterRequest userRegisterRequest) {
return userRepository.save(User.builder()
.email(userRegisterRequest.getEmail())
.password(bCryptPasswordEncoder.encode(userRegisterRequest.getPassword()))
.nickname(userRegisterRequest.getNickname())
.build()).getId();
}
}
BCryptPasswordEncoderBean을 활용하여 비밀번호를 암호화 (Encode)해준다.
UserController 안의 register() 함수가 회원가입 API의 구현체이다.
@RequestMapping("/user")
@RequiredArgsConstructor
@RestController
public class UserController {
private final UserRegisterService userRegisterService;
@PostMapping("/register")
@ResponseStatus(HttpStatus.OK)
public Long register(@Valid @RequestBody UserRegisterRequest userRegisterRequest){
return userRegisterService.save(userRegisterRequest);
}
}
Controller 클래스의 메서드에 @PostMapping("/URI") 어노테이션을 추가해준다.
1️⃣ 사용자가 POST 요청을 JSON Body 형식으로 보내면, Controller은 @RequestBody 를 통해 전달받으며 DTO 객체를 생성한다.
2️⃣ @PostMapping 으로 매핑된 메서드에서 요청을 처리해주고, @ResponseBody 를 통해서 응답할 객체를 넘겨준다.
⚠️ 그렇다면, UserController 에서 @ResponseBody 는 어디 있을까?
✅
@Controller대신에@ResponseBody를 포함하는@RestController를 Controller에 매핑함으로써 컨트롤러 내에 리턴값을 ResponseBody 로 감싸는 역할을 해준다.
그렇기 때문에 @Controller 를 사용한 채로 return 타입을 Long으로 하면 아래와 같은 에러가 발생한다.
Request processing failed:java.lang.IllegalArgumentException:
Unknown return value type: java.lang.Long] with root cause
Postman 으로 API 테스트를 해보니 성공적으로 200 OK 가 뜨며, 고유 id 값이 반환된다!
