Skip to content

Latest commit

Β 

History

History
308 lines (221 loc) Β· 17.9 KB

File metadata and controls

308 lines (221 loc) Β· 17.9 KB

item 41 : μ •μ˜ν•˜λ €λŠ” 것이 νƒ€μž…μ΄λΌλ©΄ 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λΌ

1. 마컀 μΈν„°νŽ˜μ΄μŠ€μ™€ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ˜ 비ꡐ 및 ν™œμš©

1) 마컀 μΈν„°νŽ˜μ΄μŠ€λž€?

μžλ°” ν”„λ‘œκ·Έλž˜λ°μ—μ„œ 마컀 μΈν„°νŽ˜μ΄μŠ€(marker interface)λž€ λ©”μ„œλ“œλ₯Ό ν•˜λ‚˜λ„ λ‹΄κ³  μžˆμ§€ μ•ŠμœΌλ©΄μ„œ, μžμ‹ μ„ κ΅¬ν˜„ν•˜λŠ” ν΄λž˜μŠ€κ°€ νŠΉμ • 속성을 가짐을 ν‘œμ‹œν•΄μ£ΌλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ§ν•œλ‹€. λŒ€ν‘œμ μΈ 예둜 Serializable μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ“€ 수 μžˆλ‹€. 이 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 클래슀의 μΈμŠ€ν„΄μŠ€λŠ” ObjectOutputStream을 톡해 직렬화할 수 μžˆμŒμ„ λ‚˜νƒ€λ‚Έλ‹€.

2) 마컀 μ• λ„ˆν…Œμ΄μ…˜

λ°˜λ©΄μ— 마컀 μ• λ„ˆν…Œμ΄μ…˜(marker annotation)은 μžλ°” 5λΆ€ν„° λ„μž…λœ μ• λ„ˆν…Œμ΄μ…˜ κΈ°λŠ₯을 ν™œμš©ν•˜μ—¬, ν΄λž˜μŠ€λ‚˜ λ©”μ„œλ“œ 등에 νŠΉμ • 속성을 λΆ€μ—¬ν•˜λŠ” 데 μ‚¬μš©λœλ‹€. 예λ₯Ό λ“€μ–΄ @Deprecated μ• λ„ˆν…Œμ΄μ…˜μ€ ν•΄λ‹Ή μš”μ†Œκ°€ 더 이상 μ‚¬μš©λ˜μ§€ μ•ŠμŒμ„ ν‘œμ‹œν•œλ‹€.

λ§Žμ€ κ°œλ°œμžλ“€μ΄ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ΄ λ“±μž₯ν•˜λ©΄μ„œ 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” ꡬ식이 λ˜μ—ˆλ‹€κ³  생각할 수 μžˆμ§€λ§Œ, μ‹€μ œλ‘œλŠ” 마컀 μΈν„°νŽ˜μ΄μŠ€κ°€ μ—¬μ „νžˆ μœ μš©ν•œ κ²½μš°κ°€ μžˆλ‹€.

2. 마컀 μΈν„°νŽ˜μ΄μŠ€μ˜ μž₯점

마컀 μ–΄λ…Έν…Œμ΄μ…˜μ΄ λ‚˜μ™”λŠ”λ° μ‚¬μš©ν•΄μ•Όν•  μ΄μœ κ°€ μžˆμ„κΉŒ?

마컀 μΈν„°νŽ˜μ΄μŠ€λŠ”, 두 가지 λ©΄μ—μ„œ μ• λ„ˆν…Œμ΄μ…˜λ³΄λ‹€ μž₯점을 가진닀.

1) 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” νƒ€μž…μ΄κΈ° λ•Œλ¬Έμ— μ• λ„ˆν…Œμ΄μ…˜μ„ μ‚¬μš©ν–ˆλ‹€λ©΄ λŸ°νƒ€μž„μ—λ‚˜ 발견될 였λ₯˜λ₯Ό 컴파일 νƒ€μž„μ— μž‘μ„ 수 μžˆλ‹€.

즉, νƒ€μž…μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€

마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” 이λ₯Ό κ΅¬ν˜„ν•œ 클래슀의 μΈμŠ€ν„΄μŠ€λ“€μ„ κ΅¬λΆ„ν•˜λŠ” νƒ€μž…μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€. μ΄λŠ” 마컀 μ• λ„ˆν…Œμ΄μ…˜μœΌλ‘œλŠ” λΆˆκ°€λŠ₯ν•œ λΆ€λΆ„μž…λ‹ˆλ‹€. νƒ€μž…μœΌλ‘œ ν™œμš©ν•  수 μžˆλ‹€λŠ” 것은 컴파일 νƒ€μž„μ— νƒ€μž… 체크λ₯Ό 톡해 였λ₯˜λ₯Ό 사전에 방지할 수 μžˆλ‹€λŠ” λœ»μ΄λ‹€.

