1. Spring Boot 프로젝트 구조
Spring Initializr로 프로젝트를 생성하면 기본적으로 아래와 같은 구조가 만들어집니다. 개발 환경 설정과 프로젝트 생성 흐름은 Spring Boot 개발 환경 설정을 먼저 보면 이해하기 쉽습니다.
demo/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/demo/
│ │ │ └── DemoApplication.java
│ │ └── resources/
│ │ ├── application.properties
│ │ ├── static/
│ │ └── templates/
│ └── test/
│ └── java/
│ └── com/example/demo/
│ └── DemoApplicationTests.java
├── build.gradle
└── settings.gradle처음 보면 폴더가 많아 보이지만, 크게 보면 다음과 같이 나눌 수 있습니다.
src/main/java: 실제 애플리케이션 코드src/main/resources: 설정 파일과 정적 리소스src/test/java: 테스트 코드build.gradle: 프로젝트 빌드 및 의존성 설정
2. src/main/java
src/main/java는 Java 소스 코드를 작성하는 위치입니다. Spring Boot 애플리케이션의 컨트롤러, 서비스, 레포지토리, 도메인 클래스 등이 이 폴더 아래에 위치합니다.
예를 들어 기본 패키지 이름을 com.example.demo로 만들었다면, 다음 경로에 코드가 생성됩니다.
src/main/java/com/example/demo/Spring Boot에서는 보통 메인 클래스가 있는 패키지를 기준으로 하위 패키지의 컴포넌트를 자동으로 탐색합니다. 그래서 특별한 이유가 없다면 DemoApplication.java와 같은 메인 클래스 아래에 기능별 패키지를 만드는 것이 좋습니다.
com/example/demo/
├── DemoApplication.java
├── controller/
├── service/
├── repository/
├── domain/
└── dto/각 패키지의 역할은 다음과 같습니다.
| 패키지 | 역할 |
|---|---|
controller | HTTP 요청을 받고 응답을 반환 |
service | 비즈니스 로직 처리 |
repository | 데이터베이스 접근 |
domain | 핵심 도메인 객체 또는 Entity |
dto | 요청/응답 데이터를 전달하는 객체 |
3. DemoApplication.java
Spring Boot 프로젝트를 생성하면 DemoApplication.java 파일이 만들어집니다. 이 파일은 애플리케이션의 시작점입니다.
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}main 메서드에서 SpringApplication.run()을 호출하면 Spring Boot 애플리케이션이 실행됩니다.
여기서 중요한 것은 @SpringBootApplication 어노테이션입니다. 이 어노테이션은 아래 기능들을 합쳐놓은 어노테이션입니다.
@SpringBootConfiguration: Spring Boot 설정 클래스임을 나타냄@EnableAutoConfiguration: Spring Boot의 자동 설정 기능 활성화@ComponentScan: 현재 패키지와 하위 패키지에서 컴포넌트 탐색
즉, DemoApplication.java가 있는 패키지를 기준으로 Spring Bean을 찾기 때문에, 일반적으로 이 클래스는 프로젝트의 최상위 패키지에 두는 것이 좋습니다. Spring이 객체를 생성하고 연결하는 원리는 IoC와 DI 이해하기를 함께 보면 자연스럽게 이어집니다.
4. src/main/resources
src/main/resources는 Java 코드가 아닌 설정 파일과 리소스를 관리하는 위치입니다.
src/main/resources/
├── application.properties
├── static/
└── templates/4.1. application.properties
application.properties는 Spring Boot 애플리케이션의 설정을 작성하는 파일입니다. 설정 파일의 문법과 환경별 분리는 application.yml과 application.properties 설정에서 더 자세히 다룹니다.
server.port=8080
spring.application.name=demo위 설정은 서버 포트를 8080으로 지정하고, 애플리케이션 이름을 demo로 설정합니다.
설정이 많아지면 application.yml 파일을 사용할 수도 있습니다.
spring.datasource.url=jdbc:mysql://localhost:3306/demo
spring.datasource.username=root
spring.datasource.password=password같은 설정을 application.yml로 작성하면 계층 구조로 표현할 수 있습니다.
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo
username: root
password: password
properties와yml중 하나만 사용해도 됩니다. 실무에서는 설정이 많아질수록 가독성이 좋은yml을 많이 사용합니다.
4.2. static
static 폴더는 정적 파일을 넣는 위치입니다. 이미지, CSS, JavaScript 파일 등을 둘 수 있습니다.
src/main/resources/static/
├── images/
│ └── logo.png
├── css/
│ └── style.css
└── js/
└── app.js예를 들어 static/images/logo.png 파일을 넣으면 브라우저에서 아래 주소로 접근할 수 있습니다.
http://localhost:8080/images/logo.png4.3. templates
templates 폴더는 서버 사이드 템플릿 파일을 넣는 위치입니다. Thymeleaf 같은 템플릿 엔진을 사용할 때 HTML 파일을 이곳에 둡니다.
src/main/resources/templates/
└── index.html다만 REST API 서버만 만든다면 templates 폴더를 사용하지 않는 경우도 많습니다.
5. src/test/java
src/test/java는 테스트 코드를 작성하는 위치입니다.
src/test/java/com/example/demo/
└── DemoApplicationTests.javaSpring Initializr로 프로젝트를 만들면 기본 테스트 클래스가 생성됩니다.
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
}
}@SpringBootTest는 Spring Boot 애플리케이션 컨텍스트가 정상적으로 로딩되는지 확인할 때 사용할 수 있습니다. 처음에는 비어 있는 테스트처럼 보이지만, 애플리케이션 설정에 문제가 있으면 이 테스트가 실패합니다.
6. build.gradle
build.gradle은 Gradle 빌드 설정 파일입니다. 프로젝트에서 사용할 플러그인, Java 버전, 의존성 등을 정의합니다.
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.0'
id 'io.spring.dependency-management' version '1.1.5'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}주요 항목은 다음과 같습니다.
plugins: Java, Spring Boot 관련 플러그인 설정repositories: 의존성을 다운로드할 저장소 설정dependencies: 프로젝트에서 사용할 라이브러리 설정tasks.named('test'): JUnit 5를 사용하도록 테스트 설정
새로운 라이브러리가 필요하면 보통 dependencies 블록에 추가합니다.
7. settings.gradle
settings.gradle은 Gradle 프로젝트의 이름과 멀티 모듈 설정을 관리하는 파일입니다.
pluginManagement {
repositories {
maven { url = 'https://repo.spring.io/milestone' }
gradlePluginPortal()
}
}
rootProject.name = 'demo'단일 프로젝트에서는 대부분 rootProject.name 정도만 확인하면 됩니다. 멀티 모듈 프로젝트를 구성할 때는 이 파일에 하위 모듈을 추가합니다.
rootProject.name = 'demo'
include 'api'
include 'common'처음 Spring Boot를 공부할 때는 settings.gradle보다 build.gradle을 더 자주 수정하게 됩니다.
8. 실무에서 자주 사용하는 패키지 구조
작은 예제에서는 메인 클래스와 컨트롤러를 같은 패키지에 두어도 문제가 없습니다. 하지만 프로젝트가 커지면 역할별로 패키지를 나누는 것이 좋습니다.
com/example/demo/
├── DemoApplication.java
├── controller/
│ └── UserController.java
├── service/
│ └── UserService.java
├── repository/
│ └── UserRepository.java
├── domain/
│ └── User.java
└── dto/
├── UserCreateRequest.java
└── UserResponse.java예를 들어 사용자 목록을 조회하는 API를 만든다면 흐름은 다음과 같습니다.
UserController
↓
UserService
↓
UserRepository
↓
Database각 계층의 책임을 나누면 코드가 많아져도 유지보수하기 쉬워집니다.
Controller: 요청과 응답 처리에 집중Service: 핵심 로직 처리에 집중Repository: 데이터 조회와 저장에 집중Domain: 비즈니스의 핵심 개념 표현DTO: 외부로 주고받는 데이터 표현
8.1. 실무에서 패키지를 나눌 때의 기준
처음부터 패키지를 너무 세밀하게 나누면 오히려 이동 비용이 커집니다. 작은 프로젝트에서는 controller, service, repository, domain, dto 정도로 시작하고, 기능이 커질 때 user, order, payment처럼 도메인 기준으로 한 번 더 나누는 편이 관리하기 쉽습니다.
com/example/demo/
├── user/
│ ├── controller/
│ ├── service/
│ ├── repository/
│ ├── domain/
│ └── dto/
└── order/
├── controller/
├── service/
├── repository/
├── domain/
└── dto/제가 프로젝트를 시작할 때는 먼저 역할 기준으로 단순하게 나누고, 특정 도메인의 파일이 많아지기 시작하면 도메인 기준 구조로 옮기는 편입니다. 중요한 것은 처음부터 완벽한 구조를 만드는 것이 아니라, 팀이 파일 위치를 예측할 수 있게 일관성을 유지하는 것입니다.
9. 참고 자료
10. 정리
Spring Boot 프로젝트 구조는 처음에는 복잡해 보이지만, 역할을 기준으로 보면 어렵지 않습니다.
src/main/java에는 실제 애플리케이션 코드를 작성합니다.DemoApplication.java는 애플리케이션의 시작점입니다.src/main/resources에는 설정 파일과 정적 리소스를 둡니다.src/test/java에는 테스트 코드를 작성합니다.build.gradle에는 플러그인, Java 버전, 의존성을 설정합니다.- 프로젝트가 커지면
controller,service,repository,domain,dto처럼 역할별로 패키지를 나누는 것이 좋습니다.
프로젝트 구조를 이해하면 이후에 Controller, Service, Repository, JPA, 테스트를 학습할 때 각각의 코드가 어디에 위치해야 하는지 자연스럽게 이해할 수 있습니다.