REST API의 주요 4가지 상황에 대해 기본적으로 정리해보자.
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/user")
public class UserController {
private final UserService userService;
@GetMapping("{userId}/info/simple")
public ResponseEntity<ResponseSimpleUserDto> getSimpleUserInfo(@PathVariable Long userId) {
ResponseSimpleUserDto userInfo = userService.getSimpleUserInfo(userId);
return ResponseEntity.ok(userInfo);
}
}
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class ResponseSimpleUserDto {
private String name;
private String image;
public static ResponseSimpleUserDto of(String name, String image) {
return new ResponseSimpleUserDto(name, image);
}
}
{
"name": "John Doe",
"image": "https://example.com/johndoe.jpg"
}
@RequestMapping(value = "/{customerId}", method=GET)
public ResponseEntity<Customer> findById(@PathVariable int customId) throws DataNotFoundException{ //1
Customer customer = customerService.findById(customerId);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(new MediaType("text","xml", Charset.forName("UTF-8"));
headers.set("My-Header","MyHeaderValue");
return new ResponseEntity<Customer>(customer, headers, HttpStatus.OK); //3
}
@Getter
@RequiredArgsConstructor
public class ApiResponse<T> {
private ApiHeader header;
private T data;
private String msg;
private static final int SUCCESS = 200;
private ApiResponse(ApiHeader header, T data, String msg) {
this.header = header;
this.data = data;
this.msg = msg;
}
public static <T> ApiResponse<T> success(T data, String message) {
return new ApiResponse<T>(new ApiHeader(SUCCESS, "SUCCESS"), data, message);
}
public static <T> ApiResponse<T> fail(ResponseCode responseCode, T data) {
return new ApiResponse<T>(new ApiHeader(responseCode.getHttpStatusCode(), responseCode.getMessage()), data, responseCode.getMessage());
}
}
@Getter
@AllArgsConstructor
public class ApiHeader {
private int code;
private String message;
}
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/user")
public class UserController {
private final UserService userService;
@GetMapping("{userId}/info/simple")
public ApiResponse<ResponseSimpleUserDto> getSimpleUserInfo(@PathVariable Long userId) {
return ApiResponse.success(userService.getSimpleUserInfo(userId), ResponseCode.USER_CREATE_SUCCESS.getMessage());
}
}
{
"header": {
"code": 200,
"message": "SUCCESS"
},
"data": {
"name": "John Doe",
"image": "https://example.com/johndoe.jpg"
},
"msg": "User created successfully."
}
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
public enum ResponseCode {
// 400 Bad Request
BAD_REQUEST(HttpStatus.BAD_REQUEST, false, "잘못된 요청입니다."),
// 403 Forbidden
FORBIDDEN(HttpStatus.FORBIDDEN, false, "권한이 없습니다."),
// 404 Not Found
USER_NOT_FOUND(HttpStatus.NOT_FOUND, false, "사용자를 찾을 수 없습니다."),
// 405 Method Not Allowed
METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED, false, "허용되지 않은 메소드입니다."),
// 409 Conflict
USER_ALREADY_EXIST(HttpStatus.CONFLICT, false, "이미 가입한 사용자입니다."),
USER_NAME_ALREADY_EXIST(HttpStatus.CONFLICT, false, "이미 존재하는 닉네임입니다."),
// 500 Internal Server Error
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, false, "서버에 오류가 발생하였습니다."),
// 200 OK
USER_READ_SUCCESS(HttpStatus.OK, true, "사용자 정보 조회 성공"),
USER_UPDATE_SUCCESS(HttpStatus.OK, true, "사용자 정보 수정 성공"),
USER_LOGIN_SUCCESS(HttpStatus.OK, true, "사용자 로그인 성공"),
// 201 Created
USER_CREATE_SUCCESS(HttpStatus.CREATED, true, "사용자 생성 성공"),
private final HttpStatus httpStatus;
private final Boolean success;
private final String message;
public int getHttpStatusCode() {
return httpStatus.value();
}
}
@AllArgsConstructor
@Getter
public class BaseException extends RuntimeException {
private final ResponseCode responseCode;
@Override
public String getMessage() {
return responseCode.getMessage();
}
}
public class UserException extends BaseException {
public UserException(ResponseCode responseCode) {
super(responseCode);
}
}
회원정보 조회 기능에 대한 구체적인 코드 실행 상황에 대해 살펴보자.
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/user")
public class UserController {
private final UserService userService;
// 회원정보 조회
@GetMapping("{userId}/info/simple")
public ApiResponse<ResponseSimpleUserDto> getSimpleUserInfo(@PathVariable Long userId) {
return ApiResponse.success(userService.getSimpleUserInfo(userId), ResponseCode.USER_CREATE_SUCCESS.getMessage());
}
}
@Transactional(readOnly = true)
public ResponseSimpleUserDto getSimpleUserInfo(Long userId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new UserException(ResponseCode.USER_NOT_FOUND));
return ResponseSimpleUserDto.of(user.getName(), user.getImage());
}
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserException.class)
public ApiResponse<Void> handleUserException(UserException e) {
log.info("UserException: {}", e.getMessage());
return ApiResponse.fail(e.getResponseCode(), null);
}
}
덕분에 깔끔히 정리하고 갑니다 감사합니다!