본문 바로가기
Spring & Spring Boot 실무 가이드

ddl-auto 옵션 종류 & 실무주의: 운영DB 테이블 날리는 사고 막기(JPA)

by devcomet 2025. 9. 19.
728x90
반응형

Spring JPA ddl-auto options guide for production database safety and best practices
ddl-auto 옵션 종류 & 실무주의: 운영DB 테이블 날리는 사고 막기(JPA)

 

JPA의 spring.jpa.hibernate.ddl-auto 설정은 개발부터 운영까지 데이터베이스 스키마 관리의 핵심이지만, 잘못된 설정으로 인해 운영 데이터베이스 테이블을 삭제하는 심각한 사고를 일으킬 수 있는 위험한 옵션입니다.


ddl-auto 옵션이란?

ddl-auto 옵션이란? 섹션 이미지 데이터베이스가 이어져 있는 이미지

 

Spring Boot와 JPA를 사용할 때 spring.jpa.hibernate.ddl-auto 속성은 Hibernate가 데이터베이스 스키마를 어떻게 처리할지 결정하는 중요한 설정입니다.

이 설정은 애플리케이션 실행 시 Entity 클래스를 기반으로 데이터베이스 테이블을 자동으로 생성, 수정, 삭제할 수 있는 강력한 기능을 제공합니다.

ddl-auto의 표준 Hibernate 속성값은 create, update, create-drop, validate, none입니다.


ddl-auto 옵션 종류 완벽 분석

ddl-auto 옵션 종류 완벽 분석 총 정리 이미지

 

none: 운영환경의 필수 기본값

none 옵션은 DDL 생성을 완전히 비활성화합니다.

 

동작 방식

  • 데이터베이스 스키마에 대한 어떤 변경도 수행하지 않음
  • Entity 클래스가 변경되어도 데이터베이스에 영향을 주지 않음
  • 스키마 검증도 수행하지 않음

사용 시기

  • 운영 프로덕션 환경에서 반드시 사용
  • 데이터베이스 스키마가 별도로 관리되는 환경
  • Flyway 또는 Liquibase와 같은 마이그레이션 도구를 사용하는 경우

validate: 운영환경 ddl-auto 설정 권장사항

validate 옵션은 Entity 매핑과 데이터베이스 스키마 간의 일치성을 검증합니다.

 

동작 방식

  • 스키마 변경 없이 검증만 수행
  • Entity 클래스와 데이터베이스 스키마가 일치하지 않으면 예외 발생
  • 애플리케이션 시작 시점에 스키마 검증 실행

validate 설정 방법

spring.jpa.hibernate.ddl-auto=validate

 

주의사항

  • validate는 애플리케이션 시작 프로세스에서 병목이 될 수 있으며, 특히 객체 모델이 광범위하거나 네트워크 관련 요인이 있을 때 더욱 그렇습니다
  • 대규모 애플리케이션에서는 시작 시간이 증가할 수 있음

update: 개발환경 update 옵션 제한

update 옵션은 Entity 변경사항을 기반으로 스키마를 자동 업데이트합니다.

 

동작 방식

  • 기존 테이블은 유지하면서 새로운 컬럼이나 테이블 추가
  • 기존 테이블이나 컬럼은 삭제하지 않음
  • 데이터 손실 위험이 상대적으로 낮음

제한사항

  • update를 사용할 때, Hibernate는 컬럼 이름 변경이나 삭제 작업을 자동으로 처리하지 않습니다
  • 복잡한 스키마 변경에 대한 완전한 처리 불가
  • NotNull 컬럼 추가 시 기존 데이터에 대한 문제 발생 가능

create: create 옵션 삭제 위험성

create 옵션은 애플리케이션 시작 시마다 전체 스키마를 재생성합니다.

 

동작 방식

  • 기존 테이블 전체 삭제 (DROP TABLE)
  • Entity 기반으로 새 테이블 생성
  • 모든 기존 데이터가 완전히 삭제됨

위험성

  • 운영환경에서 절대 사용 금지
  • 실수로 운영에 적용 시 전체 데이터 손실
  • 되돌릴 수 없는 치명적인 결과 초래

create-drop: create-drop 위험성과 테스트 환경 활용

create-drop 옵션은 가장 위험한 설정 중 하나입니다.

 

