Post

🐹 chap14. μžλ°” λͺ¨λ“ˆ μ‹œμŠ€ν…œ

μžλ°” 9μ—μ„œ κ°€μž₯ 많이 κ±°λ‘ λ˜λŠ” μƒˆλ‘œμš΄ κΈ°λŠ₯은 λͺ¨λ“ˆ μ‹œμŠ€ν…œμ΄λ‹€.

14.1 μ••λ ₯ : μ†Œν”„νŠΈμ›¨μ–΄ μœ μΆ”

μ €μˆ˜μ€€ μ˜μ—­ : μœ μ§€λ³΄μˆ˜ν•˜κΈ° μ‰¬μš΄ μ½”λ“œλ₯Ό κ΅¬ν˜„

κ³ μˆ˜μ€€ μ˜μ—­ : ꢁ극적으둜 μ†Œν”„νŠΈμ›¨μ–΄ μ•„ν‚€ν…μ²˜(κ³ μˆ˜μ€€ 기반 μ½”λ“œ)λ₯Ό λ°”κΏ”μ•Ό ν•  λ•Œ μœ μΆ”ν•˜κΈ° μ‰¬μš°λ―€λ‘œ 생산성을 높일 수 μžˆλŠ” μ†Œν”„νŠΈμ›¨μ–΄ ν”„λ‘œμ νŠΈκ°€ ν•„μš”

β†’ 관심사 뢄리와 정보 은닉

14.1.1 관심사 뢄리

: 컴퓨터 ν”„λ‘œκ·Έλž¨μ„ 고유의 κΈ°λŠ₯으둜 λ‚˜λˆ„λŠ” λ™μž‘μ„ ꢌμž₯ν•˜λŠ” 원칙

Soc(Seperation of concerns) - 관심사 뢄리

ex) λ‹€μ–‘ν•œ ν˜•μ‹μœΌλ‘œ κ΅¬μ„±λœ μ§€μΆœμ„ νŒŒμ‹±ν•˜κ³ , λΆ„μ„ν•œ λ‹€μŒ κ²°κ³Όλ₯Ό κ³ κ°μ—κ²Œ μš”μ•½ λ³΄κ³ ν•˜λŠ” νšŒκ³„ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 개발

SoC(관심사 뢄리)λ₯Ό μ μš©ν•¨μœΌλ‘œ νŒŒμ‹±, 뢄석, 레포트 κΈ°λŠ₯을 λͺ¨λ“ˆμ΄λΌλŠ” 각각의 λΆ€λΆ„ 즉, μ„œλ‘œ 거의 κ²ΉμΉ˜μ§€ μ•ŠλŠ” μ½”λ“œ 그룹으둜 뢄리할 수 μžˆλ‹€.

β†’ 클래슀λ₯Ό κ·Έλ£Ήν™”ν•œ λͺ¨λ“ˆμ„ μ΄μš©ν•΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 클래슀 κ°„μ˜ 관계λ₯Ό μ‹œκ°μ μœΌλ‘œ 보여쀄 수 μžˆλ‹€.

λͺ¨λΈ, λ·°, 컨트둀러 같은 μ•„ν‚€ν…μ²˜ 관점 그리고 볡ꡬ 기법을 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직과 λΆ„λ¦¬ν•˜λŠ” λ“±μ˜ ν•˜μœ„ μˆ˜μ€€ μ ‘κ·Ό λ“±μ˜ 상황 β†’ SoC 원칙이 유용

[ SoC μ›μΉ™μ˜ μž₯점 ]

  • κ°œλ³„ κΈ°λŠ₯을 λ”°λ‘œ μž‘μ—…ν•  수 μžˆμœΌλ―€λ‘œ νŒ€μ΄ μ‰½κ²Œ ν˜‘μ—…ν•  수 μžˆλ‹€.
  • κ°œλ³„ 뢀뢄을 μž¬μ‚¬μš©ν•˜κΈ° 쉽닀.
  • 전체 μ‹œμŠ€ν…œμ„ μ‰½κ²Œ μœ μ§€λ³΄μˆ˜ν•  수 μžˆλ‹€.

14.1.2 정보 은닉

: μ„ΈλΆ€ κ΅¬ν˜„μ„ μˆ¨κΈ°λ„λ‘ μž₯λ €ν•˜λŠ” 원칙

μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό κ°œλ°œν•  λ•Œ μš”κ΅¬μ‚¬ν•­μ€ 자주 λ³€κ²½λœλ‹€. μ„ΈλΆ€ κ΅¬ν˜„μ„ μˆ¨κΉ€μœΌλ‘œ ν”„λ‘œκ·Έλž¨μ˜ μ–΄λ–€ 뢀뢄을 바꿨을 λ•Œ λ‹€λ₯Έ λΆ€λΆ„κΉŒμ§€ 영ν–₯을 λ―ΈμΉ  κ°€λŠ₯성을 쀄일 수 μžˆλ‹€.

β†’ μ½”λ“œλ₯Ό κ΄€λ¦¬ν•˜κ³  λ³΄ν˜Έν•˜λŠ” 데 μœ μš©ν•œ 원칙

μΊ‘μŠν™”

νŠΉμ • μ½”λ“œ 쑰각이 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λ‹€λ₯Έ λΆ€λΆ„κ³Ό κ³ λ¦½λ˜μ–΄ μžˆλ‹€.

μΊ‘μŠν™”λœ μ½”λ“œμ˜ 내뢀적인 λ³€ν™”κ°€ μ˜λ„μΉ˜ μ•Šκ²Œ 외뢀에 영ν–₯을 λ―ΈμΉ  κ°€λŠ₯성이 쀄어든닀. 클래슀 λ‚΄μ˜ μ»΄ν¬λ„ŒνŠΈμ— 적절히 private ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν–ˆλŠ”μ§€λ₯Ό κΈ°μ€€μœΌλ‘œ 컴파일러λ₯Ό μ΄μš©ν•΄ μΊ‘μŠν™”λ₯Ό 확인할 수 μžˆλ‹€.

μžλ°” 9 μ΄μ „κΉŒμ§€λŠ” ν΄λž˜μŠ€μ™€ νŒ¨ν‚€μ§€κ°€ μ˜λ„λœ λŒ€λ‘œ κ³΅κ°œλ˜μ—ˆλŠ”μ§€λ₯Ό 컴파일러둜 확인할 수 μžˆλŠ” κΈ°λŠ₯이 μ—†μ—ˆλ‹€.

14.1.3 μžλ°” μ†Œν”„νŠΈμ›¨μ–΄

잘 μ„€κ³„λœ μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό λ§Œλ“€λ €λ©΄ μœ„μ˜ 두 가지 원칙을 λ”°λ₯΄λŠ” 것이 ν•„μˆ˜λ‹€.

