스프링 Data Jpa로 API 만들기

2024. 3. 16. 23:33Backend 취업준비/Spring

스프링이 HTTP응답을 처리하는 방식 3가지가 있었다

  • 정적 컨텐츠
  • MVC와 템플릿 엔진 (동적 컨텐츠, 타임 리프)
  • API

세가지 방식이 있는 것을 알겠는데, 개발자는 어떤 때에 어떤 방식을 선택해서 개발을 해나가야 할까?

 

기본서에서 글 작성, 글 목록 조회, 글 단건 조회, 글 삭제, 수정 등 여러 API를 만들었었다

 

하지만 정작 블로그를 구현할 때는 타임리프를 사용해서 뷰와 함께 구현하거나, 삭제 기능 같은 경우는 자바스크립트 만을 사용하여 기능 구현을 하였다

 

  • 타임리프(Thymeleaf):
    • 서버 측 렌더링(Server-side Rendering)이 필요한 경우: 사용자에게 동적인 HTML 콘텐츠를 제공해야 하는 경우, 타임리프를 사용하여 서버 측에서 HTML을 동적으로 생성.
    • 서버 측에서 모델(Model) 데이터를 HTML에 바인딩하는 경우: 서버 측에서 전달되는 데이터를 HTML 템플릿에 삽입하여 클라이언트에게 제공해야 할 때 유용.
  • REST API:
    • 클라이언트랑 서버의 완전분리 (웹, 모바일앱등 여러가지에서 하나의 API를 사용해야할떄),
    • 클라이언트랑 서버의 완전분리 => 클라이언트-서버 간에 데이터를 주고받아야 하는 경우: 클라이언트 애플리케이션과 서버 간에 데이터를 교환할 때 REST API를 사용. 이는 주로 AJAX 호출을 통해 이루어지며, JSON 또는 XML 형식으로 데이터를 전송.
    • 비동기적으로 데이터를 업데이트하거나 가져와야 하는 경우: 웹 애플리케이션에서 페이지 새로고침 없이 데이터를 업데이트하거나 가져와야 할 때 REST API를 활용
    • 동적인 UX제공시 (페이지 일부분만의 업데이트가 제공되어야할때)
  • 자바스크립트(Javascript):
    • 비동기데이터 처리 필요시 (동적 웹 구성)
    • 프론트엔드 상태관리(컴포넌트 기반 개발과 상태관리 로직 구현, UI업데이트시 유리)

 

API방식 ( 스프링 Data JPA를 사용 )

 

먼저 API란?

  • API : 유저랑 서버가 데이터를 주고 받기 위한 방법(결국 코드)

 

JPA를 사용하려면?

  • JPA를 사용하려면 Entity가 필요함
  • Entity 객체에는 기본생성자가 꼭 필요하다

  • 위 사진에서는 생성자에 빌더 어노테이션을 사용하였으므로 기본 생성자가 자동으로 생성되지 않아 오류가 남
    • @NoArgsConstructor를 사용하거나 직접 기본 생성자를 선언해 줘야 한다
  • 기본 생성자가 꼭 필요한 이유
    • 리플랙션 & 프록시..

 

@Builder => 클래스 위에 선언, 생성자 위에 선언

 

클래스 위에 선언

  • 클래스 레벨에 @Builder를 선언하면 해당 클래스의 모든 필드에 대한 빌더 메서드가 생성된다.
  • 이는 모든 필드에 대해 빌더를 사용하고자 할 때 유용하다.
  • 그러나 객체 생성 시 받지 않아야 할 매개변수들도 빌더에 노출될 수 있다

생성자 위에 선언

  • 생성자 레벨에 @Builder를 선언하면 해당 생성자만을 위한 빌더 메서드가 생성.
  • 해당 생성자로 초기화 되는 필드들에 대해서만 빌더 메서드가 생성.
  • 이는 특정 생성자에만 빌더 패턴을 적용하고 싶을 때 유용.

빌더 패턴 정리
https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EB%B9%8C%EB%8D%94Builder-%ED%8C%A8%ED%84%B4-%EB%81%9D%ED%8C%90%EC%99%95-%EC%A0%95%EB%A6%AC

 

 

