사전적 정의와 개념은 이미 너무나도 좋은 자료가 많으니, 여기서는 나의 언어로 작성하겠다(틀린 게 있어도 오해하지 말고 찾아보기!)
이번 프로젝트를 진행하면서, 기존의 3-layer 계층의 설계가 아닌 클린 아키텍처의 설계를 학습하면서 적용해 보는 노력을 하였다. 프로젝트 초반에 익숙하지 않은 형식의 설계와 완숙하지 못한 Nest 프레임워크 실력에 의존성 오류를 엄청 많이 겪으면서 삽질을 하는 시간이었다.
지금 와서 생각해 보면, 인터페이스의 개념과 사용법을 체득하지 못한 상태여서 기본적인 에러의 원인구조를 빨리 파악하지 못한 듯하다.
이번에 구현하면서 체득한 내가 생각하는 의존성 역전 원칙이란 한마디로, 직접 상속하지 마!이다.
객체지향에서 이야기하는 설계원칙의 핵심은 유연성과 확장성(재활용)이라고 생각이 든다. 그런 측면에서 의존성 역전 원칙을 잘 지키면서 설계하는 것은 중요한 것 같다. 막상 설계하고 구현할 때는 크게 생각하지 못하였지만 의존성 역전 원칙을 지키려고 하다 보니, 개방-폐쇄 원칙과, 단일 책임 원칙을 같이 가져간 것 같다.
"클래스 간의 의존관계가 만들어질 때, 필요한 객체를 직접적으로 호출해 사용하게 된다면, 서비스의 기능과 변화가 커질수록 계속해서 코드를 바꿔야 하는 일이 발생한다" 이 말이 이제 이해가 되기 시작했다.
A기능을 구현하기 위해서 B라는 기능이 필요할 때, B에 코드 변화가 일어나면 A라는 코드도 그에 맞게 수정해주어야 한다. 하지만, 추상클래스인 인터페이스 타입의 객체로 참조를 한다면 클라이언트 객체코드의 변화 없이 필요한 기능의 확장에 무리가 없어진다.
여기서 드는 의문이 있다. 위의 장점들이 있기 때문에 수많은 인터페이스를 생성하여 의존 주입을 받는 것이 정답일까?라는 생각이 든다. 실제로 수많은 구현체를 위한 인터페이스를 설계를 진행하다 보면 시간이 매우 많이 소비될 때가 많은데, “시간은 곧 돈이다”라는 명언이 생각이 나면서, 간단한 구현체 혹은 재사용성이 없는 구현체 기능들은 어떤 식으로 처리하는 것이 좋을까?라는 고민을 하고 때에 맞게 시간과 비용을 고려하여 프로그래밍 구조를 잡아가야 하는 것이 맞을 것 같다는 지금의 결론이다.