μ½”λ“œλ§ŒμœΌλ‘œλŠ” μ†Œν”„νŠΈμ›¨μ–΄ λ™μž‘μ„ μΆ”λ‘ ν•˜κΈ° μ–΄λ ΅λ‹€. λ”°λΌμ„œ UML λ‹€μ΄μ–΄κ·Έλž¨κ°™μ€ 도ꡬλ₯Ό μ΄μš©ν•˜λ©΄ κ·Έλ£Ή μ½”λ“œ κ°„μ˜ μ˜μ‘΄μ„±μ„ μ‹œκ°μ μœΌλ‘œ 보여쀄 수 μžˆμœΌλ―€λ‘œ μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό μΆ”λ‘ ν•˜λŠ”λ° 도움이 λœλ‹€.

정보은닉을 μ‚΄νŽ΄λ³΄λ©΄ μžλ°”μ—μ„œ public, protected, private λ“±μ˜ μ ‘κ·Ό μ œν•œμžμ™€ νŒ¨ν‚€μ§€ μˆ˜μ€€ μ ‘κ·Ό κΆŒν•œμ„ μ΄μš©ν•΄ λ©”μ„œλ“œ, ν•„λ“œ 클래슀의 접근을 μ œμ–΄ν–ˆλ‹€.

ν•˜μ§€λ§Œ 이런 λ°©μ‹μœΌλ‘œλŠ” μ›ν•˜λŠ” μ ‘κ·Ό μ œν•œμ„ λ‹¬μ„±ν•˜κΈ° μ–΄λ €μš°λ©° 심지어 μ΅œμ’… μ‚¬μš©μžμ—κ²Œ μ›ν•˜μ§€ μ•ŠλŠ” λ©”μ„œλ“œλ„ κ³΅κ°œν•΄μ•Ό ν•˜λŠ” 상황이 λ°œμƒν–ˆλ‹€.

14.2 μžλ°” λͺ¨λ“ˆ μ‹œμŠ€ν…œμ„ μ„€κ³„ν•œ 이유

14.2.1 λͺ¨λ“ˆν™”μ˜ ν•œκ³„

μžλ°” 9 μ΄μ „κΉŒμ§€λŠ” λͺ¨λ“ˆν™”λœ μ†Œν”„νŠΈμ›¨μ–΄ ν”„λ‘œμ νŠΈλ₯Ό λ§Œλ“œλŠ” 데 ν•œκ³„κ°€ μžˆμ—ˆλ‹€.

μžλ°”λŠ” 클래슀, νŒ¨ν‚€μ§€, JAR μ„Έ 가지 μˆ˜μ€€μ˜ μ½”λ“œ κ·Έλ£Ήν™”λ₯Ό μ œκ³΅ν•œλ‹€. ν΄λž˜μŠ€μ™€ κ΄€λ ¨ν•΄ μžλ°”λŠ” μ ‘κ·Ό μ œν•œμžμ™€ μΊ‘μŠν™”λ₯Ό μ§€μ›ν–ˆλ‹€.

ν•˜μ§€λ§Œ νŒ¨ν‚€μ§€μ™€ JAR μˆ˜μ€€μ—μ„œλŠ” μΊ‘μŠν™”λ₯Ό 거의 μ§€μ›ν•˜μ§€ μ•Šμ•˜λ‹€.

μ œν•œλœ κ°€μ‹œμ„± μ œμ–΄

μžλ°”μ˜ λ„€ 가지 κ°€μ‹œμ„±. μ ‘κ·Όμž

β†’ public, protected, νŒ¨ν‚€μ§€ μˆ˜μ€€(default) , private

νŒ¨ν‚€μ§€ κ°„μ˜ κ°€μ‹œμ„±μ€ μ–΄λ–»κ²Œ μ œμ–΄ν• κΉŒ?

ν•œ νŒ¨ν‚€μ§€μ˜ ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ‹€λ₯Έ νŒ¨ν‚€μ§€λ‘œ κ³΅κ°œν•˜λ €λ©΄ public을 μ„ μ–Έν•΄μ•Ό ν•œλ‹€. 결과적으둜 이듀 ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€λŠ” λͺ¨λ‘μ—κ²Œ κ³΅κ°œλœλ‹€.

특히 κΈ°λ³Έ κ΅¬ν˜„μ„ μ œκ³΅ν•˜λŠ” 의미둜 β€œimplβ€μ΄λΌλŠ” λ¬Έμžμ—΄μ„ 가진 νŒ¨ν‚€μ§€μ—μ„œ 이런 λ¬Έμ œκ°€ λ‘λ“œλŸ¬μ§„λ‹€. 이런 μƒν™©μ—μ„œ 보톡 νŒ¨ν‚€μ§€ λ‚΄λΆ€μ˜ μ ‘κ·Όμž public μ΄λ―€λ‘œ μ‚¬μš©μžκ°€ 이 λ‚΄λΆ€ κ΅¬ν˜„μ„ λ§ˆμŒλŒ€λ‘œ μ‚¬μš©ν•  수 μžˆλ‹€.

β‡’ λ‹€λ₯Έ ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μž„μ‹œμ μœΌλ‘œ μ‚¬μš©ν•΄ 정착해버릴 수 μžˆμœΌλ―€λ‘œ 기쑴의 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ§κ°€λœ¨λ¦¬μ§€ μ•Šκ³  라이브러리 μ½”λ“œλ₯Ό λ°”κΎΈκΈ° μ–΄λ €μ›Œμ§„λ‹€. λ³΄μ•ˆ μΈ‘λ©΄μ—μ„œλ„ μ½”λ“œκ°€ λ…ΈμΆœλ˜μ—ˆμœΌλ―€λ‘œ μž„μ˜λ‘œ μ‘°μž‘ν•˜λŠ” μœ„ν˜‘μ— 도 많이 λ…ΈμΆœλ  수 μžˆλ‹€.

클래슀 경둜

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ²ˆλ“€ν•˜κ³  μ‹€ν–‰ν•˜λŠ” κΈ°λŠ₯κ³Ό κ΄€λ ¨ν•΄ μžλ°”λŠ” νƒœμƒμ μœΌλ‘œ 약점을 κ°–κ³  μžˆλ‹€. 클래슀λ₯Ό λͺ¨λ‘ μ»΄νŒŒμΌν•œ λ‹€μŒ 보톡 ν•œ 개의 ν‰λ²”ν•œ JAR νŒŒμΌμ— λ„£κ³  클래슀 κ²½λ‘œμ— 이 JAR νŒŒμΌμ„ μΆ”κ°€ν•΄ μ‚¬μš©ν•  수 μžˆλ‹€. 그러면 JVM이 λ™μ μœΌλ‘œ 클래슀 κ²½λ‘œμ— μ •μ˜λœ 클래슀λ₯Ό ν•„μš”ν•  λ•Œ μ½λŠ”λ‹€.