예λ₯Ό λ“€μ–΄, λ‹€μŒκ³Ό 같이 Serializable을 κ΅¬ν˜„ν•œ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ°›μ•„λ“€μ΄λŠ” λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•  수 μžˆλ‹€.

μ΄λ ‡κ²Œ ν•˜λ©΄ Serializable을 κ΅¬ν˜„ν•˜μ§€ μ•Šμ€ 객체λ₯Ό 인수둜 μ „λ‹¬ν•˜λ €κ³  ν•  λ•Œ 컴파일 였λ₯˜κ°€ λ°œμƒν•œλ‹€. 즉, λŸ°νƒ€μž„μ΄ μ•„λ‹Œ 컴파일 νƒ€μž„μ— 였λ₯˜λ₯Ό λ°œκ²¬ν•  수 μžˆμ–΄ μ•ˆμ •μ„±μ„ 높일 수 μžˆλ‹€.

public void saveObject(Serializable obj) {
    // 객체λ₯Ό μ €μž₯ν•˜λŠ” 둜직
}

{% hint style="info" %} 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” μ–΄μ—Ών•œ νƒ€μž…μ΄κΈ° λ•Œλ¬Έμ—, 마컀 μ• λ„ˆν…Œ μ΄μ…˜μ„ μ‚¬μš©ν–ˆλ‹€λ©΄ λŸ°νƒ€μž„μ—μ•Ό 발견될 였λ₯˜λ₯Ό μ»΄νŒŒμΌνƒ€μž„ 에 μž‘μ„ 수 μžˆλ‹€ {% endhint %}

ν•˜μ§€λ§Œ μžλ°”μ˜ μ§λ ¬ν™”λŠ” 컴파일 νƒ€μž„ 였λ₯˜ κ²€μΆœμ˜ 이점을 살리지 λͺ»ν–ˆλ‹€.

Serializable 이 μ•„λ‹Œ μƒμœ„ νƒ€μž…μΈ Object λ₯Ό 객체둜 받도둝 μ„€κ³„λ˜μ–΄ λŸ°νƒ€μž„μ—μ•Ό λ¬Έμ œκ°€ λ°œμƒν–ˆλ‹€λŠ” 것을 μ•Œ 수 있기 λ•Œλ¬Έμ΄λ‹€.

2) 적용 λŒ€μƒμ„ 더 μ •λ°€ν•˜κ²Œ 지정할 수 μžˆλ‹€

마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” νŠΉμ • 클래슀 κ³„μΈ΅μ—λ§Œ μ μš©λ˜λ„λ‘ μ œν•œν•  수 μžˆλ‹€.

마크 μ• λ„ˆν…Œμ΄μ…˜μ€ 적용 λŒ€μƒ( @Target )을 Element.Type 으둜 μ„ μ–Έν•œ μ• λ„ˆν…Œμ΄μ…˜μ€ λͺ¨λ“  νƒ€μž…(클래슀, μΈν„°νŽ˜μ΄μŠ€, μ—΄κ±° νƒ€μž…, μ• λ„ˆν…Œμ΄μ…˜)에 달 수 μžˆμ§€λ§Œ, λΆ€μ°©ν•  수 μžˆλŠ” νƒ€μž…μ„ 더 μ„Έλ°€ν•˜κ²Œ μ œν•œν•  μˆ˜λŠ” μ—†λ‹€.

반면, 마크 μΈν„°νŽ˜μ΄μŠ€λŠ” κ·Έλƒ₯ λ§ˆν‚Ήν•˜κ³  싢은 ν΄λž˜μŠ€μ—μ„œλ§Œ κ·Έ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λ©΄ λ§ˆν‚Ήλœ νƒ€μž…μ€ μžλ™μœΌλ‘œ κ·Έ μΈν„°νŽ˜μ΄μŠ€μ˜ ν•˜μœ„ νƒ€μž…μž„μ΄ 보μž₯λœλ‹€.

public interface SpecialFeature extends BaseFeature {
    // 마컀 μΈν„°νŽ˜μ΄μŠ€μ΄λ―€λ‘œ λ©”μ„œλ“œ μ—†μŒ
}

μ΄λ ‡κ²Œ ν•˜λ©΄ BaseFeatureλ₯Ό κ΅¬ν˜„ν•œ ν΄λž˜μŠ€λ“€ μ€‘μ—μ„œ SpecialFeatureλ₯Ό κ΅¬ν˜„ν•œ ν΄λž˜μŠ€λ§Œμ„ λŒ€μƒμœΌλ‘œ νŠΉμ • λ‘œμ§μ„ μ μš©ν•  수 μžˆλ‹€.

