B2024001225 윤지선

Java SpringBoot 3주차 본문

Java SpringBoot

Java SpringBoot 3주차

윤지선 2026. 7. 25. 12:19

3주차 학습 정리

1. Spring Boot 프로젝트의 전체 구조

Spring Boot 프로젝트를 생성하면 여러 폴더와 파일이 만들어진다.

처음 프로젝트를 생성했을 때는 파일이 많지 않기 때문에 각각의 역할을 쉽게 파악할 수 있지만, 실제 프로젝트의 규모가 커지면 많은 클래스와 설정 파일이 추가된다.

따라서 프로젝트를 효율적으로 관리하기 위해 각 파일과 기능을 역할에 따라 분리하여 구성하는 것이 중요하다.

기본적인 Spring Boot 프로젝트는 다음과 같은 구조로 구성할 수 있다.

프로젝트
├── src
│   ├── main
│   │   ├── java
│   │   └── resources
│   │
│   └── test
│
├── build.gradle
└── settings.gradle
 

각각의 위치에 어떤 파일을 작성하는지 알아두는 것이 Spring Boot 프로젝트를 이해하는 기본이 된다.


2. src/main/java

src/main/java

: 실제로 실행되는 Java 코드를 작성하는 공간

Spring Boot에서 사용하는 Controller, Service, Repository, Entity 등의 Java 클래스를 이곳에 작성한다.

프로젝트가 커지면 모든 Java 파일을 하나의 폴더에 넣는 것이 아니라 기능이나 역할에 따라 패키지를 나누어 관리한다.

예를 들어 다음과 같이 구성할 수 있다.

src/main/java
└── com.example.blog
    ├── controller
    ├── service
    ├── repository
    └── domain
 

각 패키지에 서로 다른 역할을 가진 클래스를 배치한다.

controller → 요청 처리
service → 비즈니스 로직
repository → 데이터 접근
domain → 데이터와 관련된 객체
 

이렇게 역할을 나누어 관리하면 프로젝트의 코드가 많아져도 각각의 기능을 쉽게 찾을 수 있다.


3. src/main/resources

src/main/resources

: Java 코드 외에 애플리케이션 실행에 필요한 설정이나 리소스를 저장하는 공간

대표적으로 Spring Boot의 설정 파일인 application.properties 또는 application.yml을 이곳에 작성한다.

예를 들어 서버의 Port를 변경할 수 있다.

 
server.port=8081
 

이렇게 설정하면 Spring Boot 서버가 기본 Port가 아닌 8081 Port에서 실행된다.

localhost:8081
 

따라서 src/main/java가 실제 Java 코드를 작성하는 공간이라면, src/main/resources는 애플리케이션을 실행하는 데 필요한 설정이나 리소스를 관리하는 공간이라고 정리할 수 있다.


4. src/test

src/test

: 애플리케이션의 기능을 테스트하기 위한 코드를 작성하는 공간

실제 애플리케이션 코드와 테스트 코드를 분리해서 관리한다.

src
├── main
│   └── 실제 애플리케이션 코드
│
└── test
    └── 테스트 코드
 

예를 들어 회원가입 기능을 만들었다면 해당 기능이 제대로 동작하는지 확인하기 위한 테스트 코드를 src/test에 작성할 수 있다.

테스트에 대한 자세한 내용은 4주차에서 본격적으로 학습할 예정이지만, 프로젝트를 구성할 때부터 실제 코드와 테스트 코드를 분리한다는 점을 먼저 이해하였다.


5. build.gradle

build.gradle

: 프로젝트의 빌드와 의존성을 관리하는 파일

Spring Boot 프로젝트에서는 필요한 라이브러리를 직접 프로젝트에 넣는 것이 아니라 Gradle을 이용하여 관리할 수 있다.

예를 들어 Spring Web을 사용하려면 다음과 같은 의존성을 추가한다.

 
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
}
 

이렇게 작성하면 Gradle이 해당 의존성을 프로젝트에서 사용할 수 있도록 관리한다.

즉,

build.gradle
      ↓
필요한 Dependency 작성
      ↓
Gradle이 의존성 관리
      ↓
프로젝트에서 해당 기능 사용
 

의 구조로 이해할 수 있다.


6. Gradle이란?

Gradle

: 프로젝트의 빌드와 의존성 등을 관리하는 빌드 자동화 도구

Spring Boot 프로젝트에서는 Gradle을 이용해 프로젝트에 필요한 라이브러리를 관리하고 프로그램을 빌드할 수 있다.

특히 개발을 하다 보면 Spring Web, JPA, 데이터베이스 드라이버 등 여러 가지 라이브러리가 필요하다.

