자바

모던 자바 인 액션 -12-

정한_s 2021. 12. 20. 12:02

자바 모듈 시스템을 설계한 이유

 

모듈화의 한계

자바는 클래스, 패키지, JAR 세 가지 수준의 코드 그룹화를 제공한다. 클래스와 관련해 접근 제한자와 캡슐화를 제공하지만 패키지와 JAR 수준에서는 캡슐화를 거의 지원하지 않는다

 

제한된 가시성 제어

패키지의 가시성 제어 기능이 부족함 : 패키지의 클래스와 인터페이스를 다른 패키지에 공개하려면 public으로 선언해야한다. 따라서 내부적으로 사용할 목적으로 만든 클래스와 인터페이스들이 모두에게 공개된다.

 

클래스 경로

클래스는 모두 컴파일 한 다음 보통 한개의 평범한 JAR 파일에 넣고 클래스 경로에 이 JAR 파일을 추가해 사용할 수 있다. 그러면 JVM 동적으로 클래스 경로에 정의된 클래스를 필요할 때 읽는다. 클래스 경로와 JAR 조합에는 약점이 존재한다. 따라서 다음과 같은 문제로 메이븐이나 그레이들 같은 빌드 도구를 사용했다.

 

첫 번째 문제, 클래스 경로에는 같은 클래스를 구분하는 버전 개념이 없다 : 클래스를 지정할 때 버전을 지정할 수 없으므로 클래스 경로 두 가지 버전의 같은 라이브러리가 존재할 때 어떤 일이 일어날지 예측할 수 없다

 

두 번째 문제, 클래스 경로는 명시적인 의존성을 지원하지 않는다 : 각각의 JAR 안에 있는 모든 클래스는 classes 라는 주머니로 합쳐진다. 즉, 한 JAR가 다른 JAR에 포함된 클래스 집합을 사용하라고 명시적으로 의존성을 정의하는 기능을 제공하지 않는다. 이 상황에서 클래스 경로 때문에 어떤 일이 일어나지는 파악하기 어렵다.

 

자바 모듈 시스템 - Java 9

관심사 분리(SoC, Seperation of concerns)

컴퓨터 프로그램을 고유의 기능으로 나누는 동작을 권장하는 원칙이다. Soc를 적용해 서로 겹치지 않은 코드 그룹으로 분리할 수 있다. 자바 9 모듈은 클래스가 어떤 다른 클래스를 볼 수 있는지를 컴파일 시간에 정교하게 제어할 수 있다. (자바 패키지도 클래스를 그룹화 할 수 있지만 이러한 기능을 지원하지 않는다)

 

정보 은닉

세부 구현을 숨기도록 장려하는 원칙이다. 소프트웨어를 개발할 때 요구사항은 자주 바뀐다. 세부 구현을 숨김으로서 프로그램의 어떤 부분을 바꿨을 때 다른 부분까지 영향을 미칠 가능성을 줄일 수 있다. 캡슐화를 통해 내부적인 변화가 외부에 영향을 주는 것을 줄일 수 있다.

자바9 에서는 클래스와 패키지가 의도된 대로 공개되었는지 컴파일러로 확인할 수 있는 기능을 제공한다.

 

자바 모듈 

모듈은 module 이라는 새 키워드에 이름과 바디를 추가해서 정의한다.

모듈 디스크립터는 module-info.java라는 파일에 저장되고, 보통 패키지와 같은 폴더에 위치한다.



1) exports 구문

exports는 패키지 단위로 다른 모듈에서도 사용할 수 있도록 공개하는 키워드이다.

지정한 패키지를 다른 모듈에서 이용할 수 있도록 공개 형식을 만든다. 아무 패키지도 공개하지 않는 것이 기본 설정이다, 패키지 명을 인수로 받는다. 

 

2) requires 구문

requires는 의존하고 있는 모듈을 지정하는 키워드이다.

기본적으로 모든 모듈은 java.base 라는 모듈을 의존하고 있다.

때문에, 이 java.base는 생략가능하며, java.base 가 아닌 모듈을 의존하는 경우에 requires를 사용해야 한다.

컴파일 타임과 런타임에 한 모듈이 다른 모듈에 의존함을 정의한다. 모듈명을 인수로 받는다

 

3) requires transitive

다른 모듈이 제공하는 공개 형식을 한 모듈에서 사용할 수 있다고 지정할 수 있다. 

module com.iteratrlearning.ui {
    requires transitive com.iteratrlearning.core;

    exports com.iteratrlearning.ui.panels;
    exports com.iteratrlearning.ui.widgets;
}

module com.iteratrlearning.application {
    requires com.iteratrlearning.ui
}

결과적으로 com.iteratrlearning.application 모듈은 com.iteratrlearning.core 에서 노출한 공개 형식에 접근 가능하다. 즉, 자신을 참조하는 모듈도 자신이 필요한 모듈에 접근 가능하게 하는 것.

 

4) exports to

exports to 구문은 사용자에게 공개할 기능을 제한함으로 가시성을 좀 더 정교하게 제어할 수 있다.

module com.iteratrlearning.ui {
    requires com.iteratrlearning.core;

    exports com.iteratrlearning.ui.panels;
    exports com.iteratrlearning.ui.widgets to
            com.iteratrlearning.ui.widgetuser;
}

com.iteratrlearning.ui.widgets 에 접근 권한을 가진 사용지의 권한을 com.iteratrlearning.ui.widgetuser로 제한한다.

 

5) open 과 opens

모듈 선언에 open 키워드를 사용하면 모든 패키지를 다른 모듈에 반사적으로 접근을 허용할 수 있다.

전체 모듈을 개방하지 않고도 opens 구문을 모듈 선언에 이용해 필요한 개별 패키지만 개방할 수 있습니다.

 

* 자바 9에서 모듈 시스템을 이용할 때, 기본적으로 리플렉션을 사용해 상태를 고치는 것을 허용하지 않는다. 따라서 그런 기능이 필요하다면 특정 패키지를 개방하는 opens 구문이나 open으로 명시적으로 개방해야한다.