Spring 핵심 원리 기본편 (2) - SOLID / 객체지향 설계와 Spring

김정욱·2021년 2월 15일
0
post-thumbnail
post-custom-banner

좋은 객체 지향 설계의 5가지 원칙(SOLID)

  • 클린코드로 유명로버트 마틴좋은 객체 지향 설계의 5가지 원칙을 정리
  • 5가지 목록
    • SRP(Single responsibility Principle)
      : 단일 책임 원칙
    • OCP(Open/Closed Principle)
      : 개방-폐쇄 원칙
    • LSP(Liskov Substitution Principle)
      : 리스코프 치환 원칙
    • ISP(Interface Segregation Principle)
      : 인터페이스 분리 원칙
    • DIP(Dependency Inversion Principle)
      : 의존 관계 역전 원칙
  • OCP / DIP가 가장 중요!

1. SRP(Single responsibility Principle)

  • 단일 책임 원칙
  • 한 클래스는 하나의 책임만 가져야 한다
    ('하나의 책임'이라는 것은 모호한 면이 있음
    --> 문맥과 상황에 따라 다름)
  • 즉, 핵심은 변경이 있을 때 파급 효과가 적어야 한다는 것!
    (UI변경 / 객체의 생성과 사용 분리 등)

2. OCP(Open/Closed Principle)

  • 개방-폐쇄 원칙
  • S/W 요소는 확장에는 열려있으나 변경에는 닫혀있어야 한다
  • 핵심은 다형성을 활용하는 것
  • 새로운 구현체를 사용한 확장은 열어두면서, 기존 코드의 변경은 닫혀있게 해야 한다
  • 예시
    (이러한 문제를 해결하기 위해 Spring이 필요한 것 !)

3. LSP(Liskov Substitution Principle)

  • 리스코프 치환 원칙
  • 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 함
    • 자동차 인터페이스에서 액셀앞으로 가라는 기능 이라는 정확성을 만족시켜야 우리가 믿고 쓸 수 있음
  • 즉, 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다!
  • 다형성을 지원하기 위한 원칙
  • 인터페이스를 구현한 구현체를 믿고 사용하려면 필요한 원칙

4. ISP(Interface Segregation Principle)

  • 인터페이스 분리 원칙
  • 특정 클라이언트를 위한 인터페이스 여러개가 범용 인터페이스 하나보다 낫다
    • 자동차 인터페이스 -> 운전 / 정비 인터페이스로 분리!
  • 인터페이스가 명확해지고, 대체 가능성이 높아진다.

5. DIP(Dependency Inversion Principle)

  • 의존관계 역전 원칙
  • 코드가 구현클래스에 의존하지 말고, 인터페이스에 의존해야함
  • 즉, 코드는 역할(Role)에 의존해야 한다!
  • 프로그래머는 "추상화에 의존해야지, 구체화에 의존하면 안된다"
  • 앞에서 다룬 예시는 OCP를 위반했지만 DIP도 위반한 예시이다
    : MemberRepository라는 인터페이스만 의존하는 것이 아니라, 그 구현체들도 new해서 사용하게 된다
    즉, 구현체에 의존을 하는 것이므로 DIP에 위배!
    --> OCP / DIP를 위배한 것은 앞으로 Spring의 특성을 통해 맞추어 나갈 것임

정리

  • 객체 지향의 핵심은 다형성
  • 하지만, 다형성 만으로는 쉽게 부품을 갈아 끼우듯이 할 수 없음
  • 즉, 다형성 만으로 OCP / RIP를 만족하는 코드를 짤 수 없음
    --> 추가적인 무언가가 필요함!! (이것이 바로 Spring의 역할)

객체지향 설계와 Spring

Spring Framework

  • Spring이라는 Framework는 다음 기술로 다형성 + OCP/DIP 가능하게 지원
    • DI(Dependency Injection) : 의존관계, 의존성 주입
    • DI 컨테이너 제공
  • 클라이언트 코드의 변경 없이 기능 확장

객체지향 설계

  • 모든 설계에 역할 / 구현을 분리
  • 이상적으로는 모든 설계에 인터페이스(interface)를 부여하는 것
    하지만, 인터페이스는 추상화 라는 비용이 발생한다!!
  • 추상화 비용
    : 추상화를 하게 되면 1차원 적으로 코드가 추가되는 것도 있지만, 그것보다는 프로그래머가 코드를 봤을 때 인터페이스 만으로는 어떤 구현체를 사용했는지 알 수 없기에 한번 더 들어가서 확인해야 하는 것이 바로 '추상화 비용' 이다!
  • 정리
    1) 기능을 확장할 가능성이 없으면 --> 구현체 클래스 직접 사용
    2) 확장 할 가능성 있으면 --> 인터페이스 사용
    3) 애매하면 --> 일단 구현체로 하고 향후 리팩토링 하는 것도 방법!
profile
Developer & PhotoGrapher
post-custom-banner

0개의 댓글