이때 각각의 라이브러리를 직접 다운로드하고 관리하는 대신 Gradle을 이용하면 필요한 의존성을 설정 파일에 작성하여 관리할 수 있다.

예시

Spring Boot 프로젝트
       ↓
build.gradle
       ↓
Spring Web
JPA
MySQL Driver
...
       ↓
Gradle이 필요한 의존성 관리
 

따라서 프로젝트에서 어떤 라이브러리를 사용하고 있는지 확인하고 싶다면 build.gradle을 확인하면 된다.


7. 계층형 아키텍처

Spring Boot 프로젝트에서는 코드를 하나의 클래스에 모두 작성하지 않고 각자의 역할에 따라 여러 계층으로 나누어 관리한다.

이러한 구조를 계층형 아키텍처(Layered Architecture)라고 한다.

대표적으로 다음과 같은 계층으로 나눌 수 있다.

Controller
    ↓
Service
    ↓
Repository
    ↓
Database
 

각 계층마다 담당하는 역할이 다르다.


8. Controller

Controller

: 클라이언트의 요청을 가장 먼저 받아 처리하는 계층

사용자가 웹 페이지에서 특정 기능을 실행하면 클라이언트는 서버에 요청을 보낸다.

Spring Boot에서는 Controller가 이러한 요청을 받아 적절한 작업을 수행하도록 연결해준다.

예시

사용자가 게시글 목록을 확인한다고 가정한다.

사용자
 ↓
게시글 목록 요청
 ↓
Controller
 

Controller는 요청을 받은 후 필요한 작업을 Service에 전달한다.

Controller
    ↓
Service
 

Controller에서 모든 비즈니스 로직을 처리하는 것이 아니라 요청을 받고 적절한 다음 단계로 연결하는 역할에 집중한다.


9. Service

Service

: 서비스에서 필요한 실제 비즈니스 로직을 처리하는 계층

Controller가 요청을 받았다면, 실제로 어떤 작업을 수행해야 하는지는 Service에서 처리한다.

예를 들어 쇼핑몰에서 상품을 주문한다고 생각해보자.

상품 주문 요청
      ↓
Controller
      ↓
Service
      ↓
재고 확인
      ↓
주문 가능 여부 확인
      ↓
주문 처리
 

상품의 재고가 충분한지 확인하거나 주문 조건을 확인하는 등의 서비스에서 필요한 규칙과 처리 과정을 Service에서 담당할 수 있다.

따라서 Service는 단순히 데이터를 가져오는 역할이 아니라 서비스의 핵심적인 동작을 담당하는 계층이다.


10. Repository

Repository

: 데이터베이스에 접근하여 데이터를 조회하거나 저장하는 계층

Service에서 데이터를 필요로 하는 경우 Repository를 통해 데이터베이스에 접근한다.

예를 들어 게시글 목록을 조회한다면,

Controller
    ↓
Service
    ↓
Repository
    ↓
Database
 

Repository가 데이터베이스에서 게시글 정보를 조회하고 그 결과를 다시 Service에 전달한다.

Repository가 담당하는 작업

  • 데이터 조회
  • 데이터 저장
  • 데이터 수정
  • 데이터 삭제

애플리케이션의 데이터와 데이터베이스 사이를 연결하는 역할을 한다.


11. Controller / Service / Repository를 나누는 이유

그렇다면 굳이 코드를 이렇게 여러 계층으로 나누는 이유는 무엇일까?

하나의 클래스에 모든 코드를 작성하면 처음에는 간단해 보이지만 프로젝트가 커질수록 코드가 복잡해진다.

예를 들어 Controller 안에 다음 작업을 전부 작성한다고 생각해보자.

요청 받기
 ↓
사용자 확인
 ↓
상품 조회
 ↓
재고 확인
 ↓
주문 생성
 ↓
DB 저장
 ↓
응답 생성
 

기능이 많아질수록 Controller가 지나치게 복잡해진다.

그래서 역할을 나누어 관리한다.

Controller → 요청 처리
Service → 비즈니스 로직
Repository → 데이터 처리
 

이렇게 분리하면 각각의 코드가 담당하는 역할이 명확해진다.


12. 계층형 구조를 하나의 예시로 이해하기

쇼핑몰에서 사용자가 상품 목록을 조회한다고 생각해보자.

① 사용자가 요청

사용자
 ↓
상품 목록 확인
 

② Controller

상품 목록 요청
 ↓
Controller
 

Controller가 클라이언트의 요청을 받는다.

③ Service

Controller
 ↓
Service
 

Service에서는 상품 목록을 가져오기 위해 필요한 작업을 처리한다.

④ Repository

Service
 ↓
