hobokai 님의 블로그

Spring Boot 완전 가이드 Part 1: 기초편 - 시작하기 본문

Backend

Spring Boot 완전 가이드 Part 1: 기초편 - 시작하기

hobokai 2025. 8. 6. 10:25

 

시리즈 소개: 실무에서 바로 써먹는 Spring Boot 완전 가이드

Part 1: Spring Boot 기초 - 시작하기 ← 현재
Part 2: 설정과 자동구성
Part 3: 웹 개발과 REST API
Part 4: 데이터 액세스와 배치
Part 5: 운영과 모니터링

 


🚀 Spring Boot란 무엇인가?

Spring Boot의 등장 배경

전통적인 Spring Framework는 강력하지만 복잡한 설정이 필요했습니다:

<!-- 전통적인 Spring XML 설정 (과거) -->
<beans xmlns="http://www.springframework.org/schema/beans">
    <context:component-scan base-package="com.example" />
    <mvc:annotation-driven />
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
        <!-- 수십 줄의 설정... -->
    </bean>
</beans>

Spring Boot의 철학:

"Convention over Configuration"
설정보다는 관례! 90%의 일반적인 설정은 자동으로 처리

Spring Boot vs 전통적인 Spring

구분전통적인 SpringSpring Boot

프로젝트 설정 XML + Java Config 거의 자동화
의존성 관리 수동으로 호환성 확인 스타터로 자동 관리
서버 설정 외부 톰캣 설치/설정 내장 서버 (톰캣, 젠킨스 등)
배포 WAR 파일 + 서버 배포 JAR 파일 단독 실행
개발 시간 초기 설정 2-3일 5분 만에 시작

🛠️ Spring Boot 프로젝트 생성하기

방법 1: Spring Initializr 웹사이트 (추천)

  1. https://start.spring.io 접속
  2. 프로젝트 정보 입력:
  3. Project: Maven (또는 Gradle) Language: Java Spring Boot: 3.2.x (최신 안정 버전) Project Metadata: Group: com.example Artifact: spring-boot-demo Name: spring-boot-demo Package name: com.example.demo Packaging: Jar Java: 17 (또는 21)
  4. Dependencies 선택:
    • Spring Web: REST API 개발
    • Spring Data JPA: 데이터베이스 연동
    • H2 Database: 테스트용 인메모리 DB
    • Spring Boot DevTools: 개발 편의 도구

방법 2: IDE에서 직접 생성

IntelliJ IDEA:

File → New → Project → Spring Initializr

VS Code:

Ctrl+Shift+P → Spring Initializr: Generate a Maven Project

방법 3: Spring CLI 사용

# Spring CLI 설치 후
spring init --dependencies=web,data-jpa,h2,devtools spring-boot-demo
cd spring-boot-demo

📁 Spring Boot 프로젝트 구조 이해하기

표준 디렉토리 구조

spring-boot-demo/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/demo/
│   │   │       ├── DemoApplication.java        ← 메인 클래스
│   │   │       ├── controller/                 ← 컨트롤러
│   │   │       ├── service/                    ← 서비스 레이어
│   │   │       ├── repository/                 ← 데이터 액세스
│   │   │       └── model/                      ← 엔터티/DTO
│   │   └── resources/
│   │       ├── application.properties          ← 설정 파일
│   │       ├── static/                         ← 정적 파일 (CSS, JS)
│   │       └── templates/                      ← 템플릿 (Thymeleaf 등)
│   └── test/
│       └── java/
│           └── com/example/demo/
│               └── DemoApplicationTests.java   ← 테스트 클래스
├── target/                                     ← 빌드 결과물
├── pom.xml                                     ← Maven 설정
└── README.md

핵심 파일 분석

1. 메인 클래스 (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);
    }
}

@SpringBootApplication 분해:

// 실제로는 이 3개 어노테이션의 조합
@SpringBootConfiguration  // → @Configuration과 동일
@EnableAutoConfiguration  // → 자동 설정 활성화
@ComponentScan           // → 컴포넌트 스캔
public class DemoApplication { ... }

