Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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
Tags more
Archives
Today
Total
관리 메뉴

Programing_Java

[Spring] new 없이 객체 주입? Autowired와 Component로 배우는 낮은 결합도 본문

✅ Spring

[Spring] new 없이 객체 주입? Autowired와 Component로 배우는 낮은 결합도

Joyfullyever 2025. 4. 15. 18:28

✅ Spring DI 개념, 제대로 이해하기
의존 관계 주입(Dependency Injection) == DI

 

1️⃣ 의존 관계란 무엇인가?

“A는 B에 의존한다”

 

프로그래밍에서는 곧

👉 A 클래스 안에 B 클래스 타입의 멤버변수가 있다는 뜻

 

예시:

// SamsungTv는 Remote에 의존
public class SamsungTv {
    private Remote remote;
}

 

2️⃣ 상속보다는 "추상화"로 이해

public interface Remote {
    void powerOn();
    void powerOff();
    void volumeUp();
    void volumeDown();
}
// 삼성 리모컨, 엘지 리모컨은 이 Remote 인터페이스를 구현
@Component
public class SamsungRemote implements Remote { ... }

@Component
public class LgRemote implements Remote { ... }

 

인터페이스가 정의되어 있다는 건?
👉 "구현체를 나중에 꽂아줄 수 있다" 는 뜻
즉, 코드 결합도를 낮출 수 있는 구조

 

3️⃣ DI에는 3가지 방식이 있다

• 생성자 주입 (Constructor Injection)

• Setter 주입 (Setter Injection)

• 필드 주입 (@Autowired)

 

4️⃣ 예제 구현

삼성TV는 삼성리모컨을 생성자 주입, 엘지TV는 엘지리모컨을 setter 주입으로 DI

 

인터페이스 정의

public interface Tv {
    void on();
    void off();
}
// TV 구현체
@Component
public class SamsungTv implements Tv {

    private Remote remote;

    @Autowired
    public SamsungTv(SamsungRemote remote) {
        this.remote = remote;
    }

    public void on() {
        System.out.println("Samsung TV 켭니다.");
        remote.powerOn();
    }

    public void off() {
        System.out.println("Samsung TV 끕니다.");
        remote.powerOff();
    }
}
// // TV 구현체
@Component
public class LgTv implements Tv {

    private Remote remote;

    @Autowired
    public void setRemote(LgRemote remote) {
        this.remote = remote;
    }

    public void on() {
        System.out.println("LG TV 켭니다.");
        remote.powerOn();
    }

    public void off() {
        System.out.println("LG TV 끕니다.");
        remote.powerOff();
    }
}

 

// 리모컨 구현체들
@Component
public class SamsungRemote implements Remote {
    public void powerOn() { System.out.println("삼성 리모컨: 전원 ON"); }
    public void powerOff() { System.out.println("삼성 리모컨: 전원 OFF"); }
    public void volumeUp() {}
    public void volumeDown() {}
}
// 리모컨 구현체들
@Component
public class LgRemote implements Remote {
    public void powerOn() { System.out.println("LG 리모컨: 전원 ON"); }
    public void powerOff() { System.out.println("LG 리모컨: 전원 OFF"); }
    public void volumeUp() {}
    public void volumeDown() {}
}

 

 

5️⃣ Client 테스트 클래스

@Component
public class TvClient {

    @Autowired
    SamsungTv samsungTv;

    @Autowired
    LgTv lgTv;

    public void test() {
        samsungTv.on();
        lgTv.on();
    }
}
// main
public class App {
    public static void main(String[] args) {
		AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");
        TvClient client = factory.getBean(TvClient.class);
        client.test();
    }
}

 

6️⃣ 핵심 요약

 

개념 의미 비유
@Component 스프링 창고에 등록 Kiwi를 창고에 넣음
@Autowired 등록된 것을 꺼내다 씀 Apple이 Kiwi를 꺼내 먹음
생성자 주입 강한 결합도 → 테스트 쉬움 Apple(과일 마니아)은 Kiwi만 좋아함
Setter 주입 선택형 Apple은 입맛에 따라 바꿀 수 있음
인터페이스 추상화 "리모컨"이라는 개념만 알고 있음
구현체 실제 리모컨 삼성 리모컨, LG 리모컨 등

 

7️⃣ 마무리

Spring에서 new를 직접 쓰지 않고 의존성을 주입하는 이유는 코드를 더 유지보수 가능하게 만들고 테스트와 확장을 유연하게 하기 위함

의존관계 주입은 무조건 알아야 할 개념