SPRING - 오브젝트와 의존관계 (4)

Sungjin·2021년 10월 14일
1

Spring

목록 보기
18/23
post-thumbnail

🔍 원칙과 패턴

코드를 개선해온 결과를 객체지향 기술의 여러 가지 이론을 통해 알아봅시다.

개방 폐쇄 원칙 (OCP, Open-Closed Principle)

  • '클래스나 모듈은 확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다.'
    • service에서 repository의 기능은 언제든지 확장이 가능한 상태입니다. 동시에 확장을 하더라도, service 자신의 핵심
      기능을 구현한 코드는 그런 변화에 영향을 받지 않고 유지할 수 있으므로 변경에는 닫혀 있다고 할 수 있습니다.
  • 잘 설계된 객체지향 클래스의 구조를 살펴보면 OCP를 아주 좋게 지키고 있습니다.

높은 응집도와 낮은 결합도

개방 폐쇄 원칙은 높은 응집도와 낮은 결합도라는 소프트웨어 개발의 고전적인 원리로도 설명 가능합니다.
응집도가 높다는 것은 하나의 모듈, 클래스가 하나의 책임 또는 관심사에만 집중되어 있다는 것을 뜻하고,
불필요하거나 직접 관련이 없는 외부의 관심과 책임이 얽혀 있지 않다는 뜻입니다.

  • 높은 응집도

    • 변화가 일어날 때 해당 모듈에서 변하는 부분이 크다는 것을 의미. 즉, 변경이 일어날 때 모듈의 많은 부분이 함께 바뀐다면 응집도가 높다고 말할 수 있습니다.
      • 모듈의 일부분만 변경이 일어난다면, 어떤 부분이 변경 되었는지 파악하기 어렵고, 그 변경으로 인해 다른 부분에 영향을 끼칠 수 도 있습니다.
    • 작업은 항상 전체적으로 일어나고 무엇을 변경할지 명확하며, 변경으로 인해 다른 클래스의 수정을 요구하지 않고, 기능에도 영향을 주지 않을 수 있습니다.
  • 낮은 결합도

    • 책임과 관심사가 다른 오브젝트 또는 모듈과 낮은 결합도, 즉 느슨하게 연결된 형태를 유지하는 것이 바람직 합니다.
    • '결합도'란 하나의 오브젝트가 변경이 일어날 때에 관계를 맺고있는 다른 오브젝트에게 변화를 요구하는 정도를 말합니다.
  • 즉, repository라는 관심사를 하나의 관심사로 분리 하였으며, 인터페이스를 활용하였기 때문에 응집도가 높고, 결합도가 낮다고 할 수 있습니다.

전략 패턴

전략패턴은 자신의 기능에서, 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고, 이를 구현한 구체적인 알고리즘 클래스를 필요에 따라 바꿔서
사용할 수 있는 디자인 패턴을 말합니다.
즉, 컨텍스트(service)를 사용하는 클라이언트(AppConfig)는 컨텍스트가 사용할 전략(repository)를 컨텍스트의 생성자등을 통해 제공해주는 것을 말합니다.

지금 까지 개선해온 코드가 OCP, 높은 응집도, 낮은 결합도, 전략 패턴을 잘 지켰음을 증명했습니다.

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


🚀 제어의 역전(IOC)

🔧 팩토리

객체의 생성 방법을 결정하고 그렇게 만들어진 오브젝트를 돌려주는 일을 하는 오브젝트를 뜻합니다.
오브젝트를 생성하는 쪽과 생성된 오브젝트를 사용하는 쪽의 역할과 책임을 깔끔하게 분리하려는 목적으로 사용합니다.

이는, Ver 5. 에서 만들어봤던 AppConfig 와 같은 클래스를 뜻합니다.

@RequiredArgsConstructor
public class AppConfig {

    private final EntityManager em;

    public UserRepositoryV5 userRepository(){
        return new UserRepositoryV5Impl(em);
    }

    public UserServiceV5 userService(){
        return new UserServiceV5(userRepository());
    }
}

service -> repository 와 같은 의존 관계를 형성하고 있을 때, 새로운 repository 구현 클래스로 변경이 필요하면 AppConfig클래스만 수정해주면 됩니다.

예를 들자면, repositoryImplV1repositoryImplV2와 같은 repository구현체가 있을 때,

@RequiredArgsConstructor
public class AppConfig {

    private final EntityManager em;

    public UserRepositoryV5 userRepository(){
       // return new UserRepositoryV5Impl(em);
      return new UserRepositoryV5ImplV2(em);
    }

    public UserServiceV5 userService(){
        return new UserServiceV5(userRepository());
    }
}

이런 식으로만, 바꿔준다면 되는 것을 의미합니다.

🔧 제어권의 이전을 통한 제어관계 역전

일반적인 프로그램의 흐름은 main() 메소드와 같은 프로그램이 시작되는 지점에서 사용할 오브젝트, 오브젝트의 메소드 호출 등등
모든 종류의 작업을 사용자가 능동적으로, 직접 제어하는 구조입니다.

제어의 역전이란 이런 일반적인 프로그램의 흐름을 거꾸로 뒤집는 것 입니다.

제어의 역전에서는 자신이 사용할 오브젝트를 결정하지 않을 뿐더럴 생성조차 하지 않습니다.
모든 제어 권한을 자신이 아닌 다른 대상에게 위임하는 것을 뜻합니다.

흔히, 스프링과 같은 프레임워크는 제어의 역전 개념이 적용된 대표적인 기술이라고 합니다.
프레임워크와 라이브러리를 혼동할수도 있는데 둘은 엄연히 차이가 있습니다.

  • 라이브러리
    • 동작하는 중에 필요한 기능이 있을 때, 능동적으로 라이브러리를 사용. 애플리케이션의 흐름은 직접 제어
  • 프레임워크
    • 애플리케이션 코드가 프레임워크에 의해 사용.
    • 프레임워크 위에 개발한 클래스를 등록해두고, 프레임워크가 흐름을 주도하는 중에 개발자가 만든 애플리케이션 코드를 사용하는 방식.

지금, 우리가 만든 repositoryservice 사이에서도 제어의 역전이 적용 되어 있습니다.
일반적인 프로그램의 경우, repository의 구현 클래스를 결정하고 오브젝트를 만드는 결정권한은 service에 있을 것입니다.
그러나, 지금음 AppConfig에 있습니다. service는 능동적인 존재가 아닌, 수동적인 존재가 되었다고고 말할 수 있습니다.
service는 자기 자신도 수동적으로 만들어 지며, 사용할 오브젝트 또한 수동적으로 공급 받게 됩니다.

현재 지금 만든 것은 가장 단순한 IOC 프레임워크를 만들었다고 보면 될것이고, 이제 애플리케이션 전반에 걸쳐 사용하기 위해서는 대표적인 IOC 프레임워크인
스프링의 도움이 필요하합니다.(컴포넌트의 생성과 관계설정, 사용, 생명주기 관리등을 관장하는 존재)

👋 다음 포스팅에서 이어서 하도록 하겠습니다!

profile
WEB STUDY & etc.. HELLO!

2개의 댓글

comment-user-thumbnail
2022년 3월 27일

깔끔한 정리 잘 봤습니다!
혹시 실례가 되지 않는다면 따로 정리를 해도 될까요? 출처 남기겠습니다!

1개의 답글