Home 김영한의 스프링 핵심 원리 기본편 - 객체지향 설계와 스프링
Post
Cancel

김영한의 스프링 핵심 원리 기본편 - 객체지향 설계와 스프링

객체지향 설계와 스프링

  • 김영한님의 스프링 핵심 원리 기본편 강의 중 객체지향 설계와 스프링의 탄생 배경, 그리고 좋은 객체지향 설계를 위한 SOLID 원칙을 정리함



스프링의 탄생 배경과 역사

EJB의 한계와 스프링의 등장

  • EJB (Enterprise Java Beans)
    • 과거 자바 표준 기술이었던 EJB는 매우 복잡하고 어렵다는 단점이 있었음
  • 로드 존슨의 책 출간 (2002)
    • EJB의 문제점을 지적하며, EJB 없이도 고품질 애플리케이션 개발이 가능함을 보여줌
    • 이 책의 예제 코드가 현재 스프링의 모태가 됨
  • 스프링(Spring) -‘EJB라는 겨울을 지나 봄이 왔다’는 의미

스프링 생태계

  • 구성
    • 스프링은 단순히 하나의 프레임워크가 아니라 스프링 부트, 스프링 데이터, 스프링 시큐리티 등을 포함한 거대한 생태계임
  • 스프링 부트 (Spring Boot)
    • 내장 서버(Tomcat)와 자동 구성 기능을 통해 스프링을 편리하게 사용할 수 있도록 지원함



스프링의 본질과 객체지향

스프링의 핵심

  • 스프링이 존재하는 이유
    • 스프링은 자바 언어 기반의 프레임워크이며, 자바의 가장 큰 특징인 객체지향의 강력한 특징을 살려내는 데 집중함
    • 결국 스프링은 좋은 객체지향 애플리케이션을 개발할 수 있도록 돕는 도구임

다형성 (Polymorphism)

  • 역할과 구현
    • 세상을 역할(Role, 인터페이스)과 구현(Implementation, 객체)으로 구분하면 시스템이 단순하고 유연해짐
      • ex) 운전자(클라이언트)는 자동차의 내부 구조를 몰라도 자동차 역할(인터페이스)만 알면 다양한 차(구현체)를 운전할 수 있음
    • 클라이언트는 구현 대상의 내부 구조가 변경되거나 대상 자체가 바뀌어도 영향을 받지 않음



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

5가지 핵심 원칙

  • SRP(단일 책임 원칙, Single Responsibility Principle)
    • 한 클래스는 하나의 책임만 가져야 함
    • 중요한 기준은 변경
      • 변경이 있을 때 파급 효과가 적어야 함
  • OCP(개방-폐쇄 원칙, Open/Closed Principle)
    • 확장에는 열려 있으나 변경에는 닫혀 있어야 한다는 가장 중요한 원칙
    • 다형성을 활용하여 인터페이스를 구현한 새로운 클래스를 만들어 기능을 확장함
  • LSP(리스코프 치환 원칙, Liskov Substitution Principle)
    • 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 함
    • ex) 자동차 엑셀은 앞으로 가야 한다는 규약을 지켜야 함 (뒤로 가면 위반)
  • ISP(인터페이스 분리 원칙, Interface Segregation Principle)
    • 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 나음
    • 인터페이스가 명확해지고, 대체 가능성이 높아짐
  • DIP(의존관계 역전 원칙, Dependency Inversion Principle)
    • 추상화(인터페이스)에 의존해야지 구체화(구현 클래스)에 의존하면 안 된다는 원칙
    • 클라이언트 코드가 구현 클래스를 바라보지 않고 인터페이스만 바라봐야 함



왜 스프링이 필요한가?

순수 자바의 한계

  • 다형성만으로는 부족함
    • 순수 자바의 다형성만 사용하면 구현 객체를 변경할 때 클라이언트 코드도 함께 변경되는 문제가 발생함
    • 이는 OCP(변경 발생)와 DIP(구체 클래스 의존) 원칙을 위반하게 됨

