web +a

스프링부트 ~19 | REST API를 적용하여 CRUD 구현하기

냥냥체뤼 2022. 7. 21. 19:34

intro : 

∨ 지난시간에 모했나

: 연습용 RestAPI 서버를 통해 http 요청/응답 실습했다.

: 그리고 Rest API의 응답 표준인 json 개념도 알았다.

스프링부트 ~ 18 | REST API와 JSON

 

 

∨ 참고) 보충! Status code는 크게 5분류된다.

더보기

1xx  : informational

2xx : successful | 200(OK), 201(Created)

3xx : redirection 

4xx : client error | 404(Not Found)

5xx : sever error | 500(Internal Server Error)

 


이번 내용: 

기존 Article 데이터를 CRUD하기 위한 Rest API 구현하기

 

먼저 Rest API 주소를 설계한다.

그냥.. 이런거 정하자는 거다.

∨ GET 요청을 보낼 url

- /api/articles

- /api/articles/{id}

 POST 요청을 보낼 url

- /api/articles

 PATCH 요청을 보낼 url

- /api/articles/{id}

 DELETE 요청을 보낼 url

- /api/articles/{id}

 

 

이렇게 주소설계한 다음에 실습 고고!!

 

이번 실습

+ 요청을 받아 json으로 반환해줄 컨트롤러 만들어줄거임 RestController

+ 적절한 status code 반환을 위한 클래스인 ResponseEntity를 사용해보자.

 

 

Rest API 구현하기 실습 시쟉쟉

REST api에 대한 개념은 맨 아래 살짝 정리해두었다.

 

 


@RestController

컨트롤러를 하나 만들어 줄건데

이전에는 일반 컨트롤러 @Controller를 썼지만 이제부터는 @RestController 써줄 거다.

 

@Controller : 뷰 템플릿 페이지를 반환함 (html)

@RestController : 일반적으로 JSON을 반환한다. String을 반환할 수도 있다.

중요한 것은 '데이터를 반환'한다는 것!

 

∨ 간단예시

@RestController
public class FirstApiController {
    @GetMapping("/api/hello")
    public String hello() {
        return "hello world!";
    }
}

 

cf. 구체적으로 무슨 응답을 반환하는지는

저번에 해본 '연습용 API 서버'에서 확인해보면 된다 >v <

 

자 이렇게 @RestController가 뭔지 알았다능

 

 


note_ 우리가 하고 있는 것은 

"기존 Article 데이터를 CRUD하기 위한 Rest API 구현하기"라는 것을 다시한번 상기하고 가자. 

=> rest API용 컨트롤러를 구현하자.

 

ArticleApiController

@RestController

public class ArticleApiController{ ... }에다가 CRUD 기능을 구현해 줄 것이다.

note_ 이 컨트롤러는 JSON을 반환한다는 것도 잊지 말자

 

 

자 이제부터 컨트롤러에 GET, POST, PATCH, DELETE를 구현하자. 

recall) 컨트롤러가 웹(http 프로토콜)의 4가지 요청을 처리

recall) 컨트롤러에 Repository를 멤버로 두고 썼던 걸 기억하자

recall) JPA의 Repository를 통해 server와 DB간 소통을 한다는 것도 기억하자

 

 


● GET 요청 처리

일단 컨트롤러에 GET요청 처리를 구현하기 전에 api 테스터에서 http 요청을 보내보자.

GET http://localhost:8080/api/articles 요청을 보내면 404(not found) 에러를 만날 수 있다.

위 url에 대한 get요청 처리를 안 했기 때문이다. 구럼 이제 구현시쟉 >v <

모든 articles 내용을 read하여 json 데이터로 받도록 GET 요청을 처리해보자.

 

모든 목록을 조회

@GetMapping("/api/articles")
public List<Article> index() {
    return articleRepository.findAll();
}

 

단일 Entity를 조회

@GetMapping("/api/articles/{id}")
public Article show(@PathVariable Long id) {
    return articleRepository.findById(id).orElse(null);
}

 

원하는대로 매핑해준 뒤,

url 요청을 보낸 결과를 보면 articles데이터가 json형식으로 잘 담겨 응답한다.

http 응답의 body를 보아도 데이터가 json형식으로 실려온 것을 확인가능하다.

 

 

 


 POST 요청 처리

POST http://localhost:8080/api/articles 요청을 보낸다고 하자. 

body에 json 데이터를 실어서 보내자.

{

    "title": "배스킨최애맛",

    "content": "체리쥬빌레는 사람을 주겨!!"

}

아래의 @PostMapping이 해당 url에서의 POST 요청을 받는다.

@PostMapping("/api/articles")
public Article create(@RequestBody ArticleDto dto) {
	Article article = dto.toEntity();
    return articleRepository.save(article);
}

 

※ 폼에서 데이터를 던질 때에는 파라미터에서 dto로 받아오는데

rest API에서 json으로 데이터를 던질 때에는 @RequestBody 어노테이션을 표시해주어야 받을 수 있다.

※ @RequestBody : JSON 데이터 받기

ㄴ 요청의 body에서 데이터를 받아오란 의미

 

DB에서 확인해보면, 데이터가 잘 추가된 것을 확인 가능!

 

 

 


 PATCH 요청 처리