동작 방식

  • 애플리케이션 시작 시: 기존 스키마 삭제 후 재생성
  • 애플리케이션 종료 시: 전체 스키마 삭제
  • create-drop과 유사하게 create하지만, Hibernate가 모든 작업이 완료된 후 데이터베이스를 삭제합니다

적절한 사용 사례

  • 통합 테스트 환경
  • 매번 깨끗한 데이터베이스가 필요한 테스트 시나리오
  • create-drop은 통합 테스트에 편리한 옵션으로 각 테스트 실행 전에 스키마를 재생성합니다

환경별 ddl-auto 설정 가이드

개발 환경 (Development)

# 개발환경 권장 설정
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.format-sql=true

 

권장 이유

  • 스키마 변경 시 데이터 보존
  • 개발 중 생성된 테스트 데이터 유지
  • 빠른 개발 사이클 지원

 

테스트 환경 (Test)

# 테스트환경 권장 설정
spring.jpa.hibernate.ddl-auto=create-drop
spring.sql.init.mode=embedded

 

권장 이유

  • 각 테스트마다 깨끗한 데이터베이스 상태
  • 테스트 간 데이터 간섭 방지
  • 일관된 테스트 결과 보장

운영 환경 (Production)

# 운영환경 필수 설정
spring.jpa.hibernate.ddl-auto=none
# 또는
spring.jpa.hibernate.ddl-auto=validate

 

설정 이유

  • 프로덕션에서는 none을 사용하거나 이 속성을 지정하지 않는 것이 강력히 권장됩니다. 이는 데이터베이스 변경, 특히 데이터베이스가 여러 서비스와 애플리케이션에서 공유되는 경우 DBA가 마이그레이션 스크립트를 검토하는 것이 일반적인 관행이기 때문입니다
  • 예기치 않은 스키마 변경 방지
  • 데이터 안전성 보장

프로파일 별 설정 Best Practice

Spring Boot의 프로파일을 활용하여 환경별로 적절한 ddl-auto 설정을 관리하세요.

application.yml 설정 예시

spring:
  profiles:
    active: dev

---
spring:
  profiles: dev
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

---
spring:
  profiles: test  
  jpa:
    hibernate:
      ddl-auto: create-drop

---
spring:
  profiles: prod
  jpa:
    hibernate:
      ddl-auto: none

환경 변수를 통한 안전한 설정

# 운영환경에서는 환경 변수로 명시적 설정
export SPRING_JPA_HIBERNATE_DDL_AUTO=none

운영환경에서 발생할 수 있는 치명적인 사고 사례

사고 시나리오 1: create 옵션 실수 배포

상황

  • 개발자가 로컬 개발 시 create 옵션 사용
  • 설정 변경 없이 운영 환경에 배포
  • 애플리케이션 재시작과 동시에 전체 테이블 삭제

결과

  • 모든 운영 데이터 손실
  • 서비스 중단
  • 백업에서 복구까지 장시간 소요

사고 시나리오 2: create-drop 설정으로 인한 데이터 삭제

상황

  • 테스트용 create-drop 설정이 운영에 적용
  • 애플리케이션 정상 종료 시 전체 스키마 삭제
  • 서버 재시작이나 배포 과정에서 데이터 완전 소실

결과

  • 복구 불가능한 데이터 손실
  • 비즈니스 연속성 파괴

DB 스키마 관리 모범 사례

DB 스키마 관리 모범 사례 - db 마이그레이션을 하는 모니터 화면

1. 마이그레이션 도구 활용

<!-- Flyway 의존성 추가 -->
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
</dependency>

 

Flyway 스크립트 예시

-- V1__Create_user_table.sql
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(100) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Flyway 공식 문서에서 상세한 사용법을 확인할 수 있습니다.

2. 스키마 버전 관리

Git을 활용한 스키마 관리

  • 모든 마이그레이션 스크립트를 버전 관리
  • 코드 변경과 스키마 변경을 함께 추적
  • 롤백 가능한 스크립트 작성

3. 환경별 배포 검증

배포 전 검증 단계

  1. 개발 환경에서 스키마 변경 테스트
  2. 스테이징 환경에서 운영 데이터 복사본으로 검증
  3. 운영 환경 배포 전 백업 수행

ddl-auto와 Spring Boot 기본값 이해

ddl-auto와 Spring Boot 기본값 이해 - 위험성 정리 이미지

 

Spring Boot는 데이터베이스가 임베디드인지 여부에 따라 기본값을 선택합니다.