스프링 Data JPA를 사용하려면 JpaRepository 인터페이스를 상속

  • JpaRepository 인터페이스를 상속하면 Spring Data JPA는 자동으로 Repository 구현체를 생성하고 빈으로 등록해 준다. => 역시 프록시 개념이 나온다.. 언젠가는 꼭 공부해야 할 것 같다
  • EntityManager를 관리해 줄 필요 없다
  • @Repository어노테이션을 사용할 필요 없다
  • 이를 통해 개발자는 구현체를 직접 작성할 필요가 없고, 인터페이스만을 작성하여 데이터베이스에 대한 기본 CRUD(Create, Read, Update, Delete) 기능을 제공받을 수 있다.
  • @NoRepositoryBean 어노테이션은 Spring Data JPA가 해당 인터페이스를 기반으로 자동으로 Repository 구현체를 생성하지 않도록 막는 역할을 한다.
  • 이 어노테이션이 붙은 인터페이스는 스프링 데이터의 기본적인 기능을 상속받는 용도로만 사용되며, 직접적으로 스프링 데이터의 구현체가 될 수 없다.

 

@ResponseBody

  • 컨트롤러 메서드가 HTTP 응답의 본문(body)으로 직접 데이터를 반환할 때 사용
  • HTTP 규격에 맞는 응답을 만들어주기 위한 Annotation
  • ViewResolver 대신에 HttpMessageConverter 가 동작. HTTPMessageConverter 는 해당 Annotation 이 붙은 대상을 response body 에 직렬화를 하는 방식으로 작동

 

ResponseEntity

  • HTTP 응답을 만들어주기 위한 객체. 
  • @ResponseBody 와 달리 Annotation 이 아닌 객체로 사용. 즉, 응답으로 변환될 정보를 모두 담은 요소들을 객체로 만들어서 반환해 준다.
  • HTTP 상태 코드 설정: ResponseEntity.status(HttpStatus status) 메서드를 사용하여 HTTP 응답의 상태 코드를 설정할 수 있다. 예를 들어, ResponseEntity.ok()는 HTTP 상태 코드 200(OK)를 설정
  • 헤더 설정: ResponseEntity.headers(HttpHeaders headers) 메서드를 사용하여 HTTP 응답의 헤더를 설정할 수 있다. 이를 통해 응답에 추가적인 정보를 포함할 수 있다.
  • 본문 설정: ResponseEntity.body(T body) 메서드를 사용하여 HTTP 응답의 본문을 설정할 수 있다. 이를 통해 클라이언트에게 데이터를 반환. 본문은 제네릭 타입 T로 지정되며, 반환될 데이터의 타입에 따라 적절한 타입을 지정

 

 

스프링 데이터 JPA에서 쿼리 날리기

 

메소드 규칙

@Query

  • @Query 어노테이션은 Spring Data JPA에서 메소드 상단에 사용된다.
  • JPQL을 사용하여 자동 생성되는 쿼리 메소드 외의 데이터 베이스 쿼리를 직접 정의할 때 사용된다.
public interface PostRepository extends JpaRepository<Post, Long> {

    @Query("select p from Post p join fetch p.comments")
    List<Post> findAllInnerFetchJoin();

    @Query("select distinct p from Post p join fetch p.comments")
    List<Post> findAllInnerFetchJoinWithDistinct();

    //...
}

 

  • 간단한 로직을 작성하는데 큰 문제는 없으나, 복잡한 로직의 경우 개행이 포함된 쿼리 문자열이 상당히 길어진다.
  • JPQL 문자열에 오타 혹은 문법적인 오류가 존재하는 경우, 정적 쿼리라면 어플리케이션 로딩 시점에 이를 발견할 수 있으나 그 외는 런타임 시점에서 에러가 발생한다.

 

이러한 문제를 어느 정도 해소하는데 기여하는 프레임워크가 바로 QueryDSL

 

QueryDSL은 정적 타입을 이용해서 SQL 등의 쿼리를 생성해주는 프레임워크

 

QueryDSL의 장점

  1. 문자가 아닌 코드로 쿼리를 작성함으로써, 컴파일 시점에 문법 오류를 쉽게 확인할 수 있다.
  2. 자동 완성 등 IDE의 도움을 받을 수 있다.
  3. 동적인 쿼리 작성이 편리하다.
  4. 쿼리 작성 시 제약 조건 등을 메서드 추출을 통해 재사용할 수 있다.

자세한 예시

https://tecoble.techcourse.co.kr/post/2021-08-08-basic-querydsl/