Theme:

코드를 한 줄 수정할 때마다 서버를 수동으로 재시작하고 있다면, 개발 시간의 상당 부분을 낭비하고 있는 것은 아닐까요?

Spring Boot DevTools란

DevTools는 Spring Boot 개발 생산성을 높이는 도구 모음입니다. 코드 변경 시 자동 재시작, 브라우저 자동 새로고침, 개발에 적합한 기본 설정을 제공합니다.

의존성 추가

JAVA
// build.gradle
dependencies {
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
}

developmentOnly로 선언하면 배포용 JAR에 포함되지 않습니다. 운영 환경에서 DevTools가 동작할 걱정은 없습니다.

자동 재시작 (Automatic Restart)

동작 원리

DevTools는 두 개의 ClassLoader를 사용합니다.

PLAINTEXT
Base ClassLoader     — 라이브러리 클래스 (변경 없음, 유지)
Restart ClassLoader  — 애플리케이션 클래스 (변경 시 교체)

파일이 변경되면 Restart ClassLoader만 새로 만들어서 애플리케이션 클래스를 다시 로드합니다. JVM을 재시작하지 않으므로 일반 재시작보다 훨씬 빠릅니다.

트리거 조건

IDE에서 빌드/컴파일이 수행되면 클래스 파일이 변경되어 재시작이 트리거됩니다.

  • IntelliJ IDEA: Build → Build Project (Ctrl+F9) 또는 자동 빌드 설정
  • Eclipse/STS: 저장 시 자동 빌드 (기본 동작)

IntelliJ에서 자동 빌드를 활성화하려면:

PLAINTEXT
Settings → Build, Execution, Deployment → Compiler
→ "Build project automatically" 체크

Settings → Advanced Settings
→ "Allow auto-make to start even if developed application is currently running" 체크

재시작 제외 설정

정적 리소스 변경에는 재시작이 필요 없습니다.

