Files
spring-boot-examples/docs/01_Spring Boot MVC.md
2025-04-08 19:56:24 +09:00

326 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
아래는 Spring Boot MVC 프로젝트의 아키텍처, 프로젝트 구조, 패키징 전략, 레이어드 아키텍처, 그리고 Spring Initializr 사용법을 실무 중심으로 설명한 글입니다. SEO를 고려해 키워드를 자연스럽게 배치하고, 흥미로운 주제를 앞부분에 배치하며, 읽기 쉽게 작성했습니다. Gradle은 `build.gradle.kts`로 작성했으며, 코드 예제도 포함했습니다.
---
# Spring Boot MVC 프로젝트 아키텍처 완벽 정리: 구조, 패키징, 레이어드 아키텍처까지
Spring Boot는 MVC(Model-View-Controller) 패턴을 기반으로 빠르고 효율적인 웹 애플리케이션 개발을 가능하게 합니다. 실무에서 Spring Boot MVC 프로젝트를 시작하려면 아키텍처 설계가 중요하죠. 이 글에서는 **Spring Boot MVC 아키텍처**, **프로젝트 구조**, **패키징 전략**, 그리고 **레이어드 아키텍처**를 실무 관점에서 다룹니다. 보너스로 **Spring Initializr** 사용법까지 소개하니, 초보자부터 숙련자까지 유용할 거예요. 바로 시작해볼까요?
## 1. Spring Boot MVC 아키텍처란?
Spring Boot MVC는 전통적인 MVC 패턴을 따르며, Spring의 강력한 기능을 더해줍니다.
- **Model**: 데이터와 비즈니스 로직을 담당.
- **View**: 사용자 인터페이스(HTML, Thymeleaf 등).
- **Controller**: 요청을 처리하고 Model과 View를 연결.
Spring Boot는 설정을 자동화해 개발자가 비즈니스 로직에 집중할 수 있게 도와줍니다. 예를 들어, `@RestController`를 사용하면 JSON 응답을 쉽게 반환할 수 있죠.
**실무 팁**:
- REST API 중심이라면 `@RestController`를, 템플릿 기반 웹이라면 `@Controller`와 Thymeleaf를 활용하세요.
## **1. Spring Boot MVC 주요 구성 요소**
Spring Boot MVC는 다음과 같은 핵심 요소로 구성됩니다.
### **1.1 DispatcherServlet (디스패처 서블릿)**
- Spring MVC의 중심 역할을 담당하는 **프론트 컨트롤러**.
- 모든 요청을 받아서 적절한 컨트롤러로 전달하고, 결과를 다시 응답으로 반환.
- Spring Boot에서는 기본적으로 `DispatcherServlet`이 자동 설정됨.
### **1.2 컨트롤러 (Controller)**
- 사용자의 요청을 받아 처리하는 클래스.
- `@Controller` 또는 `@RestController`를 사용하여 정의.
- 요청을 매핑하는 `@RequestMapping`, `@GetMapping`, `@PostMapping` 등의 어노테이션과 함께 사용.
### **1.3 서비스 (Service)**
- 비즈니스 로직을 처리하는 계층.
- `@Service` 어노테이션을 사용하여 선언.
- 컨트롤러에서 받은 요청을 처리하고, 데이터를 가공하여 리포지토리 또는 외부 API와 연결.
### **1.4 리포지토리 (Repository)**
- 데이터베이스와 직접적으로 통신하는 계층.
- Spring Data JPA를 활용하여 `@Repository`로 선언하고, 엔터티를 저장/조회하는 기능을 수행.
### **1.5 모델 (Model)**
- 응답 데이터로 전달될 객체.
- `Model` 객체를 통해 View에 데이터를 전달.
- JPA에서 `@Entity`를 사용하여 데이터베이스 테이블과 매핑.
### **1.6 뷰 (View)**
- 클라이언트에게 데이터를 시각적으로 보여주는 역할.
- Spring Boot에서는 기본적으로 **Thymeleaf**를 사용하여 HTML을 렌더링.
## 2. Spring Boot 프로젝트 구조: 실무에서 추천하는 방식
Spring Boot 프로젝트를 처음 생성하면 기본 구조가 제공되지만, 실무에서는 역할별로 잘 정리된 구조가 필요합니다. 예시 구조를 보죠:
```
com.example.myapp
├── MyAppApplication.java # 메인 클래스
├── controller # 요청 처리
│ └── UserController.java
├── service # 비즈니스 로직
│ └── UserService.java
├── repository # 데이터 접근
│ └── UserRepository.java
├── model # 엔티티
│ └── User.java
├── config # 설정 클래스
│ └── WebConfig.java
└── resources
├── application.yml # 설정 파일
└── templates # 뷰 템플릿 (Thymeleaf 등)
```
**설명**:
- `MyAppApplication.java`: 애플리케이션 진입점. `@SpringBootApplication` 어노테이션이 핵심입니다.
- `controller`, `service`, `repository`: 레이어드 아키텍처를 반영한 분리.
- `resources`: 정적 파일, 설정 파일, 뷰 템플릿을 관리.
## 3. 패키징 전략: 깔끔하고 유지보수 쉽게
패키지를 어떻게 나누느냐는 프로젝트의 확장성과 가독성에 큰 영향을 미칩니다. 두 가지 접근법이 흔히 사용됩니다:
### 기능별 패키징 (Feature-based)
```
com.example.myapp
├── user
│ ├── UserController.java
│ ├── UserService.java
│ └── UserRepository.java
├── product
│ ├── ProductController.java
│ ├── ProductService.java
│ └── ProductRepository.java
```
- **장점**: 모듈별로 독립적이어서 팀 작업에 유리.
- **실무 추천**: 마이크로서비스로 전환할 가능성이 있다면 이 방식이 좋습니다.
### 레이어드 패키징 (Layer-based)
위의 예시처럼 `controller`, `service`, `repository`로 나눕니다.
- **장점**: 전통적이고 직관적. 소규모 프로젝트에 적합.
- **실무 팁**: 패키지가 너무 커지면 하위 패키지로 세분화하세요 (예: `controller.api`, `controller.web`).
## 4. 레이어드 아키텍처: 계층별 역할과 코드 예제
Spring Boot에서 레이어드 아키텍처는 책임을 명확히 분리해 유지보수를 쉽게 만듭니다. 각 레이어의 역할과 예제를 보죠.
### Controller Layer
```java
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
return ResponseEntity.ok(userService.getUser(id));
}
}
```
### Service Layer
```java
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User getUser(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found"));
}
}
```
### Repository Layer
```java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
```
### Model Layer
```java
@Entity
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
}
```
**실무 팁**:
- **의존성 방향**: Controller → Service → Repository로 단방향 유지.
- **예외 처리**: Service 레이어에서 비즈니스 예외를 처리하고, Controller에서 HTTP 상태로 변환하세요.
## 5. Spring Initializr로 프로젝트 시작하기
Spring Initializr는 Spring Boot 프로젝트를 빠르게 생성하는 공식 도구입니다. 사용법은 간단합니다:
1. **웹사이트 접속**: [start.spring.io](https://start.spring.io)에 들어갑니다.
2. **설정 선택**:
- 프로젝트: Gradle (Kotlin)
- 언어: Java
- Spring Boot 버전: 최신 stable (예: 3.2.3)
- 의존성: `Spring Web`, `Spring Data JPA`, `Lombok` 추가.
3. **생성**: "Generate" 버튼을 눌러 다운로드.
4. **압축 해제 후 실행**: IDE에서 열고 `gradlew bootRun`으로 실행.
### Gradle 설정 (build.gradle.kts)
```kotlin
plugins {
id("org.springframework.boot") version "3.2.3"
id("io.spring.dependency-management") version "1.1.4"
java
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")
runtimeOnly("com.h2database:h2")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks {
test {
useJUnitPlatform()
}
}
```
## **2. Spring Boot MVC 요청 흐름**
Spring Boot MVC에서 **클라이언트의 요청이 들어와서 응답이 반환되기까지의 과정**은 다음과 같이 진행됩니다.
### **1⃣ 클라이언트의 요청**
클라이언트(웹 브라우저, API 호출 등)가 특정 URL로 요청을 보냄.
```
GET http://localhost:8080/home
```
### **2⃣ DispatcherServlet이 요청을 받음**
Spring Boot에서는 `DispatcherServlet`이 모든 요청을 받아서 처리할 컨트롤러를 찾음.
### **3⃣ 컨트롤러에서 요청 처리**
컨트롤러는 요청을 처리하고, 필요한 경우 서비스 계층을 호출하여 데이터 가공을 수행.
```java
@Controller
public class HomeController {
@GetMapping("/home")
public String home(Model model) {
model.addAttribute("message", "Welcome to Spring Boot MVC!");
return "home"; // home.html 뷰 반환
}
}
```
### **4⃣ 서비스 계층 호출 (비즈니스 로직 수행)**
서비스는 필요한 데이터 조회 및 가공을 수행.
```java
@Service
public class HomeService {
public String getWelcomeMessage() {
return "Welcome to Spring Boot MVC!";
}
}
```
컨트롤러에서 이 서비스를 호출할 수도 있음.
```java
@Controller
public class HomeController {
private final HomeService homeService;
public HomeController(HomeService homeService) {
this.homeService = homeService;
}
@GetMapping("/home")
public String home(Model model) {
model.addAttribute("message", homeService.getWelcomeMessage());
return "home"; // home.html 뷰 반환
}
}
```
### **5⃣ 데이터베이스 조회 (필요한 경우)**
서비스 계층이 데이터를 필요로 하면 리포지토리를 통해 데이터베이스에서 값을 가져옴.
```java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
```
```java
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public List<User> getUsers() {
return userRepository.findAll();
}
}
```
### **6⃣ 뷰에 데이터 전달**
- 컨트롤러에서 `Model` 객체를 이용하여 데이터를 뷰로 전달.
- `home.html`에서 이를 활용.
```html
<!-- home.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Home</title>
</head>
<body>
<h1 th:text="${message}"></h1>
</body>
</html>
```
### **7⃣ 뷰를 렌더링하여 응답 반환**
- `DispatcherServlet`이 컨트롤러에서 받은 뷰(`home.html`)를 렌더링하고, HTML을 클라이언트에게 응답으로 반환.
## 마무리
Spring Boot MVC 아키텍처는 실무에서 구조화된 설계로 생산성을 높여줍니다. **프로젝트 구조**와 **패키징 전략**을 잘 잡고, **레이어드 아키텍처**로 책임을 분리하면 유지보수도 쉬워지죠. Spring Initializr로 시작해 위 예제를 참고하면 금방 적응할 거예요. 질문이 있다면 언제든 물어보세요!
---
### SEO 및 가독성 반영
- **키워드**: "Spring Boot MVC 아키텍처", "Spring Boot 프로젝트 구조", "레이어드 아키텍처" 등 자연스럽게 사용.
- **흥미로운 주제 전반부**: 아키텍처와 구조를 먼저 다뤄 실무 개발자의 관심을 끌었음.
- **가독성**: 소제목, 코드 블록, 간결한 설명으로 구성.
추가로 보완할 내용이나 다른 요청이 있다면 말씀해주세요!