스프링의 해결책

  • DI (Dependency Injection)
    • 스프링은 DI 컨테이너를 통해 객체를 생성하고 연관관계를 맺어주는 역할을 수행함
    • 이를 통해 클라이언트 코드의 변경 없이 기능을 확장하고 부품을 교체하듯이 개발할 수 있게 됨
    • 결국 스프링은 다형성을 극대화하여 SOLID 원칙을 지킬 수 있도록 지원하는 기술임



실무적인 설계 원칙

이상과 현실

  • 이상적인 설계
    • 모든 설계에 역할(인터페이스)과 구현을 분리하는 것이 가장 이상적임
  • 현실적인 타협
    • 인터페이스 도입에는 추상화라는 비용이 발생함 (코드를 한 번 더 열어봐야 함)
    • 기능 확장 가능성이 없다면 구체 클래스를 먼저 사용하고, 향후 필요할 때 리팩터링하여 인터페이스를 도입하는 것도 방법임



연습 문제

  1. 2000년대 초반, 자바 엔터프라이즈 개발 환경에서 EJB 사용의 주요 어려움 중 하나는 무엇이었나요?

    • a. 복잡한 설정과 기술에 대한 높은 의존성

    • EJB는 복잡하고 설정이 어려웠으며, 특정 EJB 인터페이스에 강하게 의존하는 설계로 유연성이 떨어졌음
    • 이는 개발 시간과 비용 증가의 원인이 되었음
  2. 스프링의 핵심 기술(DI 컨테이너 등)이 객체 지향 설계에 도움을 주는 이유는 무엇인가요?

    • a. 객체 생성과 의존 관계를 관리하여 유연한 설계를 지원하기 때문

    • 스프링의 DI 컨테이너는 객체 생성과 관계 설정을 대신함
    • 개발자가 객체 간 의존성을 관리하고 구현체를 유연하게 교체할 수 있도록 도움
  3. 객체 지향 설계 원칙인 SOLID 중, ‘클라이언트 코드가 구체 클래스가 아닌 추상화(인터페이스)에 의존해야 한다’는 점을 강조하는 원칙은 무엇인가요?

    • a. 의존 역전 원칙 (DIP)

    • 의존 역전 원칙(DIP)은 고수준 모듈이 저수준 모듈에 의존하는 대신, 둘 다 추상화에 의존해야 함을 강조함
    • 이를 통해 구체 클래스 변경에도 영향을 받지 않음
  4. 스프링의 DI 컨테이너를 쓰면 OCP(개방/폐쇄 원칙)와 DIP(의존 역전 원칙)를 지키는 데 어떤 도움이 될까요?

    • a. 객체 생성 및 의존 관계 설정을 외부에 맡겨 클라이언트 코드를 변경 없이 유지하게 한다

    • 스프링 DI 컨테이너는 객체의 생성 및 의존 관계 연결 책임을 개발자 코드 밖으로 옮김
    • 클라이언트 코드를 변경하지 않고도 구현체를 교체할 수 있게 함
  5. 스프링 부트가 기존 스프링 프레임워크보다 개발하기 편한 이유는 뭘까요?

    • a. 설정 간소화 및 내장 웹 서버 제공으로 개발 편의성 향상

    • 스프링 부트는 스프링 프레임워크를 기반으로 설정 자동화, 스타터 의존성, 내장 서버 등을 제공함
    • 개발자가 프로젝트를 더 쉽고 빠르게 시작하고 개발할 수 있도록 도움



요약 정리

  • 객체지향의 확장
    • 스프링은 자바의 객체지향적 특징(다형성)을 극대화하여 좋은 객체지향 애플리케이션을 개발하도록 도움
  • SOLID
    • SRP(단일 책임), OCP(개방-폐쇄), LSP(리스코프 치환), ISP(인터페이스 분리), DIP(의존관계 역전)
  • DI (의존관계 주입)
    • 다형성만으로는 해결되지 않는 OCP, DIP 위반 문제를 해결하고 유연한 확장을 가능하게ㄴ 함



Reference

Contents