Skip to main content
Summary

프로젝트 구조를 먼저 보면 길을 잃지 않는다

Spring Boot 프로젝트를 처음 열면 파일과 폴더가 많아 보입니다. 하지만 지금 모두 외울 필요는 없습니다. 먼저 이렇게 생각하면 됩니다.

  • src/main/java: 자바 코드를 쓰는 곳

  • src/main/resources: 자바 코드는 아니지만 실행할 때 필요한 파일을 두는 곳

  • build.gradle: 프로젝트에 필요한 기능을 가져오는 주문서

  • application.properties 또는 application.yml: 실행 설정을 적는 메모장

  • BoardApplication.java: 애플리케이션을 시작하는 출발점

2장에서 만든 게시판 프로젝트는 대략 다음과 비슷한 구조를 가집니다.

board/
├── build.gradle
├── settings.gradle
├── gradlew
├── gradlew.bat
└── src/
    ├── main/
    │   ├── java/
    │   │   └── com/example/board/
    │   │       ├── BoardApplication.java
    │   │       └── HelloController.java
    │   └── resources/
    │       └── application.properties
    └── test/
        └── java/
            └── com/example/board/
                └── BoardApplicationTests.java

여기서 가장 자주 만지는 곳은 src/main/java, src/main/resources, build.gradle입니다. 나머지 파일은 당장 자세히 몰라도 괜찮습니다.

Spring Boot 프로젝트 구조 이해하기AI 생성 이미지

src/main/java: 애플리케이션의 자바 코드가 사는 곳

src/main/java는 우리가 직접 작성하는 자바 코드의 중심입니다. 컨트롤러, 서비스, 리포지토리, 도메인 클래스 같은 파일이 이곳에 들어갑니다.

예를 들어 게시판 API를 만든다면 나중에 다음과 같이 폴더를 나눌 수 있습니다.

src/main/java/com/example/board/
├── BoardApplication.java
├── controller/
│   └── PostController.java
├── service/
│   └── PostService.java
├── repository/
│   └── PostRepository.java
└── domain/
    └── Post.java

폴더 이름은 자바에서는 보통 패키지라고 부릅니다. 패키지는 비슷한 역할의 클래스를 정리해 두는 서랍입니다.

예를 들어 PostController.java 파일이 com/example/board/controller 폴더 안에 있다면 파일 맨 위에는 보통 이렇게 적습니다.

package com.example.board.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PostController {

    @GetMapping("/posts")
    public String getPosts() {
        return "게시글 목록입니다.";
    }
}

여기서 중요한 점은 폴더 위치와 package 문장이 맞아야 한다는 것입니다.

폴더: src/main/java/com/example/board/controller
패키지: package com.example.board.controller;

폴더의 /는 패키지에서 .으로 바뀐다고 보면 됩니다.

기본 패키지 아래에 코드를 두는 이유

처음 생성된 메인 클래스는 보통 다음 위치에 있습니다.

src/main/java/com/example/board/BoardApplication.java

그리고 파일 내용은 대략 다음과 같습니다.

package com.example.board;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BoardApplication {

    public static void main(String[] args) {
        SpringApplication.run(BoardApplication.class, args);
    }
}

여기서 com.example.board를 기본 패키지처럼 생각하면 됩니다. 앞으로 만드는 controller, service, repository 폴더는 가능하면 이 기본 패키지 아래에 둡니다.

좋은 예
com.example.board.BoardApplication
com.example.board.controller.PostController
com.example.board.service.PostService
com.example.board.repository.PostRepository

반대로 다음처럼 기본 패키지 밖에 클래스를 만들면 Spring이 자동으로 찾지 못해 동작하지 않을 수 있습니다.

주의할 예
com.example.other.PostController

초보자 단계에서는 간단한 규칙 하나만 기억하면 됩니다.

새 자바 클래스는 BoardApplication.java가 있는 패키지와 그 하위 패키지 안에 만든다.

이 규칙을 지키면 Spring Boot가 컨트롤러나 서비스 클래스를 발견하기 쉽습니다.

src/main/resources: 코드가 아닌 실행 재료를 두는 곳

src/main/resources는 자바 코드는 아니지만 애플리케이션 실행에 필요한 파일을 두는 곳입니다. 대표적으로 설정 파일이 여기에 들어갑니다.

src/main/resources/
├── application.properties
├── static/
└── templates/

