Spring - Validation, Content Type, OpenAPI, Swagger

JungWooLee·2022년 9월 24일
0

Spring

목록 보기
3/5
post-thumbnail

1. Validation

가령 아래와 같은 Rest API 호출이 있다 가정해보자

현재 서비스에서는 아무런 유효성 검사를 실시하지 않기에 이 정보 그대로 유저가 만들어진다

😢 그럼 유효성 검사는 ?

  1. 필드의 validation 을 어노테이션 기반으로 spring boot 에서 간편하게 설정할 수 있다
    Pom.xml 에서 다음과 같은 디펜던시를 추가한다

  2. 먼저 유효성 검사를 적용하고자 하는 곳에 @Valid 를 추가한다

동작 순서 : request가 들어와 Request 에서 User 객체로 바인딩 → 해당 객체의 유효성 검사가 명시된 곳에 자동으로 유효성 검사를 실시

그렇다면 이제 User 빈에서 유효성 검사를 명시해주자

이름의 경우 최소 2글자, birthDate의 경우 과거로 유효성 검사를 실시하게 해준다


라이브러리를 살펴보면 다음과 같이 다양한 유효성 검사를 빠르게 실시할 수 있다. ( #Regex )

결과확인


다음과 같이 Bad Request code를 던지게 바꾸어 줍니다

2. Validation Error 수정하기


Status Code는 올바르게 바꾸어 주었지만 Response body 를 보고 사용자가 어디부분에서 잘못된것인지 확인 할 수가 없습니다
( REST API 는 항상 사용자를 먼저 고려하자 )

구조를 바꾸어 사용자 친화적으로 에러 객체를 던지도록 수정합니다

1.ResponseEntityExceptionHandler

ResponseEntityExceptionHandler에서 handleMethodArgumentNotValid 를 찾아줍시다


이 곳에서 not valid 에 대한 exception을 관리합니다

그렇다면 이를 커스텀 exception 핸들러에서 재정의 해봅니다

자세히 살펴보면 다음과 같이 ResponseEntityExceptionHandler에서 handleMethodArgumentNotValid 를 호출하는 것을 알 수 있습니다.

이를 @ControllerAdvice 가 적용된 구현체에 Override 하게 되면 재정의된 메서드로 반환되게 됩니다. 여기서는 Override를 사용하였기 때문에 Object 타입을 유지 시킵니다.


이후에 확인해보면 다음과 같이 재정의된 Response Body를 확인해볼 수 있음!

2. Validation 메시지, 에러 메시지길이 수정하기

메시지를 확인해보면

다음과 같이 긴 메시지를 확인해볼 수 있다. 사용자에 따라 이는 굉장히 불친절한 메시지. 그렇다면 jakarta.validation 에서 제공하는 message 를 재정의하여 사용자 중심적으로 메시지를 바꿔보자



하지만 본질적인 길이를 줄이는 데에는 실패

Exception에서 제공하는 error field를 수정하여 보자

getDefaultMessage 를 통하여 재정의한 메시지를 가져오고 delimeter를 통하여 조인시킨후 한줄로 만들어 메시지를 정의한다


3. RestAPI 의 문서화

Rest API 문서는 다음 세가지를 필수적으로 가져야 한다

Rest api:

  • Resources
  • Actions
  • Request/Response Structure (Constraints/Validations)

Challenge

  • 정확도 : 문서화가 최신화 되어있고 정확한지 여부?
  • 지속성 : 100 개의 REST API 가 있다 하였을 때 지속성의 보장? (같은 형태의 지속성)

해결법

  • 수작업….
  • 코드를 통해 자동화된 문서화 작업

Swagger 와 OpenAPI를 통하여 자동화된 문서화 작업을 해보자

OpenAPI & Spring boot


오픈 소스인 openapi 에대한 api 문서와 github를 통해 코드를 확인해보자


문서를 보았을 때 자동적으로 api 문서화를 제공해주는 라이브러리임을 알 수 있고 아래 support를 통하여 지원하는 항목을 볼 수 있다

Spring boot version 3 이상일때

  • 위 branch 에서 master의 경우 현재 지원하는 spring boot v1,2 를 관리하고 2.x의 경우에는 spring boot 3 을 지원한다
  • 이곳에서 webmvc 의 pom.xml 을 확인하여 수정하면 적용이 가능하다
  • 현재기준 M6 스냅샷 까지 배포되었지만 안정적인 버전을 사용하기 위해 M5를 사용한다

디펜던시 추가 후 swagger-ui.html 을 입력하면 다음과 같이 자동으로 api 문서화가 됨을 알 수 있다

Swagger-ui 를 통해 확인하기

api-docs

Api-docs 를 확인해보면 다음과 같이 json 으로 정의되어있는 것을 알 수 있다
Path : resources, actions
Servers : server
Component : 사용된 스키마

자세히 보면 다음과 같이 상세한 api 에 대한 명세를 확인해볼 수 있다

가령 $ref 의 경우 리턴된 responseBody 가 User 빈인것을 볼 수 있고

파라미터로 지정된 id 의 경우 type과 path variable 임을 확인 해볼 수 있다

정리해보자면 open API 는 API 정의를 제공하고 swagger-ui 의 경우 이를 시각화하여 적용해볼 수 있게 해준다


4. Content Negotiation

Same Resource - > Same URI

  • 같은 리소스를 얻고자 하였을 때 같은 uri로 접근하도록 보장한다. 다만 현재 json 으로 반환되는 값을 사용자가 xml 형태로 받고자 할때는 어떻게 할까? Uri 를 바꾸어 접근하도록 한다? 그렇게 되면 자칫 RESTFUL 하지 못할 수 있다
  • 또한 다른 언어로 제공받고자 할 수도 있다 (영어, 독일어, 한글)

👍 해결법 : Content Negotiation

  • Accept header (application/xml, application/json,…)
  • Accept-Language header (en,nl,fr,kr,..)

즉, Content Negotiation 이란 header를 통하여 사용자가 어떤 representation을 원하는지 요청을 하고 서비스 제공자는 이를 토대로 협상을 진행한다 (헤더에 맞는 올바른 반환값으로 매칭시켜 반환)

실습

기존 자바 빈으로 반환하였을 때 JacksonHttpMessageConverters 를 통하여 json 타입으로 auto configure 반환 되던 것을 xml 로 반환하는 방법으로 실습해보자

부트에서는 디펜던시를 추가하는 것만으로도 간편하게 해결해볼 수 있다


기존 json 으로 반환하던 것이 accept header 를 통하여 xml 로 반환되는 것을 확인해볼 수 있다

간단하게 디펜던시를 추가해준 것 만으로 이를 구현할 수 있다

만약 사용자가 json 형태로 반환 받기를 원한다면 application/json 으로 Accept 를 바꾸어주면 된다

이렇게 같은 리소스에서 두가지의 representaitons 를 만들 수 있다

0개의 댓글