의존성과 의존성 주입

June·2022년 5월 1일
0

우테코

목록 보기
35/84

의존성

의존성이란

어떤 객체가 예정된 작업을 정상적으로 수행하기 위해 다른 객체를 필요로 하는 경우 두 객체 사이에 의존성이 존재한다. -오브젝트-

@Controller
public class ChessGameController {

    private final ChessGameService service;

    ...
}

ChessGameController에서 생략된 코드에서 ChessGameService 객체를 사용하고 있다. ChessGameController 객체가 ChessGameService 객체에 의존하고 있는 것이다.

의존성은 전이될 수 있는데 A가 B에 의존하고 있고, B가 C에 의존하고 있다면 결국 A는 C에도 의존하고 있는 셈이다. 물론 캡슐화에 따라 전이가 되지 않을 수도 있다.

의존성은 무조건 나쁜가?

의존성 자체가 무조건 나쁘다고 볼 수 없다. 객체끼리 협력하는 코드를 작성하기 위해서 의존성은 필요하나 정도가 지나치면 결합도가 높아지게 된다. 결합도가 높아진다의 기준은 자신이 의존하고 있는 객체에 대해 알고 있는 정보의 양으로 결정된다.

문제 상황

@Service
public class ChessGameService {

    private final ChessBoardDao chessBoardDao = new ChessBoardDao();

    public move(MoveDto moveDto) {
        chessBoardDao.move(moveDto);
    }
    ...
}

여기서는 new를 이용해서 직접 의존하고 있는 객체를 생성하고 있다. 객체를 생성하기 위해 구체클래스의 이름을 직접 적고 있고 생성하는데 어떤 인자를 쓰는지도 알아야 한다 (여기서는 인자를 받지 않고 ChessBoardDao객체를 생성했다). 의존하고 있는 객체에 대해 많은 정보를 알고 있다.

이렇게 되면 dao의 구현이 변경될 때 ChessGameService에 있는 코드에서도 변경이 일어날 가능성이 높다. OCP 위반인 셈이다.

해결책

OCP를 위반하는 가장 대표적인 방법으로 우선 ChessBoardDao 인터페이스를 만들어서 구현체가 아닌 인터페이스에 의존하게 하자. 그리고 의존하는 객체를 만약 외부에서 누군가가 알려준다면(넣어준다면) 나는 의존하는 객체에 대해 최소한의 정보만 알아도 된다.

의존성 주입 (Dependency Injection)

DI는 필요한 객체를 직접 생성하거나 찾지 않고 외부에서 넣어 주는 방식이다.

@Service
public class ChessGameService {

    private final ChessBoardDao chessBoardDao;

    public ChessGameService(ChessBoardDao chessBoardDao) {
        this.chessBoardDao = chessBoardDao;
    }
    ...
}

의존성 주입을 해주는 어딘가

public class Assembler {
    public ChessGameService getChessGameService() {
        return new ChessGameServiceImpl(new ChessBoardDao());
    }

이런식으로 어디선가 ChessGameService에서 필요한 의존 객체들을 다 넣어줄 수 있다. 이러한 방식을 의존성 주입이라고 한다.

이거는 이펙티브 자바 아이템5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라에서도 다루는 내용이다.

하지만 만약 프로그램이 커진다면 이렇게 필요한 의존성들을 일일이 넣어주는 것이 번거롭다. 이렇게 객체 생성과 조립을 편리하게 해주는 것이 DI 프레임워크이고, 이것이 스프링 프레임워크를 사용하는 이유 중 하나이다.

번외 - 그렇다면 이것도 나쁜가요?

public abstract class DiscountPolicy {
    private List<DiscountPolicy> conditions = new ArrayList<>();
}

일반적으로 많이 사용하는 코드다. 하지만 위 코드는 괜찮다. 표준 클래스는 수정될 확률이 굉장히 낮기 때문에 변화에 대해 걱정하지 않아도 된다.

0개의 댓글