Post

(코딩 자율학습 스프링 부트3) 11장


REST API와 JSAON의 등장 배경

웹 서비스를 사용하는 클라이언트는 매우 다양하다 스마트폰, 스마트워치, 태블릿등 서버는 이러한 모든 클라이언트의 요청에 응답해야한다 따라서 효율적인 서버 자원 사용을 위해서 나타난 기술이 REST API(Representational State Transfer API)이다 REST API 방식에서는 HTTP 요청에 대한 응답으로 서버의 자원을 반환한다
버는 클라이언트의 요청에 대한 응답으로 화면(view)이 아닌 데이터(data)를 전송한다 이때 사용하는 응답 데이터는 JSON(JavaScript Object Notation)이다 과거에는 응답 데이터로 XML을 많이 사용했지만, 최근에는 JSON으로 통일되는 추세이다

[XML 예시]

1
2
3
4
5
6
7
<article-form>
    <id>1</id>
    <title>가가가가</title>
    <content>1111</content>
</article-form>

[JSON 예시]

1
2
3
4
5
6
7

{
    "id": 1,
    "title: "가가가가",
    "content": "1111"
}

ON 데이터는 키(key)와 값(value)으로 구성된 정렬되지 않은 속성(property)의 집합이다 키는 문자열이므로 항상 큰따옴표(““)로 감싸고, 값은 문자열인 경우에만 큰따옴표(““)로 감싸도록 한다

JSON 실습

Placeholder(API제공 테스 사이트)

