객체 지향 설계와 스프링 - 1

최창수·2024년 8월 21일
0

스프링은 객체지향 설계를 통해 어떤 장점을 가지고 있으며, 왜 객체지향을 선택하게 되었는가

스프링의 탄생까지

  1. EJB 표준의 유행 - 강력한 분산 지원, 선언적 트랜잭션, Entity bean(ORM) 지원 등... 이론적으로는 고성능
  2. EJB 표준의 문제점:
    • 고비용,
    • 높은 복잡성,
    • 높은 난이도,
    • 코드 가독성 감소
    • 낮은 속도
    • EJB에 과하게 의존적인 코드 형성
  3. 개빈 킹, 로드존슨의 등장
    • 개빈킹의 하이버네이트
      - EJB 엔티티 빈 기술 대체
      - 표준 인터페이스인 JPA(Java Persistence API) 등장에 기여. 가장 널리 쓰이는 구현체.
    • 로드존슨의 스프링
      - EJB 컨테이너 대체

스프링의 역사

2002년, 로드 존슨 - EJB의 문제점을 지적하면서 EJB 없이도 고품질의 확장 가능한 어플리케이션의 개발이 가능함을 제시. 30,000라인 이상의 기반기술을 예제 코드로 선보였다.

이 예제코드를 보고 유겐 휠러, 얀 카로프가 오픈소스 프로젝트를 제안하였으며 스프링(EJB winter 다음)으로 명명.

릴리즈 타임라인

  1. 스프링 프레임워크 1.0 (xml)
  2. 스프링 프레임워크 2.0 (xml편의기능)
  3. 스프링 프레임워크 3.0 (자바 코드로 설정)
  4. 4.0 - java 8
  5. spring boot 1.0
    • 웹 서버 내장으로 편리하게
  6. 5.0, boot 2.0리엑티브 프로그래밍 지원

스프링 소개

1. 스프링 생태계

필수

  • 스프링 프레임워크 - core
  • 스프링부트 - 편리하게 사용하도록 돕는 tool

선택

  • 스프링 데이터,
  • 스프링 세션,
  • 스프링 시큐리티,
  • 스프링 rest docs - 문서화와 테스트,
  • 스프링 배치 - 데이터 batch처리,
  • 스프링 클라우드
  • ...

2. 스프링 프레임워크

핵심기술

  • 스프링DI 컨테이너, AOP, event, etc.

웹 기술, 데이터 접근 기술, 기술통합, 테스트, 언어(코틀린, groovy)

3. 스프링 부트

  • 스프링을 편리하게(단독 사용 불가). 최근에는 기본으로 사용.
  • 단독 실행가능한 스프링 어플리케이션 쉽게 생성
  • tomcat 등 웹서버 내장. 별도 웹서버 필요x
  • 손쉬운 빌드 구성을 위한 starter 종속성 제공 (종속성 관리 용이)
  • 스프링과 3rd party 라이브러리 자동 구성
  • 메트릭, 상태확인, 외부 구성같은 프로덕션 준비기능 제공
  • 관례에 의한 간결한 설정

4. 'Spring' 정의

  1. 스프링 DI 컨테이너 기술
  2. 스프링 프레임워크
  3. 스프링 생태계

스프링의 핵심

  1. 이 기술을 왜 만들었을까?
  2. 이 기술의 핵심 concept(개념)은?
  • 스프링은 자바 언어 기반의 프레임 워크다.
  • 자바는 객체지향 언어다.
  • 스프링은 객체지향의 강력한 특징을 활용하는 프레임 워크다.

결론: 스프링 핵심은 좋은 객체 지향 어플리케이션을 개발 할 수 있게 하는 프레임워크다.

1. 객체지향 프로그래밍

  • 프로그램을 객체들의 모임으로 파악
  • 각 객체는 메시지를 주고받고 데이터를 처리할 수 있다
  • 프로그램을 유연하고 변경을 쉽게 만든다
    -> 다형성

예시)
운전자와 차량 모델 A,B가 있을 때 A모델에서 B모델로 바꾸어도 운전이 가능하다.

  • 즉 운전자(역할)는 차량(역할)이라는 인터페이스에 의존적이다.

2. 역할과 구현의 분리

클라이언트에 영향을 주지않고 새로운 기능을 추가 가능

  • 세상이 단순, 유연해지며 변경이 편리해진다.
  • 클라이언트는 역할(인터페이스)만 알면 된다.
  • 구현 대상의 내부구조를 알 필요가 없다.
  • 내부구조가 변경되어도 영향 받지 않는다.

