관리 메뉴

나구리의 개발공부기록

객체지향 설계와 스프링, 스프링 탄생 배경, 스프링이란?, 좋은 객체 지향 프로그래밍?, 좋은 객체 지향 설계의 5가지 원칙(SOLID),객체 지향 설계와 스프링 본문

인프런 - 스프링 완전정복 코스 로드맵/스프링 핵심원리 - 기본편

객체지향 설계와 스프링, 스프링 탄생 배경, 스프링이란?, 좋은 객체 지향 프로그래밍?, 좋은 객체 지향 설계의 5가지 원칙(SOLID),객체 지향 설계와 스프링

소소한나구리 2024. 1. 25. 15:58

  출처 : 인프런 - 스프링 핵심원리 - 기본편(유료) / 김영한님  
  유료 강의이므로 정리에 초점을 두고 코드는 일부만 인용  

https://inf.run/kCYMv


1. 스프링 탄생 배경

  • 2000년대 초반 자바의 표준 기술인 EJB 기술이 있었음
  • EJB: 엔터프라이즈 자바 빈즈의 줄임말
  • EJB는 당시의 여러 고급 기술들을 모아놓은 종합 세트 같은 느낌이였음(Transaction. Entity Bean(ORM)기술 등등)
  • 당시에는 오픈소스 같은 것들은 비주류 기술 취급을 많이 함
  • 하지만 EJB는 1대에 수천만원 할정도로 매우 비쌌고 어렵고 복잡하고 너무 느려서 오히려 순수한 자바로 다시 돌아가자는 말이 나올 정도 였음(Plan Old Java Object)
  • 두명의 개발자가 이 상황을 타파하기 위해 오픈 소스를 만듦

1) 로드존슨 , 유겐휠러(Juergen Hoeller), 얀카로프(Yann Caroff) - 스프링(겨울이 끝나고 봄이 왔다)

  • EJB의 문제점을 지적하면서 책을 출간함
  • 3만 라인 이상의 예제 코드를 기반으로 여러가지의 개념을 모두 집어 넣음 -> 개발자들이 그 예제코드를 프로젝트에 사용
  • 유겐휠러와 얀카로프가 오픈소스 프로젝트를 제안 -> 현재도 핵심 코드의 상당수는 지금까지도 유겐 휠러가 개발하고 있음

2) 개빈킹 - 하이버네이트(Entity Bean을 대체)

  • Hibernate가 잘나가자 자바 표준을 논의하고 만드는 곳에서 개빈킹을 영입함
  • Hibernate를 거의 복사 붙혀넣기해서 만들게 된 것이 JPA
  • 결과적으로 ORM 시장은 JPA가, 구현체로는 하이버네이트가 주로 사용 되고 있음

3) 스프링 간단 히스토리

  • 2003년 스프링 프레임워크 1.0 출시 - XML
  • 2006년 스프링 프레임워크 2.0 출시 - XML 편의 기능 지원
  • 2009년 스프링 프레임워크 3.0 출시 - 자바 코드로 설정
  • 2013년 스프링 프레임워크 4.0 출시 - 자바 8
  • 2014년 스프링 부트 1.0 출시
  • 2017년 스프링 프레임 워크 5.0, 스프링 부트 2.0 출시 - 리엑티브 프로그래밍 지원
  • 현재도 쭉 업데이트 중..

2. 스프링이란?

  • 스프링은 여러가지 기술의 모음이라고 볼 수 있음
  • 스프링 프레임워크 자체를 뜻하기도 하지만 스프링 DI 컨테이너 기술이나 스프링부트, 스프링 프레임워크를 모두 포함한 것을 칭함

1) 필수 기술

(1) 스프링 프레임워크

  • 핵심 기술: 스프링 DI컨테이너, AOP이벤트, 기타
  • 웹 기술: 스프링 MVC, 스프링 WebFlux
  • 데이터 접근 기술: 트랜잭션, JDBC, ORM지원, XML지원
  • 기술통합 : 캐시, 이메일, 원격접근, 스케줄링
  • 테스트: 스프링 기반 테스트 지원
  • 언어: 코틀린, 그루비
  • 최근에는 스프링 부트를 통해서 스프링 프레임워크 기술들을 편리하게 사용