임베디드 데이터베이스의 경우 기본값은 create-drop이고, 그렇지 않은 경우 none입니다.

임베디드 데이터베이스 감지 기준

임베디드로 인식되는 데이터베이스

  • H2
  • HSQLDB
  • Derby

외부 데이터베이스

  • MySQL
  • PostgreSQL
  • Oracle
  • SQL Server

기본값의 위험성

메모리 내 데이터베이스에서 "실제" 데이터베이스로 전환할 때 새로운 플랫폼에서 테이블과 데이터의 존재에 대한 가정을 하지 않도록 주의하세요.

개발 단계에서 H2를 사용하다가 운영에서 MySQL로 변경할 때 특히 주의가 필요합니다.


NotNull 컬럼 추가 시 문제점과 해결책

문제 상황

기존 테이블에 NotNull 컬럼을 추가할 때 update 옵션으로는 한계가 있습니다.

@Entity
public class User {
    @Id
    private Long id;

    private String username;

    // 새로 추가된 NotNull 컬럼
    @Column(nullable = false)
    private String email;  // 기존 데이터에는 null 값
}

 

해결 방법

1단계: 기본값과 함께 컬럼 추가

-- V2__Add_email_column.sql
ALTER TABLE users 
ADD COLUMN email VARCHAR(100) DEFAULT 'temp@example.com';

 

2단계: 실제 데이터로 업데이트

-- V3__Update_email_values.sql
UPDATE users 
SET email = CONCAT(username, '@company.com')
WHERE email = 'temp@example.com';

 

3단계: NotNull 제약조건 추가

-- V4__Make_email_not_null.sql
ALTER TABLE users 
MODIFY COLUMN email VARCHAR(100) NOT NULL;

모니터링과 알림 시스템 구축

DDL 실행 감지

@Component
public class SchemaChangeMonitor {

    @EventListener
    public void onSchemaUpdate(SchemaUpdateEvent event) {
        if (isProductionEnvironment()) {
            alertService.sendCriticalAlert(
                "Production DDL execution detected!", 
                event.getDetails()
            );
        }
    }

    private boolean isProductionEnvironment() {
        return Arrays.asList(environment.getActiveProfiles())
                    .contains("prod");
    }
}

설정 검증 자동화

@Component
public class ConfigurationValidator implements ApplicationRunner {

    @Value("${spring.jpa.hibernate.ddl-auto}")
    private String ddlAuto;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        if (isProdProfile() && isUnsafeDdlAuto()) {
            throw new IllegalStateException(
                "Unsafe ddl-auto setting in production: " + ddlAuto
            );
        }
    }

    private boolean isUnsafeDdlAuto() {
        return Arrays.asList("create", "create-drop", "update")
                    .contains(ddlAuto);
    }
}

성능 최적화 고려사항

validate 옵션 성능 영향

validate는 애플리케이션 시작 프로세스 중에 병목이 될 수 있으며,

특히 객체 모델이 상당히 광범위하거나 다른 네트워크 관련 요인이 작용할 때 더욱 그렇습니다.

 

대용량 애플리케이션에서의 해결책

  • 스키마 검증을 별도 프로세스로 분리
  • CI/CD 파이프라인에서 검증 수행
  • 운영환경에서는 none 옵션 사용

시작 시간 최적화

# 불필요한 검증 비활성화
spring.jpa.hibernate.ddl-auto=none
spring.jpa.defer-datasource-initialization=false

실무 체크리스트

배포 전 필수 확인사항

✅ 환경별 설정 검증

  • 개발: update 또는 create-drop
  • 테스트: create-drop
  • 운영: none 또는 validate

✅ 코드 리뷰 체크포인트

  • application.properties/yml에서 ddl-auto 설정 확인
  • 프로파일별 설정 분리 여부
  • 환경 변수 사용 여부

✅ 운영 배포 안전장치

  • 데이터베이스 백업 수행
  • 마이그레이션 스크립트 검증
  • 롤백 계획 수립

CI/CD 파이프라인 통합

# .github/workflows/deploy.yml
- name: Validate Production Config
  run: |
    if grep -q "ddl-auto.*\(create\|update\|create-drop\)" application-prod.yml; then
      echo "Unsafe ddl-auto setting detected for production!"
      exit 1
    fi

마이그레이션 도구와의 통합 전략

Flyway와 JPA 함께 사용하기

