스프링 - Path parameter, Spring Error HttpStatus, Response Body, RestAPI Http Method

JungWooLee·2022년 9월 24일
0

Spring

목록 보기
2/5
post-thumbnail

1. Path parameter 란?

가령 다음과 같은 url 을 호출하는 api 가 있다고 생각

/users/{id}/todos/{id} => /users/1/todos/101

여기서 id 는 variable 으로서 유동적으로 변할 수 있다

대부분의 Rest API url 들은 위와 같이 path 파라미터로 이루어져있다

Path 파라미터 사용법


이를 브라우저에서 확인해보면


이렇듯 variable 값들을 PathVarible들을 어노테이션을 통하여 매핑해줄 수 있다.

대부분의 rest api 들을 이러한 PathVarible 들을 갖고 있기 때문에 이해하고 넘어가야한다

실습

이해를 바탕으로 소셜 미디어 애플리케이션을 만들어 보자
명세는 아래와 같다

각 리소스에 대해서 CRUD 에 대한 비즈니스 로직들을 수행하여야한다

이때에 rest api 를 사용한다면 Request Method, 즉 Http Method 를 이용하여 자원에 대한 표현을 진행한다
기존의 PathVariable 을 통하여 생성된 컨트롤러를 확인하여 보면 다음과 같은 Get Method 가 실행되었음을 알 수 있다
이는 GetMapping 으로 컨트롤러에서 지정하였기 때문에 브라우저에서 url 을 입력하였을 때 디스패처 서블릿이 이와 일치하는 Get Method 인 helloWorldPathVariable 메서드와 매핑시켜 주었고 이를 default message converter 인 json 으로 반환하여 브라우저에 전달한 것을 알 수 있다


2. Rest API 에서 Http Method

Rest api 는 한정된 url 을 사용하여 자원을 표현하기에 Http Method 를 활용하여 자원에 대한 action 을 명시 한다

Http Method 에 따른 Rest API

  • GET = 리소스에 대한 상세 정보 조회
  • POST = 새로운 리소스를 생성
  • PUT = 이미 존재하는 리소스를 업데이트
  • PATCH = 이미 존재하는 리소스 중 일부를 변경하고자 할 때
  • DELETE = 리소스를 지우고자 할 때

보편적으로는 PATCH 까지는 안쓰이고 주로 PATCH 를 제외한 나머지 HTTP 메서드들을 통하여 자원의 CRUD 를 실시한다

실습

REST API 상세 명세는 다음과 같다
Users Rest API

  • 모든 유저들을 조회
    • GET /users
  • 유저 생성
    • POST /users
  • 하나의 유저를 조회
    • GET /users/{id}
  • 유저를 삭제
    - DELETE /users/{id}
    Posts REST API
  • 유저의 모든 포스트 조회
    • GET /users/{id}/posts
  • 유저의 새로운 포스트 생성
    • POST /users/{id}/posts
  • 유저의 포스트를 조회
    • GET /users/{id}/posts/{post_id}

자원 이름에 대한 지정

UsersUser 로 표현하지 않는 이유는 개발자의 취향 차이에 가깝지만 복수형으로 만들때에 훨씬 사용자의 입장에서 보다 자원에 대해 이해하기 쉽기에 복수형으로 진행


GetMapping

User Bean 만들기


추가적으로 게터와 세터를 만들어 준다

User DAO

빈을 생성한 이후에 이러한 엔티티들을 관리하기 위해 data access object, 즉 dao 를 생성하여 관리한다

다오의 경우 데이터베이스와 연동하여 진행하지만 전체적인 틀을 짜고 있기 때문에 static 하게 DB에 접속 없이 리스트에 담아 관리하여 메소드들을 만들어 본다

User Controller

유저 리소스에 대한 컨트롤을 할 컨트롤러를 생성한다

/users

그렇다면 id 를 입력받고 해당 id 를 가진 유저를 찾고자 한다면 어떻게 서비스를 구성해야 할까?

컨트롤러

서비스

Stream 을 이용하여 해당 id 를 가진 유저를 검색하고 만족하는 첫번째 유저를 가져와 반환시킨다

/users/{id}

Get 에서 Body 를 가질 수 있을까?

답은 NO 다. XHR does not allow payloads for GET request.
Get 메서드의 활용법에는 어긋나지만 만약 보내야할 파라미터가 있다면 query param 으로 보내면 됨


Post Mapping

새로운 유저를 만들고자 할 때

서비스

동일한 id 를 가진 유저가 존재하면 안되기에 유저 카운트를 0으로 새로운 유저가 들어온다면 1을 추가할 수 있도록한다

컨트롤러

RequestBody 를 통하여 Body에 들어온 값들을 자바 빈과 매핑시켜 User 빈으로 받을 수 있도록 한다
이후 서비스를 호출하여 저장

Post 의 경우 body 를 입력할 수 없기에 별도의 툴을 사용하여야 한다. PostMan 을 사용하여 실습진행

