본문 바로가기

토비의 스프링 정리

프로그래머스 - 7.4 인터페이스 상속을 통한 안전한 기능확장

7.4.1 기능확장

  • 긴급하게 애플리케이션이 사용중인 SQL을 변경해야 할 수도 있음
  • 지금까지 만든 SqlService 구현 클래스는 초기에 리소스로부터 SQL 정보를 읽어오면, 이를 메모리에 두고 그대로 사용함
  • 현재 상태로서는 애플리케이션을 새로 시작하지 않고 특정 SQL의 내용만 변경 불가능 함
  • 현재 구조에 영향을 주지 않고 기능확장을 해야 함

7.4.2 DI와 인터페이스 프로그래밍

  • 인터페이스를 통한 DI 덕분에 느슨한 결합 구조를 지닐 수 있음
  • 인터페이스를 사용하는 첫 번째 이유는 다형성 때문임
  • 하나의 인터페이스를 통해 여러 개의 구현을 바꿔가면서 사용할 수 있었음
  • 하지만, 구현을 바꾸는 것은 템플릿 메소드 패턴 처럼 일반적 상속을 통해서도 가능함
  • 인터페이스를 사용하는 두 번째 이유는 하나의 오브젝트에서 여러 인터페이스를 구현할 수 있기 때문임
  • 하나의 오브젝트에서 여러 인터페이스를 구현 한다는 것은, 해당 오브젝트를 바라보는 각 클라이언트가 관심목적을 가지고 해당 오브젝트에 의존한다는 의미임
  • 오브젝트가 관심과 목적이 각기 다른 클라이언트가 있다면 인터페이스를 통해 적절히 분리해 줘야 함
  • 이를 인터페이스 분리 원칙(ISP, Interface Segregation Principle)이라 함

7.4.3 인터페이스 상속

  • 인터페이스 분리 원칙은 모든 클라이언트가 자신의 관심에 따른 접근 방식을 불필요한 간섭 없이 유지할 수 있다는 장점이 있음
  • 따라서, 기존의 클라이언트에 영향을 주지 않은 채로 오브젝트의 기능을 확장하거나 수정할 수 있음
  • 기존의 클라이언트는 자신이 사용하던 인터페이스를 통해 동일한 접근을 유지한다면, 오브젝트 변경에 영향을 받지 않음
  • 기존의 BaseSqlService는 SqlReader와 SqlRegistry를 DI 받음
  • BaseSqlService는 SqlRegistry를 통해 MySqlRegistry에 접근하기 때문에, MySqlRegistry가 확장되더라도 BaseSqlService에 영향을 주지 않음
  • MySqlRegistry기능이 확장된다는 것은, 해당 확장 기능을 사용하는 새로운 클라이언트가 나타날 수 있다는 의미임
  • 동일한 접근 구조를 유지하면서 MySqlRegistry을 확장하고자 할 때, SqlRegistry를 수정할 필요는 없음

7.4.4 SqlRegistry의 확장

  • 기존의 SqlRegistry는 등록과 검색 두 가지 메소드만 지니고 있음
public interface SqlRegistry {
    void registrySql(String key, String sql);

    String findSql(String key) throws SqlRetrievalFailException;
}
  • MySqlRegistry의 경우 해당 두 가지 메소드를 지님
  • 여기서 이미 등록된 SQL을 변경할 수 있는 기능을 넣어 확장할 것임
  • BaseSqlService는 기존의 SqlRegisty에서 제공하는 두 가지 메소드면 충분하기 때문에, SqlRegistry를 수정하는 것은 바람직하지 않음
  • 관리자가 SQL을 변경할 수 있도록 하며, 기존의 등록 및 검색 기능을 이용할 수 있게 SqlRegistry를 상속하여 기능 확장이 올바름
  • 사용자인 BaseSqlService는 SqlRegistry으로 접근하고, 관리자인 SqlAdminService는 UpdatableSqlRegistry로 접근 함

  • SqlAdminService와 의존 xml 코드 이미지