클래슀 κ²½λ‘œμ™€ JAR μ‘°ν•©μ—λŠ” λͺ‡ 가지 약점이 μ‘΄μž¬ν•œλ‹€.

  1. 클래슀 κ²½λ‘œμ—λŠ” 같은 클래슀λ₯Ό κ΅¬λΆ„ν•˜λŠ” 버전 κ°œλ…μ΄ μ—†λ‹€.

    ex) νŒŒμ‹± 라이브러리 JSONParser 클래슀λ₯Ό 지정할 λ•Œ 버전 1.0을 μ‚¬μš©ν•˜λŠ”μ§€ 버전 2.0을 μ‚¬μš©ν•˜λŠ”μ§€ 지정할 μˆ˜κ°€ μ—†μœΌλ―€λ‘œ 클래슀 κ²½λ‘œμ— 두 가지 λ²„μ „μ˜ 같은 λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μ‘΄μž¬ν•  λ•Œ μ–΄λ–€ 일이 일어날지 μ˜ˆμΈ‘ν•  수 μ—†λ‹€.

    λ‹€μ–‘ν•œ μ»΄ν¬λ„ŒνŠΈκ°€ 같은 라이브러리의 λ‹€λ₯Έ 버전을 μ‚¬μš©ν•˜λŠ” 상황이 λ°œμƒν•  수 μžˆλŠ” 큰 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ 이런 λ¬Έμ œκ°€ λ‘λ“œλŸ¬μ§„λ‹€.

  2. 클래슀 κ²½λ‘œλŠ” λͺ…μ‹œμ μΈ μ˜μ‘΄μ„±μ„ μ§€μ›ν•˜μ§€ μ•ŠλŠ”λ‹€.

    각각의 JAR μ•ˆμ— μžˆλŠ” λͺ¨λ“  ν΄λž˜μŠ€λŠ” classesλΌλŠ” ν•œ μ£Όλ¨Έλ‹ˆλ‘œ 합쳐진닀. 즉 ν•œ JARκ°€ ν¬ν•¨λœ 클래슀 집합을 μ‚¬μš©ν•˜λΌκ³  λͺ…μ‹œμ μœΌλ‘œ μ˜μ‘΄μ„±μ„ μ •μ˜ν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•˜μ§€ μ•ŠλŠ”λ‹€. 이 μƒν™©μ—μ„œλŠ” 클래슀 경둜 λ•Œλ¬Έμ— μ–΄λ–€ 일이 μΌμ–΄λ‚˜λŠ”μ§€ νŒŒμ•…ν•˜κΈ° μ–΄λ €μš°λ©°, λ‹€μŒκ³Ό 같은 의문이 λ“ λ‹€.

    • 빠진 게 μžˆλŠ”κ°€?
    • 좩돌이 μžˆλŠ”κ°€?

    λ©”μ΄λΈμ΄λ‚˜ κ·Έλ ˆμ΄λ“€ 같은 λΉŒλ“œ λ„κ΅¬λŠ” 이런 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 데 도움을 μ€€λ‹€.

    ν•˜μ§€λ§Œ μžλ°” 9 μ΄μ „μ—λŠ” μžλ°”, JVM λˆ„κ΅¬λ„ λͺ…μ‹œμ μΈ μ˜μ‘΄μ„± μ •μ˜λ₯Ό μ§€μ›ν•˜μ§€ μ•Šμ•˜λ‹€.

14.2.2 κ±°λŒ€ν•œ JDK

μžλ°” 개발 ν‚€νŠΈ(JDK)

μžλ°” ν”„λ‘œκ·Έλž¨μ„ λ§Œλ“€κ³  μ‹€ν–‰ν•˜λŠ” 데 도움을 μ£ΌλŠ” λ„κ΅¬μ˜ 집합

  • javac - μžλ°” ν”„λ‘œκ·Έλž¨ 컴파일러
  • java - μžλ°” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ‘œλ“œν•˜κ³  μ‹€ν–‰
  • JDK 라이브러리 - μž…μΆœλ ₯을 포함해 λŸ°νƒ€μž„ 지원을 제곡
  • μ»¬λ ‰μ…˜
  • 슀트림

등이 μžˆλ‹€.

μžλ°” 8의 컴팩트 ν”„λ‘œνŒŒμΌ 기법

κ΄€λ ¨ 뢄야에 따라 JDKλΌμ΄λΈŒλŸ¬λ¦¬κ°€ μ„Έ 가지 ν”„λ‘œνŒŒμΌλ‘œ λ‚˜λ‰˜μ–΄ 각각 λ‹€λ₯Έ λ©”λͺ¨λ¦¬ ν’‹ν”„λ¦°νŠΈλ₯Ό 제곡

14.3 μžλ°” λͺ¨λ“ˆ : 큰 κ·Έλ¦Ό

μžλ°” 8λŠ” λͺ¨λ“ˆμ΄λΌλŠ” μƒˆλ‘œμš΄ μžλ°” ν”„λ‘œκ·Έλž¨ ꡬ쑰 λ‹¨μœ„λ₯Ό μ œκ³΅ν•œλ‹€.

moduleμ΄λΌλŠ” μƒˆ ν‚€μ›Œλ“œμ— 이름과 λ°”λ””λ₯Ό μΆ”κ°€ν•΄μ„œ μ •μ˜ν•œλ‹€.

λͺ¨λ“ˆ λ””μŠ€ν¬λ¦½ν„°

  • module-info.javaλΌλŠ” νŠΉλ³„ν•œ νŒŒμΌμ— μ €μž₯
  • 보톡 νŒ¨ν‚€μ§€μ™€ 같은 폴더에 μœ„μΉ˜ν•˜λ©° ν•œ 개 μ΄μƒμ˜ νŒ¨ν‚€μ§€λ₯Ό μ„œμˆ ν•˜κ³  μΊ‘μŠν™”ν•  수 μžˆμ§€λ§Œ λ‹¨μˆœν•œ μƒν™©μ—μ„œλŠ” 이듀 νŒ¨ν‚€μ§€ 쀑 ν•œ 개만 μ™ΈλΆ€λ‘œ λ…ΈμΆœμ‹œν‚΄

μ§μ†Œ 퍼즐에 λΉ„μœ ν•˜μžλ©΄ exports - λŒμΆœλΆ€, requires - 패인 λΆ€λΆ„ 으둜 생각할 수 μžˆλ‹€.

메이븐 같은 도ꡬλ₯Ό μ‚¬μš©ν•  λ•Œ λͺ¨λ“ˆμ˜ λ§Žμ€ μ„ΈλΆ€ 사항을 IDEκ°€ μ²˜λ¦¬ν•˜λ©° μ‚¬μš©μžμ—κ²ŒλŠ” 잘 λ“œλŸ¬λ‚˜μ§€ μ•ŠλŠ”λ‹€.

14.4 μžλ°” λͺ¨λ“ˆ μ‹œμŠ€ν…œμœΌλ‘œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ κ°œλ°œν•˜κΈ°

14.4.1 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ…‹μ—…

