객체 지향 설계의 다섯 가지 원칙
단일 책임 원칙 (SRP) - single responsibility principle
- 하나의 클래스가 하나의 책임을 가져야 한다.
- 클래스가 여러 책임을 가질 경우, 하나의 변경이 다른 기능에도 영향을 미칠 수 있다.
- 여러 책임이 생길 경우, 클래스를 분리해 작성하면 이 원칙을 잘 지킬 수 있다.
개방-폐쇄 원칙 (open/closed principle)
- 소프트웨어 구성 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
- 기존 코드를 수정하지 않고도 새로운 기능을 추가할 수 있도록 설계해야 한다.> 변경 없이 확장하여 버그를 줄이고 유지 보수가 쉬워짐
- 정책을 인터페이스로 추상화하고, 구현체를 추가하면 기존 코드를 건드리지 않고 확장할 수 있다.
리스코프 치환 원칙 (LSP) - Liskov substitution principle
- 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
- 다형성을 안정하게 사용하고 예측 가능한 동작을 보장한다.
인터페이스 분리 원칙 (ISP) - interface segregation principle
- 클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다.
- 하나의 복합적인 인터페이스보다는 목적과 기능에 맞도록 여러 인터페이스로 분리해서 사용해야 한다.
- 인터페이스가 명확해지고, 대체 가능성이 높아진다.
의존관계 역전 원칙 (DIP) - dependency inversion principle
- 추상화는 구체화에 의존하면 안 된다. 구체화가 추상화에 의존해야 한다. (구체적인 구현이 아니라, 인터페이스에 의존해야 한다.)
- 인터페이스를 추출하고 구현체를 분리해 구현한다.
AppConfig의 등장

예상한 의존 관계를 표현한 클래스 다이어그램

실제 의존 관계를 표현한 클래스 다이어그램
예상과 달리 클라이언트가 인터페이스뿐 아니라 구체 클래스도 함께 의존
> 그렇기 때문에 만약 구체 클래스를 변경하게 될 경우 클라이언트도 함께 변경해야 한다 (OCP 위반)
>> 따라서 클라이언트가 추상 클래스에만 의존하도록 설계해야 한다.
>>> AppConfig의 등장
AppConfig
애플리케이션의 전체 동작 방식을 구성(config)하기 위해, 구현 객체를 생성하고, 연결하는 책임을 가지는 별도의 설정 클래스

AppConfig는 애플리케이션의 실제 동작에 필요한 구현 객체를 생성하고, 구현 객체는 생성자를 통해 주입된다.
보통의 흐름
뷰(클라이언트) > 컨트롤러(요청과 응답) > 서비스(비즈니스 로직 실행) > 레포지토리(DB 저장 관리) > 데베
AppConfig가 필요한 이유
AppConfig가 없다면 관리가 매우 불편해짐