
이 내용은 Backend(Controller/API Layer)에 해당한다. Frontend(브라우저/React/모바일 앱)는 HTTP로 API를 호출하고, Spring Boot는 Controller에서 요청을 받아 Service/Repository로 넘긴 뒤 DB(JPA)로 데이터를 읽고/저장한다. 응답은 보통 JSON으로 내려가고, 프론트는 그 JSON을 화면에 렌더링한다.
웹 서비스는 HTTP 프로토콜을 통해 인터넷 상에서 통신하는 애플리케이션이다. 그 중에서도 최근 가장 많이 쓰는 방식이 RESTful API이다.
REST(Representational State Transfer)는 “표준 프레임워크”가 아니라 로이 필딩이 제시한 제약 조건(원칙)의 집합에 가까운 아키텍처 스타일이다. 특정 언어/플랫폼에 종속되지 않고 다양한 클라이언트(브라우저, 모바일 앱, 다른 서버)와 통신하기 쉽게 만든다.
특히 REST에서 실무적으로 가장 체감되는 포인트는 URI 설계 + HTTP 메서드 + JSON 응답 규격이 일관되게 유지되는 것이다.
Spring Boot에서 HTTP 요청은 Controller가 처리한다. 따라서 domain 패키지와 동일 레벨에 controller 패키지를 만들고, 그 안에 CarController를 만들어 엔드포인트를 노출한다.
Controller는 “요청을 받는 창구”이고, DB 접근은 Repository(JPA)가 담당한다. 즉, Controller가 Repository를 호출해 데이터를 가져와 반환하면, Spring이 객체(List<Car>)를 JSON으로 변환해준다.
아래 코드는 Controller/API Layer에서 GET /cars 요청을 처리하는 예시다. 핵심은 @RestController 덕분에 Java 객체가 JSON으로 자동 변환된다는 점이다.
package com.korit12.cardatabase.controller;
import com.korit12.cardatabase.domain.Car;
import com.korit12.cardatabase.domain.CarRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequiredArgsConstructor
public class CarController {
private final CarRepository carRepository;
@GetMapping("/cars")
public List<Car> getCars() {
return carRepository.findAll();
}
}

여기서 데이터 흐름은 다음과 같다.
Spring Data REST는 Repository만으로 REST API를 자동으로 노출해주는 방식이다. 또한 기본적으로 HATEOAS 형태의 응답도 지원한다.
// build.gradle
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
Repository 기반 API의 base path를 /api로 고정한다.
// application.properties
spring.data.rest.basePath=/api
이제 브라우저/Postman에서 GET 요청을 보내면, 예: GET http://localhost:8080/api/cars 자동으로 JSON 응답이 나온다.
Spring Data REST는 아래 CRUD를 자동 제공한다.
전체 삭제가 아니라 특정 리소스 삭제면 “리소스 식별자(id)”가 필요하다.
예: DELETE http://localhost:8080/api/vehicles/1
POST 시점에는 id가 없다. DB에서 저장되면서 id가 생성된다. Content-Type은 application/json이어야 한다.
예: POST http://localhost:8080/api/vehicles
예: PATCH body
{
"color": "검정"
}
Spring Data REST는 연관관계 수정도 엔드포인트로 제공한다. 예를 들어 Car에 Owner를 연결하려면 보통 “연관 필드 URL”에 PUT을 날린다.
예: PUT http://localhost:8080/api/vehicles/4/owner
이때 Content-Type이 text/uri-list이고, body에는 연결할 Owner의 URI를 넣는다.
http://localhost:8080/api/owners/{ownerId}
이 방식은 내부적으로 “FK 연결”을 REST로 표현한 형태라고 보면 된다.
실제로 UI 사용자 입장에서 “내 차를 수정/삭제하려면 id가 필요”한데, 사용자는 DB의 id를 모르거나 노출하면 안 되는 경우가 많다. 그래서 보통은 다음 중 하나가 필요하다.
이 문제를 해결하기 위해 Repository에 검색 메서드를 추가하면, Spring Data REST가 /search 엔드포인트를 자동으로 만든다.
Repository에 Query Method를 추가하고, @RepositoryRestResource로 path를 정리한다. 또한 query parameter 이름을 명확히 하려면 @Param을 붙인다.
package com.korit12.cardatabase.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import java.util.List;
@RepositoryRestResource(path = "vehicles")
public interface CarRepository extends JpaRepository<Car, Long> {
List<Car> findByBrand(@Param("brand") String brand);
List<Car> findByColor(@Param("color") String color);
}
이제 아래처럼 호출 가능하다.