각 역할은 다음과 같습니다.

  • application.properties: Spring Boot 설정값을 적는 파일

  • static: 이미지, CSS, JavaScript 같은 정적 파일을 두는 폴더

  • templates: 서버에서 HTML 화면을 만들 때 사용하는 템플릿 파일을 두는 폴더

이 책에서는 당분간 REST API를 중심으로 진행하므로 static과 templates는 자주 사용하지 않습니다. 가장 중요한 파일은 application.properties입니다.

Spring Boot는 실행될 때 src/main/resources 아래의 application.properties, application.yml, application.yaml 같은 설정 파일을 읽을 수 있습니다.1

예를 들어 서버 포트를 바꾸고 싶다면 application.properties에 이렇게 적습니다.

server.port=9090

이제 애플리케이션을 다시 실행하면 기본 주소가 바뀝니다.

기존: http://localhost:8080
변경: http://localhost:9090

자바 코드를 고치지 않고 설정 파일만 바꿔서 실행 방식을 바꾼 것입니다. 설정 파일은 자동차의 운전석 버튼과 비슷합니다. 엔진 구조를 뜯지 않아도 에어컨 온도나 라디오 볼륨을 바꿀 수 있듯이, 설정 파일로 애플리케이션의 실행 환경을 조정할 수 있습니다.

application.properties와 application.yml의 차이

Spring Boot 설정 파일은 보통 두 방식 중 하나를 사용합니다.

첫 번째는 application.properties입니다.

server.port=9090
spring.application.name=board

key=value 형태로 한 줄씩 적습니다. 초보자에게는 이 방식이 단순합니다.

두 번째는 application.yml입니다.

server:
  port: 9090
spring:
  application:
    name: board

yml은 들여쓰기로 구조를 표현합니다. 같은 내용을 계층적으로 묶어 볼 수 있어 설정이 많아지면 읽기 좋습니다. 대신 들여쓰기가 틀리면 설정이 제대로 읽히지 않을 수 있습니다.

두 파일은 표현 방식만 다를 뿐, 위 예시는 같은 의미입니다. 처음에는 application.properties로 시작해도 충분합니다.

주의할 점이 있습니다. 같은 프로젝트에서 application.properties와 application.yml에 같은 설정을 동시에 적으면 어떤 값이 적용되는지 헷갈릴 수 있습니다. 초보자 단계에서는 둘 중 하나만 선택해서 사용하는 편이 좋습니다.

build.gradle: 필요한 기능을 가져오는 주문서

build.gradle은 프로젝트를 어떻게 빌드하고, 어떤 라이브러리를 사용할지 적는 파일입니다. 여기서 빌드란 자바 코드를 컴퓨터가 실행할 수 있는 형태로 준비하는 과정입니다.

2장에서 Spring Initializr로 프로젝트를 만들 때 Spring Web을 추가했습니다. 그 선택 결과가 build.gradle에 들어갑니다.

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

여기서 dependencies는 의존성 목록입니다. 의존성은 내 프로젝트가 사용하기 위해 가져오는 외부 라이브러리입니다. 스마트폰에 앱을 설치하면 기능이 늘어나는 것처럼, Spring Boot 프로젝트도 의존성을 추가하면 할 수 있는 일이 늘어납니다.

예를 들어 spring-boot-starter-web이 있으면 다음 기능을 사용할 수 있습니다.

  • 웹 서버 실행

  • HTTP 요청과 응답 처리

  • @RestController 사용

  • @GetMapping, @PostMapping 같은 매핑 애너테이션 사용

  • JSON 응답 처리

그래서 2장에서 우리가 작성한 컨트롤러가 동작할 수 있었습니다.

@RestController
public class HelloController {

    @GetMapping("/")
    public String hello() {
        return "게시판 API 서버가 실행 중입니다.";
    }
}

만약 나중에 데이터베이스를 사용한다면 build.gradle에 JPA나 데이터베이스 드라이버 의존성을 추가하게 됩니다.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'com.h2database:h2'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

지금은 코드를 모두 이해하지 않아도 됩니다. 핵심은 이것입니다.

build.gradle에 의존성을 추가하면 프로젝트가 사용할 수 있는 기능이 늘어난다.

단, 의존성을 추가한 뒤에는 Gradle이 새 라이브러리를 내려받도록 프로젝트를 다시 불러와야 합니다. IntelliJ에서는 보통 Gradle 새로고침 버튼을 누르거나, 오른쪽 Gradle 창에서 Reload를 실행하면 됩니다.

