TIL - 0609

REST API ATDD

REST API

  • REST 디자인 원칙을 지켜서 만든 Web/HTTP API : 여기서 API는 원격에서 다른 시스템의 메소드를 콜하는 인터페이스를 말함(리소스 핸들링을 위한 - 기본적으로 CRUD)
  • REST 등장 배경 : 현재 형성된 웹 환경을 파괴하지않으면서도 HTTP를 발전 시킬 수 없을까? 웹서버에 변경이 생기더라도 클라이언트에는 아무런 영향을 미치지않도록 발전시킬 수 없을까?
    • 궁극적으로 서버와 클라이언트의 디펜던시를 제거함으로서 얻을 수 있는 이점을 얻기위해서 원칙을 만들게 됨
    • 어떻게 디펜던시를 제거하나? 일관된 URI 디자인(요청), 요청에 대한 응답 결과의 메세지만으로도 클라이언트는 어떻게 처리해야할지 알 수 있도록 메세지 구성(응답)
  • 참고자료

ATDD

  • Acceptance Test Driven Development : 테스트 주도 개발인데, 단위 테스트가 아닌 인수테스트
    • 인수테스트란? end to end 테스트, 요청 했을 때 어떤 응답 결과를 받는지 예상하고 실제 요청한 응답 결과가 예상과 맞는지 테스트를 함
    • 스프링에서 ATDD 하기 : 스프링에서는 외부 API(원격 메소드 콜 - 클라이언트)요청을 위한 API(프로그래밍을 통해서 제공하는 기능을 사용하게 하는 인터페이스)로 RestTemplate가 있는데, 해당 API를 wrapping하여 테스트용으로 만든 클래스(TestRestTemplate)를 활용(클라이언트)해서 테스트함
  • 여기서 알 수 있는 사실은 브라우저만이 웹어플리케이션의 클라이언트가 아님 : 컨트롤러 처리나 비즈니스 로직을 만들 때 고려하고 만들어야함(예외처리)

전체 코드

테스트 중복(or 위험) 제거

  • 인수 테스트를 할 때 주의해야할 점은 mockito를 사용할 때처럼 repository를 mock으로 만드는게 아니라 실제 서버 환경을 만들어두고 한다는 점임(실제 요청을 받아서 응답을 받는 과정임) 그렇기때문에 각 테스트가 같은 repository에 작업을 하는 것 : 테스트 대상 리소스를 생성한 후 해당 리소스를 가지고 테스트 코드를 작성하도록 해야함(중복)
    • createResource를 호출하면서 동시에 테스트도 할 수 있음 : 정상적으로 리소스를 생성하는지(Post 요청을 정상적으로 수행하는지)
public <T> String createResource(TestRestTemplate template, String path, T bodyPayload) {
    ResponseEntity<String> response = template.postForEntity();
    assertThat(response.getStatusCode(), is(HttpStatus.CREATED));
    return response.getHeaders().getLocation().getPath();
}
  • 리소스를 생성 -> 리소스 생성에 대한 응답으로 CREATED 코드와 생성된 리소스의 URI를 받음 -> 해당 URI를 가지고 테스트를 진행하면 해당 리소스에 대한 핸들링 테스트를 하는 것
  • 해당 메소드를 AcceptanceTest마다 구현하는게 아니라 AcceptanceTest 상위 클래스를 만들어서 구현해둔 뒤에 하위 클래스에서 사용하도록 코드를 구성하면 중복을 제거할 수 있음
    • 해당 메소드 뿐만 아니라 모두가 필요한 기능을 상위에 모아두고, 사용하도록 하면 됨

하면서 알게된 것과 생각해봐야할 것

  1. API 요청과 응답 정책(어떤 데이터와 메타데이터를 부과해서 응답할지)에 대해서 프론트, 백엔드 개발자가 협의해야한다는 점을 인식하게 됨 : 기본적으로 기계(클라이언트)가 처리를 할 수 있도록 충분히 메세지를 구성해야한다는 점은 알겠음(REST한 API를 만들기위해서)
  2. 트랜잭션 처리 시점 : 모든 것을 트랜잭션 처리 선언을 해두면 그만큼 비효율이 생길 것(이전 상태를 알고있어야 하거나 적용 전 임시버퍼에 적용할 것을 쌓아두거나 할텐데 이 부분에 대해서도 공부를 해봐야함)인데, @Transactional 선언을 언제하면 딱 알맞을지 생각해보기

지금까지 사용하면서 깨달은 JPA 장점 정리

  • JDBC API를 직접 다루는 것도 좋지만(표준이라서!) 커넥션과 커넥션 관리, 쿼리 작성 등을 추상화 시켰다는 점 : 비즈니스 로직에만 더 전념할 수 있는 환경을 만들어줌
  • 개발자 입장에서 편하다는 장점도 있지만 쿼리/테이블 주도 개발이 아니라 도메인 객체의 입장이 되어서 개발할 수 있음 : 자바 객체가 단순히 set, get만 하는 것이 아니라 원래 처리하는 역할을 하는 애야 라는 생각을 가지고 개발을 할 수 있음, 한마디로 모든 기능을 쿼리로 개발하려고하지않고 도메인에서 처리해서 repository에 영구 저장하는 용도로 사용하려고 함
  • 유지보수 관점에서 변경점이 흩어져있지않음 : 쿼리 작성에 대해서 조금 더 살펴보자면 개발자 입장에서는 엔티티.메소드 형태로 개발해두면 변환이 됨, 엔티티의 attr(column)을 변경(추가, 삭제, 이름 변경 등)하면 쿼리도 자동으로 변경됨 - 쿼리를 작성해두는 방식으로 개발한다면 일일이 다 수정해줘야함, 더더군다나 디버깅 어려움(한글자라도 잘못되면 에러 뿜음)
  • 객체 생성 : 조회 결과를 받아서 객체에 맞게 set해주는 작업을 일일이 하지않고, 자바빈 규약에 맞춰 엔티티 클래스를 만들어두면 set해서 인스턴스화되어 리턴받을 수 있음
  • 상속 관계 : JPA가 제공하는 어노테이션만 적용해두면 개발자 입장에서는 똑같이 상속관계를 구현해두면 내부적으로 알아서 처리해줌