Search

의존성 주입

태그
우테코
프로그래밍 일반
Java
작성 상태
작성 완료
작성일
2024/03/23
참고 링크
참고 링크 2

의존

어떤 요소 A가 동작하기 위해서 다른 요소 B가 필요하다면, A가 B를 의존한다.
public class Ladder { private final List<Line> lines; Ladder() { this.lines = new ArrayList<>(); } }
Java
복사
Ladder가 동작하기 위해서는 List<Line> 이 필요하다. 즉, Laddder는 List와 Line을 의존한다.
정말 간단하게 자바에서 import 하는 모든 것을 의존한다고 보면 된다. 단, 그게 전부는 아니다.
이하의 글에서 A 를 의존을 하는 쪽, B를 의존 대상 이라 표현한다.

주입

주입의 사전적 의미는 다음과 같다.
어떤 물체 안에 액체나 기체 따위를 집어넣음. - 네이버 국어사전
어떤 대상의 외부에서, 내부로 무언가를 집어 넣는 것!

의존성 주입

의존을 하는 것이 의존 대상이 되는 것을 직접 만들지 않고, 외부에서 의존 대상을 집어 넣는 것!
조금 더 쉬운 이해를 위해 코드로 살펴 보자
public class Ladder { private final List<Line> lines; Ladder() { this.lines = new ArrayList<>(); // 생략 } // 생략 }
Java
복사
의존성 주입을 사용하지 않은 코드
public class Ladder { private final List<Line> lines; Ladder(List<Line> lines) { this.lines = lines; } // 생략 }
Java
복사
의존성 주입을 사용한 코드
의존성 주입을 사용하지 않은 코드에서는 의존 대상을 직접 생성했다. 반면, 의존성 주입을 사용한 코드는 의존 대상을 생성자를 통해 외부에서 받아왔다.

의존성 주입의 장점과 주의할 점

장점

1.
의존을 하는 쪽을 의존 대상의 변경으로부터 안전하게 보호할 수 있다.
2.
의존 대상을 다른 것으로 변경할 수 있다.
3.
테스트를 쉽게 할 수 있다.

주의할 점

의존을 하는 쪽 입장에서 의존 대상을 구현 세부 사항으로 바라볼 수 있다.

의존성 주입의 사용 예시

Stream API

private Piece findPiece(Position from) { return piecesOnBoard.stream() .filter(piece -> piece.isOn(from)) .findFirst().orElseThrow(); }
Java
복사
.filter(piece -> piece.isOn(from)) 이 부분은 스트림 외부에서 Piece 를 boolean 으로 바꾸는 방법을 주입 받는 것이다. 즉, 의존성 주입이다.

블랙잭

카드를 뽑는 방법을 선택할 수 있는 Deck

Deck 은 카드 뭉치를 추상화 한 것으로, 카드를 선택하는 전략을 외부에서 주입받아 카드 한 장을 반환한다.
public class Deck { private final List<Card> cards; public Deck(List<Card> cards) { this.cards = new ArrayList<>(cards); } public Card draw(CardSelectStrategy cardSelectStrategy) { if (cards.isEmpty()) { throw new IllegalArgumentException("덱이 비어있습니다."); } Card card = cardSelectStrategy.select(cards); cards.remove(card); return card; } }
Java
복사
전략을 주입한 Deck
이를 통해 Deck이 제대로 동작하는지 테스트를 할 수 있게 되었다.
class DeckTest { private static final FirstCardSelectStrategy FIRST_CARD_SELECT_STRATEGY = new FirstCardSelectStrategy(); @Test @DisplayName("원하는 방식대로 카드가 뽑히는지 검증") void validateDraw() { Deck deck = Deck.of(ACE_HEART); Card card = deck.draw(FIRST_CARD_SELECT_STRATEGY); Assertions.assertThat(card) .isEqualTo(ACE_HEART); } }
Java
복사
의존성 주입을 사용해 테스트가 쉬운 Deck

Deck의 구현 세부 사항을 아는 Player

Player 는 블랙잭 게임의 참가자 중 플레이어를 추상화 한 것으로, 카드 뭉치에서 카드 한장을 뽑는 행동을 한다.
public class Player { private final String name; private final BettingMoney bettingMoney; public DrawResult draw(Deck deck, CardSelectStrategy cardSelectStrategy) { return deck.draw(cardSelectStrategy); } }
Java
복사
카드를 뽑는 전략을 주입받아 덱에서 카드를 선택하는 Player
덱에서 어떤 카드가 선택되는지는 덱의 세부 구현사항 아닌가? 플레이어가 이를 선택하는 것이 옳은가?

두마리의 토끼를 모두 잡은 Deck

이 경우는 의존성 주입을 사용하되, 패키지 내부에서만 사용하는 방법을 채택할 수 있다.
public class Deck { private final List<Card> cards; public Deck(List<Card> cards) { this.cards = new ArrayList<>(cards); } public Card draw() { return draw(RandomCardSelectStrategy.INSTANCE); } Card draw(CardSelectStrategy cardSelectStrategy) { if (cards.isEmpty()) { throw new IllegalArgumentException("덱이 비어있습니다."); } Card card = cardSelectStrategy.select(cards); cards.remove(card); return card; } }
Java
복사