(2) 스프링 부트

  • 스프링을 편리하게 사용할 수 있도록 지원 -> 최근에는 기본으로 사용
  • 단독으로 실행할 수 있는 스프링 애플리케이션을 쉽게 생성
  • Tomcat 같은 웹 서버를 내장 -> 별도의 웹 서버를 설치 않아도 됨
  • 손쉬운 빌드 구성을 위한 starter 종속성 제공
  • 스프링과 3rd patch(외부) 라이브러리 자동 구성
  • 메트릭, 상태 확인, 외부 구성같은 프로덕션 준비 기능 제공
  • 관례에 의한 간결한 설정

** 스프링 부트는 스프링 프레임워크랑 별도로 사용할 수 있는 것이 아님

2) 선택 기술

(1) 스프링 데이터

  • 관계형데이터베이스, noSQL 모두 CRUD는 비슷함 -> 해당 작업을 편리하게 도와주는 기술
  • 제일 많이 쓰는 것은 스프링 데이터 JPA

(2) 스프링 세션

  • 세션 기능을 편리하게 사용할 수 있도록 도와주는 기술

(3) 스프링 시큐리티

  • 보안과 관련된 것

(4) 스프링 Rest Docs

  • API문서와 테스트를 엮어서 문서화를 편하게 해주는 것

(5) 스프링 배치

  • 배치처리에 특화된 기술
  • 다량의 데이터를 나눠서 저장하는 것을 배치처리라 함

(6) 스프링 클라우드

  • 클라우드에 특화

(7) 그 외

  • spring.io를 들어가면 설명한 것 외에도 굉장히 많은 프로젝트들이 있음

3) 스프링은 왜 만들었는가?

(1) 스프링의 핵심 컨셉과 개념

  • 자바 언어 기반의 프레임워크, 자바 = 객체 지향 언어
  • 객체 지향 언어가 가진 특징을 살려내고 좋은 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임워크

(2) 좋은 객체 지향 프로그래밍이란?

  • 객체지향의 핵심 - 다형성 (유연하고 변경에 용이)
  • 역할(인터페이스)구현(인터페이스를 구현한 클래스, 구현 객체)분리
  • 역할과 구현으로 구분하면 단순해지고 유연해지며 변경이 편리해짐
  • 클라이언트는 인터페이스(역할)만 알면 되고 내부 구조(구현)은 몰라도 되며, 내부 구조가 변경 되어도, 구현 대상 자체를 변경해도 영향을 받지 않음

(3) 객체의 협력 관계

  • 수 많은 객체 클라이언트와 객체 서버는 서로 협력 관계를 가짐
  • 클라이언트 : 요청 , 서버: 응답

클라이언트를 변경하지 않고 서버의 구현 기능을 유연하게 변경할 수 있다

(4) 다형성의 본질

  • 협력이라는 객체 사이의 관계에서 시작해야 다형성의 본질을 이해 할 수 있음
  • 클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경 할 수 있음
  • 자바의 오버라이딩 - 다형성으로 인터페이스를 구현한 객체나, 상속 관계도에서의 자손 객체에서 오버라이딩 된 메서드가 실행 됨

(5) 정리

  • 인터페이스를 안정적(가장 변화가 없는 방법)으로 잘 설계하는 것이 매우매우 중요
  • 인터페이스(역할)이 변하면 클라이언트, 서버 모두 큰 변경이 발생함

(6) 스프링과 객체 지향

  • 다형성이 가장 중요함.
  • 다형성을 극대화해서 편리하게 이용할 수 있게 도와줌

3. 좋은 객체 지향 설계의 5가지 원칙(SOLID) - 간혹 면접에 나오기도..?

