출시·고도화 중
Java 안내서 · 4/6
프로그램이 커지면 코드를 나누고, 외부 라이브러리를 가져오고, 배포할 파일을 만들어야 합니다. Java에서는 패키지로 클래스를 묶고, Maven이나 Gradle로 빌드와 의존성을 관리하며, 필요하면 모듈 시스템으로 공개 범위를 더 엄격하게 정합니다. 결과물은 보통 JAR 파일로 배포합니다.
패키지는 클래스의 이름 공간입니다. 파일 맨 위에 package 선언을 두고, 디렉터리 구조를 패키지 이름과 맞춥니다. 이름 충돌을 피하기 위해 소유한 도메인을 거꾸로 쓴 형태(com.example)를 관례로 씁니다.
// src/main/java/com/example/shop/order/OrderService.java
package com.example.shop.order;
import java.time.LocalDate;
import java.util.List;
import com.example.shop.product.Product;
import static java.lang.Math.max; // 정적 멤버 가져오기
public class OrderService {
public int totalQuantity(List<Product> products) {
int total = 0;
for (Product p : products) total += max(0, p.quantity());
return total;
}
public LocalDate today() {
return LocalDate.now();
}
}java.lang 패키지(String, Math, Integer 등)는 자동으로 가져오므로 import 가 필요 없습니다. import java.util.*; 처럼 패키지 전체를 가져올 수도 있지만, 어떤 클래스를 쓰는지 드러나도록 하나씩 적는 경우가 많습니다. 접근 제어자를 적지 않은 클래스와 멤버는 같은 패키지 안에서만 보입니다.
Maven은 pom.xml 한 파일에 프로젝트 정보, 의존성, 플러그인을 선언합니다. 의존성은 그룹 ID, 아티팩트 ID, 버전의 세 좌표로 지정하고, Maven Central 같은 저장소에서 자동으로 내려받습니다.
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>shop</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
</dependencies>
</project>maven.compiler.release 에는 대상 Java 버전(예시의 21 자리에 팀이 쓰는 LTS 버전)을 적고, ${gson.version} 같은 속성에는 Maven Central에서 확인한 최신 버전을 넣습니다. 자주 쓰는 명령은 다음과 같습니다.
mvn compile # 컴파일
mvn test # 테스트 실행
mvn package # target/ 에 JAR 생성
mvn dependency:tree # 의존성 트리 확인Gradle은 Kotlin 또는 Groovy 스크립트로 빌드를 설정합니다. 프로젝트에 포함된 래퍼(gradlew)를 쓰면 Gradle을 따로 설치하지 않아도 모두가 같은 버전으로 빌드할 수 있습니다.
// build.gradle.kts
plugins {
application
}
repositories {
mavenCentral()
}
dependencies {
implementation("com.google.code.gson:gson:<버전>")
testImplementation(platform("org.junit:junit-bom:<버전>"))
testImplementation("org.junit.jupiter:junit-jupiter")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
java {
toolchain { languageVersion = JavaLanguageVersion.of(21) }
}
application {
mainClass = "com.example.shop.App"
}
tasks.test { useJUnitPlatform() }implementation 은 컴파일과 실행에, testImplementation 은 테스트에만 쓰이는 의존성입니다. ./gradlew build 로 컴파일 · 테스트 · 패키징을 한 번에 하고, ./gradlew run 으로 mainClass 를 실행합니다. 새 프로젝트는 gradle init 으로 뼈대를 만들 수 있습니다.
패키지만으로는 "이 라이브러리의 내부 패키지는 쓰지 마세요"를 강제할 수 없습니다. 모듈 시스템(JPMS)은 module-info.java 로 모듈이 무엇을 필요로 하고(requires) 무엇을 공개하는지(exports) 선언합니다. exports 하지 않은 패키지는 public 클래스라도 다른 모듈에서 접근할 수 없습니다.
// src/main/java/module-info.java
module com.example.shop {
requires java.net.http; // JDK 모듈
requires com.google.gson; // 라이브러리 모듈
exports com.example.shop.api; // 외부에 공개하는 패키지
opens com.example.shop.model to com.google.gson; // 리플렉션 허용
}opens 는 리플렉션으로 내부를 들여다보는 직렬화 라이브러리 같은 도구에 접근을 허용할 때 씁니다. 모듈 시스템은 선택 사항이며, module-info.java 가 없으면 예전처럼 클래스패스에서 동작합니다. 많은 애플리케이션은 모듈 없이 시작하고, 라이브러리를 배포하거나 jlink 로 작은 런타임 이미지를 만들 때 도입합니다.
JAR는 컴파일된 클래스와 자원을 ZIP 형식으로 묶은 파일입니다. 매니페스트에 Main-Class 를 지정하면 java -jar 로 바로 실행할 수 있습니다. 빌드 도구 없이 직접 만드는 과정은 다음과 같습니다.
javac -d out $(find src/main/java -name "*.java")
jar --create --file app.jar --main-class com.example.shop.App -C out .
java -jar app.jar외부 라이브러리를 쓰는 경우 기본 JAR에는 의존성이 들어가지 않습니다. 실행할 때 java -cp "app.jar:libs/*" com.example.shop.App 처럼 클래스패스를 지정하거나(Windows에서는 구분자가 ;), 의존성을 함께 묶는 Maven Shade 플러그인이나 Gradle의 installDist 같은 배포 작업을 활용합니다.
import 로 다른 패키지의 클래스를 가져옵니다.pom.xml, Gradle은 build.gradle.kts 에 의존성과 빌드 설정을 선언합니다.module-info.java 의 requires, exports 로 모듈 경계를 명확히 할 수 있습니다.java -jar 로 실행하고, 의존성 포함 여부를 배포 방식에 맞게 정합니다.
댓글 0개
로그인 · 로그인하면 댓글을 남길 수 있습니다.
첫 댓글을 남겨 보세요.