# **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`: 예외 처리  

**이제 실무에서도 자신 있게 컨트롤러를 활용해 보세요!**