μžλ°” λͺ¨λ“ˆ μ‹œμŠ€ν…œμ„ μ μš©ν•˜κΈ° μœ„ν•΄ μ½”λ“œλ₯Ό κ΅¬ν˜„ν•  예제 ν”„λ‘œμ νŠΈλ‘œ 영수증 λΉ„μš© 관리 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ΅¬ν˜„ν•΄λ³΄μž. λ‹€μŒκ³Ό 같은 μ—¬λŸ¬ μž‘μ—…μ„ μ²˜λ¦¬ν•΄μ•Ό ν•œλ‹€.

  • νŒŒμΌμ΄λ‚˜ URLμ—μ„œ λΉ„μš© λͺ©λ‘μ„ μ½λŠ”λ‹€.
  • λΉ„μš©μ˜ λ¬Έμžμ—΄ ν‘œν˜„μ„ νŒŒμ‹±ν•œλ‹€.
  • 톡계λ₯Ό κ³„μ‚°ν•œλ‹€.
  • μœ μš©ν•œ μš”μ•½ 정보λ₯Ό ν‘œμ‹œν•œλ‹€.
  • 각 νƒœμŠ€ν¬μ˜ μ‹œμž‘, 마무리 지점을 μ œκ³΅ν•œλ‹€.

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ κ°œλ…μ„ λͺ¨λΈλ§ν•  μ—¬λŸ¬ ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•΄μ•Ό ν•œλ‹€.

[ Reader μΈν„°νŽ˜μ΄μŠ€ ]

μ†ŒμŠ€μ—μ„œ μ–»μ–΄μ˜¨ μ§λ ¬ν™”λœ μ§€μΆœμ„ μ½λŠ” μ—­ν• 

  • μ†ŒμŠ€κ°€ 어디냐에 따라 HttpReader, FileReader λ“± μ—¬λŸ¬ κ΅¬ν˜„μ„ μ œκ³΅ν•΄μ•Ό ν•œλ‹€.
  • JSON 객체λ₯Ό μžλ°” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” 도메인 객체 Expense둜 μž¬κ΅¬μ„±ν•  Parser μΈν„°νŽ˜μ΄μŠ€λ„ ν•„μš”ν•˜λ‹€.
  • 주어진 Expense 객체 λͺ©λ‘μœΌλ‘œ 톡계λ₯Ό κ³„μ‚°ν•˜κ³  SummaryStatistics 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” SummaryCalculator ν΄λž˜μŠ€κ°€ ν•„μš”ν•˜λ‹€.

ν”„λ‘œμ νŠΈλ₯Ό μ€€λΉ„ν–ˆμœΌλ‹ˆ μžλ°” λͺ¨λ“ˆ μ‹œμŠ€ν…œμœΌλ‘œ 이듀을 λͺ¨λ“ˆν™”ν•΄μ•Ό ν•œλ‹€. ν”„λ‘œμ νŠΈμ—λŠ” λ‹€μŒμ²˜λŸΌ 뢄리할 수 μžˆλŠ” μ—¬λŸ¬ κΈ°λŠ₯(관심사)이 μžˆλ‹€.

  • λ‹€μ–‘ν•œ μ†ŒμŠ€μ—μ„œ 데이터λ₯Ό 읽음(Reader, HttpReader, FileReader)
  • λ‹€μ–‘ν•œ 포맷으둜 κ΅¬μ„±λœ 데이터λ₯Ό νŒŒμ‹±(Parse, JSONParser, ExpenseJSON-Parser)
  • 도메인 객체λ₯Ό ꡬ체화(Expense)
  • 톡계λ₯Ό κ³„μ‚°ν•˜κ³  λ°˜ν™˜(SummaryCalculator, SummaryStatics)
  • λ‹€μ–‘ν•œ κΈ°λŠ₯을 뢄리 μ‘°μ •(ExpensesApplication)

κ΅μˆ˜λ²•μ— 따라 μ•„μ£Ό μ„ΈλΆ€μ μœΌλ‘œ 문제λ₯Ό λ‚˜λˆ„λŠ” μ ‘κ·Ό 방법을 μ΄μš©ν•œλ‹€. λ‹€μŒμ²˜λŸΌ 각 κΈ°λŠ₯을 κ·Έλ£Ήν™”ν•  수 μžˆλ‹€(λͺ¨λ“ˆμ„ λͺ…λͺ…ν•œ 배경은 λ‚˜μ€‘μ— μ„€λͺ…ν•œλ‹€)

  • expenses.readers
  • expenses.readers.http
  • expenses.readers.file
  • expenses.parsers
  • expenses.parsers.json
  • expenses.model
  • expenses.statistics
  • expenses.application

이 κ°„λ‹¨ν•œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ λͺ¨λ“ˆ μ‹œμŠ€ν…œμ˜ μ—¬λŸ¬ 뢀뢄이 λ‘λ“œλŸ¬μ§ˆ 수 μžˆλ„λ‘ 잘게 λΆ„ν•΄ν–ˆλ‹€.

κ°„λ‹¨ν•œ ν”„λ‘œμ νŠΈμ—μ„œ 이처럼 잘게 λΆ„ν•΄ν•΄ μž‘μ€ κΈ°λŠ₯κΉŒμ§€ μΊ‘μŠν™”ν•˜λŠ” 것은 μž₯점에 λΉ„ν•΄ 초기 λΉ„μš©μ΄ 높아진닀. ν•˜μ§€λ§Œ ν”„λ‘œμ νŠΈκ°€ 점점 μ»€μ§€λ©΄μ„œ λ§Žμ€ λ‚΄λΆ€ κ΅¬ν˜„μ΄ μΆ”κ°€λ˜λ©΄ μ΄λ•ŒλΆ€ν„° μΊ‘μŠν™”μ™€ μΆ”λ‘ μ˜ μž₯점이 λ‘λ“œλŸ¬μ§„λ‹€.

μœ„ λͺ©λ‘λ“€μ€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 경계에 μ˜μ‘΄ν•˜λŠ” νŒ¨ν‚€μ§€ λͺ©λ‘μœΌλ‘œ 생각할 수 μžˆλ‹€. μ•„λ§ˆ 각 λͺ¨λ“ˆμ€ λ‹€λ₯Έ λͺ¨λ“ˆλ‘œ λ…ΈμΆœν•˜κ³  싢지 μ•ŠλŠ” λ‚΄λΆ€ κ΅¬ν˜„μ„ 포함할 것이닀.

ex) expenses.statistics λͺ¨λ“ˆμ€ μ‹€ν—˜μ μΈ 톡계 방법을 λ‹€λ₯Έ λ°©λ²•μœΌλ‘œ κ΅¬ν˜„ν•œ μ—¬λŸ¬ νŒ¨ν‚€μ§€λ₯Ό 포함할 수 μžˆλ‹€. 이듀 νŒ¨ν‚€μ§€μ—μ„œ μ–΄λ–€ 것을 μ‚¬μš©μžμ—κ²Œ λ¦΄λ¦¬μŠ€ν• μ§€λŠ” λ‚˜μ€‘μ— κ²°μ •ν•  수 μžˆλ‹€.