YAML
spring:
  devtools:
    restart:
      enabled: true
      # 재시작 트리거에서 제외할 경로
      exclude: static/**,public/**,templates/**
      # 추가 감시 경로 (클래스패스 외부)
      additional-paths: src/main/resources
      # 재시작 간 최소 대기 시간 (밀리초)
      poll-interval: 1000
      quiet-period: 400

재시작 완전 비활성화

YAML
spring:
  devtools:
    restart:
      enabled: false

또는 시스템 프로퍼티로:

JAVA
public static void main(String[] args) {
    System.setProperty(
        "spring.devtools.restart.enabled", "false");
    SpringApplication.run(MyApp.class, args);
}

라이브 리로드 (Live Reload)

DevTools는 내장 LiveReload 서버(포트 35729)를 실행합니다. 브라우저에 LiveReload 확장 프로그램을 설치하면 서버 재시작 또는 리소스 변경 시 자동으로 브라우저가 새로고침됩니다.

YAML
spring:
  devtools:
    livereload:
      enabled: true    # 기본: true
      port: 35729      # LiveReload 서버 포트

정적 리소스(HTML, CSS, JS) 변경은 서버 재시작 없이 LiveReload만 트리거됩니다.

개발용 기본 설정

DevTools가 클래스패스에 있으면 개발에 적합하도록 여러 속성이 자동 변경됩니다.

속성기본값DevTools 적용값이유
spring.thymeleaf.cachetruefalse템플릿 변경 즉시 반영
spring.freemarker.cachetruefalse템플릿 변경 즉시 반영
spring.web.resources.cache.period-0정적 리소스 캐시 비활성화
server.error.include-stacktraceneveralways에러 상세 정보
spring.h2.console.enabledfalsetrueH2 Console 활성화

H2 Console

인메모리 DB를 웹 브라우저에서 직접 조회할 수 있는 도구입니다.

YAML
spring:
  h2:
    console:
      enabled: true
      path: /h2-console     # 접속 경로
      settings:
        web-allow-others: false  # 로컬만 접근
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver

http://localhost:8080/h2-console로 접속하여 SQL을 직접 실행하고 데이터를 확인할 수 있습니다.

Spring Security와 함께 사용

JAVA
@Configuration
@Profile("local")
public class LocalSecurityConfig {

    @Bean
    public SecurityFilterChain localFilterChain(HttpSecurity http)
            throws Exception {
        return http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/h2-console/**").permitAll()
                .anyRequest().authenticated()
            )
            .csrf(csrf -> csrf
                .ignoringRequestMatchers("/h2-console/**"))
            .headers(headers -> headers
                .frameOptions(frame -> frame.sameOrigin()))  // iframe 허용
            .build();
    }
}

원격 디버깅

실행 중인 애플리케이션에 디버거를 연결하여 코드를 단계별로 실행할 수 있습니다.

JVM 디버그 옵션

BASH
# Java 9+
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 \
  -jar myapp.jar

Spring Boot Gradle 플러그인

BASH
./gradlew bootRun --debug-jvm
# 또는
./gradlew bootRun -Dagentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005

IntelliJ 원격 디버거 설정

PLAINTEXT
Run → Edit Configurations → + → Remote JVM Debug
Host: localhost
Port: 5005

개발 프로파일 활용

YAML
# application-local.yml — 개발 전용 설정
spring:
  datasource:
    url: jdbc:h2:mem:testdb
  jpa:
    show-sql: true
    properties:
      hibernate:
        format_sql: true
    hibernate:
      ddl-auto: create-drop

logging:
  level:
    org.hibernate.SQL: DEBUG
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
    com.example: DEBUG
BASH
# 로컬 프로파일로 실행
SPRING_PROFILES_ACTIVE=local ./gradlew bootRun

Actuator 개발 활용

YAML
# application-local.yml
management:
  endpoints:
    web:
      exposure:
        include: "*"    # 모든 엔드포인트 노출 (개발 전용!)
  endpoint:
    health:
      show-details: always

유용한 엔드포인트:

  • /actuator/beans — 등록된 모든 빈 목록
  • /actuator/mappings — 모든 URL 매핑
  • /actuator/env — 환경 설정 값
  • /actuator/configprops — @ConfigurationProperties 값
  • /actuator/loggers — 런타임 로그 레벨 변경

개발 워크플로 최적화 팁

1. Gradle 연속 빌드

BASH
# 파일 변경 감지 시 자동 빌드
./gradlew build --continuous

2. 테스트 자동 실행

BASH
# 파일 변경 시 관련 테스트 자동 실행
./gradlew test --continuous

3. 프론트엔드 프록시

REST API 개발 시 프론트엔드 개발 서버와 연동:

YAML
# Spring Boot는 8080, React는 3000에서 실행
# React의 package.json
# "proxy": "http://localhost:8080"

4. Docker Compose 연동

YAML
# Spring Boot 3.1+ — Docker Compose 자동 관리
spring:
  docker:
    compose:
      enabled: true
      file: docker-compose-dev.yml
      lifecycle-management: start-and-stop
YAML
# docker-compose-dev.yml
services:
  mysql:
    image: mysql:8.0
    ports: ["3306:3306"]
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mydb
  redis:
    image: redis:7
    ports: ["6379:6379"]

Spring Boot가 시작될 때 Docker Compose를 자동으로 실행하고, 종료될 때 컨테이너를 정리합니다.

정리

  • DevTools는 개발 생산성을 크게 높여줍니다. developmentOnly로 추가하면 배포에 영향을 주지 않습니다.
  • 자동 재시작은 두 개의 ClassLoader로 빠르게 동작합니다. IDE의 자동 빌드 설정을 확인하세요.
  • LiveReload로 브라우저 수동 새로고침을 없앨 수 있습니다.
  • H2 Console은 인메모리 DB를 직접 조회하는 데 유용합니다. Security와 함께 사용할 때 설정에 주의하세요.
  • 개발 프로파일(local)을 활용하여 SQL 로깅, Actuator 노출, Docker Compose 연동 등을 설정하세요.
  • Spring Boot 3.1+의 Docker Compose 지원으로 개발 인프라 관리가 간편해졌습니다.
댓글 로딩 중...