5.0 KiB
자바 모듈 시스템(Module System) 완벽 정리
1. 자바 모듈이란?
자바 9에서 도입된 모듈 시스템은 코드를 논리적으로 분리하고, 불필요한 의존성을 줄이며, 캡슐화를 강화하는 기능이다.
기존의 JAR 파일을 묶는 개념이 아니라, 모듈 자체가 의존성 관리 및 접근 제어 기능을 갖는다.
2. 모듈의 핵심 개념
✅ 모듈의 구성 요소
module-info.java파일 (모듈의 정의 파일)- 패키지 (캡슐화할 클래스 포함)
- 다른 모듈에 대한 의존성 선언
✅ 모듈의 주요 키워드
| 키워드 | 설명 |
|---|---|
module |
모듈을 정의하는 키워드 |
requires |
다른 모듈을 가져올 때 사용 |
exports |
특정 패키지를 외부에서 사용 가능하도록 공개 |
opens |
리플렉션(Reflection)을 허용 (ex: Jackson, Hibernate) |
provides ... with |
서비스 제공자 패턴 구현 시 사용 |
uses |
특정 서비스 인터페이스 사용 시 명시 |
3. 모듈 예제
✅ 모듈 프로젝트 구성
다음과 같은 두 개의 모듈이 있다고 가정하자.
com.example.moduleA(API를 제공하는 모듈)com.example.moduleB(moduleA의 기능을 사용하는 모듈)
📁 프로젝트 구조
/project
├── moduleA
│ ├── src/com/example/moduleA/MyService.java
│ ├── src/module-info.java
│
├── moduleB
│ ├── src/com/example/moduleB/MainApp.java
│ ├── src/module-info.java
✅ 1. moduleA (API 제공 모듈)
📌 moduleA는 MyService 클래스를 제공하며, moduleB에서 사용 가능하도록 공개해야 한다.
📌 📄 moduleA/src/module-info.java
module com.example.moduleA {
exports com.example.moduleA; // 패키지 공개
}
📌 📄 moduleA/src/com/example/moduleA/MyService.java
package com.example.moduleA;
public class MyService {
public String getMessage() {
return "Hello from Module A!";
}
}
✅ 2. moduleB (API 사용 모듈)
📌 moduleB는 moduleA의 클래스를 사용하므로, requires 키워드로 moduleA를 포함해야 한다.
📌 📄 moduleB/src/module-info.java
module com.example.moduleB {
requires com.example.moduleA; // moduleA를 사용하기 위해 선언
}
📌 📄 moduleB/src/com/example/moduleB/MainApp.java
package com.example.moduleB;
import com.example.moduleA.MyService;
public class MainApp {
public static void main(String[] args) {
MyService service = new MyService();
System.out.println(service.getMessage());
}
}
4. 모듈 프로젝트 실행 방법
📌 터미널에서 모듈을 직접 컴파일하고 실행할 수도 있다.
✅ 1. 모듈별 컴파일
# moduleA 컴파일
javac -d out/moduleA src/moduleA/module-info.java src/moduleA/com/example/moduleA/MyService.java
# moduleB 컴파일 (moduleA를 classpath에 추가)
javac -d out/moduleB --module-path out/moduleA src/moduleB/module-info.java src/moduleB/com/example/moduleB/MainApp.java
✅ 2. 프로그램 실행
java --module-path out/moduleA:out/moduleB --module com.example.moduleB/com.example.moduleB.MainApp
✔ Hello from Module A! 출력
5. exports와 opens 차이점
| 키워드 | 설명 |
|---|---|
exports 패키지명; |
패키지를 외부 모듈에서 사용할 수 있도록 공개 |
opens 패키지명; |
리플렉션(Reflection)으로 접근 가능하지만 일반적인 import는 불가능 |
📌 예를 들어, Jackson, Hibernate 같은 프레임워크는 리플렉션을 사용하므로 opens가 필요하다.
module com.example.moduleA {
opens com.example.moduleA to jackson.databind;
}
6. 모듈 시스템의 장점
✅ 1. 강력한 캡슐화:
필요한 패키지만 exports 가능하여, 불필요한 내부 코드 노출 방지
✅ 2. 명확한 의존성 관리:
requires 키워드로 명확한 모듈 간 의존성을 선언
✅ 3. 경량화된 런타임:
JVM이 필요 없는 모듈을 제외하고 실행 가능 (예: jlink 사용)
7. 모듈 시스템의 단점
❌ 1. 기존 라이브러리와의 호환성 문제:
기존 JAR 파일 중에는 모듈 시스템을 지원하지 않는 것들이 있음
❌ 2. 학습 곡선이 존재:
모듈 시스템을 처음 접하는 경우, 기존 classpath 방식보다 설정이 다소 복잡
8. 결론
자바 모듈 시스템은 의존성을 명확하게 관리하고 캡슐화를 강화하는 강력한 기능이다.
하지만, 기존 라이브러리와의 호환성을 고려해야 하며, 소규모 프로젝트에서는 필요하지 않을 수도 있다.
대규모 프로젝트에서는 모듈을 도입하면 유지보수성과 성능이 향상될 수 있다.