505 lines
14 KiB
Markdown
505 lines
14 KiB
Markdown
# **Spring Boot MVC: 컨트롤러와 요청 처리**
|
|
|
|
Spring Boot의 핵심 기능 중 하나는 **MVC(Model-View-Controller) 패턴을 사용한 웹 요청 처리**입니다.
|
|
이 글에서는 **Spring Boot에서 컨트롤러가 어떻게 요청을 처리하는지**, 그리고 실무에서 **자주 사용하는 컨트롤러 관련 기능**을 예제와 함께 설명합니다.
|
|
|
|
---
|
|
|
|
## **1. 컨트롤러란?**
|
|
컨트롤러(Controller)는 **클라이언트의 요청을 받아서 비즈니스 로직을 수행하고, 응답을 반환하는 역할**을 합니다.
|
|
Spring Boot에서는 `@RestController` 또는 `@Controller` 어노테이션을 사용하여 컨트롤러를 정의합니다.
|
|
|
|
---
|
|
|
|
## **2. 기본 컨트롤러 작성하기**
|
|
|
|
Spring Boot에서는 `@RestController`를 사용하면 JSON 형태로 응답을 반환할 수 있습니다.
|
|
|
|
### **📌 기본 컨트롤러 예제**
|
|
```java
|
|
@RestController
|
|
@RequestMapping("/api")
|
|
public class HelloController {
|
|
|
|
@GetMapping("/hello")
|
|
public String sayHello() {
|
|
return "Hello, Spring Boot!";
|
|
}
|
|
}
|
|
```
|
|
#### **📌 실행 결과 (`http://localhost:8080/api/hello` 요청)**
|
|
```json
|
|
Hello, Spring Boot!
|
|
```
|
|
**설명:**
|
|
- `@RestController` → REST API를 위한 컨트롤러를 정의.
|
|
- `@RequestMapping("/api")` → 모든 경로가 `/api`로 시작하도록 설정.
|
|
- `@GetMapping("/hello")` → `/api/hello`로 GET 요청이 들어오면 `"Hello, Spring Boot!"` 반환.
|
|
|
|
---
|
|
|
|
## **3. 요청 매개변수 처리**
|
|
|
|
클라이언트가 **쿼리 파라미터** 또는 **URL 경로 변수**를 전달하면, 이를 컨트롤러에서 처리할 수 있습니다.
|
|
|
|
### **📌 `@RequestParam` 사용 (쿼리 파라미터)**
|
|
```java
|
|
@RestController
|
|
@RequestMapping("/api")
|
|
public class GreetingController {
|
|
|
|
@GetMapping("/greet")
|
|
public String greet(@RequestParam String name) {
|
|
return "Hello, " + name + "!";
|
|
}
|
|
}
|
|
```
|
|
#### **📌 실행 결과 (`http://localhost:8080/api/greet?name=John` 요청)**
|
|
```json
|
|
Hello, John!
|
|
```
|
|
**설명:**
|
|
- `@RequestParam`을 사용하면 **쿼리 파라미터에서 값을 가져올 수 있음**.
|
|
- 예제에서는 `name` 값을 받아 `"Hello, John!"`을 반환.
|
|
|
|
---
|
|
|
|
### **📌 `@PathVariable` 사용 (URL 경로 변수)**
|
|
```java
|
|
@RestController
|
|
@RequestMapping("/api")
|
|
public class UserController {
|
|
|
|
@GetMapping("/user/{id}")
|
|
public String getUser(@PathVariable int id) {
|
|
return "User ID: " + id;
|
|
}
|
|
}
|
|
```
|
|
#### **📌 실행 결과 (`http://localhost:8080/api/user/5` 요청)**
|
|
```json
|
|
User ID: 5
|
|
```
|
|
**설명:**
|
|
- `@PathVariable`을 사용하면 **URL 경로에서 변수를 추출**할 수 있음.
|
|
- 예제에서는 `/user/5` 요청 시, `id=5`로 인식하여 `"User ID: 5"` 반환.
|
|
|
|
---
|
|
|
|
## **4. 요청 본문 처리 (POST 요청)**
|
|
|
|
클라이언트가 **JSON 데이터를 요청 본문(body)에 담아 전송**하면, 이를 컨트롤러에서 처리할 수 있습니다.
|
|
|
|
### **📌 `@RequestBody` 사용**
|
|
```java
|
|
@RestController
|
|
@RequestMapping("/api")
|
|
public class ProductController {
|
|
|
|
@PostMapping("/product")
|
|
public String createProduct(@RequestBody Product product) {
|
|
return "Product created: " + product.getName();
|
|
}
|
|
}
|
|
|
|
class Product {
|
|
private String name;
|
|
private double price;
|
|
|
|
// 기본 생성자 필요 (JSON 역직렬화)
|
|
public Product() {}
|
|
|
|
public String getName() { return name; }
|
|
public double getPrice() { return price; }
|
|
}
|
|
```
|
|
#### **📌 실행 결과 (`POST /api/product` 요청)**
|
|
##### **요청 본문(JSON)**
|
|
```json
|
|
{
|
|
"name": "Laptop",
|
|
"price": 1200.00
|
|
}
|
|
```
|
|
##### **응답**
|
|
```json
|
|
Product created: Laptop
|
|
```
|
|
**설명:**
|
|
- `@RequestBody`를 사용하면 **JSON 데이터를 Java 객체로 변환하여 받을 수 있음**.
|
|
- 클라이언트가 `{ "name": "Laptop", "price": 1200.00 }`을 전송하면, 이를 `Product` 객체로 매핑.
|
|
- `"Product created: Laptop"`을 반환.
|
|
|
|
---
|
|
|
|
## **5. 응답 데이터 처리**
|
|
|
|
Spring Boot에서는 다양한 방식으로 응답을 반환할 수 있습니다.
|
|
|
|
### **📌 `ResponseEntity`를 사용한 응답 처리**
|
|
```java
|
|
@RestController
|
|
@RequestMapping("/api")
|
|
public class ResponseController {
|
|
|
|
@GetMapping("/status")
|
|
public ResponseEntity<String> getStatus() {
|
|
return ResponseEntity.status(HttpStatus.OK)
|
|
.body("Everything is fine!");
|
|
}
|
|
}
|
|
```
|
|
#### **📌 실행 결과 (`GET /api/status` 요청)**
|
|
```json
|
|
Everything is fine!
|
|
```
|
|
**설명:**
|
|
- `ResponseEntity`를 사용하면 **HTTP 상태 코드와 응답 데이터를 함께 설정 가능**.
|
|
- `HttpStatus.OK` → 200 응답 코드 설정.
|
|
|
|
---
|
|
|
|
## **6. 요청 및 응답 헤더 처리**
|
|
|
|
### **📌 `@RequestHeader` 사용 (요청 헤더 읽기)**
|
|
```java
|
|
@RestController
|
|
@RequestMapping("/api")
|
|
public class HeaderController {
|
|
|
|
@GetMapping("/header")
|
|
public String getHeader(@RequestHeader("User-Agent") String userAgent) {
|
|
return "Your User-Agent: " + userAgent;
|
|
}
|
|
}
|
|
```
|
|
#### **📌 실행 결과 (`GET /api/header` 요청)**
|
|
```json
|
|
Your User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
|
|
```
|
|
**설명:**
|
|
- `@RequestHeader("User-Agent")`를 사용하여 요청 헤더에서 **User-Agent 값 추출**.
|
|
|
|
---
|
|
|
|
## **7. 예외 처리 (`@ExceptionHandler`)**
|
|
|
|
### **📌 컨트롤러에서 예외 처리하기**
|
|
```java
|
|
@RestController
|
|
@RequestMapping("/api")
|
|
public class ExceptionController {
|
|
|
|
@GetMapping("/error")
|
|
public String throwError() {
|
|
throw new RuntimeException("Something went wrong!");
|
|
}
|
|
|
|
@ExceptionHandler(RuntimeException.class)
|
|
public ResponseEntity<String> handleRuntimeException(RuntimeException e) {
|
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
.body("Error: " + e.getMessage());
|
|
}
|
|
}
|
|
```
|
|
#### **📌 실행 결과 (`GET /api/error` 요청)**
|
|
```json
|
|
Error: Something went wrong!
|
|
```
|
|
**설명:**
|
|
- `@ExceptionHandler(RuntimeException.class)`을 사용하여 **컨트롤러 내에서 예외 처리**.
|
|
|
|
---
|
|
|
|
## **8. 정리**
|
|
| 기능 | 어노테이션 | 설명 |
|
|
|------|----------|------|
|
|
| **기본 컨트롤러** | `@RestController` | REST API 컨트롤러 정의 |
|
|
| **GET 요청 처리** | `@GetMapping` | HTTP GET 요청 매핑 |
|
|
| **POST 요청 처리** | `@PostMapping` | HTTP POST 요청 매핑 |
|
|
| **쿼리 파라미터** | `@RequestParam` | URL 쿼리 매개변수 받기 |
|
|
| **URL 경로 변수** | `@PathVariable` | URL 경로에서 값 추출 |
|
|
| **JSON 요청 본문** | `@RequestBody` | 요청 본문을 객체로 매핑 |
|
|
| **요청 헤더 처리** | `@RequestHeader` | 요청 헤더 값을 읽기 |
|
|
| **응답 처리** | `ResponseEntity` | 상태 코드와 함께 응답 반환 |
|
|
| **예외 처리** | `@ExceptionHandler` | 예외 발생 시 응답 처리 |
|
|
|
|
Spring Boot의 컨트롤러는 **간결하면서도 강력한 기능**을 제공합니다.
|
|
실무에서는 **REST API 개발 시 `@RestController`, 요청 처리 시 `@RequestParam`, `@RequestBody`, 예외 처리 시 `@ExceptionHandler`** 등을 적극 활용하면 좋습니다!
|
|
|
|
------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# **Spring Boot MVC에서 컨트롤러와 요청 처리**
|
|
|
|
Spring Boot MVC에서 컨트롤러는 **클라이언트 요청을 받아 적절한 응답을 반환하는 역할**을 합니다. 컨트롤러를 정의하려면 `@Controller` 또는 `@RestController`를 사용하며, 요청을 처리하는 메서드는 `@RequestMapping`, `@GetMapping`, `@PostMapping` 등의 어노테이션을 사용하여 HTTP 요청을 매핑할 수 있습니다.
|
|
|
|
---
|
|
|
|
## **1. 컨트롤러 기본 개념**
|
|
|
|
컨트롤러는 **MVC(Model-View-Controller) 패턴에서 "C(Controller)" 역할**을 하며, 클라이언트의 요청을 받아서 처리한 후 적절한 뷰(HTML) 또는 데이터를 응답으로 반환합니다.
|
|
|
|
### **📌 컨트롤러를 정의하는 어노테이션**
|
|
| 어노테이션 | 설명 |
|
|
|------------|----------------------------------|
|
|
| `@Controller` | 뷰(HTML)를 반환하는 컨트롤러 |
|
|
| `@RestController` | JSON, XML 데이터를 반환하는 컨트롤러 |
|
|
| `@RequestMapping` | HTTP 요청을 특정 메서드에 매핑 |
|
|
| `@GetMapping` | GET 요청을 처리 |
|
|
| `@PostMapping` | POST 요청을 처리 |
|
|
| `@PutMapping` | PUT 요청을 처리 |
|
|
| `@DeleteMapping` | DELETE 요청을 처리 |
|
|
|
|
---
|
|
|
|
## **2. 기본 컨트롤러 예제**
|
|
|
|
```java
|
|
import org.springframework.stereotype.Controller;
|
|
import org.springframework.ui.Model;
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
|
|
@Controller
|
|
public class HomeController {
|
|
|
|
@GetMapping("/")
|
|
public String home(Model model) {
|
|
model.addAttribute("message", "Hello, Spring Boot!");
|
|
return "home"; // home.html 템플릿을 반환
|
|
}
|
|
}
|
|
```
|
|
|
|
### **🛠️ 코드 설명**
|
|
- `@Controller` → **이 클래스를 컨트롤러로 선언**
|
|
- `@GetMapping("/")` → **루트 경로(`/`)로 GET 요청이 들어오면 `home()` 메서드 실행**
|
|
- `Model` 객체를 이용해 `"message"` 데이터를 뷰로 전달
|
|
- `return "home"` → **`home.html` 템플릿을 사용하여 응답 반환**
|
|
|
|
---
|
|
|
|
## **3. `@RestController`를 사용한 JSON 응답 컨트롤러**
|
|
|
|
```java
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
import org.springframework.web.bind.annotation.RequestParam;
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
|
|
@RestController
|
|
public class ApiController {
|
|
|
|
@GetMapping("/api/hello")
|
|
public String hello(@RequestParam(defaultValue = "Guest") String name) {
|
|
return "Hello, " + name + "!";
|
|
}
|
|
}
|
|
```
|
|
|
|
### **🛠️ 코드 설명**
|
|
- `@RestController` → **뷰가 아니라 JSON 데이터 응답을 위한 컨트롤러**
|
|
- `@GetMapping("/api/hello")` → **`/api/hello`로 GET 요청이 들어오면 `hello()` 실행**
|
|
- `@RequestParam("name")` → **쿼리 파라미터(name)를 받아서 사용**
|
|
- `return "Hello, " + name + "!";` → **단순한 문자열을 응답으로 반환**
|
|
|
|
### **✅ 실행 예시**
|
|
요청:
|
|
```
|
|
GET http://localhost:8080/api/hello?name=John
|
|
```
|
|
응답:
|
|
```json
|
|
Hello, John!
|
|
```
|
|
|
|
---
|
|
|
|
## **4. `@RequestParam`과 `@PathVariable`의 차이**
|
|
|
|
### **1) `@RequestParam`: 쿼리 파라미터 받기**
|
|
```java
|
|
@GetMapping("/search")
|
|
public String search(@RequestParam String keyword) {
|
|
return "검색어: " + keyword;
|
|
}
|
|
```
|
|
- 요청 예시:
|
|
```
|
|
GET /search?keyword=spring
|
|
```
|
|
- 응답: `"검색어: spring"`
|
|
|
|
---
|
|
|
|
### **2) `@PathVariable`: URL 경로 변수 받기**
|
|
```java
|
|
@GetMapping("/user/{id}")
|
|
public String getUser(@PathVariable int id) {
|
|
return "User ID: " + id;
|
|
}
|
|
```
|
|
- 요청 예시:
|
|
```
|
|
GET /user/123
|
|
```
|
|
- 응답: `"User ID: 123"`
|
|
|
|
---
|
|
|
|
## **5. `@PostMapping`을 이용한 데이터 전송 처리**
|
|
|
|
### **📌 POST 요청을 이용한 폼 데이터 처리**
|
|
```java
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
@RestController
|
|
public class UserController {
|
|
|
|
@PostMapping("/user")
|
|
public String createUser(@RequestParam String name, @RequestParam int age) {
|
|
return "User Created: " + name + ", Age: " + age;
|
|
}
|
|
}
|
|
```
|
|
- 요청 예시 (POST 요청):
|
|
```
|
|
POST /user
|
|
Content-Type: application/x-www-form-urlencoded
|
|
|
|
name=John&age=25
|
|
```
|
|
- 응답:
|
|
```
|
|
User Created: John, Age: 25
|
|
```
|
|
|
|
---
|
|
|
|
## **6. `@RequestBody`를 이용한 JSON 데이터 처리**
|
|
`@RequestBody`를 사용하면 **JSON 데이터를 Java 객체로 변환**할 수 있습니다.
|
|
|
|
```java
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
@RestController
|
|
public class UserController {
|
|
|
|
static class User {
|
|
public String name;
|
|
public int age;
|
|
}
|
|
|
|
@PostMapping("/user")
|
|
public String createUser(@RequestBody User user) {
|
|
return "User Created: " + user.name + ", Age: " + user.age;
|
|
}
|
|
}
|
|
```
|
|
|
|
### **✅ 실행 예시**
|
|
요청 (POST 요청, JSON 데이터 전달):
|
|
```json
|
|
POST /user
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"name": "Alice",
|
|
"age": 30
|
|
}
|
|
```
|
|
|
|
응답:
|
|
```json
|
|
User Created: Alice, Age: 30
|
|
```
|
|
|
|
---
|
|
|
|
## **7. `@ResponseEntity`를 활용한 응답 제어**
|
|
`ResponseEntity`를 사용하면 **HTTP 상태 코드와 응답을 함께 제어**할 수 있습니다.
|
|
|
|
```java
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
@RestController
|
|
public class ResponseController {
|
|
|
|
@GetMapping("/status")
|
|
public ResponseEntity<String> getStatus() {
|
|
return ResponseEntity.ok("서버 정상 작동 중");
|
|
}
|
|
|
|
@GetMapping("/error")
|
|
public ResponseEntity<String> getError() {
|
|
return ResponseEntity.status(400).body("잘못된 요청입니다.");
|
|
}
|
|
}
|
|
```
|
|
|
|
### **✅ 실행 예시**
|
|
- 정상 요청:
|
|
```
|
|
GET /status
|
|
```
|
|
응답: `200 OK`, `"서버 정상 작동 중"`
|
|
|
|
- 오류 요청:
|
|
```
|
|
GET /error
|
|
```
|
|
응답: `400 Bad Request`, `"잘못된 요청입니다."`
|
|
|
|
---
|
|
|
|
## **8. `@ExceptionHandler`를 활용한 예외 처리**
|
|
```java
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
@RestController
|
|
public class ExceptionController {
|
|
|
|
@GetMapping("/divide")
|
|
public int divide(@RequestParam int a, @RequestParam int b) {
|
|
return a / b; // b가 0이면 오류 발생
|
|
}
|
|
|
|
@ExceptionHandler(ArithmeticException.class)
|
|
public ResponseEntity<String> handleArithmeticException() {
|
|
return ResponseEntity.status(400).body("0으로 나눌 수 없습니다.");
|
|
}
|
|
}
|
|
```
|
|
|
|
### **✅ 실행 예시**
|
|
- 정상 요청:
|
|
```
|
|
GET /divide?a=10&b=2
|
|
```
|
|
응답: `5`
|
|
|
|
- 오류 요청 (`b=0`):
|
|
```
|
|
GET /divide?a=10&b=0
|
|
```
|
|
응답: `400 Bad Request`, `"0으로 나눌 수 없습니다."`
|
|
|
|
---
|
|
|
|
## **🔍 정리**
|
|
Spring Boot MVC에서 컨트롤러를 사용하면 **HTTP 요청을 처리하고, 클라이언트에게 적절한 응답을 반환**할 수 있습니다.
|
|
- `@Controller`: HTML 뷰 반환
|
|
- `@RestController`: JSON 응답 반환
|
|
- `@RequestParam`, `@PathVariable`: 요청 데이터 받기
|
|
- `@PostMapping` + `@RequestBody`: JSON 데이터 처리
|
|
- `ResponseEntity`: 응답 제어
|
|
- `@ExceptionHandler`: 예외 처리
|
|
|
|
**이제 실무에서도 자신 있게 컨트롤러를 활용해 보세요!** |