티스토리 뷰

반응형

스프링에 들어가기 앞서, 스프링에 관련된 소스를 작성하여 스프링의 내부 구조를 살펴보자.

 

상속을 통한 확장

  • 만약, 우리의 UserDao를 고객사에게 제공할 건데, UserDao의 클래스 파일만 제공하고 고객이 필요한 부분만(getConnection())을 수정해서 사용하게끔 할 수 있는가?

  • Connection 부분을 추상메소드로 만들어 고객에게 직접 구현할 수 있게끔 한다.

    • 즉, 상속을 통해 확장하는 것이다.

      image

 

상속을 통한 확장에는 두 가지 패턴을 사용하게 된다.

템플릿 메소드 패턴

  • 상속을 통해 슈퍼클래스의 기능을 확장할 때 사용하는 가장 대표적인 방법이다.
  • 서브 클래스에서 필요에 맞게 추상 메소드를 구현해서 사용하는 방법을 디자인한 것이다.

팩토리 메소드 패턴

  • 서브클래스에서 구체적인 오브젝트 생성 방법을 결정하게 하는 것을 디자인 한 것이다.

 

 

상속의 단점

  • 현재 상속 받고 있는 슈퍼클래스의 다른 목적이 필요할 경우 해당 슈퍼클래스를 상속받아야 하는데, 자바에서는 다중 상속이 지원되지 않는다.
  • 서브클래스와 슈퍼클래스는 밀접한 관계를 가지고 있다. 즉, 슈퍼 클래스의 수정이 서브 클래스에 영향을 미친다.

 

 

클래스 분리

  • 상속의 단점을 해결하기 위해 두개의 독립된 클래스로 분리해보자.

    image
  • 하지만 이 방법을 사용할 시 고객사에 납품할 때 UserDao의 소스코드를 함께 제공해야지만 DB 연결방법을 바꿔야한다는 문제점이 나타난 것이다.

    • DB 커넥션의 클래스를 UserDao가 참조하고 있으므로, 해당 클래스를 사용하려면 고객사에서 직접 DB 커넥션 클래스를 추가해줘야 한다.
    //UserDao.java
    simpleConnectionMaker = new SimpleConnectionMaker();    //해당 클래스는 고객사마다 다르게 구현될 것.
  • 자유로운 확장이 가능하게끔 하려면 두 가지 문제를 해결해야 한다.

    1. SimpleConnectionMaker(고객사)의 메소드가 문제이다.

      • 각 고객사에서 DB 커넥션하는 메소드의 명이 다르면 UserDao의 add(), get()에서 수정이 필요하게 된다.

        Connection c = simpleConnectionMaker.openConnection();
    2. DB 커넥션을 제공하는 클래스가 어떤 것인지를 UserDao가 구체적으로 알고 있어야 한다.

      • 고객사에서 다른 클래스를 구현하게되면 UserDao에 직접적인 수정이 필요하다.
  • 이런 문제를 해결하기 위해서 인터페이스가 도입되었다.

 

 

인터페이스의 도입

  • 서로 긴밀하게 연결되어 있지 않도록 중간에 추상적인 느슨한 연결고리를 만들어주는 것이다.

    image
  • UserDao가 인터페이스를 사용하게 되면 인터페이스의 메소드를 통해 알 수 있는 기능에만 관심을 가지면 되므로, 그 기능을 어떻게 구현했는지에 대해서는 관심을 둘 필요가 없다.

  • 결과적으로, 고객에게 납품할 때는 UserDao 클래스와 함께 ConnectionMaker 인터페이스도 전달하게 된다.

    • 고객은 ConnectionMaker의 인터페이스를 구현한 클래스를 만들고 UserDao를 사용하면 되는 것이다.
  • 하지만, 이 방법 또한 UserDao를 직접적으로 수정해야한다.

    //UserDao
    connectionMaker = new DConnctionMaker();    //D사가 구현한 인터페이스 구현 클래스

     

 

관계설정 책임의 분리

