[Spring] 김영한 스프링 핵심원리 기본_chap01 객체지향 설계와 스프링

HMS·2023년 3월 28일

해당 내용은 김영한 스프링 핵심원리 기본 강의를 들으며 강의 자료를 참고하여 정리한 내용입니다.

김영한 스프링 핵심원리 기본


스프링 핵심원리 기본 강의 학습목표
스프링 기본 기능 학습
스프링 본질 깊은 이해
스프링이란건 결국 좋은 객체지향 어플리케이션을 작성할 수 있도록 도와주는 프레임워크
객체지향 설계를 고민하는 개발자로 성장

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

스프링의 역사
2000년 초반에는 EJB(enterprise java beans) 기업환경시스템 구현을 위한 컴포넌트 모델을 사용-> 트랜잭션이나 분산시스템 orm기술등을 지원 -> 너무 비싸고 어렵고 복잡하고 느렸음
pojo(plain old java object) 오래된방식의 간단한 자바 오브젝트로 돌아가자는 말들이 나옴
POJO - (Plain Old Java Object)란 뭘까?
로드존슨이 ejb를 문제점을 지적하는 책을냄 -> EJB없이도 고품질의 확장가능한 30000라인 이상의 기반기술을 코드로 구현
해당코드들에 스프링 핵심개념과 기반코드가 들어있음
BeanFactory,ApplicationContext, POJO, 제어의역전, 의존관계주입 ….
게빈킹이 Hivernate 오픈소스를 만듬
ejb엔티티빈 기술을 대체하게됨
EJB 에서는 하이버네이트를 정제하여 JPA라는 표준 인터페이스를 만듬
로드존슨의 책 출간 후 유겐휠러와 얀카로프가 로드존슨과 함께 스프링 오픈소스프로젝트를 진행
the fact that Spring represented a fresh start after the “winter” of traditional J2EE.
J2EE(EJB)라는 겨울을 넘어 봄이왔다는 뜻으로 Spring이라 지음
2003년 스프링 프레임워크 1.0 출시 - XML
2006년 스프링 프레임워크 2.0 출시 - XML 편의기능 지원
2009년 스프링 3.0 출시 - 자바코드로 설정
xml없이 자바코드로 설정 가능하도록 확장
2013년 스프링 4.0 출시 - 자바8
2014년 스프링 부트 1.0출시
톰켓같은 웹 서버에 war파일을 넣고 배포해야하는데 그런 과정이 복잡했음
당시 스프링 개발은 스프링 설정이 절반이다 할 정도로 설정이 많았음 부트는 그러한 작업을 대신 해 주어 불편함을 엄청나게 해소
2017년 스프링 프레임워크 5.0, 스프링 부트 2.0 출시 - 리엑티브 프로그래밍 지원

스프링이란?
스프링 프레임워크?
스프링 DI 컨테이너, AOP, 중복코드 제거, 다른 프레임워크 통합등의 핵심 기술을 제공하여 좋은 객체지향 설계를 할 수 있도록 돕는 java 기반의 back-end Framework
스프링 부트?
스프링을 편리하게 사용할 수 있도록 지원, 최근에는 기본으로 사용
단독으로 실행할 수 있는 스프링 애플리케이션을 쉽게생성
Tomcat같은 웹 서버를 내장해서 별도의 웹 서버를 설치하지 않아도됨
스프링부트가 빌드하고 서버띄우는것까지 몇줄 코드로 가능
손쉬운 빌드 구성을 위한 starter 종속성 제공
starter가 여러 라이브러리 묶음을 빌드해줌
스프링과 3rd party(외부) 라이브러리 자동구성
예전에는 외부라이브러리와 스프링 버전간의 호환성을 하나하나 고민하여 맞춰야했음
부트가 외부라이브러리의 버전과의 궁합이 잘 맞는지 지정해줌
메트릭, 상태확인, 외부 구성 같은 프로덕션 준비기능 제공
운영환경에서 모니터링같은것들을 제공
관례에 의한 간결한 설정
필요한 설정들을 기본적으로 설정해주고 필요한 부분만 수정해주면됨
스프링 부트는 기본적으로 스프링 프레임워크를 사용해야 사용할 수 있는것
스프링 단어?
스프링 DI 컨테이너 기술
스프링 프레임워크
스프링 부트, 스프링 프레임워크등을 모두 포함한 스프링 생태계
스프링 왜 만들었나? 핵심 개념,컨셉 본질을 아는것이 중요하다
이 기술을 왜 만들었는가?
-> 스프링은 좋은 객체지향 프로그래밍을 할 수 있도록 도와주는 도구다
이 기술의 핵심 컨셉은?
스프링은 자바 언어 기반의 프레임워크다
자바언어의 가장 큰 특징은 객체 지향 언어
스프링은 객체지향 언어가 가진 강력한 특징을 살려내는 프레임워크
스프링은 좋은 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임워크
EJB에 의존적으로 만들면 ejb스타일로 만들게 되어 객체지향의 좋은점을 잃어버리게 되었다

