[Java/Spring] 스프링 MVC 패턴(2) : Controller

SujiPark·2025년 2월 10일

Java

목록 보기
6/7

지난 포스팅에 이어서, Controller에 대해 알아보도록 하자.

Spring MVC의 Controller

  • Spring MVC에서 Controller(컨트롤러)는 클라이언트의 요청을 받아 비즈니스 로직(Service)View(예를 들면, Thymeleaf)를 연결하는 역할을 한다.
  • Controller사용자 요청을 처리하고, 데이터를 Model에 담아 View로 전달하는 역할을 한다.

Controller의 역할

  • 클라이언트의 HTTP 요청을 처리한다.
  • Service를 호출하여 비즈니스 로직을 수행한다.
  • Model을 사용하여 View로 데이터 전달
  • REST API를 제공하는 경우 JSON 응답 반환 가능하다.

Controller는 클라이언트(View 또는 API 요청)와 Service 간의 다리 역할을 수행한다고 생각하면 된다.

📌 Spring MVC의 데이터 흐름 정리

클라이언트 → Controller → Service → Repository → Entity → DB → Entity → Repository → Service → Controller → Model → View(Thymeleaf) → 클라이언트 응답

📍 참고로, 여기에 있는 Model은 MVC 패턴의 Model과 같은 것이 아니다.

  • 이 Model은 Spring MVC에서의 Model 객체 (org.springframework.ui.Model)인데,
    Spring MVC에서 Model 객체는 Controller가 데이터를 View로 전달하는 역할을 한다.
    즉, 여기서의 Model 객체단순히 View에서 사용할 데이터를 담는 컨테이너일 뿐이다!

이제, 기본적인 예제를 살펴보도록 하자.

1. Controller 기본 예제

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", "Spring MVC 프로젝트에 오신 것을 환영합니다!");
        return "home"; // home.html로 이동
    }
}
  • @Controller를 사용하여 Spring MVC 컨트롤러로 등록
  • @GetMapping("/") → 사용자가 / 경로로 GET 요청을 하면 home.html을 반환
  • Model을 사용하여 View에 데이터를 전달

2. Controller에서 Service 연동 예제

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;

@Controller
public class UserController {
    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/users")
    public String getUsers(Model model) {
        List<UserDTO> users = userService.getAllUsers();
        model.addAttribute("users", users);
        return "user-list"; // user-list.html로 이동
    }
}
  • Service를 호출하여 데이터 가져오기
  • Model을 사용하여 View에 데이터를 전달

3. 요청 파라미터 처리

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class SearchController {

    @GetMapping("/search")
    public String search(@RequestParam String keyword, Model model) {
        model.addAttribute("keyword", keyword);
        return "search-results";
    }
}
  • view에서 이용 예시
<p>검색어: <span th:text="${keyword}"></span></p>

어노테이션이 굉장히 많은데, 어노테이션을 이해하면 Controller를 이해하기 더 쉬울 것이다.
다음으로 Controller에서 주로 사용하는 어노테이션에 대해 알아보자.

📍 Controller에서 사용하는 주요 어노테이션

1. @Controller vs @RestController

Controller를 정의할 때 가장 많이 사용하는 어노테이션이다.

@Controller

  • Spring MVC 컨트롤러를 정의하는 어노테이션이다.
  • 반환 타입은 View(Thymeleaf, JSP)이다.
  • Thymeleaf와 같은 View 템플릿을 사용하여 HTML을 반환하는 경우 사용한다.
@Controller
public class HomeController {
    @GetMapping("/")
    public String home(Model model) {
        model.addAttribute("message", "Spring MVC 프로젝트!");
        return "home"; // home.html 템플릿 반환
    }
}

@RestController

  • REST API 컨트롤러를 정의하는 어노테이션이다.
  • REST API를 개발할 때 사용하며, JSON 데이터를 반환할 때 사용한다.
