개발 공부/Java

[TIL]Spring Boot 숙련(3)-RestTemplate와 JPA 연관관계, Fetch 전략

eunkonge 2026. 6. 26. 15:55

오늘은 Spring Boot에서 외부 API를 호출하는 RestTemplate, JPA의 연관관계 매핑, 그리고 Fetch 전략과 Cascade에 대해 공부했다. 프로젝트를 구현하기 전에 JPA가 객체 간의 관계를 어떻게 관리하는지와 Spring에서 외부 API를 호출하는 방법을 중심으로 정리하였다.


1. RestTemplate란?

Spring Boot에서는 클라이언트의 요청을 처리하는 것뿐만 아니라 우리 서버가 다른 서버의 API를 호출해야 하는 경우도 많다.

예를 들어

  • 네이버 검색 API
  • 카카오 API
  • 공공데이터 API

등을 사용할 때는 우리 서버가 Client 역할을 수행한다.

Spring에서는 이러한 Server to Server 통신을 위해 RestTemplate을 제공한다.

RestTemplate의 특징

  • GET, POST, PUT, DELETE 요청 지원
  • JSON ↔ Java 객체 자동 변환
  • HTTP Header 설정 가능
  • ResponseEntity를 이용한 응답 처리

2. RestTemplate 요청 방식

GET 요청

GET 요청은 getForEntity()를 사용한다.

ResponseEntity<ItemDto> response =
        restTemplate.getForEntity(uri, ItemDto.class);

조회 목적의 API 호출에 주로 사용된다.


POST 요청

POST 요청은 postForEntity()를 사용한다.

ResponseEntity<ItemDto> response =
        restTemplate.postForEntity(uri, requestDto, ItemDto.class);

객체를 전달하면 Spring이 자동으로 JSON으로 변환하여 Body에 담아 전송한다.


exchange()

가장 많이 사용하는 방식이다.

RequestEntity<User> request =
        RequestEntity
                .post(uri)
                .header("Authorization", token)
                .body(user);

ResponseEntity<String> response =
        restTemplate.exchange(request, String.class);

Header와 Body를 모두 직접 설정할 수 있기 때문에 JWT와 같이 Authorization Header를 보내야 하는 경우 자주 사용된다.


3. JPA 연관관계

데이터베이스에서는 여러 테이블이 서로 관계를 가진다.

JPA에서는 이러한 관계를 객체 간의 관계로 표현하며 다음과 같은 애너테이션을 제공한다.

  • @OneToOne
  • @ManyToOne
  • @OneToMany
  • @ManyToMany

@OneToOne

하나의 Entity가 하나의 Entity와만 연결되는 관계이다.

예시

  • 회원 ↔ 프로필
  • 학생 ↔ 학생증
@OneToOne
@JoinColumn(name = "user_id")
private User user;

핵심

  • 외래 키의 주인을 직접 지정해야 한다.
  • @JoinColumn을 가진 Entity가 외래 키를 관리한다.

@ManyToOne

실무에서 가장 많이 사용하는 연관관계이다.

여러 개의 Entity가 하나의 Entity를 참조한다.

예시

  • 게시글 → 회원
  • 상품 → 회원
  • 댓글 → 게시글
@ManyToOne
@JoinColumn(name = "user_id")
private User user;

반대쪽에서는

@OneToMany(mappedBy = "user")
private List<Food> foodList;

와 같이 조회할 수 있다.


@OneToMany

한 개의 Entity가 여러 Entity를 가지는 관계이다.

예를 들어

  • 회원 → 게시글
  • 카테고리 → 상품

등이 있다.

@OneToMany(mappedBy = "user")
private List<Post> posts;

단방향 OneToMany는 외래 키가 반대 테이블에 존재하기 때문에 추가 UPDATE가 발생할 수 있어 실무에서는 많이 사용하지 않는다.


@ManyToMany

다대다 관계는 중간 테이블을 이용하여 관리한다.

@ManyToMany
@JoinTable(...)
private List<User> users;

하지만 실무에서는 @ManyToMany를 거의 사용하지 않는다.

그 이유는

  • 중간 테이블 관리가 어렵고
  • 컬럼 추가가 어렵고
  • 확장성이 떨어지기 때문이다.

대신 중간 Entity를 만들어

  • ManyToOne
  • OneToMany

두 관계로 풀어서 구현하는 방식을 많이 사용한다.


4. Fetch 전략

JPA에서는 연관 Entity를 언제 조회할 것인지도 설정할 수 있다.

EAGER

즉시 로딩

@ManyToOne(fetch = FetchType.EAGER)

Entity를 조회하는 순간 연관 Entity까지 함께 조회한다.

불필요한 SQL이 발생할 수 있다.


LAZY

지연 로딩

@ManyToOne(fetch = FetchType.LAZY)

실제로 연관 객체를 사용할 때 SQL을 실행한다.

필요한 시점에만 조회하므로 성능이 더 좋으며 실무에서는 대부분 LAZY를 사용한다.


5. Cascade(영속성 전이)

Cascade는 부모 Entity의 작업을 자식 Entity에게 전파하는 기능이다.

대표 옵션

  • PERSIST
  • REMOVE
  • MERGE
  • ALL

예를 들어

@OneToMany(
    cascade = CascadeType.PERSIST
)

를 사용하면 부모만 저장해도 자식 Entity도 함께 저장된다.

이를 통해 Repository를 여러 번 호출하지 않아도 된다.


6. orphanRemoval

부모 Entity와의 관계가 끊어진 자식 Entity를 자동으로 삭제하는 기능이다.

@OneToMany(
    orphanRemoval = true
)

Cascade REMOVE와 차이점

Cascade REMOVE

  • 부모를 삭제하면 자식도 삭제

orphanRemoval

  • 부모와의 관계만 끊어져도 자식 Entity 삭제

따라서 연관관계 관리가 중요한 프로젝트에서 자주 사용된다.


오늘은 Spring Boot에서 외부 API를 호출하기 위한 RestTemplate의 사용법과 JPA의 연관관계 매핑 방식을 공부했다. 특히 @ManyToOne과 @OneToMany의 차이, 외래 키의 주인 개념, mappedBy의 역할을 이해하면서 객체와 데이터베이스 간의 관계를 어떻게 표현하는지 알 수 있었다.

또한 Fetch 전략에서 EAGER와 LAZY의 차이를 비교하며, 실무에서는 불필요한 조회를 줄이기 위해 LAZY를 기본으로 사용하는 이유를 이해할 수 있었다. 마지막으로 Cascade와 orphanRemoval을 통해 부모 Entity의 변경이 자식 Entity에 어떻게 전파되는지 학습하면서 JPA가 단순한 ORM을 넘어 객체 간의 생명주기까지 관리한다는 점을 알게 되었다.