Repository
 

Repository가 데이터베이스에서 상품 정보를 조회한다.

⑤ Database

Repository
 ↓
Database
 

데이터베이스에서 상품 정보를 가져온다.

그리고 결과는 반대 방향으로 다시 전달된다.

Database
   ↓
Repository
   ↓
Service
   ↓
Controller
   ↓
Client
 

결국 전체적인 흐름은

Client
  ↓
Controller
  ↓
Service
  ↓
Repository
  ↓
Database
 

가 된다.


13. 요청 처리 흐름

Spring Boot에서 가장 중요한 부분 중 하나가 클라이언트의 요청이 실제 코드에서 어떤 과정을 거치는지 이해하는 것이다.

예를 들어 사용자가 게시글 하나를 조회한다고 가정한다.

GET /posts/1
 

이라는 요청을 보냈다고 생각해보자.

전체적인 과정은 다음과 같다.

클라이언트
    ↓
HTTP 요청
    ↓
Controller
    ↓
Service
    ↓
Repository
    ↓
Database
 

데이터베이스에서 게시글을 조회한 뒤에는 다시 결과가 반대 방향으로 전달된다.

Database
    ↓
Repository
    ↓
Service
    ↓
Controller
    ↓
HTTP 응답
    ↓
클라이언트
 

즉,

요청은 Controller → Service → Repository 방향으로 이동하고, 처리된 결과는 다시 Repository → Service → Controller 방향으로 돌아온다.


14. Controller의 요청 처리

Spring Boot에서는 Controller에 특정 애너테이션을 사용하여 어떤 요청을 처리할지 지정할 수 있다.

예를 들어,

 
@GetMapping("/posts")
public List<Post> getPosts() {
    ...
}
 

와 같이 작성하면 /posts로 들어오는 GET 요청을 해당 메서드에서 처리할 수 있다.

@GetMapping

: GET 요청을 특정 메서드와 연결하는 애너테이션

예를 들어 사용자가 게시글 목록을 요청하면,

GET /posts
      ↓
@GetMapping("/posts")
      ↓
Controller 메서드 실행
 

과 같은 흐름으로 연결된다.


15. GET과 POST

웹 API에서는 요청의 목적에 따라 HTTP 메서드를 구분하여 사용한다.

GET

: 데이터를 조회할 때 주로 사용

예를 들어 게시글 목록을 조회한다면,

GET /posts
 

와 같은 요청을 사용할 수 있다.

POST

: 새로운 데이터를 생성할 때 주로 사용

새로운 게시글을 작성한다면,

POST /posts
 

와 같은 요청을 사용할 수 있다.

그 외에도

PUT    → 데이터 수정
DELETE → 데이터 삭제
 

등의 HTTP 메서드가 있다.

이러한 메서드를 이용하면 API가 어떤 작업을 수행하는지 요청 자체에서도 어느 정도 구분할 수 있다.


16. 요청과 계층 구조 연결하기

앞에서 공부했던 HTTP 요청과 계층형 아키텍처를 연결하면 이해하기 쉽다.

예를 들어 게시글을 작성한다고 가정한다.

POST /posts
 

전체 흐름

사용자
 ↓
게시글 작성
 ↓
Client
 ↓
POST /posts
 ↓
Controller
 ↓
Service
 ↓
Repository
 ↓
Database
 

각 단계에서 담당하는 역할은 다음과 같다.

Client: 게시글 작성 요청을 보낸다.
Controller: 게시글 작성 요청을 받는다.
Service: 게시글 작성에 필요한 비즈니스 로직을 처리한다.
Repository: 게시글 데이터를 데이터베이스에 저장한다.
Database: 게시글 데이터를 실제로 저장한다.

이렇게 보면 Controller, Service, Repository를 왜 분리하는지 조금 더 명확하게 이해할 수 있다.


17. 의존성 주입

Spring을 공부하면서 함께 알아야 하는 개념이 의존성 주입(DI, Dependency Injection)이다.

의존성

: 어떤 객체가 다른 객체를 필요로 하는 관계

예를 들어 Service가 Repository를 사용한다면 Service는 Repository에 의존한다고 할 수 있다.

Service
   ↓ 의존
Repository
 

Service에서 Repository 객체가 필요하기 때문에 둘 사이에는 의존 관계가 발생한다.


18. 의존성 주입(DI)

의존성 주입

: 객체가 필요한 의존 객체를 직접 생성하지 않고 외부에서 전달받는 방식

객체가 필요한 다른 객체를 직접 생성한다고 생각해보자.

 
Repository repository = new Repository();
 

이런 방식으로 객체를 직접 생성하면 객체 사이의 결합이 강해질 수 있다.

