공공부하자개발 · 영어 학습 노트
자바
실무 확장Excel · 파일 업로드 · DB 연동0/22 완료
  • 01Excel(XLSX) 구조와 순수 JDK로 읽기/쓰기
  • 02Apache POI로 Excel 업로드/다운로드
  • 03파일 업로드/다운로드 서버 (HttpServer)
  • 04JDBC 기초와 트랜잭션 (H2)
  • 05MyBatis 어노테이션 매퍼로 쿼리 연동
  • 06MyBatis XML 매퍼 · Oracle 방언 · PageHelper · Spring Boot
  • 07REST API 서버와 JSON
  • 08Vue 3 SPA 와 Java 서버 연동
  • 09@Scheduled 운영
  • 10로깅 실무: 레벨·계층, MDC 추적, 예외·성능, 마스킹, 롤링, JSON 로그
  • 11외부 API 연동
  • 12테스트 실무
  • 13암호화·개인정보 보호
  • 14인코딩·한글 실무
  • 15@Transactional 심화
  • 16긴 작업 비동기 처리와 진행률
  • 17SFTP·FTP 파일 연계
  • 18로컬 캐시와 @Cacheable
  • 19메일·알림 발송
  • 20웹 보안 체크리스트
  • 21빌드 도구와 폐쇄망 의존성 반입
  • 22성능 측정: p50·p95·p99, 측정 계층, JFR, JMH 함정, 자체 부하 테스트, 병목 순위
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 실무 확장 › 21 / 22

빌드 도구와 폐쇄망 의존성 반입

Maven 좌표·범위·충돌, 로컬 저장소 반입, 사내 미러, 재현 가능한 빌드
섹션 7진행 0 / 22
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

2. 핵심 원리

2.1 Maven 좌표와 pom.xml 최소 구성

Maven 은 모든 라이브러리를 groupId(조직), artifactId(라이브러리 이름), version(버전) 세 값으로 식별합니다. 이 세 값을 합쳐 좌표라고 부릅니다. pom.xml 은 이 좌표들과 빌드 방법을 적는 파일입니다.

Spring Boot 프로젝트는 보통 spring-boot-starter-parent 를 부모로 상속해 버전 관리 대부분을 부모에 맡깁니다. properties 에 java.version 을 적으면 컴파일러 버전이 맞춰지고, dependencies 에는 라이브러리 좌표를, build/plugins 에는 컴파일·패키징 방식을 커스터마이즈하는 플러그인을 적습니다.

2.2 의존성 범위(scope)

같은 라이브러리라도 언제 필요한지에 따라 범위가 다릅니다. 범위를 잘못 잡으면 실행 시 ClassNotFoundException 이 나거나, 반대로 배포 jar 가 불필요하게 커집니다.

scope 컴파일 실행(런타임) 배포 포함 예
compile(기본값) O O O spring-boot-starter-web
provided O X(컨테이너 제공) X servlet-api
runtime X O O mysql-connector-j
test 테스트만 테스트만 X junit-jupiter

provided 는 WAS 가 이미 클래스를 제공해서 배포 jar 에는 넣지 않는 경우입니다. runtime 은 코드에서 직접 참조하지 않고 인터페이스로만 쓰는 JDBC 드라이버 같은 라이브러리에 씁니다.

2.3 전이 의존성과 충돌 해결

A 를 추가하면 A 가 쓰는 B, C 까지 자동으로 딸려 옵니다. 이것이 전이 의존성입니다. 문제는 서로 다른 라이브러리가 같은 B 의 다른 버전을 요구할 때입니다.

Maven 은 기본적으로 "POM 트리에서 더 가까운 버전이 승리"하는 규칙을 씁니다. 같은 깊이면 먼저 선언된 쪽이 이깁니다. mvn dependency:tree 로 실제 어떤 버전이 선택됐는지, 어디서 충돌이 나는지 확인합니다.

text
mvn dependency:tree
# [INFO] +- com.example:lib-a:jar:1.0:compile
# [INFO] |  \- (commons-lang3:3.12 -> 3.14로 승격, lib-b 요구)

원치 않는 버전이 딸려 오면 두 가지 방법으로 고칩니다. <exclusions> 로 특정 전이 의존성을 빼거나, dependencyManagement(또는 BOM: Bill of Materials) 로 버전을 프로젝트 전체에 고정합니다. spring-boot-starter-parent 자체가 거대한 BOM 역할을 합니다.

2.4 Gradle 대응표

이 회사는 Maven 을 표준으로 쓰지만, 오픈소스 예제는 Gradle 로 배포되는 경우가 많아 대응 개념을 알아 둘 필요가 있습니다. build.gradle.kts 는 이 레슨 폴더에 문법 참고용으로만 넣었고 실행 검증은 하지 않습니다.