Set μΈν„°νŽ˜μ΄μŠ€μ— λŒ€ν•œ 생각

Set μΈν„°νŽ˜μ΄μŠ€λ„ μΌμ’…μ˜ μ œμ•½μ΄ μžˆλŠ” 마컀 μΈν„°νŽ˜μ΄μŠ€λ‘œ λ³Ό 수 μžˆλ‹€.

Set은 Collection의 ν•˜μœ„ νƒ€μž…μ—λ§Œ μ μš©ν•  수 있으며, Collection이 μ •μ˜ν•œ λ©”μ„œλ“œ μ™Έμ—λŠ” μƒˆλ‘œ μΆ”κ°€ν•œ 것이 μ—†λ‹€. 보톡은 Set 을 마컀 μΈν„°νŽ˜μ΄μŠ€λ‘œ μƒκ°ν•˜μ§€ μ•ŠλŠ”λ°, add, equals, hashCode λ“± Collection 의 λ©”μ„œλ“œ λͺ‡ 개의 κ·œμ•½μ„ 살짝 μˆ˜μ •ν–ˆκΈ° λ•Œλ¬Έμ΄λ‹€. add, equals, hashCode λ“±μ˜ λ©”μ„œλ“œμ— λŒ€ν•œ λ™μž‘ κ·œμ•½μ„ λ³€κ²½ν•˜μ—¬ 집합(set)의 νŠΉμ„±μ„ κ΅¬ν˜„ν–ˆλ‹€. ν•˜μ§€λ§Œ λ‹€μ‹œ λ§ν•˜μ§€λ§Œ 좔가적인 λ©”μ„œλ“œλŠ” μ •μ˜ν•˜μ§€ μ•Šμ•˜λ‹€.

ν•˜μ§€λ§Œ νŠΉμ • μΈν„°νŽ˜μ΄μŠ€ 의 ν•˜μœ„ νƒ€μž…μ—λ§Œ μ μš©ν•  수 있으며, 아무 κ·œμ•½μ—λ„ μ†λŒ€μ§€ μ•Šμ€ 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” μΆ©λΆ„νžˆ μžˆμŒμ§ν•˜λ‹€. 이런 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” 객체의 νŠΉμ • 뢀뢄을 뢈 변식(invariant)으둜 κ·œμ •ν•˜κ±°λ‚˜, κ·Έ νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λŠ” λ‹€λ₯Έ 클래슀의 νŠΉμ • λ©”μ„œλ“œκ°€ μ²˜λ¦¬ν•  수 μžˆλ‹€λŠ” 사싀을 λͺ…μ‹œν•˜λŠ” μš©λ„λ‘œ μ‚¬μš©ν•  수 μžˆμ„ 것이닀

3. 마컀 μ• λ„ˆν…Œμ΄μ…˜μ˜ μž₯점

1) μ• λ„ˆν…Œμ΄μ…˜ ν”„λ‘œμ„Έμ‹±μ˜ 지원

마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ μžλ°”μ˜ κ°•λ ₯ν•œ μ• λ„ˆν…Œμ΄μ…˜ ν”„λ‘œμ„Έμ‹± κΈ°λŠ₯을 ν™œμš©ν•  수 μžˆλ‹€. μ΄λŠ” λ¦¬ν”Œλ ‰μ…˜(reflection)을 톡해 λŸ°νƒ€μž„μ— μ• λ„ˆν…Œμ΄μ…˜μ΄ 달린 μš”μ†Œλ₯Ό μ‰½κ²Œ μ°Ύκ³  μ²˜λ¦¬ν•  수 있게 ν•΄μ€€λ‹€.

λ˜ν•œ, μ• λ„ˆν…Œμ΄μ…˜μ€ 클래슀뿐만 μ•„λ‹ˆλΌ λ©”μ„œλ“œ, ν•„λ“œ, λͺ¨λ“ˆ, νŒ¨ν‚€μ§€ λ“± λ‹€μ–‘ν•œ ν”„λ‘œκ·Έλž¨ μš”μ†Œμ— μ μš©ν•  수 μžˆλ‹€. λ”°λΌμ„œ ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€ μ™Έμ˜ μš”μ†Œμ— λ§ˆν‚Ήν•΄μ•Ό ν•  λ•ŒλŠ” 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ‚¬μš©ν•  μˆ˜λ°–μ— μ—†λ‹€.