PATCH http://localhost:8080/api/articles/1 요청을 보내자.

body에는 patch할 내용을 json으로 넣어 보내면 되겠다.

{

    "id": 1,

    "title": "난바뀌었다",

    "content": "누가나를바꿧느냐"

}

 

@PatchMapping("/api/articles/{id}")
public Article update(@PathVariable Long id,
                      @RequestBody ArticleDto dto) {
    // 수정용 Entity 생성
    Article article = dto.toEntity();
    
    
    // 대상 Entity 조회
    Article target = articleRepository.findById(id).orElse(null);
    
    // 잘못된 요청을 처리 (대상이 없음 || 요청url의 id != 수정대상 id)
    if (target == null || id != article.getId()) {
        retrun ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
    }
    
    // 정상적으로 업데이트 및 정상 응답(200) 
    Article updated = articleRepository.save(article);
    return ResponseEntity.status(HttpStatus.OK).body(updated); 
}

※ 응답 status를 리턴하는 방법? 

이 update 메서드의 반환타입이 순수 Article이면 안되고, 

ResponseEntity에 담아서 반환해야 한다.

반환타입을 ResponseEntity<Article>로 설정하자.

그럼 여기에 '상태코드'를 담아 반환할 수 있다.

 

.

.

 

∨ 더 생각해볼 것: 

PATCH시 데이터를 누락해서 보내면 어떻게 될까? 

id, title, content에 값을 담아 보내야 하는데 만약 title을 누락했다면 null이 담겨서 간다.

 

이 문제를 보강하려면 어떻게 해야 할까?

수정되어 들어온 json 데이터만 patch하고, 빠진 데이터는 기존데이터로 유지하면 좋지 않을까?

 

given : 

수정 내용을 담은 Entity 존재

수정 대상 Entity

when : 

수정 요청이 올바르다면 (id가 유효함 등)

then : 

수정대상 Entity에 수정내용 Entity를 덮어씌운다! 

명시한 내용만 수정되도록.. 

 

=> then에 해당하는 기능을 추가해보자.

메서드를 어디에 넣어야 할까?

자연스럽게 Entity 클래스에 넣으면 된다.

그 Entity 데이터에 대한 patch가 이루어지는 거니까..

public class Article {

    ...

    public void patch(Article article) {
        if (article.title != null)
            this.title = article.title;
        if (article.content != null)
            this.content = article.content;
    }
}

그럼 이제 컨트롤러에서 

target.patch(article);

Article updated = articleRepository.save(target);

return ResponseEntity.status(HttpStatus.OK).body(updated);

이런식으로 수정할 것만 수정해서 넣어줄 수 있다.

 

 

 


 DELETE 요청 처리

DELETE http://localhost:8080/api/articles/1 요청을 보내자.. 

 

@DeleteMapping("/api/article/{id}")
public ResponseEntity<Article> delete(@PathVariable Long id) {
    // 대상 찾기
    Article target = articleRepository.findById(id).orElse(null);
    
    // 잘못된 요청 처리
    if (target == null) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
    }
    
    // 대상 삭제
    articleRepository.delete(target);  
    // 데이터 반환
    return ResponseEntity.status(HttpStatus.OK).build();
}

 

그취.. ㅡ

DB에서 확인해보면 2번이 사라진 거 확인 ㄱㄴ

 

 


우왓 짱신기 ~.~

↓ 약간 감이 덜 와서 다시 정리하며 이해하겠다.

 

지금 실습은 Rest api를 적용해서 CRUD를 구현한 것이다.

Rest api를 적용했다는 것은 Representational State Transfer 방식 즉 REST의 원리를 따르게끔 api를 설계하여 적용한 것이다. 참고로 REST 원리와는 별개로 REST api의 설계 규칙도 지켜야 진정하게 RESTful한 설계를 한 것이다.

 

위 말을 이해하려면 REST의 원리는 무엇이며 REST api의 설계 규칙은 뭔지 알아야겠다. 

참고 : https://khj93.tistory.com/entry/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-REST-API%EB%9E%80-REST-RESTful%EC%9D%B4%EB%9E%80

일단 REST의 핵심 개념은 "자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것"이다. 

좀 더 자세히 말하면 REST란,

- HTTP URI를 통해 자원을 '명시'하고

- HTTP의 4가지 메서드인 POST, GET, PUT, DELETE를 통해

- 해당 자원(URI에 명시)에 대한 CRUD를 적용하는 것을 의미한다.

 

더 자세한 내용,

예를들면 REST api 개념과 설계 규칙 등은 링크를 보기 >v <

 

 

 

+ 참고 : 지난 시간에는 REST api라는 걸 이렇게 알고 들어갔다.

REST api 적용의 결과적인 개념만을 간단히 알고 실습시작한 것 같다. 

그래서 더 어렵지 않게 실습할 수 있었다.

자세한 개념은 추후 보강하자.


오예!~

 

일단은 진도 먼저 쭉쭉 나가고

나중에 실제 프로젝트 진행할 때 RESTful하게 설계하며 개념을 더 확실히 하도록 하쟈

json과 REST 개념이 어떻게 연관되는지도 그때 공부하도록 하자.

꼭 그러쟈

반응형