마이크로서비스 아키텍쳐에는 애플리케이션 기능을 RESTful API로 노출하는것이 일반적이다
-
1. 스프링부트로 RESTful APi를 설계하고 구축하는 방법
2. 응답 데이터 규격, HTTP 응답코드 등 API 사용자에게 필요한 정보를 문서화하여 제공하는 방법
3. API를 테스트하기위해 단위 테스트를 작성하는 방법
4. RESTful API에 보안을 적용하여 보호하는 방법
-
REST 아키텍쳐 스타일을 따르는 API
REpresentational State Transefer
클라이언트가 서버에 있는 자원을 요청하면 서버는 해당 자원의 상태를 규격에 맞게 표현한 정보를 반환한다
Represntation : 상태 정보 : JSON / 단순 문자열 / HTML 등 여러가지 형식 중 특히 JSON
-
스프링부트는 REST API 설계와 구축을 프레임워크 차원에서 지원
-
사용시 기능1 : 백엔드와 프런트엔드UI 사이의 결합을 끊어낼 수 있으며 앵귤러, 리액트, 뷰 등 자유롭게 원하는 FE 프레임워크를 선택해서 사용할 수 있다
-
POJO로 course 클래스 를 만든다
리포지토리 작성
서비스 : API에서 제공하는 연산으로 구성된 인터페이스를 정의하고 추가로 구현체를 작성하는게 좋음
컨트롤러에서 특정 구현체에 의존하는 대신 인터페이스에 의존해서 사용자 요청을 처리하도록
(기능 수정되더라도 컨트롤러에서 변경X)
컨트롤러는 @RestController = @Controlller + @ResponseBody
메타 어노테이션
리스폰스바디는 메서드의 반환값이 HTTP 응답 본문에 자동 바인딩됨
-
create하는 Post의 요청본문(payload)는 @RequestBody 로 들어온다
JSON으로 전달되며 이 JSON에 매핑되는 POJO클래스를 넣는다 (DTO 대신)
JSON을 POJO 객체로 디시리얼리제이션하는것은 스프링부트가 자동으로 수행
-
Put으로 업데이트 역시 마찬가지, 단 put은 변경 대상인 id도 pathVariable로 받을것
-
REST 엔드포인트 테스트
포스트맨 : GUI를 통해 편리하게 엔드포인트를 호출하고 테스트
EP를 모아 그룹으로 관리 가능, 내보내서 공유 가능, 내보낸 정보는 가져와서 재사용 가능
터미널을 사용하는게 좋다면 -> cURL이나 HTTPie
cURL -> 유닉스 내장
HTTPie -> 터미널에서 실행되는 HTTP 클라이언트로서 HTTP URL 호출 가능
-
> http POST : 8080/courses/1 HTTP/1.1 200
-
JSON 변환에는 기본적으로 Jackson 라이브러리 사용
엔드포인트에는 명사의 복수형 사용
Courses / Persons / Vehicles
동사는 어차피 HTTP 메서드에 들어있으니 굳이 복잡하게 할 필요없다
-----------------------예외 처리---------------------
CourseNotFoundException 런타임익셉션 상속해서 개설
코스서비스Impl 중 findBy에 orElseThrow 넣어준뒤 String.format으로 에러메시지 처리
컨트롤러에서 직접 처리하지않고, 글로벌로 @ControllerAdvice 처리한다
---------------------테스트----------------------
@AutoConfigureMockMvc
ObjectMapper 인스턴스 만들어서 자바객체-제이슨 직렬화한다
andExepect
------------------문서화-------------------
OpenAPI 명세는 RESTful API를 문서화하는 표준을 제공, API 사용자가 API 기능을 일관성있게 파악
디펜던시 추가 - > 스웨거까지 자동으로 만들어짐
컨트롤러에 해당 어노테이션 제공
@Tag
@ResponseStatus
@Operation
@SpringBootApplication에 OpenAPI 빈 생성
apllication.yml에 값 미리 넣어두기
-
기본 제공되는 uri에 접속하면 HTML / JSON으로 문서를 얻을 수 있다
코드젠 -> JSON으로부터 클라이언트 애플리케이션 생성
-----------------REST API 버저닝-----------------
URI
요청 파라미터
커스텀 HTTP 헤더
미디어 타입
-----------------보안--------------
JWT 토큰 사용
인가 서버를 거침(키클록 사용)
디펜던시 추가
@AuthenticationPrincipal 사용해서 JWT 저장된 값에 접근가능
IDOR 이슈 : insecure direct object reference
엔드포인트에서는 토큰의 유효성만 체크할뿐, 누구의 토큰인지 구분 x
-> @PreAuthorize / @PostAuthorize 와 SpEL를 사용해서 단순 토큰 유효성 외에 추가적인 접근 제어 적용가능
= 메서드 수준 시큐리티 필요
메인 클래스에 @EnableGlobalMethodSecurity(prePostEnabled = true) 추가로 시작
원하는 메서드에 @PostAuthorize("@getAuthor.apply(returnObject, principal.clains['user_name'])")
BiFunction에서 메서드 내 코스의 author. userid를 비교 로직 실행
-> 403 : 인증에는 성공했지만 인가되지않음
-
SCOPE 도 사용가능
해당 스코프를 포함하고 있는 토큰만 엔드포인트에 접근
ex) 서드파티 클라이언트 애플리케이션에게 특정 강사가 개설한 모든 과정을 조회할 수 있게 해주지만, 저장은 할 수 없게 하고 싶을때
@PreAuthorize("hasAuthority('SCOPE_course:read)')")
스프링 시큐리티는 filterChain과 여러 필터를 사용해서 보안성을 높이는데 베어러 토큰 인증 처리를 위해 BearerTokenAuthneticationFilter 제공