RESTful Web Service 개발 - User Service API 구현_2

2023. 1. 19. 22:06·공부/Spring
반응형

 

 

Spring Boot를 이용한 RESTful Web Services 개발

HTTP Status Code 제어

GET Method와 POST Method OK 응답 코드 구분하기

  • UserController.java 수정
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
    User savedUser = service.save(user);

    URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                    .path("/{id}")
                    .buildAndExpand(savedUser.getId()) // {id}에 값 지정
                    .toUri(); // uri 형태로 변환

    return ResponseEntity.created(location).build();
}

 

  • 포스트맨에서 확인

포스트맨에서 새 사용자를 추가하면 응답 코드로 200이 아닌 201 Created가 보인다. 이렇게 서버로부터 요청 결과 값에 적절한 상태 코드를 반환시켜 주는 것이 좋은 REST API를 설계하는 방법이다.

그 다음 header 정보를 봐보자.

header 정보에 Location 값이 아까 Controller에서 추가한 코드의 값이 저장되어 있는 걸 확인할 수 있다. 관련 된 코드는 아래와 같다.

URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(savedUser.getId()) // {id}에 값 지정
                .toUri(); // uri 형태로 변환
                
return ResponseEntity.created(location).build();
반응형

 

정해진 응답 코드 외 의미 없는 값을 넘기고 싶으면 아래 코드와 같이 작성하면 된다.

return ResponseEntity.status(222).location(location).build();

 

  • HTTP Status Code
    • 2XX → OK
    • 4XX → Client로부터 발생된 예외
    • 5XX → Server로부터 발생된 예외

 

HTTP Status Code 제어를 위한 Exception Handling

  • 포스트맨 확인

사용자 id는 총 3번까지만 있는데 존재하지 않는 10번의 사용자를 검색해도 200 OK로 떨어진다. 컨트롤러와 서비스의 코드는 아래와 같다.

// 컨트롤러
@GetMapping("/users/{id}")
public User retrieveUser(@PathVariable int id) {
    return service.findOne(id);
}

// 서비스
public User findOne(int id) {
    for( User user : users ) {
        if(user.getId() == id) return user;
    }
    // 없으면 null 반환
    return null;
}

서비스 코드를 보면 알겠지만 user list에 매개변수로 전달받은 id를 가진 user가 있으면 해당하는 User 객체를 반환하고, 없으면 null을 반환한다. null을 반환하는 행위는 서버 입장에서 보면 잘못된 로직이 아니라, 정상적으로 잘 수행했기 때문에 200 OK가 떨어진 것이다.

그래서 user list에서 검색 결과가 null일 경우 예외를 일으키도록 코드를 변경해야한다.

  • UserController.java
@GetMapping("/users/{id}")
public User retrieveUser(@PathVariable int id) {
    User user = service.findOne(id);
    
    if(user == null) {
        throw new UserNotFoundException(String.format("ID[%s] not found", id));
    }
    return user;
}
  • UserNotFoundException.java
public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}

생성자는 message를 부모쪽으로 넘겨버리면 끝이다.

 

  • 서버 재실행 후 포스트맨에서 확인

Status code가 500으로, server에서 발생된 에러 코드라 적혀있다. 지금 발생시킨 에러는 서버에서 잘못 처리된 것이 아니라 적절하게 처리된 것으로 결과 값을 찾을 수 없다는 예외 코드(404)로 변경해주자.

 

  • UserNotFoundException.java 수정
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}

 

  • 서버 재실행 후 포스트맨에서 확인

 

 

Spring의 AOP를 이용한 Exception Handling

위에서 발생한 에러를 자세히 살펴보자. 에러 메세지 중 trace를 잘 보면 어느 곳에서 에러가 발생했는지, 몇번째 줄인지가 보인다. 이런 메세지는 외부로 노출되면 보안상의 이슈가 되기 때문에 적절하게 없애주는 것이 좋다.

Spring의 AOP를 이용한 Exception Handling은 exception 객체를 생성해주어야한다. exception 객체는 user에서만 사용하는 것이 아니라 전체적으로 사용할 것이기 때문에 따로 package를 생성한다.

반응형

 

  • ExceptionResponse.java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExceptionResponse {

    private LocalDateTime timestamp;
    private String message;
    private String details;

}
  • CustomizedResponseEntityExceptionHandler.java
@RestController
@ControllerAdvice // 모든 컨트롤러가 실행될 때 이 어노테이션이 붙은 Bean이 사전에 실행되도록 한다.

