티스토리 뷰

📌 목차

1️⃣ 의존 관계

2️⃣ 의존 역전

3️⃣ 의존 주입 패턴

4️⃣ 의존성을 주입 해주는 주체

 


 

1️⃣ 의존 관계

💁🏻‍♀️ 의존이 뭔데?

💡 한쪽(B)의 변경사항이 다른 한쪽(A)에도 영향을 미칠 때, A는 B에 의존한다고 말함

 

🔎 의존 관계가 형성되는 경우

 : 어떤 클래스가 다른 클래스(or 인터페이스)를 사용할 때

 (1) 다른 클래스의 레퍼런스 변수를 사용하는 경우 (ex. B b;)

public class A {
    private B b;
}

 (2) 다른 클래스의 인스턴스를 생성하는 경우 (ex. new B())

public class A {
    private InterfaceB b = new B(); // B는 InterfaceB 인터페이스를 구현
}

 (3) 다른 클래스를 상속받는 경우

public class A extends B {}

 

인터페이스로 의존관계를 맺어서 의존 관계를 약하게하자! (더 객체지향적)

❗ 의존 관계는'객체-객체'뿐만이 아니라 '메서드-필드' 사이에도 형성!

     → 메서드가 필드에 대해 자세하게 알고 있다면 강하게 의존하고 있는 상태 (캡슐화를 하자)

 


 

💬 유지보수하기 좋은 의존 관계는 어떻게 형성되어야 하는가?

2️⃣ 의존 역전

: 고수준 컴포넌트저수준 컴포넌트에 의존하지 않도록 의존 관계를 역전 시키는 것

  • 컴포넌트 : 여러 개의 프로그램 함수들을 모아 하나의 특정한 기능을 수행할 수 있도록 구성한 작은 기능적 단위 (ex. 클래스)
  • 고수준 : 구체적인 기술에 종속❌ (x. Service 계층)
  • 저수준 : 구체적인 기술에 종속⭕ (ex. Repository 계층)

👩🏻‍🏫 인터페이스를 사용해서 의존관계를 역전하자 (의존 방향이 인터페이스에 모이도록!)

계층을 나누고, 패키지로 구분해 각 계층간 의존성 방향을 제어 (레이어드 아키텍처)

Controller                                        표현계층
Service                                            애플리케이션 계층
Repository(interface)                    도메인 계층
Repository(구체 클래스)                  인프라스트럭처 계층

 

📎 레이어드 아키텍처

 


 

3️⃣ 의존 주입 패턴

💁🏻‍♀️ 인터페이스를 통해 의존관계를 역전했다면, 인터페이스에 구현체는 누가, 어떻게 넣어주지?

💡 외부(ex. Spring, Client)에서 구현체의 인스턴스를 생성 후 주입 해줘야 함! (컴포넌트에서 직접❌)

 

🔎 의존 주입 패턴의 장점

✔️ 테스트가 용이해짐!

📎 (참고) Test Double - 테스트 코드를 실행하기 위한 대여 클래스

 

✔️ 어떤 구현체 사용할지 코드 수정 없이, 실행 시점(Runtime)에 지정할 수 있음

 


 

4️⃣ 의존성을 주입 해주는 주체

 

🖐🏻 먼저, 스프링프레임 워크에 대해서 알아보자!

  • 스프링 프레임워크에는 프로젝트에서 사용할 구현체의 인스턴스()를 생성 / 등록해서 필요한 곳에 주입해주는  애플리케이션 컨텍스트(IoC Container, Bean Factory)가 존재!
  • 빈(Bean)은 기본적으로 싱글턴 (동일 타입의 인스턴스는 하나만 생성)
  • 프로젝트의 모든 클래스가 빈(Bean)이 되는 것은 아님 (특정 애너테이션(ex. @RestController, @Component)이 붙은 클래스만!)
  • 스프링은 빈으로 등록된 클래스만 의존성 주입에 사용할 수 있음!

💁🏻‍♀️ 빈은 왜 싱글턴으로 설계 되었나요?

💡 클라이언트 코드는 프로젝트의 클래스들 속에서 오직 메서드만 활용하기 때문 (❗동기화 문제 때문에 그렇게 해야만 함)

 

🔎 스프링 프레임워크에서 빈(Bean)을 주입해주는 방식

✔️ 실행하는 시점에 적절한 빈을 선택해보자 - Spring Profile

즉, DB Repository와 File Repository 중에서 어떤 클래스(빈)을 Repository인터페이스의 구현체로 사용할 지 프로그램이 시작하는 시점에 결정하자

@Profile("prod")
@Component
public class DatabaseRepository implements Repository { ... }
@Profile("test")
@Component
public class FileRepository implements Repository { ... }

이렇게 설정만 해주면 ↓ 아래와 같이 실행을 prod, test 중 어떤 것으로 할지 결정 후 실행 가능!

java -jar target/프로젝트명.jar --spring.profiles.active=prod

 

❕ (참고) jar파일 만드는 법

(1) 오른쪽 사이드 바에서 Maven(clean 누르기, skip test 선택) > package

(2) /target 디렉토리에서 .jar 파일 확인

 

✔️ 실행하는 중 적절한 빈을 선택해보자 - Spring Profile

즉, DB Repository와 File Repositor가 모두 빈으로 등록되어 있을 때, 프로그램 실행 중 적절한 클래스(빈)을 Repository인터페이스의 구현체로 사용하자!

@Order(0)
@Component
public class DatabaseRepository implements Repository { ... }
@Order(1)
@Component
public class FileRepository implements Repository { ... }
@Component
public class Service {
    private Repository inUseRepository;
    private Repository spareRepository;
    
    public Service(List<Repository> repositorise) {
        inUseRepository = repositorise.get(0);
        spareRepository = repositorise.get(1);
    }
    
    public void changeRepository() { // 구현체 변경하기
        Repository tempRepository = this.inUseRepository;
        inUseRepository = spareRepository;
        spareRepository = tempRepository;
    }
}

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   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
글 보관함