(1) 클린코드로 유명한 로버트 마틴이 좋은 객체 지향 설계의 5가지 원칙을 정리

  • SRP: 단일 책임 원칙(single responsibility principle)
  • LSP: 리스코프 치환 원칙 (Liskov substitution principle)
  • DIP: 의존관계 역전 원칙 (Dependency inversion principle)
  • ISP: 인터페이스 분리 원칙 (Interface segregation principle)
  • OCP: 개방-폐쇄 원칙 (Open/closed principle)

(2) SRP: 단일 책임 원칙(single responsibility principle)

  • 한 클래스는 하나의 책임만 가져야 한다 - 하나의 책임이라는 것이 모호할 수 있는데 중요한 기준은 변경임
  • 변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것
  • ex) UI변경, 객체의 생성과 사용을 분리 등등..

(3) OCP: 개방-폐쇄 원칙 (Open/closed principle) - 중요

  • 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 함 ->  다형성을 활용
  • 구현객체를 변경하려면 클라이언트 코드를 변경 해야 함 -> 다형성을 사용했지만 OCP원칙을 지킬 수 없음
  • 객체를 생성하고 연관관계를 맺어주는 별도의 조립, 설정자가 필요
public class MemberService {
     // private MemberRepository memberRepository = new MemoryMemberRepository();
     private MemberRepository memberRepository = new JdbcMemberRepository();
}

 

(4) LSP: 리스코프 치환 원칙 (Liskov substitution principle)

  • 프로그램 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 함.
  • 다형성에서 하위 클래스는 인터페이스 규약을 전부 지켜야 함
  • ex) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능(규약), 뒤로 가게 구현하면 LSP 위반, 느리더라도 앞으로 가야함

(5) ISP: 인터페이스 분리 원칙 (Interface segregation principle)

  • 특정 클라이언트를 위한인터페이스 여러개가 범용 인터페이스 하나보다 나음 -> 기능을 용도에 맞게 적당한 크기로 쪼개는 것
  • 인터페이스가 명확해지고 대체 가능성이 높아짐

(6) DIP: 의존관계 역전 원칙 (Dependency inversion principle) - 중요

  • 클라이언트가 구현클래스에 의존하지않고 인터페이스(역할)에 의존해야 함
  • 그래야 유연하게 구현체를 변경할 수 있음, 그렇지 않으면 변경이 아주 어려워짐
  • 하지만 OCP에서 설명한 코드는 구현클래스도 동시에 의존하므로 DIP를 위반함
public class MemberService {
     // JdbcMemberRepository라는 구현체를 직접 선택했으므로 DIP가 위반되었음
     private MemberRepository memberRepository = new JdbcMemberRepository();
}

 

(7) 정리

  • 객체 지향의 핵심은 다형성이지만, 다형성만으로는 OCP, DIP를 지킬 수 없음
  • 무엇인가 더 필요함.

4. 객체 지향 설계와 스프링

  • 스프링은 DI(Dependency Injection; 의존관계, 의존성 주입), DI컨테이너 기술로 다형성 + OCP, DIP를 가능하게 지원함
  • 클라이언트 코드의 변경 없이 기능을 확장할 수 있어 쉽게 부품을 교체하듯이 개발이 가능
  • 과거 좋은 객체 지향 개발을 하려고 OCP,DIP원칙을 지키며 개발 -> 너무 개발해야할게 많음 -> 프레임워크로 만들어 버림

1) 정리

  • 모든 설계에 역할구현을 분리
  • 공연이 배역에 배우는 언제든지 유연하게 변경 하는 것 처럼 애플리케이션 설계도를 만드는 것 -> 좋은 객체 지향 설계
  • 이상적으로는 모든 설계에 인터페이스를 부여 하는 것이 좋지만 추상화라는 비용이 발생(코드를 한번더 봐야함)
  • 기능을 확장할 가능성이 없다면 구체 클래스를 직접 사용하고 향후 꼭 필용할 때 리팩터링해서 인터페이스를 도입하는 것도 방법