자바 모듈 시스템
모던 자바인 액션을 읽고 정리한 내용과 읽으면서 궁금한 내용들을 작성하였습니다.
자바가 진화해야 한다는 여론으로 모듈시스템을 지원 시작
추론하기 위한 소프트웨어
자바 9에서 가장 많이 거론되는 새로운 기능이 모듈 시스템
그렇다면, 모듈화란 무엇인가, 모듈 시스템은 어떤 문제를 해결할 수 있는가
관심사 분리(SoC)
관심사분리는 컴퓨터 프로그램을 고유의 기능으로 나누는 동작을 권장하는 원칙
→ 회계 어플리케이션이 있다면 파싱, 분석, 레포트 기능을 모듈이란 각각의 부분으로 분리 가능
- 장점
- 개별 기능을 따로 작업할 수 있으므로 팀이 쉽게 협업 가능
- 개별 부분을 재사용하기 쉬움
- 전체 시스템을 쉽게 유지보수 가능
정보 은닉
세부 구현을 숨기도록 장려하는 원칙
→ 세부 구현을 숨김으로 프로그램의 어떤 부분을 변경했을 때 다른 부분에 미치는 영향을 줄일 수 있음
한계점
자바는 클래스, 패키지, JAR 3가지 수준의 코드 그룹화를 제공
- 클래스
- 자바에서는 public, protected, private 등의 접근 제한자와 패키지 수준 접근 권한 등을 이용하여 메서드, 필드 클래스의 접근을 제어함
- 하지만 원하는 접근 제한을 달성하기가 어려우며, 최종 사용자에게 원하지 않은 메서드도 공개해야 하는 상황 발생
- 패키지와 JAR
- 캡슐화를 거의 지원하지 않는다.
- 클래스 경로
- 같은 클래스를 구분하는 버전 개념이 없으므로 2가지 버전의 같은 라이브러리가 존재할 경우 예측 불가
- 클래스 경로는 명시적인 의존성을 지원하지 않음 → 한 JAR이 다른 JAR에 포함된 클래스 집합을 사용하라고 명시적으로 의존성을 정의하는 기능을 제공하지 않음 (Maven, Gradle같은 빌드 도구로 해결가능)
- 자바는 클래스를 모두 컴파일한 다음 보통 한 개의 평범한 JAR 파일에 넣고 클래스 경로에 이 JAR 파일을 추가해 사용 가능 → JVM이 동적으로 클래스 경로에 정의된 클래스를 필요할 때 읽음
주요 구조: 모듈 declarations, requires, exports 지시어
자바 모듈
자바 8에는 모듈이라는 새로운 자바 프로그램 구조 단위 제공
모듈은 module
이라는 새 키워드에 이름과 바디를 추가해서 정의하고 모듈 디스크립터는 module-info.java
라는 특별한 파일에 저장
메이븐 같은 도구를 사용할 때 모듈의 많은 세부사항을 IDE가 처리하며 사용자에는 잘 드러나지 X
기존 자바 아카이브(JAR)에 적용되는 자동 모듈
애플리케이션 셋업
애플리케이션이 해야 하는 작업
- 파일이나 URL에서 비용 목록을 읽는다.
- 비용의 문자열 표현을 파싱한다.
- 유용한 요약 정보를 표시한다.
- 각 태스크의 시작, 마무리 지점을 제공한다.
자바 모듈 시스템으로 어떻게 이들을 모듈화 할 수 있을까?
- 다양한 소스에서 데이터를 읽음(Reader, HttpReader, FileReader)
- 다양한 포맷으로 구성된 데이터를 파싱(Parser, JSONParser,,,)
- 도메인 객체를 구체화(Expense)
- 통계를 계산하고 반환(SummaryCaculator,,,)
- 다양한 기능을 분리 조정(ExpenseApplication)
모듈화와 JDK 라이브러리
시스템을 모듈화할 때 모듈 크기를 결정해야 한다.
모든 패키지가 자신의 모듈을 가진다.
거친 모듈화 기법 대부분은 한 모듈이 시스템의 모든 패키지를 포함
→ 이득에 비해 설계 비용이 증가
→ 모듈화의 모든 장점을 잃음
module-info.java
모듈 디스크립터로, 모듈의 소스 코드 파일 루트에 위치해야 함
모듈의 의존성 그리고 어떤 기능을 외부로 노출할지를 정의
동작방식
- 명령어 실행
javac module-info.java com/exmaple/.../{Application.java} d target
jar cvfe expenses-applicaion.jar com.example....{Applicaion} -C target
- 어떤 폴더와 클래스 파일이, 생성된 JAR에 포함되어있는지를 알려주는 결과 출력
added manifest add module-info: module-info.class adding: com/(in = 0) (out = 0)(stored 0%) // 생략
- 생성된 JAR를 모듈화 애플리케이션으로 실행
java --module-path expenses-applicaion.jar --module com.example....{Applicaion}
.class 파일 실행 시 추가된 옵션
--module-path
: 어떤 모듈을 로드할 수 있는지 지정
--module
: 실행할 메인 모듈과 클래스를 지정
모듈과 메이븐 빌드
module expenses.readers {
requires java.base;
exports com.example.expenses.readers;
exports com.example.expenses.readers.file;
exports com.example.expenses.readers.http;
}
exports 구문
exports는 다른 모듈에서 사용할 수 있도록 특정 패키지를 공개 형식으로 만듬
기본적으로 모듈 내의 모든 것은 캡슐화 된다.
requires 구문
의존하고 있는 모듈을 지정
기본적으로 모든 모듈은 java.base라는 플랫폼 모듈에 의존하는데, 이 java.base 외의 모듈을 임포트할 때 사용
메이븐: 컴파일과 패키징
- 먼저 각 모듈에 pom.xml을 추가해야 한다.
- 각 모듈은 독립적으로 컴파일되므로 자체적으로 각각이 한개의 프로젝트
- 전체 프로젝트 빌드를 조정할 수 있도록 모든 모듈의 부모 모듈에도 pom.xml 추가
- application 모듈의 pom.xml을 정의
- 다른 모듈을 의존성으로 추가
mvn clean pakage
명령어를 실행하여 모듈을 JAR로 생성
기본적인 requires, exports 외의 모듈 지시어 간단 요약
자동 모듈
특화 라이브러리를 사용하려고 하는 경우
module-info.java에 이 구문을 추가한다면 에러 발생
→ pom.xml도 갱신하여야 함
자바는 모듈 경로상에 있으나 module-info 파일을 가지지 않은 모든 JAR은 자동 모듈이 됨
- 자동 모듈은 암묵적으로 자신의 모든 패키지를 노출시킴
requires 구문
의존하고 있는 모듈을 지정
- 컴파일 타임과 런타임에 한 모듈이 다른 모듈에 의존함을 정의
- 기본적으로 모든 모듈은 java.base라는 플랫폼 모듈에 의존하는데, 이 java.base 외의 모듈을 임포트할 때 사용
exports 구문
exports는 다른 모듈에서 사용할 수 있도록 특정 패키지를 공개 형식으로 만듬
- 아무 패키지도 공개하지 않는 것이 기본 설정
- 기본적으로 모듈 내의 모든 것은 캡슐화 된다.
java모듈의 module-info.java, Gradle의 setting.gradle와 어떤 것이 다를까?
내가 이해한 module-info.java
프로젝트의 모듈을 정의하는 파일
멀티 모듈 프로젝트를 세팅할 때
최상위 모듈의 setting.gradle에 다른 모듈을 추가하는데 module-info.java랑 다른가??
settings.gradle란
빌드 대상 프로젝트를 설정하는 스크립트
예를 들어 프로젝트 하위에 여러개의 프로젝트가 담겨있는 멀티 프로젝트의 형태인 경우, build의 대상이 되는 프로젝트를 지정하는 스크립트 파일입니다.
모듈과 라이브러리의 차이점
- 라이브러리는 모듈과 비슷한(거의 같은) 개념
- 모듈 → 패키지 관리 기능까지 포함된 라이브러리
- 일반 라이브러리는 내부에 포함된 모든 패키지에 외부 프로그램이 접근이 가능하지만, 모듈은 다음과 같이 일부 패키지를 은닉하여 접근할 수 없게끔 할 수 있다.
목적과 실행 시점이 다르다..
module-info.java
→ Java 모듈 시스템에 의해 처리
→ 런타임에 모듈 간의 관계를 관리
→ 다른 모듈과의 의존성을 명시적으로 정의하는 데 사용
setting.gradle
→ Gradle 빌드 도구에 의해 처리
→ 프로젝트가 어떤 서브프로젝트들로 구성되어 있는지를 관리
→ Gradle에게 어떻게 빌드를 수행해야 하는지를 알려주는 역할
ETC.. Gradle 관련 파일들의 의미
- gradlew
- 리눅스 또는 맥OS용 실행 쉘 스크립트 파일
- gradlew.bat
- 윈도우용 실행 배치 스크립트 파일
- gradle-wrapper.jar
- JAR 형식으로 압축된 Wrapper 파일
- gradlew나 gradlew.bat 파일이 Gradle task를 실행하는데 사용됨.
- gradle-wrapper.properties
- Gradle Wrapper 설정 정보 파일
- Wrapper의 버전 등을 설정할 수 있음.
- build.gradle
- 프로젝트의 라이브러리 의존성, 플러그인, 라이브러리 저장소 등을 설정할 수 있는 빌드 스크립트 파일
- settings.gradle
- 프로젝트의 구성 정보 파일
- 멀티 프로젝트를 구성시 프로젝트를 모듈화할 경우, 하위 프로젝트의 구성을 설정할 수 있음.
'독서📚' 카테고리의 다른 글
[아이템 44] 표준 함수형 인터페이스를 사용하라 (0) | 2023.09.15 |
---|---|
[아이템 43] 람다보다는 메서드 참조를 사용하라 (0) | 2023.09.15 |
[아이템 42] 익명 클래스보다는 람다를 사용하라 (0) | 2023.09.15 |
새로운 인프라 환경이 온다 (0) | 2023.09.12 |
[자바의 정석] 1. 자바를 시작하기 전에 (0) | 2023.06.27 |