2. Maven 설정 (pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    
    <!-- Spring Boot 부모 POM: 의존성 버전 관리 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/>
    </parent>
    
    <groupId>com.example</groupId>
    <artifactId>spring-boot-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-demo</name>
    
    <properties>
        <java.version>17</java.version>
    </properties>
    
    <dependencies>
        <!-- Spring Boot 스타터들 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- 버전 명시 불필요! 부모 POM에서 관리 -->
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        
        <!-- 개발 도구 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        
        <!-- 테스트 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <!-- Spring Boot Maven 플러그인 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

📦 의존성 관리와 스타터

Spring Boot Starter란?

스타터(Starter)는 특정 기능에 필요한 의존성을 묶어놓은 패키지입니다:

// spring-boot-starter-web에 포함된 주요 의존성들
├── spring-web
├── spring-webmvc  
├── spring-boot-starter-tomcat (내장 톰캣)
├── spring-boot-starter-json (Jackson)
└── hibernate-validator

자주 사용하는 스타터들

스타터용도포함 라이브러리

spring-boot-starter-web 웹 애플리케이션 Spring MVC, 내장 톰캣, Jackson
spring-boot-starter-data-jpa JPA/Hibernate Spring Data JPA, Hibernate
spring-boot-starter-security 보안 Spring Security
spring-boot-starter-test 테스트 JUnit, Mockito, Spring Test
spring-boot-starter-data-redis Redis Spring Data Redis, Lettuce
spring-boot-starter-validation 검증 Hibernate Validator
spring-boot-starter-actuator 모니터링 Actuator 엔드포인트

커스텀 의존성 추가하기

스타터로 제공되지 않는 라이브러리는 직접 추가:

<dependencies>
    <!-- Spring Boot 스타터 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- 커스텀 의존성 (버전 명시) -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.12.0</version>
    </dependency>
    
    <!-- 스프링 부트에서 버전 관리하는 라이브러리 (버전 생략 가능) -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
</dependencies>

▶️ 첫 번째 Spring Boot 애플리케이션

Hello World 컨트롤러 만들기

// src/main/java/com/example/demo/controller/HelloController.java
package com.example.demo.controller;

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

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@RestController  // @Controller + @ResponseBody
public class HelloController {
    
    // 가장 간단한 엔드포인트
    @GetMapping("/hello")
    public String hello() {
        return "Hello, Spring Boot!";
    }
    
    // 요청 파라미터 받기
    @GetMapping("/hello/param")
    public String helloWithParam(@RequestParam(defaultValue = "World") String name) {
        return String.format("Hello, %s!", name);
    }
    
    // 패스 변수 사용
    @GetMapping("/hello/{name}")
    public String helloWithPath(@PathVariable String name) {
        return String.format("Hello, %s from path!", name);
    }
    
    // JSON 응답 반환
    @GetMapping("/api/status")
    public Map<String, Object> getStatus() {
        Map<String, Object> status = new HashMap<>();
        status.put("status", "UP");
        status.put("timestamp", LocalDateTime.now());
        status.put("message", "Spring Boot is running!");
        return status;
    }
}

애플리케이션 실행하기

방법 1: IDE에서 실행

  • DemoApplication.java 우클릭 → Run

방법 2: Maven 명령어

# 개발 모드로 실행
mvn spring-boot:run

# 또는 빌드 후 JAR 실행
mvn clean package
java -jar target/spring-boot-demo-0.0.1-SNAPSHOT.jar

방법 3: Gradle 명령어

./gradlew bootRun

결과 확인하기

브라우저에서 다음 URL들을 테스트해보세요:

# 기본 헬로우
http://localhost:8080/hello
→ "Hello, Spring Boot!"

# 파라미터 사용
http://localhost:8080/hello/param?name=Developer
→ "Hello, Developer!"

# 패스 변수 사용  
http://localhost:8080/hello/John
→ "Hello, John from path!"

# JSON API
http://localhost:8080/api/status
→ {"status":"UP","timestamp":"2024-01-15T10:30:00","message":"Spring Boot is running!"}

⚙️ 기본 설정과 프로파일

application.properties 설정

# 서버 포트 변경
server.port=8090

# 컨텍스트 패스 설정
server.servlet.context-path=/api

# 로깅 레벨 설정
logging.level.com.example.demo=DEBUG
logging.level.org.springframework=INFO

# 데이터베이스 설정 (H2 인메모리)
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=

# JPA 설정
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop

# H2 콘솔 활성화 (개발용)
spring.h2.console.enabled=true

YAML 형식 사용 (application.yml)

server:
  port: 8090
  servlet:
    context-path: /api

logging:
  level:
    com.example.demo: DEBUG
    org.springframework: INFO

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    username: sa
    password: 
    
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: create-drop
      
  h2:
    console:
      enabled: true

프로파일 (Profiles) 활용

환경별로 다른 설정을 사용하려면 프로파일을 활용하세요:

application-dev.yml (개발환경)

server:
  port: 8080

logging:
  level:
    com.example.demo: DEBUG
    
spring:
  jpa:
    show-sql: true
  h2:
    console:
      enabled: true

application-prod.yml (운영환경)

server:
  port: 80

logging:
  level:
    com.example.demo: WARN
    
spring:
  datasource:
    url: jdbc:mysql://prod-server:3306/myapp
    username: ${DB_USERNAME:app_user}
    password: ${DB_PASSWORD:}
    
  jpa:
    show-sql: false
    hibernate:
      ddl-auto: validate

프로파일 활성화

# 개발 환경으로 실행
java -jar app.jar --spring.profiles.active=dev

# 운영 환경으로 실행  
java -jar app.jar --spring.profiles.active=prod

# IDE에서 설정
-Dspring.profiles.active=dev

🔧 Spring Boot DevTools 활용

DevTools 기능들

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

주요 기능:

  • 자동 재시작: 클래스패스 변경 시 애플리케이션 자동 재시작
  • LiveReload: 브라우저 자동 새로고침
  • 프로퍼티 기본값: 개발에 편리한 기본 설정
  • H2 콘솔 자동 활성화

자동 재시작 최적화

# devtools 설정
spring.devtools.restart.enabled=true
spring.devtools.restart.additional-paths=src/main/resources
spring.devtools.restart.exclude=static/**,public/**

# LiveReload 설정
spring.devtools.livereload.enabled=true
spring.devtools.livereload.port=35729

🧪 간단한 테스트 작성

컨트롤러 테스트

// src/test/java/com/example/demo/controller/HelloControllerTest.java
package com.example.demo.controller;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest(HelloController.class)  // 웹 레이어만 테스트
class HelloControllerTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    void hello_ShouldReturnHelloMessage() throws Exception {
        mockMvc.perform(get("/hello"))
                .andExpect(status().isOk())
                .andExpect(content().string("Hello, Spring Boot!"));
    }
    
    @Test
    void helloWithParam_ShouldReturnCustomMessage() throws Exception {
        mockMvc.perform(get("/hello/param").param("name", "Developer"))
                .andExpect(status().isOk())
                .andExpect(content().string("Hello, Developer!"));
    }
    
    @Test
    void getStatus_ShouldReturnJsonStatus() throws Exception {
        mockMvc.perform(get("/api/status"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.status").value("UP"))
                .andExpect(jsonPath("$.message").exists());
    }
}

통합 테스트

// src/test/java/com/example/demo/DemoApplicationTests.java
package com.example.demo;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.beans.factory.annotation.Autowired;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class DemoApplicationTests {
    
    @LocalServerPort
    private int port;
    
    @Autowired
    private TestRestTemplate restTemplate;
    
    @Test
    void contextLoads() {
        // Spring Context가 정상적으로 로드되는지 테스트
    }
    
    @Test
    void hello_ShouldWork() {
        String response = restTemplate.getForObject(
            "http://localhost:" + port + "/hello", 
            String.class
        );
        assertThat(response).isEqualTo("Hello, Spring Boot!");
    }
}

📦 빌드와 배포

Maven으로 빌드하기

# 컴파일 + 테스트
mvn clean compile

# 테스트 실행
mvn test

# 패키징 (JAR 파일 생성)
mvn clean package

# 테스트 스킵하고 빌드
mvn clean package -DskipTests

# 로컬 저장소에 설치
mvn install

실행 가능한 JAR

Spring Boot는 "Fat JAR" (또는 "Uber JAR")를 생성합니다:

# 생성된 JAR 파일 구조
spring-boot-demo-0.0.1-SNAPSHOT.jar
├── BOOT-INF/
│   ├── classes/           ← 애플리케이션 클래스
│   ├── lib/              ← 의존성 라이브러리들
│   └── classpath.idx
├── META-INF/
│   └── MANIFEST.MF       ← 메인 클래스 정보
└── org/
    └── springframework/
        └── boot/
            └── loader/    ← Spring Boot 로더

실행:

# Java 17+ 환경에서
java -jar target/spring-boot-demo-0.0.1-SNAPSHOT.jar

# JVM 옵션 추가
java -Xms512m -Xmx1024m -jar target/spring-boot-demo-0.0.1-SNAPSHOT.jar

# 프로파일 지정
java -jar target/spring-boot-demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

Docker 컨테이너화

# Dockerfile
FROM openjdk:17-jdk-slim

# 작업 디렉토리
WORKDIR /app

# JAR 파일 복사
COPY target/spring-boot-demo-0.0.1-SNAPSHOT.jar app.jar

# 포트 노출
EXPOSE 8080

# 애플리케이션 실행
ENTRYPOINT ["java", "-jar", "app.jar"]
# Docker 이미지 빌드
docker build -t spring-boot-demo .

# 컨테이너 실행
docker run -p 8080:8080 spring-boot-demo

🎯 Part 1 정리

핵심 포인트 요약

  1. Spring Boot의 핵심 철학:
    • Convention over Configuration
    • 자동 설정으로 빠른 개발 시작
    • 내장 서버로 간편한 배포
  2. 프로젝트 구성 요소:
    • @SpringBootApplication 메인 클래스
    • Spring Boot Starter 의존성 관리
    • application.properties/yml 설정 파일
  3. 개발 편의 기능:
    • DevTools 자동 재시작
    • Profile별 환경 설정
    • 내장된 테스트 지원
  4. 빌드와 배포:
    • 실행 가능한 JAR 파일
    • Docker 컨테이너화 지원

실습 체크리스트

  •  Spring Initializr로 프로젝트 생성
  •  Hello World 컨트롤러 작성
  •  application.yml 설정 변경
  •  개발/운영 프로파일 분리
  •  단위 테스트 및 통합 테스트 작성
  •  Maven으로 빌드 및 실행
  •  Docker 컨테이너로 실행

다음 편 예고

Part 2: 설정과 자동구성에서는:

  • Auto Configuration 원리 깊이 이해하기
  • 커스텀 Configuration 클래스 작성
  • 외부 설정 바인딩과 검증
  • 조건부 빈 등록 실습
  • Configuration Properties 활용

Spring Boot의 마법같은 자동 설정이 어떻게 동작하는지 파헤쳐보겠습니다! 🔮


📚 참고 자료:

🏷️ 태그: #SpringBoot #Java #Backend #웹개발 #실무가이드