Maven scope Gradle configuration
compile implementation
provided compileOnly
runtime runtimeOnly
test testImplementation

Gradle 에서 전이 의존성 트리는 gradle dependencies 로 봅니다. mvn dependency:tree 와 목적은 같습니다.

2.5 로컬 저장소 ~/.m2/repository 구조

Maven 은 한 번 받은 jar 를 홈 폴더의 ~/.m2/repository 에 캐시합니다. 경로는 좌표를 그대로 폴더로 풀어낸 구조입니다.

text
~/.m2/repository/
  org/springframework/boot/
    spring-boot-starter-web/
      3.3.0/
        spring-boot-starter-web-3.3.0.jar
        spring-boot-starter-web-3.3.0.pom
        spring-boot-starter-web-3.3.0.jar.sha1

groupId 의 점(.)이 폴더 구분자(/)로 바뀌고, 그 아래 artifactId/version/ 순서로 폴더가 생깁니다. jar·pom 파일마다 .sha1 체크섬 파일이 같이 있어 무결성을 확인할 수 있습니다. 이 폴더 전체가 폐쇄망 반입의 핵심 대상입니다.

2.6 폐쇄망 반입 절차 세 가지

(a) ~/.m2/repository 통째로 반입. 인터넷 PC에서 mvn dependency:go-offline 을 실행하면 pom.xml 이 필요로 하는 의존성과 빌드 플러그인까지 로컬 저장소에 미리 받아 둡니다. 이 폴더를 tar 로 묶어 폐쇄망 서버로 옮기고, settings.xml 에서 <offline>true</offline> 와 <localRepository> 경로를 지정합니다.

이 방식은 준비가 간단하지만, 프로젝트를 새로 추가할 때마다 인터넷 PC에서 다시 받아 전체를 재반입해야 하는 단점이 있습니다. 사내 표준 저장소가 없는 소규모 팀에 적합합니다.

(b) 사내 Nexus·Artifactory 미러. 사내에 프록시 저장소를 두고, 폐쇄망 서버는 이 미러만 바라보게 settings.xml 의 <mirror> 를 설정합니다. 신규 라이브러리는 보안팀 심사를 거쳐 미러의 허용 목록에 등록하는 절차를 밟습니다.

이 방식은 초기 구축 비용이 있지만, 여러 팀·여러 프로젝트가 반복 반입 없이 공유할 수 있어 실무에서 가장 널리 쓰입니다. settings-offline.xml 예시 파일에 mirror 설정을 주석으로 넣어 두었습니다.

(c) jar 개별 반입. 특정 jar 하나만 급하게 필요할 때는 mvn install:install-file 로 로컬 저장소에 수동 등록합니다. <scope>system</scope> 로 프로젝트 폴더 안 jar 를 직접 가리키는 방법도 있지만, 저장소 관리가 안 되고 팀원마다 경로가 달라질 수 있어 권장하지 않습니다.

text
mvn install:install-file \
  -Dfile=mybatis-3.5.19.jar \
  -DgroupId=org.mybatis -DartifactId=mybatis \
  -Dversion=3.5.19 -Dpackaging=jar

2.7 반입 검증

jar 를 옮기는 과정에서 파일이 깨지거나, 의도치 않은 버전이 섞여 들어갈 수 있습니다. 반입 전후로 sha256sum 값을 대조해 무결성을 확인합니다. 라이선스 고지문 확인과 알려진 취약점(CVE) 점검도 반입 심사에 포함합니다. CVE 점검 방법은 실무 확장 20 웹 보안 레슨을 참조하세요.

이 레슨의 import-jars.sh 는 .sha256 사이드카 파일이 있는 jar 만 대조하고, 없는 jar 는 "미검증"으로만 표시합니다. 실제 반입 심사에서는 미검증 jar 를 그대로 승인하면 안 됩니다.

2.8 재현 가능한 빌드

같은 pom.xml 로 언제 빌드해도 같은 결과가 나와야 합니다. 이를 위해 버전은 항상 숫자로 고정하고, LATEST·RELEASE·SNAPSHOT 버전은 운영 빌드에 쓰지 않습니다. 시점에 따라 실제로 받아지는 jar 가 달라지기 때문입니다.

Maven Wrapper(mvnw, mvnw.cmd)는 팀원마다 다른 Maven 버전을 쓰는 문제를 없애 줍니다. 폐쇄망에서는 Wrapper 가 내려받는 Maven 배포판 자체도 미리 반입해야 동작합니다.