4. 마컀 μΈν„°νŽ˜μ΄μŠ€ vs 마컀 μ• λ„ˆν…Œμ΄μ…˜: μ–Έμ œ μ‚¬μš©ν•΄μ•Ό ν• κΉŒ?

  • νƒ€μž…μœΌλ‘œ ν™œμš©ν•΄μ•Ό ν•˜λŠ” 경우: 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•œλ‹€. 이λ₯Ό 톡해 컴파일 νƒ€μž„μ— νƒ€μž… 체크λ₯Ό ν•  수 있고, ν•΄λ‹Ή 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ§€κ°œλ³€μˆ˜λ‚˜ λ°˜ν™˜ νƒ€μž…μœΌλ‘œ μ‚¬μš©ν•˜μ—¬ μ½”λ“œμ˜ μ•ˆμ •μ„±μ„ 높일 수 μžˆλ‹€.
  • ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€ μ™Έμ˜ μš”μ†Œμ— μ μš©ν•΄μ•Ό ν•˜λŠ” 경우: 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ‚¬μš©ν•œλ‹€. λ©”μ„œλ“œλ‚˜ ν•„λ“œ, λͺ¨λ“ˆ 등에 λ§ˆν‚Ήν•΄μ•Ό ν•  λ•ŒλŠ” μ• λ„ˆν…Œμ΄μ…˜μ΄ μœ μΌν•œ 선택지이닀.
  • μ• λ„ˆν…Œμ΄μ…˜μ„ 적극 ν™œμš©ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬μ™€ 톡합해야 ν•˜λŠ” 경우: 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λŠ” 것이 일관성을 μœ μ§€ν•˜λŠ” 데 도움이 λœλ‹€. 예λ₯Ό λ“€μ–΄, μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬μ—μ„œλŠ” λ‹€μ–‘ν•œ μ• λ„ˆν…Œμ΄μ…˜μ„ 톡해 μ„€μ •κ³Ό μ˜μ‘΄μ„± μ£Όμž…μ„ κ΄€λ¦¬ν•˜λ―€λ‘œ, 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λŠ” 것이 μ μ ˆν•˜λ‹€.

5. μ‚¬μš© 예제

1) 마컀 μΈν„°νŽ˜μ΄μŠ€ μ‚¬μš© 예제

// 마컀 μΈν„°νŽ˜μ΄μŠ€ μ •μ˜
public interface Archivable {
    // λ©”μ„œλ“œ μ—†μŒ
}

// Archivable을 κ΅¬ν˜„ν•œ 클래슀
public class Document implements Archivable {
    private String content;
    // 기타 멀버
}

// Archivable을 κ΅¬ν˜„ν•˜μ§€ μ•Šμ€ 클래슀
public class Image {
    private byte[] data;
    // 기타 멀버
}

// Archivable νƒ€μž…μ˜ κ°μ²΄λ§Œμ„ μ²˜λ¦¬ν•˜λŠ” λ©”μ„œλ“œ
public void archive(Archivable item) {
    // μ•„μΉ΄μ΄λΈŒ 둜직
}

μœ„ μ½”λ“œμ—μ„œ archive λ©”μ„œλ“œλŠ” Archivable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ κ°μ²΄λ§Œμ„ 인수둜 λ°›λŠ”λ‹€. λ”°λΌμ„œ Document κ°μ²΄λŠ” 전달할 수 μžˆμ§€λ§Œ, Image κ°μ²΄λŠ” 컴파일 νƒ€μž„μ— 였λ₯˜κ°€ λ°œμƒν•œλ‹€.

2) 마컀 μ• λ„ˆν…Œμ΄μ…˜ μ‚¬μš© 예제

// 마컀 μ• λ„ˆν…Œμ΄μ…˜ μ •μ˜
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {
}

// μ• λ„ˆν…Œμ΄μ…˜μ„ μ μš©ν•œ λ©”μ„œλ“œ
public class Calculator {
    @Test
    public void testAddition() {
        // ν…ŒμŠ€νŠΈ μ½”λ“œ
    }
}

// μ• λ„ˆν…Œμ΄μ…˜ ν”„λ‘œμ„Έμ„œλ₯Ό 톡해 @Test μ• λ„ˆν…Œμ΄μ…˜μ΄ 달린 λ©”μ„œλ“œλ₯Ό μ‹€ν–‰
public class TestRunner {
    public static void main(String[] args) {
        for (Method m : Calculator.class.getDeclaredMethods()) {
            if (m.isAnnotationPresent(Test.class)) {
                // ν…ŒμŠ€νŠΈ λ©”μ„œλ“œ μ‹€ν–‰ 둜직
            }
        }
    }
}

μœ„ μ˜ˆμ œμ—μ„œ @Test 마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ λ©”μ„œλ“œμ— 적용되며, λ¦¬ν”Œλ ‰μ…˜μ„ 톡해 ν•΄λ‹Ή μ• λ„ˆν…Œμ΄μ…˜μ΄ 달린 λ©”μ„œλ“œλ₯Ό μ°Ύμ•„ μ‹€ν–‰ν•  수 μžˆλ‹€.