14.4.2 세뢀적인 λͺ¨λ“ˆν™”와 거친 λͺ¨λ“ˆν™”

  • 세뢀적인 λͺ¨λ“ˆν™”

    : λͺ¨λ“  νŒ¨ν‚€μ§€κ°€ μžμ‹ μ˜ λͺ¨λ“ˆμ„ κ°–λŠ”λ‹€.

    β†’ 섀계 λΉ„μš© 증가

  • 거친 λͺ¨λ“ˆν™”

    : ν•œ λͺ¨λ“ˆμ΄ μ‹œμŠ€ν…œμ˜ λͺ¨λ“  νŒ¨ν‚€μ§€λ₯Ό ν¬ν•¨ν•œλ‹€.

    β†’ λͺ¨λ“ˆν™”μ˜ λͺ¨λ“  μž₯점을 μžƒμŒ

κ°€μž₯ 쒋은 방법은 μ‹œμŠ€ν…œμ„ μ‹€μš©μ μœΌλ‘œ λΆ„ν•΄ν•˜λ©΄μ„œ μ§„ν™”ν•˜λŠ” μ†Œν”„νŠΈμ›¨μ–΄ ν”„λ‘œμ νŠΈκ°€ μ΄ν•΄ν•˜κΈ° 쉽고 고치기 μ‰¬μš΄ μˆ˜μ€€μœΌλ‘œ μ μ ˆν•˜κ²Œ λͺ¨λ“ˆν™”λ˜μ–΄ μžˆλŠ”μ§€ 주기적으둜 ν™•μΈν•˜λŠ” ν”„λ‘œμ„ΈμŠ€λ₯Ό κ°–λŠ” 것이닀.

λͺ¨λ“ˆν™” = μ†Œν”„νŠΈμ›¨μ–΄ λΆ€μ‹μ˜ 적

14.4.3 μžλ°” λͺ¨λ“ˆ μ‹œμŠ€ν…œ 기초

메인 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ§€μ›ν•˜λŠ” ν•œ 개의 λͺ¨λ“ˆλ§Œ κ°–λŠ” 기본적 λͺ¨λ“ˆν™” μ• ν”Œλ¦¬μΌ€μ΄μ…˜

module-info.javaλΌλŠ” 파일이 ν”„λ‘œμ νŠΈ ꡬ쑰의 일뢀에 ν¬ν•¨λ˜μ–΄ μžˆλ‹€. 이 νŒŒμΌμ€ μ•žμ—μ„œ μ„€λͺ…ν•œ λͺ¨λ“ˆ λ””μŠ€ν¬λ¦½ν„°λ‘œ λͺ¨λ“ˆμ˜ μ†ŒμŠ€μ½”λ“œ 파일 λ£¨νŠΈμ— μœ„μΉ˜ν•΄μ•Ό ν•˜λ©° λͺ¨λ“ˆμ˜ μ˜μ‘΄μ„± 그리고 μ–΄λ–€ κΈ°λŠ₯을 μ™ΈλΆ€λ‘œ λ…ΈμΆœν•  지λ₯Ό μ •μ˜ν•œλ‹€.

μ§€μΆœ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ˜ˆμ œμ—μ„œλŠ” 아직 λ‹€λ₯Έ λͺ¨λ“ˆμ— μ˜μ‘΄ν•˜κ±°λ‚˜ μ™ΈλΆ€λ‘œ λ…ΈμΆœν•˜λŠ” κΈ°λŠ₯이 μ—†μœΌλ―€λ‘œ μ΅œμƒμœ„ μˆ˜μ€€μ˜ module-info.java νŒŒμΌμ— μ΄λ¦„λ§Œ μ •μ˜λ˜μ–΄ μžˆμ„ 뿐 λ‚΄μš©μ€ λΉ„μ–΄μžˆλ‹€.

1
2
3
4
// ν˜„μž¬ module-info.java
module expenses.application {

}

[ λͺ¨λ“ˆν™” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ 방법 ]

ν”„λ‘œμ νŠΈμ˜ λͺ¨λ“ˆ μ†ŒμŠ€ λ””λ ‰ν„°λ¦¬μ—μ„œ λ‹€μŒ λͺ…령을 μ‹€ν–‰ν•œλ‹€.

1
2
javac module-info.java
    com/example/expenses/application/ExpensesApplication.java -d target
1
2
jar cvfe expenses-application.jar
    com.example.expenses.application.ExpensesApplication -C target

그럼 μ–΄λ–€ 폴더와 클래슀 파일이 μƒμ„±λœ JAR(expenses-application.jar)에 ν¬ν•¨λ˜μ–΄ μžˆλŠ”μ§€λ₯Ό λ³΄μ—¬μ£ΌλŠ” λ‹€μŒκ³Ό 같은 κ²°κ³Όκ°€ 좜λ ₯λœλ‹€.

1
2
3
4
5
6
7
added manifest
added module-info: module-info.class adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/example/(in = 0) (out= 0)(stored 0%)
adding: com/example/expenses/(in = 0) (out= 0)(stored 0%)
adding: com/example/expenses/application/(in = 0) (out= 0)(stored 0%)
adding: com/example/expenses/application/ExpensesApplicatioin.class(in = 456)
	(out= 306)(deflated 32%)

λ§ˆμ§€λ§‰μœΌλ‘œ μƒμ„±λœ JARλ₯Ό λͺ¨λ“ˆν™” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μœΌλ‘œ μ‹€ν–‰ν•œλ‹€.

1
2
java --module-path expenses-application.jar \
	 --module expenses/com.example.expenses.application.ExpensesApplication

처음 두 과정은 μžλ°” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ JAR둜 νŒ¨ν‚€μ§•ν•˜λŠ” ν‘œμ€€ λ°©λ²•μ΄λ―€λ‘œ 이미 μ΅μˆ™ν•  것이닀. μƒˆλ‘œμš΄ 뢀뢄은 컴파일 과정에 μƒˆλ‘œ μΆ”κ°€λœ module-info.javaλ‹€.

java ν”„λ‘œκ·Έλž¨μœΌλ‘œ μžλ°” .class νŒŒμΌμ„ μ‹€ν–‰ν•  λ•Œ λ‹€μŒκ³Ό 같은 두 가지 μ˜΅μ…˜μ΄ μƒˆλ‘œ μΆ”κ°€λ˜μ—ˆλ‹€.

  • --module-path : μ–΄λ–€ λͺ¨λ“ˆμ„ λ‘œλ“œν•  수 μžˆλŠ”μ§€ μ§€μ •ν•œλ‹€. 이 μ˜΅μ…˜μ€ 클래슀 νŒŒμΌμ„ μ§€μ •ν•˜λŠ” --classpath μΈμˆ˜μ™€λŠ” λ‹€λ₯΄λ‹€.
  • --module : 이 μ˜΅μ…˜μ€ μ‹€ν–‰ν•  메인 λͺ¨λ“ˆκ³Ό 클래슀λ₯Ό μ§€μ •ν•œλ‹€.