2-1. 객체의 협력?

  • 혼자 있는 객체는 없다.
  • 클라이언트는 요청, 서버는 응답하는 객체.
  • 수많은 객체 클라이언트와 객체 서버들이 관계를 가진다.

2-2. 자바 언어의 다형성

  • 구현체에서 오버라이딩 된 메서드의 실행
  • 다형성으로 인터페이스구현한 객체를 실행시점에 변경 가능

다형성의 본질은 객체간의 협력 개념을 이해함으로서 접근가능하다.

  • 다형성은 클라이언트를 변경하지 않고 서버 객체를 변경 가능하다는 것이다.
  • 확장 가능한 설계, 클라이언트에 영향을 주지 않는 변경 가능

2-3. 한계

인터페이스(역할) 자체가 변하면 클라이언트와 서버 모두 크게 변경이 필요해지므로 안정적인 인터페이스 설계가 중요해진다.

3. 스프링과 객체 지향

  • 스프링은 자바가 제공하는 객체지향적 특징 중 다형성을 극대화해 이용할 수 있게 도와준다.
  • 제어의 역전, 의존관계 주입은 다형성을 활용해서 역할과 구현을 편리하게 다룰 수 있도록 지원한다.

3-1. 좋은 객체지향 5원칙: SOLID

로버트 마틴이 정리

  1. SRP: 단일 책임 원칙 - 하나의 클래스는 하나의 책임만 가져야한다.
    • 하나의 책임이란 클수도, 작을 수도, 문맥과 상황에 따라 다를 수 도 있다.
    • 기준 = 변경. 변경이 있을 때 파급 효과가 적다면 이 원칙이 지켜진것. 경험적 체득.
    • 예시: UI 변경, 객체의 생성과 사용을 분리
  2. OCP: 개방-폐쇄 원칙 (가장 중요) - 확장에는 열려있고 변경에는 닫혀있어야 함.
    • 다형성의 활용: 인터페이스를 구현한 새로운 클래스 -> 새로운 기능의 구현(변경 없는 확장)
    • 한계: 구현객체를 변경하려면, 클라이언트 코드 변경 필요
    public class MemberService {
    			// private MemberRepository memberRepository = new MemoryMemberRepository();
    			private MemberRepository memberRepository = new JdbcMemberRepository();
    		}
    • 돌파: 객체를 생성하고 연관관계를 맺어주는 별도의 조립, 설정자 == IoC컨테이너
  3. LSP: 리스코프 치환 원칙 - 프로그램 객체는 정확성을 깨트리지 않으면서 하위타입의 인스턴스로 바꿀 수 있어야 한다.
    • 하위 클래스는 상위 인터페이스의 규약을 모두 지켜야함
    • 컴파일 오류를 넘어서는 수준의 약속으로, 구현체를 신뢰할 수 있는 기반.
    • 위반 예시: 자동차 인터페이스:"엑셀==가속기능", 구현체:"엑셀을 감속기능으로 구현"
    • 위반 예시: 아빠 클래스를 상속받은 딸 클래스(계층도)
    • 올바른 예시: 포유류 클래스를 상속받은 고래 클래스(분류도)
  4. ISP: 인터페이스 분리 원칙 - 특정 클라이언트를 위한 인터페이스 여러개가 범용 인터페이스 하나보다 좋다.
    • 자동차 인터페이스: 운전 인터페이스, 정비 인터페이스 분리
    • 사용자 클라이언트: 운전자 클라이언트, 정비사 클라이언트로 분리
    • 명확한 인터페이스, 대체 가능성 증가
  5. DIP: 의존과계 역전 원칙 (가장 중요) - 구체화가 아닌 추상화에 의존하는 방법론
    • 구현 클래스가 아닌 인터페이스에 의존해야함.
    • 구현이 아닌 역할에 의존해야함과 일치함.
    • 유연한 변경 가능.
    • 한계 :
      public class MemberService {
      			// private MemberRepository memberRepository = new MemoryMemberRepository();
      			private MemberRepository memberRepository = new JdbcMemberRepository();
      		}
    실제로는 구현클래스에도 의존함.

3-2. 결론

  • 객체 지향의 핵심은 다형성이나
  • 다형성만으로는 클라이언트 코드의 변경을 막을 수 없다.
  • 다형성 만으로는 OCP, DIP를 만족 할 수 없다.

정리:

  • 모든 설계에 역할과 구현 분리
  • 모든 설계에 인터페이스 부여
  • 그러나 추상화 비용 발생: 기능을 확장할 가능성이 없다면 구체 클래스를 직접 사용하기도 함.
profile
Hallow Word!

0개의 댓글