public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
    
    @ExceptionHandler(Exception.class) // 이 메서드가 ExceptionHandler 라는 걸 알려주는 어노테이션
    public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
        ExceptionResponse exceptionResponse 
                = new ExceptionResponse(LocalDateTime.now(), ex.getMessage(), request.getDescription(false));
        
        return new ResponseEntity(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

 

  • 서버 재기동 후 포스트맨 확인

trace 정보가 나타나지 않음을 확인한다.

이제 위에서 열심히 만들었던 UserNotFoundException에 대한 처리도 해주자.

  • CustomizedResponseEntityExceptionHandler.java
// user 클래스 전용
@ExceptionHandler(UserNotFoundException.class)
public final ResponseEntity<Object> handleUserNotFoundException(Exception ex, WebRequest request) {
    ExceptionResponse exceptionResponse
            = new ExceptionResponse(LocalDateTime.now(), ex.getMessage(), request.getDescription(false));

    return new ResponseEntity(exceptionResponse, HttpStatus.NOT_FOUND);
}

 

  • 서버 재실행 후 포스트맨에서 확인

HTTP Status Code가 404로 바뀐 걸 확인하면 된다.

 

반응형

사용자 삭제를 위한 API 구현 - DELETE HTTP Mehtod

  • UserDaoService.java 수정
public User deleteById(int id) {
    Iterator<User> iterator = users.iterator();
    
    while(iterator.hasNext()) {
        User user = iterator.next();
        if(user.getId() == id) {
            iterator.remove();
            return user;
        }
    }
    
    return null;
}

 

  • UserController.java 수정
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable int id) {
    User user = service.deleteById(id);
    if(user == null) {
        throw new UserNotFoundException(String.format("ID[%S] not found", id));
    }
}

 

  • 서버 재기동 후 포스트맨 확인

user 데이터가 없는 경우

반응형

 

user 데이터가 있는 경우

1번 사용자 삭제 후 전체 사용자 조회를 해보자.

1번 사용자가 삭제되었다.

 

  • REST API의 단점
    • HTTP Method 중 GET, POST, PUT, DELETE만 지원한다.

- 출처 : 인프런 Spring Boot를 이용한 RESTful Web Services 개발 강의

반응형
저작자표시 비영리 변경금지 (새창열림)
'공부/Spring' 카테고리의 다른 글
  • RESTful Web Service 개발 - Spring Boot API 사용
  • RESTful Web Service 개발 - RESTful Service 기능 확장
  • RESTful Web Service 개발 - User Service API 구현_1
  • RESTful Web Service 개발 - Spring Boot로 개발하는 RESTful Service
데부한
데부한
어차피 할 거면 긍정적으로 하고 싶은 개발자
    반응형
  • 데부한
    동동이개발바닥
    데부한
  • 전체
    오늘
    어제
    • 분류 전체보기 (307)
      • 방통대 컴퓨터과학과 (27)
        • 잡담 (9)
        • 3학년1학기 (17)
      • 프로젝트 및 컨퍼런스 회고 (1)
        • 프로젝트 (4)
        • 한이음 프로젝트 (0)
        • 회고 (3)
      • 공부 (165)
        • Spring (37)
        • JPA (71)
        • 인프런 워밍업 클럽_BE (10)
        • Java (6)
        • React.js (27)
        • 넥사크로 (11)
        • 기타 (3)
      • 알고리즘 (85)
        • 알고리즘 유형 (10)
        • 알고리즘 풀이 (57)
        • SQL 풀이 (18)
      • 에러 해결 (13)
      • 잡담 (7)
        • 국비교육 (2)
        • 구매후기 (5)
        • 진짜 잡담 (0)
  • 블로그 메뉴

    • Github
    • Linkedin
    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    개발자
    코딩테스트
    SpringBoot를 이용한 RESTful Web Service 개발
    MSA
    방통대
    SQL
    Spring
    QueryDSL
    알고리즘
    react
    JPA
    운영체제
    에러해결
    springboot
    RESTful
    기출문제
    스프링부트
    토이프로젝트
    넥사크로
    IT
    백준
    자바스크립트
    프론트엔드
    egov
    Java
    oracle
    전자정부프레임워크
    토비의스프링부트
    인프런
    프로그래머스
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
데부한
RESTful Web Service 개발 - User Service API 구현_2
상단으로

티스토리툴바