마컀 μΈν„°νŽ˜μ΄μŠ€μ™€ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ 각각의 μž₯단점이 μžˆμœΌλ―€λ‘œ 상황에 맞게 μ„ νƒν•˜λŠ” 것이 μ€‘μš”

  1. 컴파일 νƒ€μž„ μ•ˆμ „μ„±: 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” νƒ€μž… μ‹œμŠ€ν…œμ„ ν™œμš©ν•˜λ―€λ‘œ, 컴파일 νƒ€μž„μ— 였λ₯˜λ₯Ό λ°œκ²¬ν•  수 μžˆλ‹€. μ΄λŠ” λŒ€κ·œλͺ¨ ν”„λ‘œμ νŠΈμ—μ„œ 맀우 μ€‘μš”ν•˜λ©°, 버그λ₯Ό 사전에 방지할 수 μžˆλ‹€.
  2. λ¦¬ν”Œλ ‰μ…˜ 및 메타데이터 ν™œμš©: 마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ λŸ°νƒ€μž„μ— λ©”νƒ€λ°μ΄ν„°λ‘œ ν™œμš©ν•  수 μžˆμ–΄, 동적인 κΈ°λŠ₯ κ΅¬ν˜„μ— μœ λ¦¬ν•˜λ‹€. 특히 ν…ŒμŠ€νŠΈ ν”„λ ˆμž„μ›Œν¬λ‚˜ DI(Dependency Injection) ν”„λ ˆμž„μ›Œν¬μ—μ„œ μœ μš©ν•˜λ‹€.
  3. 적용 λ²”μœ„: 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€μ—λ§Œ μ μš©ν•  수 μžˆμ§€λ§Œ, 마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ 더 λ‹€μ–‘ν•œ ν”„λ‘œκ·Έλž¨ μš”μ†Œμ— μ μš©ν•  수 μžˆλ‹€.
  4. μ˜λ„μ™€ λͺ…ν™•μ„±: 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œλ‹€λŠ” 것은 ν•΄λ‹Ή ν΄λž˜μŠ€κ°€ νŠΉμ • νƒ€μž…μ˜ μΌλΆ€μž„μ„ λͺ…μ‹œμ μœΌλ‘œ λ‚˜νƒ€λ‚Έλ‹€. λ°˜λ©΄μ— 마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ ν•΄λ‹Ή μš”μ†Œκ°€ νŠΉμ • 속성을 가짐을 λ‚˜νƒ€λ‚΄μ§€λ§Œ, νƒ€μž…μœΌλ‘œμ„œμ˜ μ˜λ―ΈλŠ” μ—†λ‹€..

μ• λ„ˆν…Œμ΄μ…˜ 기반의 ν”„λ ˆμž„μ›Œν¬λ₯Ό 많이 μ‚¬μš©ν•˜λŠ” ν˜„λŒ€μ˜ 개발 ν™˜κ²½μ—μ„œλŠ” 마컀 μ• λ„ˆν…Œμ΄μ…˜μ˜ ν™œμš©λ„κ°€ 높아지고 μžˆλ‹€. ν•˜μ§€λ§Œ νƒ€μž… μ•ˆμ •μ„±κ³Ό λͺ…ν™•ν•œ μ˜λ„λ₯Ό μ „λ‹¬ν•˜κΈ° μœ„ν•΄μ„œλŠ” 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 쒋을 λ•Œλ„ μžˆλ‹€.

μ–Έμ–΄μ˜ νŠΉμ§•κ³Ό 개발 λ„κ΅¬μ˜ λ°œμ „μ— 따라 μ½”λ”© μŠ€νƒ€μΌκ³Ό νŒ¨ν„΄μ΄ λ³€ν™”ν•˜μ§€λ§Œ, κΈ°λ³Έ 원칙은 λ³€ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것이닀. 마컀 μΈν„°νŽ˜μ΄μŠ€μ™€ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ 각각의 λͺ©μ κ³Ό μž₯점이 μžˆμœΌλ―€λ‘œ, ν”„λ‘œμ νŠΈμ˜ μš”κ΅¬ 사항과 νŒ€μ˜ μ½”λ”© μ»¨λ²€μ…˜μ— 맞게 적절히 ν™œμš©ν•˜λŠ” 것이 μ€‘μš”ν•˜λ‹€.