@RestController
@RequestMapping("/api")
public class ApiController {
    @GetMapping("/message")
    public String getMessage() {
        return "Hello, this is a REST API response!";
    }
}

📍 만약 Controller에서 JSON을 반환하고싶다면, @ResponseBody 사용하기

@Controller
@ResponseBody
public class ExampleController {
    @GetMapping("/json")
    public String getJson() {
        return "{\"message\": \"Hello, JSON!\"}";
    }
}
  • @ResponseBody(밑에서 설명)를 사용하면 @RestController와 동일한 효과를 볼 수 있다.
  • 참고로 @RestController@Controller + @ResponseBody의 조합이다.

2. @RequestMapping vs @GetMapping vs @PostMapping

Spring에서 HTTP 요청을 처리하기 위해 사용되는 매핑 어노테이션이다.

@RequestMapping

: 공통 URL 패턴, 즉 모든 html 메서드(GET, POST, PUT 등)을 매핑하는 어노테이션이다.

@Controller
@RequestMapping("/users")
public class UserController {
    @RequestMapping("/list")
    public String getUserList() {
        return "user-list"; // user-list.html 반환
    }
}

@GetMapping

: HTTP GET 요청을 처리한다.

@PostMapping

: HTTP POST 요청을 처리한다.

@Controller
@RequestMapping("/users")
public class UserController {
    @GetMapping("/list")
    public String getUsers() {
        return "user-list"; // GET 요청
    }
    @PostMapping("/add")
    public String addUser() {
        return "redirect:/users/list"; // POST 요청
    }
}
  • @RequestMapping을 사용할 수도 있지만, @GetMapping 같은 세부적인 매핑을 권장한다고 한다!

3. @RequestParam vs @PathVariable

클라이언트가 보낸 데이터를 받을 때 사용하는 어노테이션이다.

@RequestParam

  • 쿼리 스트링 파라미터를 받는다.
  • ?key=value 형태
@Controller
@RequestMapping("/search")
public class SearchController {
    @GetMapping
    public String search(@RequestParam String keyword, Model model) {
        model.addAttribute("keyword", keyword);
        return "search-results"; // search-results.html 반환
    }
}
  • 클라이언트 요청은 http ://localhost:8080/search?keyword=Spring의 형태이며 @RequestParam을 통해 keyword 값을 가져온다.

@PathVariable

  • URL 경로 변수를 받는다.
  • /users/{id} 형태
@RestController
@RequestMapping("/api/users")
public class UserRestController {
    @GetMapping("/{id}")
    public String getUserById(@PathVariable Long id) {
        return "User ID: " + id;
    }
}

요청은 http: //localhost:8080/api/users/10의 형태이며 @PathVariable을 사용하여 id=10 값을 가져온다.

4. @ModelAttribute vs @RequestBody

마지막으로, 사용자로부터 폼 데이터를 받을 때 사용하는 어노테이션이다.

@ModelAttribute

: 폼 데이터를 객체로 변환한다. (Form (HTML)형식)

@Controller
@RequestMapping("/users")
public class UserController {

    @PostMapping("/form")
    public String submitUserForm(@ModelAttribute UserDTO userDTO) {
        System.out.println("Name: " + userDTO.getName());
        System.out.println("Email: " + userDTO.getEmail());
        return "redirect:/users";
    }
}
  • 사용예시
<form action="/users/form" method="post">
    <input type="text" name="name" placeholder="이름" />
    <input type="email" name="email" placeholder="이메일" />
    <button type="submit">제출</button>
</form>
제출

@RequestBody

: JSON 데이터를 객체로 변환한다.

@RestController
@RequestMapping("/api/users")
public class UserRestController {

    @PostMapping
    public String createUser(@RequestBody UserDTO userDTO) {
        return "User created: " + userDTO.getName();
    }
}
  • 사용 예시
{
    "name": "홍길동",
    "email": "hong@example.com"
}

0개의 댓글