λͺ¨λ“ˆ μ •μ˜λŠ” 버전 λ¬Έμžμ—΄μ„ ν¬ν•¨ν•˜μ§€ μ•ŠλŠ”λ‹€.

μžλ°” 9 λͺ¨λ“ˆ μ‹œμŠ€ν…œμ—μ„œ 버전 선택 문제λ₯Ό 크게 κ³ λ €ν•˜μ§€ μ•Šμ•˜κ³  λ”°λΌμ„œ 버전 κΈ°λŠ₯은 μ§€μ›ν•˜μ§€ μ•ŠλŠ”λ‹€. λŒ€μ‹  버전 λ¬Έμ œλŠ” λΉŒλ“œ λ„κ΅¬λ‚˜ μ»¨ν…Œμ΄λ„ˆ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ ν•΄κ²°ν•΄μ•Ό ν•  문제둜 λ„˜κ²Όλ‹€.

14.5 μ—¬λŸ¬ λͺ¨λ“ˆ ν™œμš©ν•˜κΈ°

λͺ¨λ“ˆμ„ μ΄μš©ν•œ κΈ°λ³Έ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ„€μ •ν–ˆλ‹€.

λΉ„μš© μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ†ŒμŠ€μ—μ„œ λΉ„μš©μ„ 읽을 수 μžˆμ–΄μ•Ό ν•œλ‹€. 이 κΈ°λŠ₯을 μΊ‘μŠν™”ν•œ expense.readerλΌλŠ” μƒˆ λͺ¨λ“ˆμ„ λ§Œλ“€ 것이닀. expenses.application와 expenses.readers 두 λͺ¨λ“ˆκ°„μ˜ μƒν˜Έ μž‘μš©μ€ μžλ°” 9μ—μ„œ μ§€μ •ν•œ export, requiresλ₯Ό μ΄μš©ν•΄ 이루어진닀.

14.5.1 exports ꡬ문

λ‹€μŒμ€ expenses.readers λͺ¨λ“ˆμ˜ 선언이닀.

1
2
3
4
5
6
module expenses.readers {
    // 이듀은 λͺ¨λ“ˆλͺ…이 μ•„λ‹ˆλΌ νŒ¨ν‚€μ§€λͺ…
    exports com.example.expenses.readers;
    exports com.example.expenses.readers.file;
    exports com.example.expenses.readers.http;
}

exports β†’ λ‹€λ₯Έ λͺ¨λ“ˆμ—μ„œ μ‚¬μš©ν•  수 μžˆλ„λ‘ νŠΉμ • νŒ¨ν‚€μ§€λ₯Ό 곡개 ν˜•μ‹μœΌλ‘œ λ§Œλ“ λ‹€.

기본적으둜 λͺ¨λ“ˆ λ‚΄μ˜ λͺ¨λ“  것은 μΊ‘μŠν™” λœλ‹€. λͺ¨λ“ˆ μ‹œμŠ€ν…œμ€ ν™”μ΄νŠΈ 리슀트 기법을 μ΄μš©ν•΄ κ°•λ ₯ν•œ μΊ‘μŠν™”λ₯Ό μ œκ³΅ν•˜λ―€λ‘œ λ‹€λ₯Έ λͺ¨λ“ˆμ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” κΈ°λŠ₯이 무엇인지 λͺ…μ‹œμ μœΌλ‘œ κ²°μ •ν•΄μ•Ό ν•œλ‹€(이 접근법은 μ‹€μˆ˜λ‘œ μ–΄λ–€ κΈ°λŠ₯을 μ™ΈλΆ€λ‘œ λ…ΈμΆœν•¨μœΌλ‘œ λͺ‡ 년이 μ§€λ‚œ 뒀에 해컀가 μ‹œμŠ€ν…œμ„ λ‚¨μš©ν•  여지λ₯Ό λ°©μ§€ν•œλ‹€).

ν”„λ‘œμ νŠΈμ˜ 두 λͺ¨λ“ˆμ˜ 디렉터리 κ΅¬μ‘°λŠ” λ‹€μŒκ³Ό κ°™λ‹€.

14.5.2 requires ꡬ문

λ˜λŠ” λ‹€μŒμ²˜λŸΌ module-info.javaλ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€.

1
2
3
4
5
6
7
module expenses.readers {
    requires java.base; // νŒ¨ν‚€μ§€λͺ…이 μ•„λ‹ˆλΌ λͺ¨λ“ˆλͺ…이닀.

    exports com.example.expenses.readers;
    exports com.example.expenses.readers.file;
    exports com.example.expenses.readers.http;
}

requires β†’ μ˜μ‘΄ν•˜κ³  μžˆλŠ” λͺ¨λ“ˆμ„ μ§€μ •ν•œλ‹€.

기본적으둜 λͺ¨λ“  λͺ¨λ“ˆμ€ java.baseλΌλŠ” ν”Œλž«νΌ λͺ¨λ“ˆμ— μ˜μ‘΄ν•˜λŠ”λ° 이 ν”Œλž«νΌ λͺ¨λ“ˆμ€ net, io, util λ“± μžλ°”μ˜ 메인 νŒ¨ν‚€μ§€λ₯Ό ν¬ν•¨ν•œλ‹€. (항상 기본적으둜 ν•„μš”ν•œ λͺ¨λ“ˆμ΄λ―€λ‘œ java.baseλŠ” λͺ…μ‹œμ μœΌλ‘œ μ •μ˜ν•  ν•„μš”κ°€ μ—†λ‹€.)

μžλ°”μ—μ„œ β€œclass Foo extends Object { … }β€μ²˜λŸΌ ν•˜μ§€ μ•Šκ³  β€œclass Foo { … }β€μ²˜λŸΌ 클래슀λ₯Ό μ •μ˜ν•˜λŠ” 것과 같은 원리닀.

λ”°λΌμ„œ java.base μ™Έμ˜ λͺ¨λ“ˆμ„ μž„ν¬νŠΈν•  λ•Œ requiresλ₯Ό μ‚¬μš©ν•œλ‹€.

μžλ°” 9μ—μ„œλŠ” requires와 exports ꡬ문을 μ΄μš©ν•΄ μ’€ 더 μ •κ΅ν•˜κ²Œ 클래슀 접근을 μ œμ–΄ν•  수 μžˆλ‹€. μ•„λž˜λŠ” μžλ°” 9 이전과 μ΄ν›„μ˜ μ ‘κ·Όμžμ™€ κ°€μ‹œμ„± λ³€ν™”λ₯Ό 보여쀀닀.

14.5.3 이름 μ •ν•˜κΈ°

였라클

β†’ νŒ¨ν‚€μ§€λͺ…μ²˜λŸΌ 인터넷 도메인λͺ…을 μ—­μˆœ(ex. com.iteratrlearning.training)으둜 λͺ¨λ“ˆμ˜ 이름을 μ •ν•˜λ„λ‘ κΆŒκ³ ν•œλ‹€. λ”μš±μ΄ λͺ¨λ“ˆλͺ…은 λ…ΈμΆœλœ μ£Όμš” API νŒ¨ν‚€μ§€μ™€ 이름이 κ°™μ•„μ•Ό ν•œλ‹€λŠ” κ·œμΉ™λ„ 따라야 ν•œλ‹€.