λ˜ν•œ, νƒ€μž… μ‹œμŠ€ν…œμ„ 적극적으둜 ν™œμš©ν•˜μ—¬ μ•ˆμ •μ μΈ μ½”λ“œλ₯Ό μž‘μ„±ν•˜λŠ” κ²ƒμ˜ μ€‘μš”μ„±ν•˜λ‹€. 특히 λŒ€κ·œλͺ¨ μ‹œμŠ€ν…œμ—μ„œλŠ” μž‘μ€ 였λ₯˜κ°€ 큰 문제둜 μ΄μ–΄μ§ˆ 수 μžˆμœΌλ―€λ‘œ, 컴파일 νƒ€μž„μ— μž‘μ„ 수 μžˆλŠ” 였λ₯˜λŠ” μ΅œλŒ€ν•œ κ·Έ λ‹¨κ³„μ—μ„œ ν•΄κ²°ν•˜λŠ” 것이 μ’‹λ‹€.

좔가적인 κ³ λ―Ό

  • μžλ°” 8 μ΄ν›„μ˜ κΈ°λŠ₯과의 μ‘°ν•©: λžŒλ‹€ ν‘œν˜„μ‹μ΄λ‚˜ 슀트림 API와 마컀 μΈν„°νŽ˜μ΄μŠ€ λ˜λŠ” 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ–΄λ–»κ²Œ μ‘°ν•©ν•˜μ—¬ ν™œμš©ν•  수 μžˆμ„μ§€ κ³ λ―Όν•΄λ³Ό 수 μžˆλ‹€.
  • λ‹€λ₯Έ μ–Έμ–΄μ—μ„œμ˜ 적용 사둀: μ½”ν‹€λ¦°μ΄λ‚˜ 슀칼라 같은 JVM μ–Έμ–΄μ—μ„œ 마컀 μΈν„°νŽ˜μ΄μŠ€μ™€ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ μ–΄λ–»κ²Œ ν™œμš©λ˜λŠ”μ§€ λΉ„κ΅ν•΄λ³΄λŠ” 것도 ν₯미둜울 것 κ°™λ‹€.
  • 미래의 λ°©ν–₯μ„±: μ• λ„ˆν…Œμ΄μ…˜ ν”„λ‘œμ„Έμ‹±κ³Ό λ¦¬ν”Œλ ‰μ…˜μ˜ μ„±λŠ₯ 이슈, 그리고 λͺ¨λ“ˆ μ‹œμŠ€ν…œμ˜ λ°œμ „μ— 따라 마컀 μΈν„°νŽ˜μ΄μŠ€μ™€ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ˜ μ‚¬μš© νŒ¨ν„΄μ΄ μ–΄λ–»κ²Œ 변화할지 μ˜ˆμΈ‘ν•΄λ³΄λŠ” 것도 의미 μžˆμ„ 것이닀.

6. μŠ€ν”„λ§μ—μ„œμ˜ μ‚¬μš©

1) 마컀 μ• λ„ˆν…Œμ΄μ…˜κ³Ό 마컀 μΈν„°νŽ˜μ΄μŠ€μ˜ 차이점

  • 마컀 μ• λ„ˆν…Œμ΄μ…˜: 클래슀, λ©”μ„œλ“œ, ν•„λ“œ 등에 μ• λ„ˆν…Œμ΄μ…˜μ„ λΆ€μ—¬ν•˜μ—¬ νŠΉμ • 속성을 λ‚˜νƒ€λ‚Έλ‹€. μŠ€ν”„λ§μ—μ„œλŠ” 빈 μŠ€μΊλ‹μ΄λ‚˜ AOP 등을 ν™œμš©ν•  λ•Œ 주둜 μ‚¬μš©ν•œλ‹€.
  • 마컀 μΈν„°νŽ˜μ΄μŠ€: λ©”μ„œλ“œ 없이 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•˜κ³ , 이λ₯Ό κ΅¬ν˜„ν•¨μœΌλ‘œμ¨ ν΄λž˜μŠ€μ— νŠΉμ • νƒ€μž…μ„ λΆ€μ—¬ν•œλ‹€.

2) μŠ€ν”„λ§μ—μ„œ 마컀 μΈν„°νŽ˜μ΄μŠ€μ˜ μ‚¬μš©

μŠ€ν”„λ§μ—μ„œλŠ” 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” κ²½μš°κ°€ μƒλŒ€μ μœΌλ‘œ μ μ§€λ§Œ, ν•„μš”μ— 따라 ν™œμš©ν•  수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄, νŠΉμ • νƒ€μž…μ˜ λΉˆλ§Œμ„ μ²˜λ¦¬ν•˜κ³ μž ν•  λ•Œ 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

μ˜ˆμ‹œ: 마컀 μΈν„°νŽ˜μ΄μŠ€ μ‚¬μš©

// 마컀 μΈν„°νŽ˜μ΄μŠ€ μ •μ˜
public interface SpecialService {
    // λ©”μ„œλ“œ μ—†μŒ
}

