스프링이란?
- 객체 지향 언어가 가진 강력한 특징을 살려내는 프레임워크
- 자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크
- DI (Dependency Injection) 컨테이너 지원
- AOP(Aspect Oriented Programming) 지원
- POPJ(Plain Old Java object) 지원
- 핵심 기술(DI, AOP, POPJ) 및 웹 기술 , 데이터 접근 기술, 테스팅을 지원.
스프링부트란?
스프링을 편리하게 사용할 수 있도록 지원한다.
- 톰캣 같은 웹서버를 내장해서 별도의 웹서버를 설치하지 않아도 된다.
손쉬운 빌드 구성을 위한 starter 종속성을 제공한다.
- Starter 라이브러리를 제공해서 손쉽게 프로젝트에 적용할 수 있다.
스프링과 3rd parth 라이브러리 자동 구성
- 유명한 메이저 라이브러리들은 스프링이 먼저 다 테스트하고 버전을 지정해서 다운로드 받을 수 있다. 따라서 외부 라이브러리 버전 호환을 사용자가 직접 확인할 필요가 없다.
매트릭 , 상태 확인 , 외부 구성 등 모니터링 기능을 제공한다.
스프링 부트는 스프링 프레임워크와 별도로 사용 가능한가?
- 그렇지 않다.
- 스프링 부트는 스프링의 많은 기능을 사용자가 편리 할 수 있게 만든 프레임워크이다.
왜 만들었을까? (핵심 컨셉이 무엇이길래?)
- 개발자들이 객체 지향 언어가 가진 강력한 특징을 사용할 수 있도록 도와주는 프레임워크의 필요성을 느꼈기 때문이다. 그렇다면 객체지향이란 무엇일까?
객체 지향 언어
객체 지향의 강력한 특징
- 추상화
- 캡슐화
- 상속
- 다형성(polymorphism)
객체 지향 프로그래밍이란?
객체들이 메세지를 주고 받으면서 데이터를 처리한다.
객체(컴포넌트)를 레고 블럭 조립하듯, 키보드, 마우스 갈아 끼우듯 ,컴퓨터 부품 갈아 끼우듯 쉽고 유연고 변경에 용이하게 개발할 수 있는 방법.
유연하고 변경에 용이하다?
자동차가 바뀌어도 운전자에게 영향을 주는가?
→ 주지 않는다. 역할은 서로 독립적이다.
운전자는 자동차의 역할을 이해하고 있기 때문에 운전자는 자동차의 내부 구조를 몰라도 손쉽게 사용이 가능하며 새로운 자동차가 나와도 사용에 이상이 없다.
- 운전자도 역할만 알고있으면 된다.
역할과 구현으로 구분하면 세상이 단순해진다
1. 클라이언트는 대상 역할의 인터페이스(접속 장치)만 알면된다.
2. 클라이언트는 내부구조를 몰라도 된다
3. 클라이언트는 구현대상의 내부구조가 변경 되어도 영향을 받지 않는다.
4. 클라이언트는 구현 대상 자체를 변경해도 영향을 받지 않는다.
→ 따라서 객체를 설계할 때(인터페이스)을 먼저 부여하고, 그 역할을 수행하는 구현 객체 만드는 순서로 프로그래밍한다. 인터페이스를 부여하는 것, 즉 다형성의 특성이 부여되는 것과 같다.
다형성 over-riding over-loading
인터페이스를 구현한 객체를 실행 시점에서 유연하게 변경할 수 있다는 것이, Java언어의 다형성 장점이다. (클래스 상속에서도 다형성와 오버라이딩이 적용된다.)
- 의존한다 = 내가 쟤를 알고 있다.
클라이언트를 변경하지 않고 , 서버의 구현 기능을 유연하게 변경할 수 있다는 것이 다형성의 본질이다. 인터페이스(역할) 자체가 변하면 , 클라이언트, 서버 모두에 큰 변경이 발생한다. → 설계할 때 인터페이스를 안정적으로 변화가 없는 방식으로 설계하는게 중요하다.
- API 서브 투 서브를 구현할때, 최대한 인터페이스 자체가 안 흔들리게 설계하는게 중요하다.
다형성 예시: 쇼핑몰 API
- 상품 관리 서브시스템 변경: 새로운 유형의 상품 정보를 추가하려한다. 이 변경사항은 상품 관리 시스템 내에서만 처리되고, 다른 서브시스템(주문 처리, 사용자 관리)에는 영향을 주지 않아야 한다.
- 잘 설계된 경우: 상품 정보에 변화가 있더라도, 주문 처리 시스템은 여전히 상품 ID와 기본 정보만을 사용하여 주문을 처리할 수 있다. 상품 관리 시스템의 내부 변화가 다른 시스템에 영향을 주지 않는다.
- 잘못 설계된 경우: 상품 관리 시스템의 변화로 인해 주문 처리 시스템도 수정되어야 하며, 이는 시스템 전체의 안정성을 해칠 수 있다.
- 인터페이스의 일관성 유지: 모든 서브시스템은 동일한 형식의 요청과 응답 구조를 가지고 있어야 한다. 예를 들어, 모든 API는 JSON 형식으로 데이터를 주고받고, 에러 발생 시 표준화된 에러 메시지를 반환해야 한다.
- 스프링은 이 다형성을 극대화 할 수 있도록 도와준다.
IoC, DI은 다형성을 활용해서 역할과 구현을 편리하게 다룰 수 있도록 지원한다. 따라서 레고 블럭을 조립하듯이, 공연 무대의 배우를 선택하듯 , 구현을 편리하게 변경할 수 있다.
좋은 객체지향 설계의 5가지 원칙(SOLID)
단일 책임 원칙(single responsibility principle - SRP)
중요한 기준으로는 변경을 했을 경우 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것이라고 볼 수 있다.
- 한 클래스는 하나의 책임만 가져야 한다.
실무에서는 하나의 책임이라는 것은 모호하다.(이 부분에서 경험이 필요한 것)- 클 수도 있고, 작을 수도 있다.
- 문맥과 상황에 따라 다르다.
개방-폐쇄 원칙(open/closed principle - OCP)
소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
- 코드에 변경 없이 기능을 확장 할 수 있다는 의미, 즉다형성을 활용하는 것.
인터페이스를 구현하는 새로운 클래스(abstract class)를 만들어서 새로운 기능을 구현하는 것.- 인터페이스(구현 클래스)를 만드는 것은 기존 코드를 변경하지 않는다.
다형성을 사용해도 OCP 원칙을 지킬 수 없는 경우 예시 : MemberService
MemberService 클라이언트가 구현 클래스를 직접 선택
![Untitled](https://github.com/Jedo0224/Jedo0224.github.io/assets/90050514/f422aadd-ccb0-4cd5-b095-7f426c3221b9)
- 구현 객체를 변경하려면 클라이언트 코드를 변경해야한다.
- 문제 해결 방법
- 객체를 생성하고, 연관 관계를 맺어주는 별도의 조립, 설정자가 필요하다. → IOC컨테이너의 역할.
리스코프 치환 원칙(Liskov Subsitiution Principle - LSP)
프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야한다.
자동차 인터페이스에 대한 구현체가 있다고 가정한다.
- 엑셀은 밟으면 앞으로 간다는 규약을 무조건 지켜야한다. (기능적 보장이 필요하다.)
- 단순히 컴파일이 성공하는 것은 의미없다.
인터페이스 분리 원칙(Interface segregation principle - ISP)
특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
- 자동차 인터페이스 → 운전 인터페이스, 정비 인터페이스로 분리
- 사용자 클라이언트 → 운전자 클라이언트 , 정비사 클라이언트로 분리
분리 시 정비 인터페이스가 변해도 운전자 인터페이스는 영향을 받지않는다.
- 기능에 맞게 적당한 크기로 잘 쪼개서 관리 할 수 있게 설계하면 인터페이스가 명확해지고 , 대체 가능성이 높아진다.
의존 관계 역전 원칙(Dependancy inversion principle - DIP)
프로그래머는 “추상화에 의존해야지, 구체화에 의존하면 안된다”
- 의존성 주입은 이 원칙을 따르는 방법 중 하나이다.
- 클라이언트 코드가 구현 클래스를 바라보지 말고 인터페이스만 바라보라는 의미
- 멤버 서비스가 멤버 리파지토리 인터페이스만 바라보고 메모리 멤버 리포지토리, jdbc 리파지토리 인터페이스는 몰라야한다.
- 역할과 구현을 철저하기 분리해서 언제든지 대체할 수 있게 설계한다.
- “추상화에 의존해야지, 구체화에 의존하면 안된다” → 역할(Role)에 의존하게 해야한다는 것과 같다.
멤버 서비스는 멤버리파지토리 인터페이스만 아는게 아니라 메모리 멤버 리파지토리까지 알고 있는 것이다.
- 그래서 메모리 멤버 리파지토리를 다른 것으로 바꾸려고 할 때 코드를 변경해야한다. → DIP 위반
정리
객체 지향의 핵심은 다형성
하지만 다형성 만으로는 쉽게 부품을 갈아 끼우듯이 개발 할 수 없다.
다형성 만으로는 구현 객체를 변경할 때 클라이언트 코드도 함께 변경된다.
다형성 만으로는 DIP, OCP를 지킬 수 없다.
무언가 더 필요하다. → DI 의존성 주입.