메인 애플리케이션 클래스가 실행의 출발점이다

Spring Boot 애플리케이션은 main 메서드에서 시작합니다.

@SpringBootApplication
public class BoardApplication {

    public static void main(String[] args) {
        SpringApplication.run(BoardApplication.class, args);
    }
}

자바 프로그램은 main 메서드에서 출발한다고 했습니다. Spring Boot도 마찬가지입니다. 다만 main 안에서 우리가 직접 컨트롤러 객체를 만들지 않습니다.

// 보통 이렇게 직접 만들지 않습니다.
HelloController controller = new HelloController();

대신 다음 한 줄이 Spring Boot에게 실행을 맡깁니다.

SpringApplication.run(BoardApplication.class, args);

이 코드는 "BoardApplication 클래스를 기준으로 Spring Boot 애플리케이션을 시작해 줘"라는 뜻입니다.

그 위에 붙은 @SpringBootApplication은 Spring Boot 애플리케이션이라는 표시입니다. 초보자 관점에서는 세 가지 일을 한다고 이해하면 충분합니다.

  1. 이 클래스가 설정의 출발점임을 알려 준다.

  2. 필요한 자동 설정을 켠다.

  3. 현재 패키지와 하위 패키지에서 Spring이 관리할 클래스를 찾는다.

여기서 "Spring이 관리할 클래스"란 @RestController, @Service, @Repository 같은 애너테이션이 붙은 클래스를 말합니다. 다음 장에서 다룰 IoC와 DI의 기반이 바로 여기에 있습니다. 지금은 Spring이 클래스를 찾아 객체로 준비해 둔다고만 이해하면 됩니다.

실행 흐름을 간단히 그리면 다음과 같습니다.

1. main 메서드 실행
2. SpringApplication.run(...) 호출
3. @SpringBootApplication을 기준으로 프로젝트 설정 시작
4. 현재 패키지와 하위 패키지에서 컨트롤러 등 클래스 탐색
5. 내장 웹 서버 실행
6. 브라우저 요청을 컨트롤러 메서드로 연결

그래서 HelloController를 직접 실행하지 않아도 브라우저에서 http://localhost:8080으로 접속하면 응답을 받을 수 있습니다.

흔한 실수: 파일은 맞는데 위치가 틀린 경우

Spring Boot 초보자가 자주 만나는 문제는 코드 내용보다 위치 문제입니다.

첫 번째 실수는 컨트롤러를 기본 패키지 밖에 만드는 것입니다.

BoardApplication 위치:
com.example.board

컨트롤러 위치:
com.example.controller

이 경우 Spring Boot가 컨트롤러를 자동으로 찾지 못할 수 있습니다. 다음처럼 기본 패키지 아래로 옮깁니다.

올바른 위치:
com.example.board.controller

두 번째 실수는 설정 파일 이름을 잘못 쓰는 것입니다.

잘못된 예:
applications.properties
application.property
app.properties

기본 설정 파일 이름은 application.properties 또는 application.yml입니다. 철자가 하나만 달라도 자동으로 읽히지 않습니다.

세 번째 실수는 resources가 아니라 java 아래에 설정 파일을 두는 것입니다.

잘못된 위치:
src/main/java/application.properties

올바른 위치:
src/main/resources/application.properties

설정 파일은 자바 코드가 아니므로 resources 아래에 둡니다.

이번 장의 미니 정리

이제 Spring Boot 프로젝트를 열었을 때 무엇을 먼저 봐야 하는지 알 수 있습니다.

  • 자바 코드는 src/main/java에 작성한다.

  • 설정 파일은 src/main/resources에 둔다.

  • 새 클래스는 메인 애플리케이션 클래스의 패키지 아래에 만든다.

  • build.gradle은 의존성을 통해 프로젝트 기능을 확장한다.

  • application.properties 또는 application.yml은 실행 설정을 바꾸는 곳이다.

  • BoardApplication.java의 main 메서드와 @SpringBootApplication이 실행의 출발점이다.

앞으로 우리는 게시판 API를 만들면서 controller, service, repository, domain 같은 패키지를 하나씩 채워 갈 것입니다. 프로젝트 구조를 알고 나면 새 코드를 어디에 작성해야 할지 덜 헷갈립니다.

참고

1Spring Boot Properties and Configuration

책 목록

초보자를 위한 자바 스프링 사용법

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기