// 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 클래슀
@Service
public class MySpecialService implements SpecialService {
    // κ΅¬ν˜„ λ‚΄μš©
}

// 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜μ§€ μ•Šμ€ 클래슀
@Service
public class RegularService {
    // κ΅¬ν˜„ λ‚΄μš©
}

νŠΉμ • νƒ€μž…μ˜ 빈만 κ°€μ Έμ˜€κΈ°

@Autowired
private ApplicationContext applicationContext;

public void processSpecialServices() {
    // SpecialService νƒ€μž…μ˜ 빈만 κ°€μ Έμ˜΄
    Map<String, SpecialService> beans = applicationContext.getBeansOfType(SpecialService.class);
    for (SpecialService service : beans.values()) {
        // SpecialServiceλ₯Ό κ΅¬ν˜„ν•œ λΉˆμ— λŒ€ν•œ 처리 둜직
    }
}

μ΄λ ‡κ²Œ ν•˜λ©΄ SpecialService μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ λΉˆλ“€λ§Œμ„ λŒ€μƒμœΌλ‘œ λ‘œμ§μ„ μˆ˜ν–‰ν•  수 μžˆλ‹€.

μŠ€ν”„λ§μ—μ„œ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ˜ μ‚¬μš©

ν•˜μ§€λ§Œ μŠ€ν”„λ§μ—μ„œλŠ” 마컀 μΈν„°νŽ˜μ΄μŠ€λ³΄λ‹€ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ 더 많이 μ‚¬μš©ν•œλ‹€. μ΄λŠ” μ• λ„ˆν…Œμ΄μ…˜μ΄ 더 μœ μ—°ν•˜κ³ , λ‹€μ–‘ν•œ ν”„λ‘œκ·Έλž¨ μš”μ†Œμ— μ μš©ν•  수 있기 λ•Œλ¬Έμ΄λ‹€.

μ˜ˆμ‹œ: 마컀 μ• λ„ˆν…Œμ΄μ…˜ μ‚¬μš©

// 마컀 μ• λ„ˆν…Œμ΄μ…˜ μ •μ˜
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SpecialComponent {
}

// 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ μš©ν•œ 클래슀
@SpecialComponent
@Service
public class MySpecialService {
    // κ΅¬ν˜„ λ‚΄μš©
}

// 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ μš©ν•˜μ§€ μ•Šμ€ 클래슀
@Service
public class RegularService {
    // κ΅¬ν˜„ λ‚΄μš©
}

νŠΉμ • μ• λ„ˆν…Œμ΄μ…˜μ΄ 뢙은 빈만 κ°€μ Έμ˜€κΈ°

@Autowired
private ApplicationContext applicationContext;

public void processSpecialComponents() {
    // λͺ¨λ“  빈 이름 κ°€μ Έμ˜€κΈ°
    String[] beanNames = applicationContext.getBeanDefinitionNames();
    for (String beanName : beanNames) {
        Object bean = applicationContext.getBean(beanName);
        // ν΄λž˜μŠ€μ— @SpecialComponent μ• λ„ˆν…Œμ΄μ…˜μ΄ λΆ™μ–΄ μžˆλŠ”μ§€ 확인
        if (bean.getClass().isAnnotationPresent(SpecialComponent.class)) {
            // @SpecialComponentκ°€ 뢙은 λΉˆμ— λŒ€ν•œ 처리 둜직
        }
    }
}

λ˜λŠ” μŠ€ν”„λ§ μ„€μ •μ—μ„œ 빈 μŠ€μΊλ‹ μ‹œ 필터링을 톡해 νŠΉμ • μ• λ„ˆν…Œμ΄μ…˜μ΄ 뢙은 클래슀만 빈으둜 등둝할 수 μžˆλ‹€.

@Configuration
@ComponentScan(
    basePackages = "com.example",
    includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = SpecialComponent.class)
)
public class AppConfig {
}

3) 마컀 μΈν„°νŽ˜μ΄μŠ€ vs 마컀 μ• λ„ˆν…Œμ΄μ…˜: μŠ€ν”„λ§μ—μ„œμ˜ ν™œμš©

  • 마컀 μΈν„°νŽ˜μ΄μŠ€
    • 컴파일 νƒ€μž„μ— νƒ€μž… 체크 κ°€λŠ₯
    • νŠΉμ • νƒ€μž…μ˜ 빈만 μ£Όμž…λ°›μ„ 수 있음
    • μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•˜λ―€λ‘œ, ν΄λž˜μŠ€κ°€ 이미 λ‹€λ₯Έ 클래슀λ₯Ό μƒμ†ν•˜κ³  μžˆλ‹€λ©΄ 닀쀑 상속이 λΆˆκ°€λŠ₯ν•œ μžλ°”μ˜ νŠΉμ„±μƒ μ œν•œμ΄ 있음
  • 마컀 μ• λ„ˆν…Œμ΄μ…˜
    • 클래슀 외에도 λ©”μ„œλ“œ, ν•„λ“œ 등에 적용 κ°€λŠ₯
    • λ¦¬ν”Œλ ‰μ…˜μ„ 톡해 λŸ°νƒ€μž„μ— λ‹€μ–‘ν•œ μ²˜λ¦¬κ°€ κ°€λŠ₯
    • μŠ€ν”„λ§μ˜ 빈 μŠ€μΊλ‹, AOP λ“±κ³Όμ˜ 연동이 용이