좋은 객체지향 프로그래밍이란?
객체지향이란?
프로그램을 명령어의 목록이 아닌 여러개의 독립된 객체들의 모임으로 파악하는것 객체는 메세지를 주고받고 데이터를 처리(협력)
객체지향의 목적은?
유연하고 변경이 용이하게 만들기 위함
레고 블럭 조립하듯이, 컴퓨터 부품 갈아 끼우듯이
컴포넌트를 쉽고 유연하게 변경하면서 개발할 수 있는 방법 -> 이것이 다형성이다.
객체지향의 핵심은 다형성!! 다형성이 무엇?
역할과 구현으로 세상을 구분하는것
역할이 인터페이스 구현이 구현체

운전자 - 자동차
운전자 역할은 구현된 자동차가 바뀌어도 운전을 할 수 있다
자동차 역할의 인터페이스가 구현이 되어있다고 할 수 있다
클라이언트에게 영향을 주지 않고 새로운 기능을 제공할 수 있다

로미오 역할은 줄리엣역할의 내용을 몰라도 된다 어떤 사람이 역할을 맡더라도 상관이없다
이것이 유연하고 변경에 용이하다는것
역할과 구현으로 세상을 구분했기 때문
역할과 구현을 분리하면?
장점
단순해지고 유연해지며 변경도 편리해진다
클라이언트는 대상의 역할(인터페이스)만 알면 된다.
로미오 역할이 뭔지만 알면됨
클라이언트는 구현 대상의 내부 구조를 몰라도 된다.
자동차가 어떻게 구동하는지 몰라도됨
클라이언트는 구현 대상의 내부 구조가 변경되어도 영향받지 않는다.
경유차가 전기차로 바뀌어도 상관없음
클라이언트는 구현 대상 자체를 변경해도 영향을 받지 않는다.
K3가 아반떼로 바뀌어도 상관없음
어떻게 분리?
자바언어의 다형성을 사용한다
역할 = 인터페이스
구현 = 인터페이스를 구현한 클래스, 구현 객체
역할과 구현을 명확히 분리!
구현보다 인터페이스가 우선이다 역할을 먼저 만들어 줘야하는것
객체의 협력이라는 관계
혼자있는 객체는 없음 -> 중요한건 클라이언트 요청자
클라이언트: 요청, 서버: 응답
수 많은 객체 클라이언트와 객체 서버는 협력관계
자바 언어의 다형성
오버라이딩
상속관계에서 부모객체에 있는 메소드를 자식 객체에서 오버라이딩 하여 확장한 객체에 맞는 기능으로 사용 가능

다형성의 본질
인터페이스를 구현한 객체 인스턴스를 실행 시점에 유연하게 변경가능
다형성의 본질을 이해하려면 협력이라는 객체사이의 관계에서 시작해야
클라이언트를 변경하지 않고 서버의 구현 기능을 유연하게 변경할 수 있음

DB에 저장하고싶지 않으면 메모리멤버 클래스의 SAVE를 사용할 수 도 있고 DB에 저장해야한다면 JDBC클래스의 SAVE를 사용할 수 도 있는 것 -> 클래스의 무엇도 변경하지않고 메소드 내용도 변경하지않음 의존성 주입 관계만 확실히 해주면 됨
정리
역할과 구현이라는 편리한 컨셉을 다형성을 통해 객체세상으로 나타낼 수 있음
유연하고, 변경에 용이
확장 가능한 설계 멤버리포를 무한하게 확장할 수 있음
클라이언트에 영향을 주지 않는 변경 가능
인터페이스를 안정적으로 잘 설계하는것이 중요함
한계
역할(인터페이스) 자체가 변하면 클라, 서버 모두에 큰 변경 발생
자동차를 비행기로 변경하면???? 구동이 안되지
대본이 변경되면?
인터페이스를 잘 설계해야함
스프링과 객체지향
다형성이 가장 중요
스프링은 다형성을 극대화해서 이용할 수 있게 도와줌
스프링에서 이야기하는 IOC, DI는 다형성을 활용해서 역할과 구현을 편리하게 다룰 수 있도록 지원하는것
스프링을 사용하면 조립하듯이 구현을 편리하게 할 수 있음

