Spring Boot 애플리케이션 보호

springboot는 Spring Boot 애플리케이션을 보호하며 BOOT-INF/classes, BOOT-INF/lib, Spring Boot Loader, 프레임워크 스캔을 처리합니다.

1. GUI에서 하는 방법

  1. 애플리케이션 유형 페이지에서 Spring Boot를 선택합니다.

    Spring Boot 선택

  2. 보호할 Spring Boot 애플리케이션, 함께 넣을 Java 버전, 대상 플랫폼을 선택한 뒤 간단 모드와 고급 모드 중에서 고릅니다.

    입력, Java 버전, 대상 플랫폼, 모드 선택

  3. 고급 모드에서는 출력 레이아웃, 보호할 의존성 JAR, JavaFX 설정, JVM 시작 옵션, 제외 규칙을 선택합니다. 간단 모드는 호환성 검사 결과에서 레이아웃과 제외 규칙을 정합니다. 각 옵션의 의미는 Protector4J 고급 모드 설정을 참고하세요.

    Spring Boot 고급 옵션 설정

  4. 출력 디렉터리를 선택하고 요약을 확인한 뒤 보호 실행을 클릭합니다.

    출력 디렉터리를 선택하고 보호 실행

2. CLI 예제

가장 짧은 형태:

p4j springboot app.jar dist

기본값은 p4jx-fat 레이아웃입니다. 다른 레이아웃을 직접 고르려면:

p4j springboot app.jar dist --layout fat
p4j springboot app.jar dist --layout separate

애플리케이션의 일부만 보호하는 경우:

p4j springboot app.jar dist \
  --protect 'com.example.service.impl.**' \
  --exclude 'com.example.dto.**,com.example.config.**'

3. 출력 구조와 레이아웃

p4jx-fat: 기본 레이아웃, 단일 보호 아카이브

dist/
├── app.p4jx              # jar 아카이브 확장자를 쓰면 app.jar
├── vlxjre/
├── run.sh
├── run.command
└── run.bat

특징:

  • 애플리케이션 전체가 하나의 P4JX 아카이브로 배포됩니다.
  • 물리 파일은 기본적으로 ZIP이 아닙니다.
  • Spring Boot 리소스, 중첩된 의존성, 메타데이터는 가상 JAR 뷰로 제공됩니다.
  • 보호 범위가 가장 넓어, 서드파티 클래스패스 스캐너에 의존하지 않는 애플리케이션에 적합합니다.

fat: Spring Boot 호환 레이아웃

dist/
├── app.jar
├── app.p4jx              # jar 확장자를 쓰면 app-protected.jar
├── vlxjre/
└── run.*

특징:

  • app.jar가 표준 BOOT-INF 물리 구조를 유지합니다.
  • 보호 대상 클래스의 실제 구현은 옆에 있는 P4JX 아카이브에 들어갑니다.
  • ClassGraph나 Reflections를 쓰는 등 물리적인 Spring Boot JAR 구조를 스캔해야 하는 애플리케이션에 적합합니다.
  • 두 파일은 서로 의존하므로 반드시 함께 갱신하고 함께 배포해야 합니다.

separate: 분리형 호환 레이아웃

dist/
├── plain-launcher.jar
├── app.p4jx
├── lib/
├── vlxjre/
└── run.*

