
Spring으로 API 서버를 개발할 때 가장 중요한 건 딱 하나이다.
이 서버는 "화면(View)"을 반환하는 서버인가?
아니면 "데이터(JSON)"를 반환하는 서버인가?
요즘 대부분의 시스템은 프론트엔드(React, Vue 등)와 분리된 구조이기 때문에
Spring 서버는 거의 항상 JSON 데이터를 반환하는 API 서버 역할을 한다.
이 글에서는 API 서버 개발에 필요한 핵심 개념만 빠르게 정리한다.
※ @Controller vs @RestController
API 서버라면 → 거의 무조건 @RestController 사용
▶ @Controller
@Controller
@GetMapping("/home")
public String home() {
return "home";
}
"home"이라는 데이터를 반환하는 게 아니라
home.html / home.jsp 같은 View를 찾아서 반환
▶ @Controller + @ResponseBody
@Controller에서도 API 응답이 가능하다.
기존 MVC 프로젝트에서 일부 API만 추가할 때, 특정 메서드만 JSON 응답이 필요할 때 사용
@Controller
public class UserController {
@ResponseBody
@GetMapping("/api/user")
public User getUser() {
return new User(1L, "이승엽");
}
}
{
"id": 1,
"name": "이승엽"
}
@ResponseBody를 붙이면 해당 메서드의 return 값이 View가 아니라 Response Body(JSON)로 반환된다.
▶ @RestController
(1) 문자열 응답
@RestController
@GetMapping("/api/hello")
public String hello() {
return "hello";
}
hello
(2) JSON 응답 (권장 형태)
@RestController
@GetMapping("/api/user")
public User user() {
return new User(1L, "이승엽");
}
{
"id": 1,
"name": "이승엽"
}
RestController는 return 값을 그대로 Response Body로 보낸다. 객체를 반환하면 자동으로 JSON으로 변환된다.
※ 핵심 정리
@Controller → View 반환
@RestController → JSON(Response Body) 반환
@Controller + @ResponseBody = @RestController와 동일
※ 요청 파라미터 3가지
중복되는 설명을 줄이기 위해 아래와 같은 기본 구조를 기준으로 설명한다.
@RestController
@RequestMapping("/api/users")
public class UserController {
}
즉, 모든 API의 기본 경로는
/api/users
▶ @PathVariable (경로 변수) : 리소스를 식별할 때 사용
GET /api/users/10
@GetMapping("/{userId}")
public User getUser(@PathVariable Long userId)
URL의 10 → userId로 전달됨
→ 10번 유저 조회
▶ @RequestParam (쿼리 파라미터) : 검색, 조건, 옵션에 사용
GET /api/users?keyword=lee&page=1
@GetMapping
public List<User> getUsers(
@RequestParam String keyword,
@RequestParam int page
)
keyword, page 값은 URL 뒤에서 전달됨
→ 검색 및 페이징 조건
▶ @RequestBody (요청 Body) : JSON 데이터를 전달할 때 사용
POST /api/users
Content-Type: application/json
{
"name": "이승엽",
"email": "lee@example.com"
}
@PostMapping
public void createUser(@RequestBody UserRequest request)
요청 Body(JSON)가 UserRequest 객체로 변환됨
→ 생성/수정 데이터
※ 핵심 정리
@PathVariable → URL 경로에 포함된 값 (식별자)
@RequestParam → URL 뒤에 붙는 값 (조건)
@RequestBody → 요청 Body에 담긴 JSON 데이터
※ HTTP Method
▶ 기본 개념
GET → 조회
POST → 생성
PUT → 전체 수정
PATCH → 일부 수정
DELETE → 삭제
▶ Mapping 어노테이션과의 관계
Spring에서는 HTTP Method에 따라 다음과 같은 어노테이션을 사용한다.
GET → @GetMapping
POST → @PostMapping
PUT → @PutMapping
PATCH → @PatchMapping
DELETE → @DeleteMapping
▶ @RequestMapping : 모든 매핑의 기본이 되는 어노테이션
위에서 사용한 Mapping 어노테이션들은 사실 아래의 축약형이다.
@GetMapping("/users")
@RequestMapping(value = "/users", method = RequestMethod.GET)
@PostMapping("/users")
@RequestMapping(value = "/users", method = RequestMethod.POST)
@PutMapping("/users")
@RequestMapping(value = "/users", method = RequestMethod.PUT)
@PatchMapping("/users")
@RequestMapping(value = "/users", method = RequestMethod.PATCH)
@DeleteMapping("/users")
@RequestMapping(value = "/users", method = RequestMethod.DELETE)
@RequestMapping을 컨트롤러 클래스 위에 선언하면 해당 컨트롤러의 모든 API에 공통 URL 경로(prefix)가 적용된다.
@RestController
@RequestMapping("/api/users")
public class UserController {
}
이 경우
@GetMapping("/{id}")
실제 요청 URL
/api/users/{id}
정리
클래스 위 @RequestMapping → 공통 경로
메서드 위 Mapping → 개별 API 경로
▶ 실무에서의 사용 패턴
GET
- 데이터 조회
- 주로 @PathVariable, @RequestParam 사용
- @RequestBody는 거의 사용하지 않음
POST
- 데이터 생성
- @RequestBody를 가장 많이 사용
PUT
- 데이터 전체 수정
- @PathVariable + @RequestBody 조합
PATCH
- 데이터 일부 수정
- @PathVariable + @RequestBody 조합
DELETE
- 데이터 삭제
- 주로 @PathVariable 사용
※ 핵심 정리
@RequestMapping → 모든 매핑의 기본
@GetMapping, @PostMapping 등 → HTTP Method별 축약형 (실무에서 주로 사용)
클래스 위 @RequestMapping → 공통 URL prefix 설정
※ 응답 방식
API 서버 = 거의 100% JSON(Response Body)
▶ 기본 응답 (자동 JSON 변환)
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return new User(1L, "이승엽");
}
Java 객체(User)를 반환하면
Spring이 자동으로
→ JSON 형태로 변환해서 응답
{
"id": 1,
"name": "이승엽"
}
Spring 내부에서 Jackson 라이브러리를 사용해
객체 → JSON 변환을 자동 처리
▶ 실무 방식 (ResponseEntity)
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
return ResponseEntity.ok(new User(1L, "이승엽"));
}
ResponseEntity란?
HTTP 응답 전체를 제어하는 객체
- Body (데이터)
- Status (200, 404 등)
- Header
※ 사용 예시
return ResponseEntity.ok(user); // 200 OK
return ResponseEntity.status(201).body(user); // 201 Created
return ResponseEntity.noContent().build(); // 204 No Content
장점 : 응답 상태 코드를 명확하게 제어 가능 → 실무에서 표준적으로 사용
※ axios + Controller 예시
기본 컨트롤러 구조는 다음을 기준으로 한다.
@RestController
@RequestMapping("/api/users")
public class UserController {
}
(1) @PathVariable만 사용
GET /api/users/10
axios.get('/api/users/10');
@GetMapping("/{userId}")
public User getUser(@PathVariable Long userId) {
return userService.getUser(userId);
}
10번 유저 조회 (식별자 역할)
(2) @RequestParam만 사용
GET /api/users?keyword=lee&page=1
axios.get('/api/users', {
params: {
keyword: 'lee',
page: 1
}
});
@GetMapping
public List<User> getUsers(
@RequestParam String keyword,
@RequestParam int page
) {
return userService.getUsers(keyword, page);
}
검색 및 페이징 조건
(3) @RequestBody만 사용
POST /api/users
Content-Type: application/json
{
"name": "이승엽",
"email": "lee@example.com"
}
axios.post('/api/users', {
name: '이승엽',
email: 'lee@example.com'
});
@PostMapping
public void createUser(@RequestBody UserRequest request) {
userService.createUser(request);
}
생성/수정할 실제 데이터
(4) @PathVariable + @RequestParam
GET /api/users/10/orders?status=PAID&page=1
axios.get('/api/users/10/orders', {
params: {
status: 'PAID',
page: 1
}
});
@GetMapping("/{userId}/orders")
public List<Order> getOrders(
@PathVariable Long userId,
@RequestParam String status,
@RequestParam int page
) {
return orderService.getOrders(userId, status, page);
}
10번 유저의 주문 중에서
status 조건으로 필터링 후 조회
(5) @PathVariable + @RequestBody
PUT /api/users/10
Content-Type: application/json
{
"name": "이승엽",
"email": "lee@example.com"
}
axios.put('/api/users/10', {
name: '이승엽',
email: 'lee@example.com'
});
@PutMapping("/{userId}")
public void updateUser(
@PathVariable Long userId,
@RequestBody UserRequest request
) {
userService.updateUser(userId, request);
}
10번 유저를 대상으로
Body 데이터로 수정
(6) @RequestParam + @RequestBody
실제로는 많지는 않지만 특정 케이스에서 사용
POST /api/users?notify=true
Content-Type: application/json
{
"name": "이승엽",
"email": "lee@example.com"
}
axios.post('/api/users?notify=true', {
name: '이승엽',
email: 'lee@example.com'
});
@PostMapping
public void createUser(
@RequestParam boolean notify,
@RequestBody UserRequest request
) {
userService.createUser(request, notify);
}
유저 생성 + 옵션 처리 (알림 여부 등)
(7) @PathVariable + @RequestParam + @RequestBody
POST /api/users/10/orders?urgent=true
Content-Type: application/json
{
"productId": 1,
"quantity": 2
}
axios.post('/api/users/10/orders', {
productId: 1,
quantity: 2
}, {
params: {
urgent: true
}
});
@PostMapping("/{userId}/orders")
public void createOrder(
@PathVariable Long userId,
@RequestParam boolean urgent,
@RequestBody OrderRequest request
) {
orderService.createOrder(userId, urgent, request);
}
userId → 누구의 주문인지 (대상)
urgent → 옵션 조건
request → 실제 주문 데이터
※ 핵심 정리
@PathVariable → 대상
@RequestParam → 조건
@RequestBody → 데이터
API 설계는 "대상 + 조건 + 데이터" 구조로 이해하면 쉽다.
※ 핵심 요약
1. API 서버 → @RestController 사용
2. 요청 데이터 (조합 가능)
- @PathVariable → 식별자
- @RequestParam → 조건
- @RequestBody → JSON 데이터
3. HTTP Method
GET → 조회 (주로 @PathVariable, @RequestParam 사용)
POST → 생성 (주로 @RequestBody 사용)
PUT → 전체 수정 (주로 @PathVariable + @RequestBody 사용)
PATCH → 일부 수정 (주로 @PathVariable + @RequestBody 사용)
DELETE → 삭제 (주로 @PathVariable 사용)
※ 위 조합만 가능한 것이 아니라, 상황에 따라 다르게 조합될 수 있음
4. 응답
→ 객체 반환 시 자동 JSON 변환
→ 실무는 ResponseEntity 사용
5. 핵심 문장
"RestController면 return은 거의 무조건 Body"'Java > 참고자료' 카테고리의 다른 글
| [Java] 다국어 이름 마스킹 소스 코드 (0) | 2025.12.15 |
|---|---|
| [Java] JDK 다운로드 (8, 11, 17, 21) (0) | 2025.12.05 |
| [Java] 로그 사용법 정리 (DEBUG / INFO / WARN / ERROR) (0) | 2025.11.27 |
| [Java] JPA vs Spring Data JPA (2) | 2025.08.09 |
| [Java] javax.annotation.Resource 오류 (1) | 2025.01.17 |