Files
java-examples/docs/모듈.md

155 lines
5.0 KiB
Markdown

# **자바 모듈 시스템(Module System) 완벽 정리**
## **1. 자바 모듈이란?**
자바 9에서 도입된 **모듈 시스템**은 **코드를 논리적으로 분리**하고, **불필요한 의존성을 줄이며**, **캡슐화를 강화**하는 기능이다.
기존의 **JAR 파일을 묶는 개념**이 아니라, 모듈 자체가 **의존성 관리 및 접근 제어 기능**을 갖는다.
---
## **2. 모듈의 핵심 개념**
### ✅ **모듈의 구성 요소**
1. `module-info.java` 파일 (모듈의 정의 파일)
2. 패키지 (캡슐화할 클래스 포함)
3. 다른 모듈에 대한 의존성 선언
### ✅ **모듈의 주요 키워드**
| 키워드 | 설명 |
|--------|------|
| `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**
```java
module com.example.moduleA {
exports com.example.moduleA; // 패키지 공개
}
```
#### 📌 **📄 moduleA/src/com/example/moduleA/MyService.java**
```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**
```java
module com.example.moduleB {
requires com.example.moduleA; // moduleA를 사용하기 위해 선언
}
```
#### 📌 **📄 moduleB/src/com/example/moduleB/MainApp.java**
```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. 모듈별 컴파일**
```sh
# 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. 프로그램 실행**
```sh
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`가 필요하다.
```java
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. 결론**
자바 모듈 시스템은 **의존성을 명확하게 관리하고 캡슐화를 강화**하는 강력한 기능이다.
하지만, 기존 라이브러리와의 호환성을 고려해야 하며, **소규모 프로젝트에서는 필요하지 않을 수도 있다.**
대규모 프로젝트에서는 **모듈을 도입하면 유지보수성과 성능이 향상**될 수 있다.