특징:

  • Spring Boot Loader, 보호되지 않은 클래스, 의존성을 따로 둡니다.
  • lib/* 평면 클래스패스를 요구하는 오래된 연동 환경에 적합합니다.
  • 보호 대상 클래스는 생성된 실행기가 미리 로딩합니다.
  • 새 프로젝트에서는 p4jx-fat, 또는 스캐너가 권장하는 p4jx-fat / fat을 쓰세요.

레이아웃 고르는 법

상황권장 레이아웃
표준적인 Spring Boot 서비스p4jx-fat
ClassGraph, Reflections 같은 스캐너를 실제로 사용fat
외부 의존성을 평면 디렉터리에 두거나, 의존성 파일을 따로 암호화해야 함separate
판단하기 어려움먼저 --compat-scan 실행

ZIP 오버레이는 ZIP 중앙 디렉터리를 직접 읽는 도구에만 도움이 됩니다. ClassLoader와 클래스패스 스캐너가 필요로 하는 물리적 Spring Boot 구조를 대신하지는 못합니다.

4. 실행

./run.sh --spring.profiles.active=prod

Windows:

run.bat --spring.profiles.active=prod

출력 디렉터리의 vlxjre를 시스템 JRE로 바꾸지 마세요.

Windows용으로 패키징할 때는 네이티브 실행기도 만들 수 있습니다. 세 레이아웃 모두 지원하며 실행 스크립트와 함께 존재합니다. 자세한 내용은 Windows EXE 실행기 생성을 참고하세요.

JVM 시작 옵션

패키징할 때 옵션을 고정할 수 있습니다. GUI의 JVM 시작 옵션에 한 줄에 하나씩 입력하거나 명령줄에서 지정합니다.

p4j springboot app.jar dist \
  --jvm-option -Xms1g \
  --jvm-option -Xmx2g

배포된 패키지에 한 번만 옵션을 더하려면:

APP_JAVA_OPTS="-Duser.timezone=Asia/Seoul" ./run.sh

배포된 스크립트를 직접 편집할 수도 있습니다.

  • macOS와 Linux: run.sh에서 생성된 JVM_OPTS=(...)JVM_OPTS+=(...) 뒤에 JVM_OPTS+=("-Xms1g" "-Xmx2g")를 추가합니다.
  • Windows: run.bat에서 생성된 set "JVM_OPTS=..." 뒤에 set "JVM_OPTS=%JVM_OPTS% -Xms1g -Xmx2g"를 추가합니다.

패키저가 Spring Boot나 JavaFX를 위해 만든 --add-opens, 모듈 경로 같은 옵션은 지우지 마세요. 다시 패키징하면 직접 수정한 내용은 모두 덮어씌워집니다. 자세한 내용은 JVM 시작 옵션을 참고하세요.

5. 보호 범위

기본적으로 BOOT-INF/classes 아래의 애플리케이션 클래스를 보호합니다. 다음과 같은 Spring 관련 클래스는 보호하지 않는 편이 안전합니다.

  • @Controller, @RestController, @ControllerAdvice 클래스
  • @Configuration 클래스, 자동 구성 클래스, AOT·CGLIB로 확장된 클래스
  • Jackson DTO, JPA 엔티티, 레코드, 검증 모델
  • 애플리케이션 진입점과 프레임워크가 직접 생성하거나 프록시하는 클래스
  • 실행 중 바이트코드 확장이 필요한 클래스

서비스 구현을 보호하고 공개된 파사드나 인터페이스를 통해 접근하세요. 규칙에는 정확한 클래스 이름과 pkg.*, pkg.**를 쓸 수 있습니다.

6. 의존성 JAR 보호

--protect-libBOOT-INF/lib에서 조건에 맞는 의존성을 보호합니다. 세 레이아웃 모두에서 쓸 수 있습니다.

p4j springboot app.jar dist \
  --protect-lib 'company-core-*.jar,pricing-*.jar'

자사의 비공개 의존성만 보호하세요. 「더 많이 보호하겠다」는 이유로 Spring, Tomcat, 로깅 라이브러리, 데이터베이스 드라이버 같은 서드파티 프레임워크를 암호화하지 마세요.

7. 호환성 검사

p4j springboot app.jar --compat-scan
p4j springboot app.jar dist --compat-apply

두 옵션은 함께 쓸 수 없습니다. 차이는 다음과 같습니다.

옵션동작사용 시점
--compat-scan입력 JAR를 검사해 위험 요소와 설정 권장을 출력하고 종료합니다. 인코딩하지 않고 dist도 만들지 않으므로 출력 디렉터리가 필요 없습니다.처음 보호할 때, Spring Boot나 다른 의존성을 올린 뒤, 보호 범위나 레이아웃을 바꾼 뒤, 호환성 문제를 조사할 때 먼저 보고서를 확인합니다.
--compat-apply검사한 뒤 보수적인 권장 설정을 반영하고 그대로 인코딩해 결과물을 만듭니다. 따라서 출력 디렉터리가 필요합니다.검사 결과를 확인하고 권장 설정을 받아들인 뒤 패키징을 마무리할 때 사용합니다. 규칙이 검증된 반복 빌드나 CI에도 적합합니다.

springboot에서 --compat-apply는 검사 결과에 따라 레이아웃을 고르고 제외 규칙을 추가하며 스캐너 ZIP 오버레이, JavaFX, 아카이브 확장자 등을 조정할 수 있습니다. 제외 규칙을 뺀 나머지는 명령줄에서 직접 지정한 값이 우선합니다. 권장되는 제외 규칙은 기본적으로 직접 지정한 --exclude와 합쳐집니다. 자동 추가를 원하지 않으면 --no-compat-excludes를 함께 전달하세요. 스캐너는 정적 휴리스틱 분석만 수행하므로 소스 수정이 필요한 문제는 --compat-apply로 해결되지 않으며, 패키징한 뒤에도 대상 플랫폼에서 회귀 테스트가 필요합니다.

그 밖의 CLI 명령, 전체 옵션, 환경 변수, 자동화 예제는 CLI 레퍼런스를 참고하세요.