SOLID 좋은 객체지향 설계 5대 원칙
SRP(Single responsibility principle) 단일 책임 원칙
한 클래스는 하나의 책임만 가져야 한다.
하나의 책임이라는 것은 모호함
클수도 있고 작을수도 있음 문맥과 상황에 따라 다름
하나만 가져야한다는게 아님 잘 설계하는게 객체지향 설계 묘미
중요한 기준은 변경. 변경이 있을 때 파급 효과가 적으면 단일 책임원칙을 잘 따른 것
ui를 변경하거나 생성과 사용을 분리하는 경우
OCP 개방 폐쇄 원칙 -> 중요
자신의 확장에는 열려있으나, 주변의 변화에는 닫혀있어야 한다
자동차(인터페이스) 입장에서는 다양한 자동차들(구현체)가 생겨도 기존 운전자나 자동차에 영향이 없음 확장에는 열려 있는것
운전자(클라이언트) 입장에서는 주변이 변화(마티즈 -> 아반떼)하여도 운전자는 영향을 받지 않기 때문에 변경에는 닫혀있는것
다형성을 활용해서 기존코드의 변경없이 기능변경을 할 수 있어야함
인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현
OCP의 문제점
MemberService 클라이언트가 구현클래스를 직접 선택할 때
MemberService m = new Repo1(); // 기존코드
MemberService m = new Repo2(); // 변경코드
위와같이 service클래스의 구현 객체를 변경하려면 클라이언트 코드를 변경해야 함
다형성을 사용했지만 OCP원칙이 깨지게 됨
어떻게 해결?
객체를 생성하고 연관관계를 맺어주는 조립,설정자가 필요
스프링이 해결해 줄 수 있음 ioc컨테이너와 Di가 필요함
LSP (Liskov substitution principle) 리스코프 치환 원칙
프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야함
다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것,다형성을 지원하기 위한 원칙, 인터페이스를 구현한 구현체를 믿고 기능적으로 보장
걷는다 혹은 앞으로간다 등의 인터페이스 내용이 있다면 구현체는 해당기능을 완벽히 구현해 내야 한다는의미
걷는다고 했는데 날아간다던가 앞으로가야하는데 뒤로가게 구현한다면 원칙을 위반하는것
컴파일 성공하는 것을 넘어서는 이야기
ISP(interface segregation principle) 인터페이스 분리 원칙
특정 클라이언트를 위한 인터페이스 여러개가 범용 인터페이스 하나보다 낫다
적당한 크기로 인터페이스를 잘 쪼개는것
자동차 인터페이스 -> 운전 인터페이스, 정비 인터페이스로 분리하는것
사용자 클라이언트 -> 운전자 , 정비사로 분리
분리하면 정비 인터페이스 자체가 변해도 운전자한테 영향 주지 않음
인터페이스가 명확, 대체 가능성이 높아짐
spring은 엄청나게 분리되어있음
DIP (Dependency inversion principle)의존관계 역전 원칙
추상화에 의존해야지 구체화에 의존하면 안된다.
구현 클래스에 의존하지 말고 인터페이스에 의존해야한다
역할과 구현을 철저하게 분리하여 구현이 아닌 인터페이스에 의존하여 구현체 교체가 문제없이 이루어 지도록 설계해야함
클라이언트가 인터페이스에 의존해야 유연하게 구현체를 변경할 수 있음
OCP에서 설명한 MemberService는 인터페이스에도 의존하고 구현체에도 의존한다
의존은 안다는것 클래스 내에서 생성되었다면 알고있다는것
DIP위반 -> 구체화에 의존한다
정리
객체지향 핵심은 다형성이지만
다형성 만으로는 구현 객체를 변경할 때 클라이언트 코드도 변경된다.
다형성 만으로는 쉽게 부품을 갈아 끼우듯이 개발할 수 없다.
다형성 만으로는 OCP, DIP를 지킬 수 없다
DIP를 지켰지만 인터페이스만 알고 있다면 아무것도 구현할 수 없다
다형성을 사용하여 역할과 구현을 구분했지만 MemberService안에 생성된 MemberRepository객체는 Service클래스의 코드를 변경해야 구현객체를 변경할 수 있었다 OCP를 위반했다.
추가적인 무언가가 필요함!

객체지향 설계와 스프링
스프링 이야기에서 객체지향 이야기가 나오는 이유?
스프링은 DI기술과 DI(IOC) 컨테이너 기술로 다형성+ OCP,DIP를 가능하게 지원한다.
세가지를 만족함으로써 클라이언트코드의 변경없이 기능을 확장시킬 수 있다.
스프링이 없던시절
OCP,DIP 원칙을 지키면서 객체지향 개발을 하려고 하니 할일이 너무 많았음 그래서 프레임워크로 만들었음 그게 스프링프레임워크 (DI컨테이너)
정리
모든 설계에 역할과 구현을 분리하자
애플리케이션 설계도 공연 설계하듯이 배역만 만들어두고 배우는 언제든지 유연하게 변경할 수 있도록 만드는것이 좋은 객체 지향 설계
이상적으로는 모든 설계에 인터페이스를 부여
추상화라는 비용이 발생 -> 인터페이스로는 알 수 없으니 개발자가 결국 구현클래스를 한번 더 확인해야하는 일이 발생 -> 확장가능성이 없으면 구체클래스로 작성하고 나중에 리펙터링해서 인터페이스를 구현하는걸 추천

profile
안녕하세요

0개의 댓글