Location 지정



우리는 항상 사용자의 입장에서 Rest API 의 동작을 살피는 것을 필수적으로 해야한다

그렇다면 유저가 생성된 이후에 어떻게 해야할까?

그저 생성하는 것에서 끝나는 것이 아니라 /users/{id} 에 대한 필드를 만들어 생성된 유저 정보를 확인 할 수 있게 한다면 훨씬 부드러운 서비스를 만들 수 있을 것이다

이러한 Location 에 대한 설정은 다음과 같이 처리한다

  • ServletUriComponentBuilder.fromCurrentRequest 를 통하여 현재 요청된 uri 를 받아온다
  • 이후 path 를 추가하여 id 를 variable로 설정
  • buildAndExpand 를 통하여 variable 을 id 와 매핑한다
  • 만들어진 uri 를 통하여 ResponseEntity 를 빌드


로케이션이 올바르게 설정된 것을 볼 수 있다


3. Spring Error HttpStatus, Response Body 커스텀하기

어떻게 개발을 하든 모든 코드는 완벽하지 않다고 생각한다. 그저 완벽에 가깝게 완성도 높은 코드를 만드는 것을 목표로 하는게 현실적이라 생각한다

만약 사용자가 API 를 호출하였을 때 올바르지 않은 형태로 호출하게 되면 당연히 에러가 난다

하지만 사용자가 에러에 대한 코드를 분석하여 어떤 부분이 잘못됬는지 알 수 있게 해줘야 하는 부분도 개발자의 일이다

가령 사용자가 생년월일을 입력해야하는 곳에 자신의 이름을 적고 API 를 호출했다면? 올바른 파라미터를 지정하라는 에러가 터져야 한다 (400 에러코드)

Http Status Code

  • 200 : 성공
  • 201 : 생성 성공
  • 204 : Content 가 없을 때 ( 업데이트 진행 )
  • 400 : 유효성 오류
  • 401 : 권한 없을 때 (authorization fail)
  • 404 : 없는 리소스에 접근하였을 때
  • 500 : 서버 오류

실습

실습중 Get 호출에서 없는 아이디에 접근한다면 기존 서비스에서는 다음과 같이 에러를 던진다

여기서 스택트레이스를 통하여 서비스에서 id 를 통한 predicate -> get 에서 나타남을 알 수 있다

다음과 같이 NoSuchElement 예외는 상황에 맞는 올바른 Exception이지만 status 코드를 살펴보면 500 에러로 서버사이드 에러임을 확인할 수 있다

해결

해당 아이디가 존재하지 않는다면 커스텀 에러를 던지도록 변경한다

현재는 Status Code 가 200 변경후에는 404 로 없는 리소스에 접근했다는 코드를 던져주어야함


서비스에서 받은 값이 null 일 경우 커스텀 에러를 던지도록 수정

  • ResponseStatus 를 통하여 Status 코드를 올바르게 변경 후 throw 될 수 있도록 함
  • 기본적으로 Runtime Exception 으로 던지도록 함 ( 실행중에 발생하며 시스템 환경적으로나 input 값이 잘못된 경우, 의도적으로 개발자가 잡아내기 위한 조건등에 부합할 경우에 사용됨 )

확인해보면 정상적으로 404 에러코드를 받을 수 있다

에러페이지 스택트레이스

Spring 의 화이트에러페이지의 스택트레이스는 dev tools에 의해 보여지게 된다
이는 배포 진행시 jar 파일으로 배포하게 되는데 이때 자동으로 dev tools 의 경우 자동으로 disable 되기 때문에 유의하지 않아도된다

커스텀 에러의 구조변경

현재 에러반환 데이터를 확인해보면 다음과 같다

😊 에러에 대한 구조의 경우 사용자 정의로 바꿀 수 있다

그렇다면 기존의 스프링에서 에러빈 구조는 어떻게 만들어질까?

아래에서 확인해보자

이를 토대로 커스텀 에러 핸들러를 만들어보자

@ControllerAdvice 를 통하여 모든 컨트롤러에 해당되도록 명시한다. 스프링 컨테이너가 관리하도록

확인해보면 다음과 같이 ResponseEntity를 커스터마이즈 할 수 있음을 알 수 있다

하지만 의도와는 다르게 500에러가 나타남을 알 수 있다. 이는 모든 Exception에 대해서 서버에러를 터트리도록 되어있기 때문. 이를 수정하기 위해 새로운 메서드를 추가한다


마지막으로 이전 오브젝트로 받았던 ResponseEntity 의 타입을 ErrorDetail로 맞추어 일치시킨다

결론

Rest API 에서는 Response와 status code를 통해 상세 정보를 사용자에게 전달할 수 있다.

만약 올바른 형태의 Status CodeResponseEntity를 반환하지 않는다면 사용자에게 혼란을 야기할 수 있기 때문에 rest API에서는 이 두가지를 고민하고 설계할 필요가 있다

0개의 댓글