# 마이그레이션 도구와 함께 사용할 때
spring.jpa.hibernate.ddl-auto=validate
spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration

 

장점

  • Flyway와 같은 전용 마이그레이션 도구는 더 나은 제어, 버전 관리 및 롤백 기능을 제공합니다
  • 스키마 변경 이력 추적 가능
  • 팀 간 스키마 동기화 용이

 

Liquibase 활용

<!-- Liquibase 의존성 -->
<dependency>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-core</artifactId>
</dependency>
# changelog 설정
spring:
  liquibase:
    change-log: classpath:db/changelog/db.changelog-master.yaml

Spring Boot의 Liquibase 가이드에서 상세한 설정 방법을 확인할 수 있습니다.


문제 해결 가이드

자주 발생하는 오류와 해결책

1. 스키마 불일치 오류

Schema validation: wrong column type encountered in column [email] in table [users]

 

해결책

// Entity 정의와 실제 DB 스키마 일치 확인
@Column(columnDefinition = "VARCHAR(255)")
private String email;

 

2. 테이블 생성 실패

Table 'database.users' doesn't exist

 

해결책

  • ddl-auto 설정 확인
  • 마이그레이션 스크립트 실행 상태 점검
  • 데이터베이스 연결 권한 확인

응급 복구 절차

운영 데이터 손실 시

  1. 즉시 애플리케이션 중단
  2. 최근 백업 파일 확인
  3. 데이터베이스 복원 실행
  4. 설정 수정 후 재배포

결론

ddl-auto 옵션 관련 가이드 글 마무리 섹션 이미지

 

ddl-auto 옵션은 JPA 개발의 편의성을 제공하지만, 잘못 사용하면 치명적인 결과를 초래할 수 있습니다.

 

핵심 원칙

  • 운영환경에서는 반드시 none 사용
  • 환경별 설정 분리 필수
  • 마이그레이션 도구 활용 권장
  • 배포 전 철저한 검증 수행

적절한 계획과 올바른 도구를 사용하면 애플리케이션의 성장을 지원하는 유연하고 발전하는 데이터베이스 스키마를 유지할 수 있습니다.

안전한 데이터베이스 스키마 관리를 통해 안정적인 서비스 운영을 보장하시기 바랍니다.


추가 참고 자료


같이 보면 좋은 글

 

Java split() 함수 사용법 완전정복 - regex, limit, 빈 문자열 처리까지

Java에서 문자열을 분할하는 가장 기본적이면서도 강력한 메서드인 split() 함수는 정규식을 활용해 다양한 패턴으로 문자열을 나눌 수 있습니다.이 글에서는 Java split 함수의 모든 기능을 상세히

notavoid.tistory.com

 

Comparable vs Comparator 한방에 끝내기 - 자바 정렬·비교 원리와 실무 패턴 총정리

자바에서 Comparable과 Comparator 인터페이스는 객체 정렬의 핵심으로, 자연 정렬과 커스텀 정렬 로직을 구현하여 Collections.sort()와 Arrays.sort() 메서드를 통해 효율적인 데이터 정렬을 가능하게 하는

notavoid.tistory.com

 

Spring Batch란? 개념부터 메타테이블, 코드 예제로 끝내는 입문 가이드

Spring Batch 개념부터 Job/Step 구조, 메타테이블, Tasklet/Chunk 방식까지 완벽 정리. 대용량 데이터 처리를 위한 실무 예제와 성능 최적화 팁을 제공합니다.Spring Batch란 무엇인가 Spring Batch는 Spring Framewor

notavoid.tistory.com

 

리다이렉트란? HTTP 301, 302, 307 코드 차이와 올바른 사용법

HTTP 리다이렉트는 웹사이트 운영에서 페이지 이동과 SEO 최적화를 위한 핵심 기술로, 301/302/307/308 상태 코드별 특성을 이해하고 올바르게 활용하면 검색엔진 순위와 사용자 경험을 크게 개선할

notavoid.tistory.com

 

Scanner 클래스 한방 정리 - next() vs nextLine() 차이, 입력패턴, 실수 방지 팁

Java Scanner 클래스는 System.in을 통한 사용자 입력 처리에 필수적인 도구로, next()와 nextLine()의 차이점을 정확히 이해하고 공백 구분자 처리 방법을 숙지하면 입력 관련 오류를 크게 줄일 수 있습니

notavoid.tistory.com

728x90
반응형