λͺ¨λ“ˆμ΄ νŒ¨ν‚€μ§€λ₯Ό ν¬ν•¨ν•˜μ§€ μ•Šκ±°λ‚˜ μ–΄λ–€ λ‹€λ₯Έ 이유둜 λ…ΈμΆœλœ νŒ¨ν‚€μ§€ 쀑 ν•˜λ‚˜μ™€ 이름이 μΌμΉ˜ν•˜μ§€ μ•ŠλŠ” 상황을 μ œμ™Έν•˜λ©΄ λͺ¨λ“ˆλͺ…은 μž‘μ„±μžμ˜ 인터넷 도메인 λͺ…을 μ—­μˆœμœΌλ‘œ μ‹œμž‘ν•΄μ•Ό ν•œλ‹€.

14.6 컴파일과 νŒ¨ν‚€μ§•

λ¨Όμ € 각 λͺ¨λ“ˆμ— pom.xml을 μΆ”κ°€ν•΄μ•Ό ν•œλ‹€. 사싀 각 λͺ¨λ“ˆμ€ λ…λ¦½μ μœΌλ‘œ μ»΄νŒŒμΌλ˜λ―€λ‘œ 자체적으둜 각각이 ν•œ 개의 ν”„λ‘œμ νŠΈλ‹€. 전체 ν”„λ‘œμ νŠΈ λΉŒλ“œλ₯Ό μ‘°μ •ν•  수 μžˆλ„λ‘ λͺ¨λ“  λͺ¨λ“ˆμ˜ λΆ€λͺ¨ λͺ¨λ“ˆμ—λ„ pom.xml을 μΆ”κ°€ν•œλ‹€. 전체 κ΅¬μ‘°λŠ” λ‹€μŒκ³Ό κ°™λ‹€.

μ΄λ ‡κ²Œ 3개의 pom.xml νŒŒμΌμ„ μΆ”κ°€ν•΄ 메이븐 디렉터리 ν”„λ‘œμ νŠΈ ꡬ쑰λ₯Ό μ™„μ„±ν–ˆλ‹€. λͺ¨λ“ˆ λ””μŠ€ν¬λ¦½ν„°(module-info.java)λŠ” src/main/java 디렉터리에 μœ„μΉ˜ν•΄μ•Ό ν•œλ‹€. μ˜¬λ°”λ₯Έ λͺ¨λ“ˆ μ†ŒμŠ€ 경둜λ₯Ό μ΄μš©ν•˜λ„λ‘ 메이븐이 javacλ₯Ό μ„€μ •ν•œλ‹€.

λ‹€μŒμ€ expenses.readers ν”„λ‘œμ νŠΈμ˜ pom.xml λͺ¨μŠ΅μ΄λ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0,0"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
	http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>expenses.readers</artifactId>
	<version>1.0</version>
	<packaging>jar</packaging>
	<parent>		
		<groupId>com.example</groupId>
		<artifactId>expenses</artifactId>
		<version>1.0</version>
	</parent>
</project>

순쑰둭게 λΉŒλ“œλ  수 μžˆλ„λ‘ λͺ…μ‹œμ μœΌλ‘œ λΆ€λͺ¨ λͺ¨λ“ˆμ„ μ§€μ •ν•œ μ½”λ“œλ₯Ό 보자.

λΆ€λͺ¨λŠ” ID expensesλ₯Ό ν¬ν•¨ν•˜λŠ” λΆ€μ‚°λ¬Ό(artifact)이닀. pom.xml에 λΆ€λͺ¨λ₯Ό μ •μ˜ν•΄μ•Ό ν•œλ‹€.

λ‹€μŒμœΌλ‘œ expenses.application λͺ¨λ“ˆμ˜ pom.xml을 μ •μ˜ν•œλ‹€. 이 νŒŒμΌμ€ 이전 파일과 λΉ„μŠ·ν•˜μ§€λ§Œ ExpenseApplication이 ν•„μš”λ‘œ ν•˜λŠ” ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€κ°€ μžˆμœΌλ―€λ‘œ expenses.readersλ₯Ό μ˜μ‘΄μ„±μœΌλ‘œ μΆ”κ°€ν•΄μ•Ό ν•œλ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0,0"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
	http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>expenses.application</artifactId>
	<version>1.0</version>
	<packaging>jar</packaging>
	
	<parent>
		<groupId>com.example</groupId>
		<artifactId>expenses</artifactId>
		<version>1.0</version>
	</parent>

	<dependencies>
		<dependency>
			<groupId>com.example</groupId>
			<artifactId>expenses.readers</artifactId>
			<version>1.0</version>
		</dependency>
	</dependencies>

</project>

expenses.applicationκ³Ό expenses.readers 두 λͺ¨λ“ˆμ— pom.xml을 μΆ”κ°€ν–ˆμœΌλ―€λ‘œ 이제 λΉŒλ“œ 과정을 κ°€μ΄λ“œν•  μ „μ—­ pom.xml을 μ„€μ •ν•  μ°¨λ‘€λ‹€.

메이븐은 νŠΉλ³„ν•œ XML μš”μ†Œ (μžμ‹μ˜ λΆ€μ‚°λ¬Ό IDλ₯Ό μ°Έμ‘°)을 가진 μ—¬λŸ¬ 메이븐 λͺ¨λ“ˆμ„ 가진 ν”„λ‘œμ νŠΈλ₯Ό μ§€μ›ν•œλ‹€. λ‹€μŒμ€ 두 개의 μžμ‹ λͺ¨λ“ˆ expenses.application와 expenses.readersλ₯Ό μ°Έμ‘°ν•˜λ„λ‘ μ™„μ„±ν•œ pom.xml μ •μ˜λ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0,0"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
	http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>expenses</artifactId>
	<packaging>pom</packaging>
	<version>1.0</version>

	<modules>
		<module>expenses.application</module>
		<module>expenses.readers</module>
	</modules>

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.7.0</version>
					<configuration>
						<source>9</source>
						<target>9</target>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

mvn clean package λͺ…령을 μ‹€ν–‰ν•΄μ„œ ν”„λ‘œμ νŠΈμ˜ λͺ¨λ“ˆμ„ JAR둜 λ§Œλ“€ 수 μžˆλ‹€. λ‹€μŒκ³Ό 같은 뢀산물이 λ§Œλ“€μ–΄μ§„λ‹€.

1
2
./expenses.application/target/expenses.application-1.0.jar
./expenses.readers/target/expenses.readers-1.0.jar

두 JAR을 λ‹€μŒμ²˜λŸΌ λͺ¨λ“ˆ κ²½λ‘œμ— ν¬ν•¨ν•΄μ„œ λͺ¨λ“ˆ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‹€ν–‰ν•  수 μžˆλ‹€.