Placeholder 사이트(https://jsonplaceholder.typicode.com)에 접속한다 이 사이트는 가짜(fake) API를 제공하여 무료로 각종 테스트를 진행할 수 있는 서비스를 제공한다

[Placeholder 사이트] image

위 무료로 제공하는 API사이트를 활용해서 API를 요청해보도록한다

Talend API Tester(API요청 테스트 사이트)

[Talend API Tester 검색하여 확장 추가] image

[Talend API Tester 실행] image

GET 요청하고 응답한 값 확인하기

[Placeholder 사이트에서 제공하는 API로 요청해보기] image

[Placeholder 사이트에서 응답한 값 확인하기] image

[상태 코드]

  • 1XX(정보) : 요청이 수신돼 처리 중
  • 2XX(성공) : 요청이 정상적으로 처리됨
  • 3XX(리다이렉션 메시지) : 요청을 완료하려면 추가 행동이 필요
  • 4XX(클라이언트 요청 오류) : 클라이언트의 요청이 잘못돼 서버가 요청을 수행할 수 없음
  • 5XX(서버 응답 오류) : 서버 내부에 에러가 발생해 클라이언트 요청에 대해 수행하지 못함

[HTTP 메시지는 시작 라인(start line), 헤더(header), 빈 라인(blank line), 본문(body)으로 구성된다]

• 시작 라인: HTTP 요청 또는 응답 내용이 있으며 시작 라인은 항상 한 줄로 끝난다 • 헤더: HTTP 전송에 필요한 부가 정보(metadata)가 있다 • 빈 라인: 헤더의 끝을 알리는 빈 줄로, 헤더가 모두 전송되었음을 알린다 • 본문: 실제 전송하는 데이터가 있다

Post로 요청하고 응답한 값 확인하기

[Post로 데이터 생성 요청하기] image

[서버로부터 응답 값 확인하기] image

PATCH(수정) 요청하고 응답한 값 확인하기

URL은 1번 게시글을 수정하도록 https://jsonplaceholder.typicode.com/posts/1로 작성한다
[PATCH로 1번 데이터 수정 요청하기] image

[서버로부터 응답 값 확인하기] image

DELETE(삭제) 요청하고 응답한 값 확인하기

URL은 1번 게시글을 삭제하도록 https://jsonplaceholder.typicode.com/posts/1로 작성한다
[DELETE로 1번 데이터 삭제 요청하기] image

[서버로부터 응답 값 확인하기] image

REST 컨트롤러와 일반 컨트롤러의 차이

REST 컨트롤러(FirstApiController)는 JSON이나 텍스트 같은 데이터를 반환하는 반면 일반 컨트롤러(FirstController)는 뷰 페이지를 반환한다

[Rest컨트롤러] image

[일반컨트롤러] image

API 직접 만들어보기

GET 요청을 받아 처리할 메서드를 만들기

프로젝트 탐색기의 api 패키지에서 마우스 오른쪽 버튼을 누르고 New → Java Class를 선택, 클래스 이름은 FirstApiController로 만들도록한다

1
2
3
4
5
    @GetMapping("/api/hello")
    public String hello() {
        return "hello world!";

[Talend로 위에 만든 API로 요청하기] image

GET 요청으로 모든 데이터 조회 메서드 만들기

GET 메소드로 /api/articles 를 요청하면 DB에 가지고 있는 모든 데이터를 응답할 수 있도록 만든다

[/api/FirstApiController]

1
2
3
4
5
6
7
8
9
    // 게시글 리파지터리 주입
    @Autowired
    private ArticleRepository articleRepository;
    @GetMapping("/api/articles")
    public List<Article> index(){
        return articleRepository.findAll();
    }

[Talend로 위에 만든 API로 모든 데이터 요청하기] image

GET 요청으로 단일 데이터 조회 메서드 만들기

GET 메소드로 /api/articles/{id} 를 요청하면 DB에 가지고 있는 해당 id의 데이터를 응답할 수 있도록 만든다

[/api/FirstApiController]

1
2
3
4
5
6
    @GetMapping("/api/articles/{id}")
    public Article show(@PathVariable Long id) {
        return articleRepository.findById(id).orElse(null);
    }

[Talend로 위에 만든 API로 단일 데이터 요청하기] image

POST API 요청으로 데이터 생성하기

POST 메소드로 생성할 데이터를 dto 매개변수로 받아 온다 이렇게 받은 dto는 DB에서 사용할 수 있도록 엔티티로 변환하여 article변수에 넣고, articleRepository를 통해 DB에 저장한다

[/api/FirstApiController]

1
2
3
4
5
6
7
8
9
10
    @PostMapping("/api/articles")
    // dto 매개변수 앞에 @RequestBody라는 어노테이션을
    // 사용한 이유는 기존에는 메서드의 매개변수로 dto로 받아 오기만 하면 됐으나 
    // 여기서는 json으로 데이터를 받아 와야 하므로 본문에 실어 보내는 데이터를 매개변수로 받아오기 위해 사용한다
    public Article create(@RequestBody ArticleForm dto) {
        Article article = dto.toEntity();
        return articleRepository.save(article);
    }

[Talend로 위에 만든 API로 데이터 생성 요청하기] image

PATCH API 요청으로 데이터 수정하기

PATCH 메소드로 수정할 데이터와 수정할 대상 id를 dto 매개변수로 받아 오고 엔티티로 변환한다, 이후 해당 id가 존재하는지를 확인하고 수정 결과를 응답한다

[/api/FirstApiController]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    @PatchMapping("/api/articles/{id}")
    public ResponseEntity<Article> update(@PathVariable Long id, @RequestBody ArticleForm dto) {
        // 1. DTO -> 엔티티 변환하기
        Article article = dto.toEntity();
        log.info("id: {}, article: {}", id, article.toString());
        // 2. 타깃 조회하기
        Article target = articleRepository.findById(id).orElse(null);
        // 3. 잘못된 요청 처리하기
        if (target == null || id != article.getId()){
            //400. 잘못된 요청 응답!
            log.info("잘못된 요청! id:{}, article:{}",id,article.toString());
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
        }
        // 4. 업데이트 및 정상 응답(200)하기
        // 기존 데이터에 새 데이터 붙이기
        target.patch(article);
        Article updated = articleRepository.save(article);
        return ResponseEntity.status(HttpStatus.OK).body(updated);
        //DELETE
    }

[Article.java]

1
2
3
4
5
6
7
8
    public void patch(Article article) {
        if (article.title != null)
            this.title = article.title;
        if (article.content != null)
            this.content = article.content;
    }

[Talend로 위에 만든 API로 데이터 변경 요청하기] image

Delete API 요청으로 데이터 삭제하기

Delete 메소드로 삭제할 대상을 매개변수로 받고 DB에서 대상 엔티티가 있는지 조회한다

[/api/FirstApiController]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    @DeleteMapping("/api/articles/{id}")
    public ResponseEntity<Article> delete(@PathVariable Long id){
        // 1. 대상 찾기
        Article target = articleRepository.findById(id).orElse(null);
        // 2. 잘못된 요청 처리하기
        if(target == null){
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
        }
        // 3. 대상 삭제하기
        articleRepository.delete(target);
        return ResponseEntity.status(HttpStatus.OK).body(null);
    }

[Talend로 위에 만든 API로 데이터 삭제 요청하기] image

This post is licensed under CC BY 4.0 by the author.