- section0 : Web Service & Web Application
- section1 : Spring Boot로 개발하는 RESTful API
- section2 : User Service API 추가
- section3 : Restful service 기능 확장
- section4 : Spring Boot API 사용
- section5 : JPA 사용
- section6 : REST API 설계 가이드
1. Web Service 개발 방법 SOAP과 REST의 이해
REST(Representational State Transfer):
REST란 정보를 나타내고 전달하는 방식입니다.HTTP Method를 사용하여 데이터를 처리합니다.
예시: 인터넷에서 사진을 보는 것처럼, 정보를 표현하고 전달하는 방식입니다.SOAP(Simple Object Access Protocol):
- 무엇을 의미하는가? SOAP는 간단한 객체 접근 프로토콜로, 웹 서비스 간에 통신할 때 사용됩니다. 이는 XML 기반의 메시지를 사용하여 데이터를 교환합니다.
- 특징: 보안과 신뢰성이 높습니다. 주로 기업 간 시스템 간 통신에 사용됩니다.
- 예시: 원격 서버에 데이터를 요청하고 응답을 받는 과정에서 SOAP를 사용할 수 있습니다.
- 주의할 점: SOAP는 REST보다 더 많은 오버헤드가 발생할 수 있으며, 구현이 복잡할 수 있습니다.
2. RESTful
- REST API를 제공하는 웹 서비스
Resource
- URI, 인터넷 자원을 나타내는 유일한 주소
- XML, HTML, JSON
Endpoint
- API를 통해 서버가 제공하는 리소스에 접근하기 위해서 제공되는 주소
- ex) 블로그의 게시물을 가져오기 위한 엔드포인트는 다음과 같을 수 있습니다: https://example.com/api/posts/{post_id}
- 여기서 {post_id}는 특정 게시물의 ID를 가리키며, 이 엔드포인트를 통해 클라이언트는 해당 ID를 가진 게시물에 대한 정보를 요청할 수 있습니다.
사용자가 여러 개의 글을 작성할 수 있다고 가정하고 설계(1:N)
1) 사용자 목록조회를 위해 /users를 사용하고 GET HTTP Method사용
2) 새로운 사용자 등록도 /users를 사용하고 POST HTTP Method 사용
3) 사용자 한 명 반환 /users/{id} GET HTTP Method사용
4) 사용자 삭제 /users/{id} Delete HTTP Method사용
5) 사용자의 모든 포스트 반환 /users/{id}/posts Get Method 사용
6) 사용자의 모든 포스트 생성 /users/{id}/posts POST Method 사용
7) 사용자의 모든 details 반환 /users/{id}/posts/{post_id} Get Method 사용
1) HelloWorldController라는 클래스를 추가
- 이 컨트롤러 클래스가 스프링 컨텍스트에 등록되기 위해서는
REST컨트롤러라는 어노테이션 작업을 해야 한다.- 일단 만들고자 하는
RESTful서비스에는 화면단을 가지고 있지 않기 때문에 컨트롤러가 아니라RestController를 사용한다.2) 애노테이션에
@GetMapping(path = "/hello-world")추가
이렇게 추가하면 전달하고자 하는HTTP의 메소드가 무엇인지 따로 명시하지 않아도 이Annotation이GetMethod라고 바로 알 수 있다.3) helloWorld라는 메소드를 추가해준다.
1)
@Getmapping(path = “/hello-world-bean”)추가2)
helloWorldBean메서드가HelloWorldBean클래스를 반환할 수 있도록 코드 작성3)
HelloWorldBean클래스는@Data(롬복 – getter,setter 다 자동생성),@AllArgsConstructor를 추가하여 생성자 자동 생성 어노테이션을 추가해준다.
AllArgsConstructor은 클래스의 모든 필드를 인자로 받는 생성자를 만들어주고,RequiredArgsConstructor은final이나@NotNull으로 표시된 필드만을 인자로 받는 생성자를 만들어줍니다.
SpringBoot의 설정파일 : application.yml or application.properties
application.properties-> 설정이름 = 값
application.yml-> 설정이름:값
yml파일을 쓰게 되면 계층 구조로 구분할 수 있기 때문에 같은 이름의 그룹핑이 되어 있다고 하면 훨씬 더 적은 데이터 양을 가지고 동일한 속성을 지정할 수 있다.- 따라서, 좀 더 구조적으로 컴팩트한 설정을 할 수 있다는 특징을 가지고 있습니다.
1. Spring Boot Auto Configuration
DispatcherServlet(디스패처 서블릿)
- 클라이언트의 모든 요청을 한곳으로 받아서 처리한다. 요청에 맞는
Handler로 요청을 전달하고,Handler의 실행 결과를Http Response형태로 만들어서 반환한다.ErrorMvcAutoConfiguration(에러 처리를 위해)HttpMessageConverterAutoConfiguration -> JSON convert
사용자 요청에 따른 비즈니스 로직을 처리하고 나온 결과값을 API로 호출한 사용자 혹은 클라이언트로 보내줘야 한다. 전달하기 위한 데이터 포맷 처리를 위한 것
2. Rest Controller
@Controller+@ResponseBodyView를 갖지 않는 REST data(JSON/XML)을 변환
스프링 MVC에서 사용하고자 하는 뷰 형태의 페이지를 생성할 필요가 없기 때문에 클라이언트 요청 값을 바로JSON포맷으로 변경해서 전달하는 것만 신경 쓰면 된다.- 추가로,
RseponseBody에 추가하는 작업을 따로 하지 않더라도 자동적으로RseponseBody에 담겨서 반환되기 때문에 추가 작업 필요 없다.
@PathVariable은 스프링 프레임워크에서 컨트롤러 메소드에서 가변적인URI값을 받아오기 위해 사용되는 어노테이션입니다.- 가변적인
URI란URL의 경로 부분이 변할 수 있는 경우를 말합니다.
- 예를 들어, 다음과 같은 URL이 있다고 가정해봅시다.
http://localhost:8080/books/{id}
- 여기서 {id} 부분은 가변적인 값이 될 수 있습니다.
- 클라이언트가 요청할 때 이 부분에 어떤 값을 넣느냐에 따라 다른 동작을 하도록 하고 싶다면
@PathVariable을 사용합니다.@GetMapping("/books/{id}") public ResponseEntity<Book> getBookById(@PathVariable Long id) { // id를 이용하여 해당하는 책 정보를 가져와 반환 }
위의 예제에서
@PathVariable어노테이션은 메소드 파라미터로 선언된id에 해당하는URL 경로의 가변 값을 매핑해줍니다.즉, 클라이언트가 요청한
URL에서{id}에 해당하는 값을 자동으로
id 변수에 매핑하여 메소드 내에서 사용할 수 있도록 해줍니다.이렇게 함으로써 사용자가 요청한 가변적인 URL의 값이 컨트롤러 메소드 내에서 사용될 수 있게 됩니다.
따라서 클라이언트가 지정한 값이 실제 URL에 사용될 수 있게 됩니다.
- 1)
User클래스 생성
@Data를 사용하면 자동으로getter,setter생성@AllArgsConstructor사용하면 자동으로 생성자 생성- 2)
UserDaoService라는 비즈니스 로직 생성
- (
finaAll,save,findOne) 생성
- 1) 사용자 요청을 처리할 수 있는 컨트롤러 추가
UserController이전에 추가했던 서비스 클래스의 인스턴스를 선언한 다음에 비즈니스 메서드들을 작성.- 스프링에서는 개발자가 직접 서비스의 인스턴스를 생성해서 사용하는 것이 아니라 스프링 프레임 워크 내에서 사용 가능한 인스턴스들이 빈이란 이름으로써 스프링 컨텍스트에 의해서 관리되고 있다.
- 따라서, 필요한 인스턴스가 있을 경우에는 해당 인스턴스에 대해서 스프링 컨텍스트에 등록이 되고 호출하는 방식으로 사용.
스프링이 가동이 될 때, 이
user.dao.service라는 것이 스프링 컨텍스트 메모리 안에 등록이 되고 그걸 주입 받아서 사용. 스프링의 빈은 용도에 따라서컨트롤러 빈,서비스 빈,레포지토리 빈같이 나눠서 사용한다.
- 1) 클라이언트가 사용자에게 어떠한 정보를 전달할 때는
PostMapping을 사용합니다.- 2)
JSON이라던가XML형태로 전달하기 위해서Controller에서는 해당하는 매개변수 타입을@RequestBody라는 타입으로 받아서 작업을 해줘야 한다.- 3) 그러면 클라이언트에서 전달하는 데이터의 포맷과 일치하는 필드의 값을 찾아서 우리가 유저라는 데이터 값에다가 자동으로 매핑 시켜주는 작업을 처리해주게 된다.
서버에서 PostMethod에 대한 처리를 한 다음에 정상적인 처리가 되었을 때, 기존의 200번이 아닌 다른 번호로 바꾸는 것이 가능하다.
- 1) 이를 위해
ServletUriComponentsBuilder를 사용할 것.- 2) 서버에서 반환하려는 데이터는
ResponseEntity에 담아서 반환하자.
즉, 이전에 만들었던createUser메서드를void에서ResponseEntity로 반환하는 것임!
- 3) 제일 마지막에 보면
return값이 하나 필요하게 되었다.ResponseEntity값을 하나 생성할 건데created다음에 우리는 주소값을 같이 포함시켜서 반환시켜 줄 것입니다.- 4)
servletUriComponentBuilder라는 것을 사용하고request정보로부터URI를 생성할 것입니다. 이를saverdUser값에서id값을 가지고 와서 조합할 것이고 완성이 되면toUri라는 메소드 가지고 전체 정보를Uri로 바꾸고 로케이션 정보를response엔티티에 전달하게 되면 200번 ok가 201번 created라는 요청 값으로 변경이 됩니다.
user id존재하지 않을 때도200 OK를 반환하는 경우가 존재한다.
이를 해결하기 위해throw new UserNotFoundException추가- 이때,
@ResponseStatus(HttpStatus.NOT_FOUND)사용해서404 에러발생시키기1) 이를 위해
UserController에retrieveAllUsers코드 수정
(null이면 예외 던지기)
2) 1번과 같이 수정하면 아래 클래스가 없다고 하기 때문에
UserNotFoundException클래스 생성3) 이렇게 한 다음
https://127.0.0.1:8088/users/4라고 하면 없기 때문에 에러 발생. 그러나,UserNotFoundException에 반드시HttpStatus.NOT_FOUND를 해야404 에러가 발생한다
UserNotFoundException와 같이 예외적인Exception말고 일반화된 예외클래스를 사용해서 상태 코드 혹은 클라이언트에게 보여줘야 하는 메시지를 제어해보자.
- 1) 이 예외 클래스를 위해서
ExceptionResponse클래스를 선언함- 2)
CustomizedResponseEntityExceptionHandler추가. 이때,@ControllerAdvice애너테이션을 사용해서 모든 컨트롤러가 실행될 때 반드시 해당하는CustomizedResponseEntityExceptionHandler가 실행될 수 있도록 한다.- 3)
CustomizedResponseEntityExceptionHandler여기에ResponseEntityExceptionHandler상속받는다.- 4)
CustomizedResponseEntityExceptionHandler클래스에handleAllException,handleUserNotFoundException메서드도 만든다.- 여기서 SpringAOP란 어떤 로직을 기준으로 핵심적인 관점이라던가 부가적인 관점으로 봤을 때, 관점을 기준으로 모듈화 하겠다는 의미.
- 5) 이렇게 하면 결과적으로 긴 에러 메시지가 아니라,
timestamp,message,details관련 에러 메시지가 발생하게 됩니다.
1)
Controller에Iterator로 표현할 예정
2)User에deleteUser추가