μŠ€ν”„λ§μ—μ„œ νŠΉμ • λΉˆμ„ μ‹λ³„ν•˜κ±°λ‚˜ μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄μ„œλŠ” 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λŠ” 것이 더 일반적이며 νŽΈλ¦¬ν•˜λ‹€. 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” 컴파일 νƒ€μž„ νƒ€μž… 체크 λ“±μ˜ μž₯점이 μžˆμ§€λ§Œ, μŠ€ν”„λ§μ˜ κΈ°λŠ₯κ³Ό κ²°ν•©ν•˜μ—¬ μ‚¬μš©ν•˜κΈ°μ—λŠ” 마컀 μ• λ„ˆν…Œμ΄μ…˜μ΄ 더 μ ν•©ν•˜λ‹€.

λ”°λΌμ„œ μ œκ°€ 이전에 μ œμ‹œν•œ μ˜ˆμ‹œλŠ” 마컀 μΈν„°νŽ˜μ΄μŠ€λ³΄λ‹€λŠ” 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ ν™œμš©ν•œ μ˜ˆμ‹œμ΄λ©°, μŠ€ν”„λ§μ—μ„œλŠ” μ΄λŸ¬ν•œ 방식을 톡해 νŠΉμ • 클래슀λ₯Ό μ‹λ³„ν•˜κ³  μ²˜λ¦¬ν•œλ‹€.

좔가적인 μ„€λͺ…

  • 마컀 μΈν„°νŽ˜μ΄μŠ€μ˜ μ‚¬μš© μ œν•œ
    • 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” ν΄λž˜μŠ€μ—λ§Œ 적용 κ°€λŠ₯ν•˜λ©°, μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•˜λ―€λ‘œ 닀쀑 μƒμ†μ˜ μ œμ•½μ΄ μžˆλ‹€.
    • μŠ€ν”„λ§μ—μ„œ 빈으둜 등둝할 λ•ŒλŠ” 클래슀패슀 μŠ€μΊλ‹μ„ 톡해 μ• λ„ˆν…Œμ΄μ…˜ 기반으둜 μ²˜λ¦¬ν•˜λŠ” κ²½μš°κ°€ λ§Žλ‹€.
  • 마컀 μ• λ„ˆν…Œμ΄μ…˜μ˜ μž₯점
    • λ‹€μ–‘ν•œ ν”„λ‘œκ·Έλž¨ μš”μ†Œμ— 적용 κ°€λŠ₯
    • AOP λ“±μ˜ κΈ°λŠ₯κ³Ό κ²°ν•©ν•˜μ—¬ 뢀가적인 처리λ₯Ό μ‰½κ²Œ μΆ”κ°€ν•  수 있음
    • λ©”νƒ€λ°μ΄ν„°λ‘œ ν™œμš©λ˜μ–΄ ν”„λ ˆμž„μ›Œν¬μ™€μ˜ 톡합에 용이

4) μŠ€ν”„λ§μ˜ μ„œλΉ„μŠ€, μ„œλΉ„μŠ€implκ³Ό 마컀 μΈν„°νŽ˜μ΄μŠ€ 차이

ν•­λͺ© 마컀 μΈν„°νŽ˜μ΄μŠ€ μŠ€ν”„λ§μ˜ Service/ServiceImpl
λͺ©μ  ν΄λž˜μŠ€μ— νŠΉμ • 속성 λΆ€μ—¬ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직의 μ •μ˜μ™€ κ΅¬ν˜„ 뢄리
λ©”μ„œλ“œ 쑴재 μ—¬λΆ€ λ©”μ„œλ“œ μ—†μŒ μΈν„°νŽ˜μ΄μŠ€μ— λ©”μ„œλ“œ μ‹œκ·Έλ‹ˆμ²˜ μ •μ˜
μ‚¬μš© 방식 μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„μœΌλ‘œ νƒ€μž… 지정 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜μ—¬ 둜직 κ΅¬ν˜„
μ˜ˆμ‹œ Serializable, Cloneable UserService, UserServiceImpl

좜처 및 μ°Έκ³