개요

CRaC(Coordinated Restore at Checkpoint)는 OpenJDK의 실험적 기능으로, JVM의 실행 상태를 스냅샷으로 저장하고 빠르게 복원하여 애플리케이션 시작 시간을 밀리초 수준으로 단축합니다. Spring Boot 3.5는 CRaC를 공식 지원하며, 서버리스 환경과 Auto-scaling 시나리오에서 콜드 스타트 문제를 해결합니다. 이 문서에서는 CRaC의 원리와 Spring Boot 통합 방법을 다룹니다.

CRaC 작동 원리

CRaC는 애플리케이션을 "워밍업"된 상태로 체크포인트하고, 이후 시작 시 해당 시점부터 복원합니다. 이를 통해 클래스 로딩, 스프링 컨텍스트 초기화, 데이터베이스 연결 등의 시간을 생략할 수 있습니다.

  • Checkpoint: 애플리케이션이 완전히 초기화된 후 메모리 상태를 디스크에 저장
  • Restore: 저장된 스냅샷에서 즉시 복원하여 요청 처리 시작
  • 효과: 10초 → 100ms로 시작 시간 단축 (100배 개선)

CRaC 활성화 환경 구성

CRaC를 사용하려면 특수 빌드된 OpenJDK가 필요합니다.

# CRaC 지원 OpenJDK 다운로드
wget https://github.com/CRaC/openjdk-builds/releases/download/17-crac+5/openjdk-17-crac+5_linux-x64.tar.gz
tar -xzf openjdk-17-crac+5_linux-x64.tar.gz
export JAVA_HOME=$(pwd)/openjdk-17-crac+5

# 애플리케이션 빌드
./mvnw clean package -DskipTests

# Checkpoint 생성 (sudo 필요)
sudo $JAVA_HOME/bin/java -XX:CRaCCheckpointTo=cr \
  -jar target/myapp-0.0.1-SNAPSHOT.jar

# Restore로 빠른 시작
sudo $JAVA_HOME/bin/java -XX:CRaCRestoreFrom=cr

Spring Boot CRaC 통합

Spring Boot 3.2+부터 @Checkpoint 및 @Restore 라이프사이클 훅을 지원합니다.

<dependency>
    <groupId>org.crac</groupId>
    <artifactId>crac</artifactId>
    <version>1.4.0</version>
</dependency>
@Component
public class CRaCLifecycleBean implements Resource {

    private Connection dbConnection;

    @PostConstruct
    public void init() {
        // 체크포인트 리소스 등록
        Core.getGlobalContext().register(this);
    }

    @Override
    public void beforeCheckpoint(Context<? extends Resource> context) throws Exception {
        // Checkpoint 전 정리 작업
        System.out.println("Closing connections before checkpoint...");

        if (dbConnection != null && !dbConnection.isClosed()) {
            dbConnection.close();
        }
    }

    @Override
    public void afterRestore(Context<? extends Resource> context) throws Exception {
        // Restore 후 재연결
        System.out.println("Restoring connections after restore...");

        dbConnection = DriverManager.getConnection(
            "jdbc:postgresql://localhost:5432/mydb",
            "user",
            "password"
        );
    }
}

데이터베이스 연결 처리

HikariCP 같은 Connection Pool은 Checkpoint 전에 반드시 정리해야 합니다.

@Configuration
public class DataSourceCRaCConfig {

    @Bean
    public DataSource dataSource() {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
        ds.setUsername("user");
        ds.setPassword("password");

        // CRaC 이벤트 등록
        Core.getGlobalContext().register(new Resource() {
            @Override
            public void beforeCheckpoint(Context<? extends Resource> context) {
                System.out.println("Closing HikariCP pool...");
                ds.close();
            }

            @Override
            public void afterRestore(Context<? extends Resource> context) {
                System.out.println("HikariCP will auto-reconnect on first query");
                // HikariCP는 첫 쿼리 시 자동 재연결
            }
        });

        return ds;
    }
}

서버리스 환경 통합

AWS Lambda, Google Cloud Run 등 서버리스 환경에서 CRaC 이미지를 활용합니다.

# Dockerfile
FROM ubuntu:22.04

# CRaC OpenJDK 설치
RUN wget https://github.com/CRaC/openjdk-builds/releases/download/17-crac+5/openjdk-17-crac+5_linux-x64.tar.gz && \
    tar -xzf openjdk-17-crac+5_linux-x64.tar.gz && \
    mv openjdk-17-crac+5 /opt/jdk

# 애플리케이션 복사
COPY target/myapp.jar /app.jar

# Checkpoint 생성 (빌드 시 한 번만)
RUN /opt/jdk/bin/java -XX:CRaCCheckpointTo=/cr -jar /app.jar & \
    sleep 30 && \
    jcmd myapp.jar JDK.checkpoint

# Restore로 시작
CMD ["/opt/jdk/bin/java", "-XX:CRaCRestoreFrom=/cr"]

주의사항과 제약

  • Linux만 지원: 현재 CRaC는 Linux 환경에서만 작동합니다. (Windows/macOS 미지원)
  • 파일 디스크립터: 열린 파일, 소켓은 Checkpoint 전에 정리해야 합니다.
  • 암호화 키: SecureRandom 등의 암호화 상태는 Restore 후 재초기화가 필요합니다.
  • 시간 의존성: Checkpoint 시점의 타임스탬프를 캐싱하면 Restore 후 오래된 시간이 사용될 수 있습니다.
  • 네이티브 라이브러리: JNI를 사용하는 라이브러리는 CRaC와 호환되지 않을 수 있습니다.

활용 팁

  • 서버리스 최적화: 콜드 스타트가 10초에서 100ms로 단축되어 Lambda 비용이 크게 절감됩니다.
  • Auto-scaling: 트래픽 급증 시 새 인스턴스가 즉시 요청을 처리할 수 있어 응답 시간이 안정화됩니다.
  • 테스트 환경: 통합 테스트에서 애플리케이션을 빠르게 재시작하여 테스트 속도를 개선할 수 있습니다.
  • Spring Cloud: Config Server, Service Discovery와 함께 사용 시 Restore 후 재등록 로직을 추가해야 합니다.
  • 프로덕션 검증: Checkpoint 이미지는 환경별(dev/stage/prod)로 분리하여 관리해야 합니다.

마무리

CRaC는 Spring Boot 애플리케이션의 시작 시간을 혁신적으로 단축하여 서버리스와 클라우드 네이티브 환경에서 게임 체인저가 될 수 있습니다. 아직 실험적 단계이지만, Spring Framework 팀의 적극적인 지원 덕분에 프로덕션 환경에서도 점차 도입이 증가하고 있습니다. 특히 콜드 스타트 비용이 큰 서버리스 애플리케이션이나 빠른 스케일 아웃이 필요한 마이크로서비스에서 즉각적인 효과를 볼 수 있습니다. 다만 리소스 정리와 복원 로직을 신중히 설계해야 하며, 철저한 테스트가 필수입니다.