1
2
3
4
5
java --module-path \
./expenses.application/target/expenses.application-1.0.jar:\
./expenses.readers/target/expenses.readers-1.0.jar \
	--module \
	expenses.application/com.example.expenses.application.ExpensesApplication

μ§€κΈˆκΉŒμ§€ λͺ¨λ“ˆμ„ λ§Œλ“œλŠ” 방법을 λ°°μ› μœΌλ©° requires둜 java.baseλ₯Ό μ°Έμ‘°ν•˜λŠ” 방법도 μ‚΄νŽ΄λ΄€λ‹€.

μ‹€μ œλ‘œλŠ” java.base λŒ€μ‹  μ™ΈλΆ€ λͺ¨λ“ˆκ³Ό 라이브러리λ₯Ό μ°Έμ‘°ν•΄μ•Ό ν•œλ‹€.

14.7 μžλ™ λͺ¨λ“ˆ

HttpReaderλ₯Ό μ €μˆ˜μ€€μœΌλ‘œ κ΅¬ν˜„ν•˜μ§€ μ•Šκ³  μ•„νŒŒμΉ˜ ν”„λ‘œμ νŠΈμ˜ httpclient 같은 νŠΉν™” 라이브러리λ₯Ό μ‚¬μš©ν•΄ κ΅¬ν˜„ν•œλ‹€κ³  κ°€μ •ν–ˆμ„ λ•Œ, 이런 라이브러리λ₯Ό ν”„λ‘œμ νŠΈμ˜ μΆ”κ°€ν•˜λ €κ³  ν•œλ‹€.

requires ꡬ문을 λ°°μ› μœΌλ―€λ‘œ expenses.readers ν”„λ‘œμ νŠΈμ˜ module-info.java에 이 ꡬ문을 μΆ”κ°€ν•œλ‹€. mvn clean packageλ₯Ό λ‹€μ‹œ μ‹€ν–‰ν•˜λ©΄ λ‹€μŒκ³Ό 같은 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.

1
[ERROR] module not found: httpclient

μ˜μ‘΄μ„±μ„ κΈ°μˆ ν•˜λ„λ‘ pom.xml도 κ°±μ‹ ν•΄μ•Ό ν•˜λ―€λ‘œ μ—λŸ¬κ°€ λ°œμƒν•˜λŠ” 것이닀.

메이븐 컴파일러 ν”ŒλŸ¬κ·ΈμΈμ€ module-info.javaλ₯Ό ν¬ν•¨ν•˜λŠ” ν”„λ‘œμ νŠΈλ₯Ό λΉŒλ“œν•  λ•Œ λͺ¨λ“  μ˜μ‘΄μ„± λͺ¨λ“ˆμ„ κ²½λ‘œμ— 놓아 μ μ ˆν•œ JARλ₯Ό λ‚΄λ €λ°›κ³  이듀이 ν”„λ‘œμ νŠΈμ— μΈμ‹λ˜λ„λ‘ ν•œλ‹€. λ‹€μŒκ³Ό 같은 μ˜μ‘΄μ„±μ΄ ν•„μš”ν•˜λ‹€.

1
2
3
4
5
6
7
<dependencies>
	<dependency>
		<groupId>org.apache.httpcomponents</groupId>
		<artifactId>httpclient</artifactId>
		<version>4.5.3</version>
	</dependency>
</dependencies>

λ‹€μ‹œ mvn clean packageλ₯Ό μ‹€ν–‰ν•˜λ©΄ ν”„λ‘œμ νŠΈκ°€ μ˜¬λ°”λ‘œ λΉŒλ“œλœλ‹€. ν•˜μ§€λ§Œ httpclientλŠ” μžλ°” λͺ¨λ“ˆμ΄ μ•„λ‹ˆλ‹€.

httpclientλŠ” μžλ°” λͺ¨λ“ˆλ‘œ μ‚¬μš©ν•˜λ €λŠ” μ™ΈλΆ€ 라이브러리인데 λͺ¨λ“ˆν™”κ°€ λ˜μ–΄ μžˆμ§€ μ•Šμ€ λΌμ΄λΈŒλŸ¬λ¦¬λ‹€. μžλ°”λŠ” JARλ₯Ό μžλ™ λͺ¨λ“ˆμ΄λΌλŠ” ν˜•νƒœλ‘œ μ μ ˆν•˜κ²Œ λ³€ν™˜ν•œλ‹€. λͺ¨λ“ˆ κ²½λ‘œμƒμ— μžˆμœΌλ‚˜ module-info νŒŒμΌμ„ 가지지 μ•Šμ€ λͺ¨λ“  JARλŠ” μžλ™ λͺ¨λ“ˆμ΄ λœλ‹€.

μžλ™ λͺ¨λ“ˆμ€ μ•”λ¬΅μ μœΌλ‘œ μžμ‹ μ˜ λͺ¨λ“  νŒ¨ν‚€μ§€λ₯Ό λ…ΈμΆœμ‹œν‚¨λ‹€. μžλ™ λͺ¨λ“ˆμ˜ 이름은 JAR 이름을 μ΄μš©ν•΄ 정해진닀. jar λ„κ΅¬μ˜ --describe-module 인수λ₯Ό μ΄μš©ν•΄ μžλ™μœΌλ‘œ μ •ν•΄μ§€λŠ” 이름을 λ°”κΏ€ 수 μžˆλ‹€.

1
2
jar --file=./expenses.readders/target/dependency/httpclient-4.5.3.jar \
	--describe-module httpclient@4.5.3 automatic

그러면 httpclientλΌλŠ” μ΄λ¦„μœΌλ‘œ μ •μ˜λœλ‹€.

λ§ˆμ§€λ§‰μœΌλ‘œ httpclient JARλ₯Ό λͺ¨λ“ˆ κ²½λ‘œμ— μΆ”κ°€ν•œ λ‹€μŒ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‹€ν–‰ν•œλ‹€.

1
2
3
4
5
6
java --module-path \
	./expenses.application/target/expenses.application-1.0.jar: \
	./expenses.readers/target/expenses.readers-1.0.jar \
	./expenses.readers/target/dependency/httpclient-4.5.3.jar \
	    --module \
	expenses.application/com.example.expenses.application.ExpensesApplication

14.8 λͺ¨λ“ˆ μ •μ˜μ™€ ꡬ문듀

module μ§€μ‹œμ–΄λ₯Ό μ΄μš©ν•˜λ©΄ λͺ¨λ“ˆμ„ μ •μ˜ν•  수 μžˆλ‹€. λ‹€μŒμ€ com.iteratrlearning.applicationλΌλŠ” λͺ¨λ“ˆλͺ…μ˜ μ˜ˆμ œλ‹€.

1
2
3
module com.iteratrlearning.application {

}

requires, exports ꡬ문 이외에도 requires-transitive, exports-to, open, opens, uses, provides 같은 λ‹€λ₯Έ ꡬ문듀도 μžˆλ‹€.

This post is licensed under CC BY 4.0 by the author.