Java Programming for Complete Beginners - in28Minutes Official 강의중 정리내용입니다.

모듈이란

  • 모듈이란 서로 밀접하게 연관된 패키지들과 리소스들의 그룹이다 (즉, "자바 패키지들의 패키지(package of Java Packages)"인 셈)
  • 이는 코드의 재사용성을 높이기 위해 추상화 단계를 하나 더 추가한 것이라고 볼 수 있다.

    디폴트 모듈

    Java SE9 이후로 자바를 설치하면 이전 버전과 다르게 JDK의 기존의 패키지들이 모두 모듈 시스템으로 옮겨진 것을 확인할 수 있다 java 17버전 기준으로 default modules는 다음과 같다
    java --list-modules 
    
    java.base@17.0.2
    java.compiler@17.0.2
    java.datatransfer@17.0.2
    java.desktop@17.0.2
    java.instrument@17.0.2
    java.logging@17.0.2
    java.management@17.0.2
    java.management.rmi@17.0.2
    java.naming@17.0.2
    java.net.http@17.0.2
    java.prefs@17.0.2
    java.rmi@17.0.2
    java.scripting@17.0.2
    java.se@17.0.2
    java.security.jgss@17.0.2
    java.security.sasl@17.0.2
    java.smartcardio@17.0.2
    java.sql@17.0.2
    java.sql.rowset@17.0.2
    java.transaction.xa@17.0.2
    java.xml@17.0.2
    java.xml.crypto@17.0.2
    jdk.accessibility@17.0.2
    jdk.attach@17.0.2
    jdk.charsets@17.0.2
    jdk.compiler@17.0.2
    jdk.crypto.cryptoki@17.0.2
    jdk.crypto.ec@17.0.2
    jdk.dynalink@17.0.2
    jdk.editpad@17.0.2
    jdk.hotspot.agent@17.0.2
    jdk.httpserver@17.0.2
    jdk.incubator.foreign@17.0.2
    jdk.incubator.vector@17.0.2
    jdk.internal.ed@17.0.2
    jdk.internal.jvmstat@17.0.2
    jdk.internal.le@17.0.2
    jdk.internal.opt@17.0.2
    jdk.internal.vm.ci@17.0.2
    jdk.internal.vm.compiler@17.0.2
    jdk.internal.vm.compiler.management@17.0.2
    jdk.jartool@17.0.2
    jdk.javadoc@17.0.2
    jdk.jcmd@17.0.2
    jdk.jconsole@17.0.2
    jdk.jdeps@17.0.2
    jdk.jdi@17.0.2
    jdk.jdwp.agent@17.0.2
    jdk.jfr@17.0.2
    jdk.jlink@17.0.2
    jdk.jpackage@17.0.2
    jdk.jshell@17.0.2
    jdk.jsobject@17.0.2
    jdk.jstatd@17.0.2
    jdk.localedata@17.0.2
    jdk.management@17.0.2
    jdk.management.agent@17.0.2
    jdk.management.jfr@17.0.2
    jdk.naming.dns@17.0.2
    jdk.naming.rmi@17.0.2
    jdk.net@17.0.2
    jdk.nio.mapmode@17.0.2
    jdk.random@17.0.2
    jdk.sctp@17.0.2
    jdk.security.auth@17.0.2
    jdk.security.jgss@17.0.2
    jdk.unsupported@17.0.2
    jdk.unsupported.desktop@17.0.2
    jdk.xml.dom@17.0.2
    jdk.zipfs@17.0.2

    모듈 선언

    • module-info.java라는 모듈 설명자 파일을 패키지 루트 레벨에 생성해야 한다.(모듈을 생성하는데 필요한 모든 데이터가 들어있다.)

      module myModuleName {
          // 설정값들은 모두 Optional
      }

      'module' 키워드로 모듈 선언을 시작하고, 그다음 모듈 이름을 쓴다. 이러한 선언만으로도 모듈은 동작하지만, 일반적으로 더 많은 정보(설정값들)가 필요하다.

      requires

    • 모듈의 종속성을 나타낸다.

      module my.module {
          requires module.name;
      }
    • my.module은 'module.name'에 대한 종속성을 갖게 된다(Compile & Runtime)

    • my.module는 module.name에서 외부로 공개(exports)하기로 한 모든 public type들에 대한 접근이 가능하다.

      requires static

    • 선택적 종속성(optional dependency)을 위해 사용

    • requires static 키워드를 사용하여 오직 컴파일 타임에 대한 종속성(compile-time-only dependency)을 갖게 할 수 있다.

      module my.module {
          requires static module.name;
      }

      requires transitive

    • 모듈의 사용자들이 전이된 종속성에 대한 접근이 가능하도록 강제할 수 있다.

      module my.module {
          requires transitive module.name;
      }

      이제 어떤 개발자가 자신의 모듈에 requires my.module을 추가한다면, requires module.name은 추가하지 않아도 이에 대한 접근이 가능하다.

      exports

    • 디폴트로, 모듈은 자신의 API를 다른 모듈에 노출시키지 않는다

      • 이러한 강력한 캡슐화가 모듈 시스템이 만들어진 주요 동기 중 하나였다.
      • API가 사용될 수 있게 하려면 명시적으로 공개 범위를 나타내야 한다.
    • 모듈 내의 모든 public 멤버들을 외부로 노출시키기 위해 exports 키워드를 사용한다.

      module my.module {
          exports com.my.package.name;
      }

      이제 어떤 개발자가 자신의 모듈에 'requires my.module'을 추가한다면, com.my.package.name 패키지 내의 모든 public 타입에 접근할 수 있다. 하지만 다른 패키지에는 접근할 수 없다.

      exports … to

    • exports…to 키워드를 이용하여 모듈의 API를 특정 모듈에만 공개하도록 설정할 수 있다.

      module my.module {
          export com.my.package.name to com.specific.package;
      }

      uses

    • uses 키워드를 통해 모듈이 사용할 서비스를 지정할 수 있다
      - uses 키워드 뒤에 추가될 것은 구현 클래스가 아니라 서비스의 인터페이스 혹은 추상 클래스여야 한다

      > 서비스란 다른 클래스에서 사용할 수 있는 특정 인터페이스 또는 추상 클래스의 구현을 말한다.
      > 
      module my.module {
          uses class.name.MyInterface;
      }

      provides … with

    • 모듈은 다른 모듈이 소비(uses)할 수 있는 서비스 공급자가 될 수 있다.

    • provides 뒤에는 인터페이스 또는 추상 클래스 이름을 넣는다. 그리고 with 뒤에는 구현 클래스 이름을 넣는다.

      module my.module {
          provides class.name.MyInterface with class.name.MyInterfaceImpl;
      }

      open

    • 리플렉션을 모두 허용하려면 open 키워드를 사용한다

      open module my.module {
      }

      opens

    • 만약 특정 패키지에 대해서만 리플렉션을 허용하고 싶을 경우, opens 키워드 뒤에 패키지를 명시한다

      module my.module {
        opens com.my.package;
      }

      opens … to

      만약 특정 패키지에 대한 리플랙션을 특정 모듈들에 대해서만 허용하려면 opens 뒤에 패키지를 명시하고 to 뒤에 타켓 모듈을 설정한.

      module my.module {
          opens com.my.package to moduleOne, moduleTwo, etc.;
      }

0개의 댓글