UserDao를 직접적으로 수정해야하는 문제점을 해결해보자

  • UserDao 오브젝트와 특정 클래스로부터 만들어진 ConnectionMaker 오브젝트 사이에 관계를 설정해주는 것이다.

    • 클래스 사이의 관계가 만들어지는 것은 코드에 다른 클래스의 이름이 나타나 있다는 것이고, 오브젝트 사이의 관계는 해당 클래스가 구현한 인터페이스와 관계를 맺었다는 것이다.(다형성)
  • 인터페이스를 활용한 UserDao의 관계를 자세히 보면 고객사의 DB 커넥션을 직접적으로 참조하고 있기 때문에 그림과 같이 불필요한 의존관계가 형성된다.

    image
  • 아래 그림은 런타임 시점의 오브젝트 간 관계를 나타내는 오브젝트 다이어그램이다.

    image
  • 클라이언트와 같은 제 3의 오브젝트(main)가 UserDao 오브젝트가 사용할 ConnectionMaker 오브젝트를 전달해주도록 해보자.

    • 즉, UserDao 생성자의 파라미터를 ConnectionMaker로 설정하여 클라이언트가 어떤 ConnectionMaker를 사용할지 결정하는 것이다.

      //UserDao 생성자
      public UserDao(ConnectionMaker connectionMaker) {
        this.connectionMaker = connectionMaker;
      }
      
      //Main(클라이언트)
      public static void main(String [] args) {
        ConnectionMaker connectionMaker = new DConnectionMaker();    //UserDao가 사용할 ConnectionMaker 구현 클래스를 결정하고 오브젝트를 만든다.
      
        UserDao userDao = new UserDao(connectionMaker);
      }
    • 이로 인해, ConnectionMaker 인터페이스를 구현했다면 어떤 클래스로 만든 오브젝트더라도 UserDao의 생성자 파라미터로 들어오기만 하면 되므로, UserDao는 DB 커넥션에 관련된 클래스에 관심도 없게 된다.

 

 

원칙과 패턴

개방 폐쇄 원칙

  • 개방 폐쇄 원칙을 정의하면 클래스나 모듈은 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다.
  • 예를 들어, 우리가 리팩토링한 UserDao의 경우
    • DB 연결 방법이라는 기능을 확장하는데는 열려 있고, 확장하는데 UserDao에 전혀 영향을 주지 않는다.
    • UserDao 자신의 핵심 기능을 구현한 코드는 여러 변화에 영향을 받지 않고 유지할 수 있으므로 닫혀 있다고 말할 수 있다.
  • 잘 설계된 객체지향 클래스의 구조를 살펴보면 바로 이 개방 폐쇄 원칙을 잘 지키고 있다.

 

객체 지향 설계의 5가지 원칙

SOLID 원칙이라고도 한다.

  1. SRP : 단일 책임 원칙
  2. OCP : 개방 폐쇄 원칙
  3. LSP : 리스코프 치환 원칙
  4. ISP : 인터페이스 분리 원칙
  5. DIP : 의존관계 역전 원칙

 

높은 응집도와 낮은 결합도

  • 높은 응집도

    • 하나의 모듈, 클래스가 하나의 책임 또는 관심사에만 집중되어 있다는 뜻이다.
  • 낮은 결합도

    • 느슨하게 연결된 형태를 유지하는 것이 바람직하다.
    • 느슨한 연결은 관계를 유지하는데 필요한 최소한의 방법만 간접적인 형태로 제공하고, 나머지는 서로 독립적이고 알 필요 없게 만들어주는 것이다.
      • 관계를 유지할 수 있는 메시지로만 서로를 유지하고, 메시지를 처리하는 방법은 자율적으로 선택할 수 있게 하는 것이다.
  • UserDao는 그 자체로 응집도가 높고 결합도가 낮다.

    • 높은 응집도
      • 사용자의 데이터를 처리하는 기능이 DAO 안에 모여있다.
      • 또한, ConnectionMaker는 자신의 기능에 충실하도록 독립되어 있어 순수한 자신의 책임을 담당하는데만 충실할 수 있다.
    • 낮은 결합도
      • UserDao와 ConnectionMaker의 관계는 인터페이스를 통해 매우 느슨하게 연결되어 있다.
      • UserDao는 구체적인 ConnectionMaker 구현 클래스를 알 필요도 없고, 구현 방법이나 전략에 대해서 신경쓰지 않아도 된다.

 

전략 패턴

  • 전략 패턴은 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고, 이를 구현한 알고리즘 클래스를 필요에 따라 변경하여 사용할 수 있게 하는 디자인 패턴이다.
    • 즉, UserDao와 ConnectionMaker의 관계를 말하는 것이다. DB Connection의 알고리즘을 통째로 인터페이스로 분리시킨 것처럼..

스프링이란, 지금까지 설명한 객체지향적 설계 원칙과 디자인 패턴에 나타난 장점을 자연스럽게 개발자들이 활용할 수 있게 해주는 프레임워크인 것이다.

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함