Spring에서는 필요한 객체를 Spring이 관리하고, 필요한 곳에 전달해주는 방식을 사용할 수 있다.

Spring
 ├─ Repository 객체 관리
 ├─ Service 객체 관리
 └─ Controller 객체 관리
 

그리고 필요한 객체를 서로 연결해준다.

Controller
    ↓
Service
    ↓
Repository
 

이러한 방식으로 객체를 직접 생성하고 관리해야 하는 부담을 줄일 수 있다.


19. Spring Bean

Bean

: Spring이 생성하고 관리하는 객체

Spring에서는 애플리케이션에서 사용하는 객체를 직접 생성하고 관리하는 대신 Spring이 객체의 생성과 관리를 담당할 수 있다.

이렇게 Spring이 관리하는 객체를 Bean이라고 한다.

예를 들어 Service 객체나 Repository 객체를 Spring Bean으로 등록하면 Spring이 해당 객체를 관리하고 필요한 곳에 연결할 수 있다.

Spring Container
      ↓
Bean 관리
 ┌────┼────┐
 ↓    ↓    ↓
Controller
Service
Repository
 

따라서 Spring의 구조를 이해하기 위해서는 객체를 Spring이 관리한다는 개념도 중요하다.


20. 3주차 전체 흐름

이번 주차에서 배운 내용을 하나의 흐름으로 묶으면 다음과 같다.

┌─────────────┐
│   Client    │
└──────┬──────┘
       │ HTTP Request
       ↓
┌─────────────┐
│ Controller  │
│ 요청 처리    │
└──────┬──────┘
       ↓
┌─────────────┐
│   Service   │
│ 비즈니스 로직 │
└──────┬──────┘
       ↓
┌─────────────┐
│ Repository  │
│ 데이터 접근  │
└──────┬──────┘
       ↓
┌─────────────┐
│  Database   │
└─────────────┘
 

그리고 처리된 결과는 다시

Database
   ↓
Repository
   ↓
Service
   ↓
Controller
   ↓
Client
 

순서로 전달된다.


21. 3주차 핵심 정리

이번 주차에서 배운 내용을 정리하면 다음과 같다.

src/main/java : Spring Boot에서 사용하는 Java 코드를 작성하는 공간
src/main/resources : 설정 파일과 리소스를 관리하는 공간
src/test : 테스트 코드를 작성하는 공간
build.gradle : 프로젝트의 의존성과 빌드 설정을 관리하는 파일
Gradle : 프로젝트의 빌드와 의존성을 관리하는 도구
계층형 아키텍처 : 애플리케이션을 역할에 따라 여러 계층으로 나누어 구성하는 구조
Controller : 클라이언트의 요청을 받는 계층
Service : 서비스의 비즈니스 로직을 처리하는 계층
Repository : 데이터베이스에 접근하는 계층
DI : 필요한 객체를 외부에서 주입받는 방식
Bean : Spring에서 생성하고 관리하는 객체


마무리

3주차에는 Spring Boot 프로젝트를 단순히 실행하는 것을 넘어 프로젝트 내부가 어떤 구조로 구성되어 있고 각 코드가 어떤 역할을 담당하는지를 중심으로 학습하였다.

특히 Controller, Service, Repository를 각각 따로 외우기보다는 하나의 요청이 들어왔을 때 어떤 순서로 처리되는지를 중심으로 정리하였다.

예를 들어 사용자가 게시글을 조회하면,

사용자
 ↓
Client
 ↓
Controller
 ↓
Service
 ↓
Repository
 ↓
Database
 

와 같은 흐름으로 요청이 전달되고, 데이터베이스에서 조회된 결과는 다시 반대 방향으로 전달된다.

또한 프로젝트의 규모가 커질수록 모든 기능을 하나의 클래스에 작성하기보다 각자의 역할에 맞게 코드를 분리하는 것이 중요하다는 점도 확인하였다.

2주차까지는 Spring Boot 프로젝트를 생성하고 실행하는 방법을 익혔다면, 3주차에서는 그 프로젝트 안에서 각 코드가 어떤 역할을 하고 서로 어떻게 연결되는지를 이해하는 데 집중하였다.

다음 4주차에는 이렇게 작성한 코드가 실제로 제대로 동작하는지 확인하기 위한 테스트 코드와 JUnit을 중심으로 학습할 예정이다.

'Java SpringBoot' 카테고리의 다른 글

Java SpringBoot 5주차  (0) 2026.08.26
Java SpringBoot 4주차  (0) 2026.07.25
Java SpringBoot 2주차  (0) 2026.07.25
Java SpringBoot 1주차  (0) 2026.07.11