2.9 빌드 결과물과 fat jar

일반 mvn package 는 프로젝트 코드만 담은 jar 를 만듭니다. 이 jar 는 의존성이 클래스패스에 따로 있어야 실행됩니다. Spring Boot 는 spring-boot-maven-plugin 의 repackage 목표로 의존성까지 하나에 담은 실행 가능한 jar(fat jar, uber jar)를 만듭니다.

fat jar 내부에는 BOOT-INF/classes(프로젝트 클래스)와 BOOT-INF/lib(의존성 jar 전체)가 들어 있습니다. 매니페스트의 Main-Class 는 Spring Boot 런처를 가리키고, 실제 애플리케이션의 진입점은 Start-Class 에 별도로 기록됩니다. -classifier exec 옵션을 주면 일반 jar 와 fat jar 를 파일명으로 구분할 수 있습니다.

2.10 빌드 서버 스크립트와 오류 해석

빌드 서버에서는 보통 mvn -o -B -q -DskipTests package 형태로 실행합니다. -o 는 오프라인, -B 는 배치 모드(진행바 등 대화형 출력 억제), -q 는 최소 로그, -DskipTests 는 배포 파이프라인에서 테스트를 따로 돌릴 때 씁니다. 종료 코드가 0 이 아니면 후속 배포 단계로 넘어가지 않게 스크립트에서 체크합니다.

산출물 파일명에 버전과 git 커밋 해시를 넣어 두면 배포 서버에서 어떤 소스로 만든 jar 인지 바로 알 수 있습니다. 파일명 규칙과 배포 스크립트는 리눅스 04 배포 레슨을 참조하세요.

자주 보는 오류 메시지를 표로 정리합니다.

오류 메시지(일부) 원인 조치
Could not resolve dependencies jar 를 저장소에서 못 찾음 반입 누락, 좌표 오탈자 확인
Non-resolvable parent POM 부모 POM 을 못 받음 starter-parent 도 반입 대상
plugin ... not available in offline mode 플러그인 자체가 캐시에 없음 플러그인도 go-offline 대상
인코딩 경고(불특정 문자 인코딩) sourceEncoding 미설정 project.build.sourceEncoding 지정

두 번째와 세 번째 오류는 초심자가 자주 놓칩니다. dependency:go-offline 은 dependencies 뿐 아니라 부모 POM 과 빌드에 쓰는 플러그인까지 받아 두므로, 반입 전에 반드시 실행해야 합니다.

2.11 Gradle 오프라인 주의점

Gradle 도 --offline 옵션으로 네트워크를 막고 캐시만 쓸 수 있습니다. 캐시 위치는 ~/.gradle/caches 이며 Maven 의 ~/.m2/repository 와 폴더 구조가 다릅니다.

Gradle 캐시는 메타데이터와 잠금 파일이 Gradle 버전에 민감합니다. 폐쇄망에 반입할 때 개발 PC와 빌드 서버의 Gradle 버전이 다르면 캐시를 인식하지 못하는 경우가 있어, 버전을 정확히 맞추거나 Gradle Wrapper 배포판 자체를 함께 반입해야 합니다.

2.12 이 저장소의 방식과 실제 프로젝트의 차이

이 사이트의 실무 확장 예제는 java-src/lib 폴더에 jar 를 미리 넣어 두고 -cp "..\..\lib\*;." 로 클래스패스에 잡습니다. 예제 하나만 실행하면 되므로 전이 의존성·버전 충돌·표준 폴더 구조가 필요 없어 이 방식이 더 간단합니다.

실제 프로젝트는 모듈이 여러 개고 팀원이 여러 명이라 이 방식이 곧바로 한계에 부딪힙니다. java-src/lib 는 학습용 지름길이고, 실무에서는 Maven·Gradle 이 표준이라는 점을 구분해서 이해하는 것이 이 레슨의 핵심입니다.

핵심 원리
  • 2.1 Maven 좌표와 pom.xml 최소 구성
  • 2.2 의존성 범위(scope)
  • 2.3 전이 의존성과 충돌 해결
  • 2.4 Gradle 대응표
  • 2.5 로컬 저장소 ~/.m2/repository 구조
  • 2.6 폐쇄망 반입 절차 세 가지
  • 2.7 반입 검증
  • 2.8 재현 가능한 빌드
  • 2.9 빌드 결과물과 fat jar
  • 2.10 빌드 서버 스크립트와 오류 해석
  • 2.11 Gradle 오프라인 주의점
  • 2.12 이 저장소의 방식과 실제 프로젝트의 차이
이전 섹션1 왜 배우는가2 / 7다음 섹션3 코드 예제