
🙆♀️ 알아두기
파란색 : spring framewor가 관장하는 방식
보라색 : 개발자가 관장하는 부분(MVC 패턴)
초록색 : view = html or jsp 순수 html 사용 비중 증가
① 클라이언트가 request -> 프론트 컨트롤러 역할의 dispatcher servlet은 그 요청을 처리하기 위한 컨트롤러 객체를 검색
② dispatcher servlet이 직접 컨트롤러를 검색하지 않고 HandlerMapping이라는 빈 객체에게 컨트롤러 검색을 요청
HandlerMapping은 클라이언트의 요청 경로를 이요해서이를 처리할 컨트롤러 빈 객체를 dispatcherservlet에 전달
ex. 웹 요청 경로가 /hello -> 컨트롤러 빈 중 /hello요청 경로를 처리할 controller 리턴
③ dispatcher servlet은 handler mapping이 찾아준 컨트롤러 객체를 처리할 수 있도록 handlerAdapter 빈에게 요청 처리를 위임
④ handlerAdapter는 controller의 알맞은 메서드를 호출해서 요청을 처리
⑤ 컨트롤러 처리 결과를 리턴
⑥ HandlerAdapter로 부터 컨트롤러의 요청 처리 결과를 받으면 dispatcher Adapter는 결과를 보여줄 뷰를 찾기 위해 view resolver 빈 객체 사용 -> view resolver는 이 뷰 이름에 해당하는 view 객체를 찾거나 생성해서 리턴
⑦ dispatcherservlet은 view resolver가 리턴한 view 객체에게 응답 결과 생성을 요청
⑧ view 객체는 웹 브라워에 응답결과를 생성

🙆♀️ 알아두기
Model : 사용자가 원하는 데이터나 정보를 제공(db)
View : 보여지는 화면
Controller : 사용자의 요청을 처리하고, 그 요청에 따른 전체적은 흐름을 제어

컨트롤러는 서비스의 기능을 사용하며, 서비스에 의존
서비스는 리포지토리의 기능을 사용하며, 리포지토리에 의존
IoC, Inversion of Control
제어의 흐름이 기존에는 개발자가 작성한 코드에서 객체를 생성하고 관리하는 방식에서 프레임워크나 컨테이너로 넘어가게 되는 것
개발자가 프레임워크 기능을 호출하던 것에서 -> 프레임워크가 개발자 코드를 호출
- 제어의 흐름 : 개발자가 작성한 코드 -> 프레임워크
- 개발자 -> 전체를 직접 구현 x, 자신의 코드를 부분적으로 "끼워넣기" 하는 형태로 구현
- 개발자는 비즈니스 로직에 집중 가능
프레임워크 기능
- 객체의 생성, 소멸과 같은 라이프 사이클을 관리
- 링으로부터 필요한 객체를 얻어올 수도 있음
- 프레임워크가 개발자가 작성한 코드를 호출하면서, 필요한 객체를 생성하고, 관리하고, 필요한 때에 호출
💡 예시
서비스 객체가 리포지토리 객체를 사용
: 서비스 객체가 직접 리포지토리 객체를 생성하고 사용
역전 후 :
- 지토리 객체의 생성과 관리를 프레임워크에 맡김
- 스 객체는 직접 리포지토리 객체를 생성하거나 호출하지 않고, 프레임워크에서 제공하는 기능을 이용하여 사용
결론 : 객체의 의존성을 역전 함으로서 객체간의 결합도를 줄이고 유연한 코드를 작성할 수 있게 하여 가독성 강화 및 코드 중복 최소화, 편리한 유지보수 할 수 있게 함
📌 스프링 프레임워크에서 객체를 생성하고 관리하는 곳 : 컨테이너

스프링은 실행 시 객체들을 담고 있는 Container가 존재

📌 @Autowired
- 필요한 의존 객체의 "타입"에 해당하는 빈을 찾아 주입
- 기본값이 true이기 때문에 의존성 주입을 할 대상을 찾지 못한다면 애플리케이션 구동에 실패
📌 POJO
- Plain Old Java Object, 단순한 자바 오브젝트
- 객체 지향적인 원리에 충실하면서 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트
Component Scan
컴포넌트 스캔의 대상
① Field Injection (필드 주입)
@Autowired
private MemberRepository memberRepository;
② Setter Injection (수정자 주입)
private MemberRepository memberRepository;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
③ Constructor Injection (생성자 주입)
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
// 현재 클래스에서만 접근 가능하도록 막아두기
// 의존 관계가 한번 만들어지면 아예 수정이 불가능한 상태로 만들어주기
- SRP : 단일 책임 원칙 (Single responsibility principle)
- OCP : 개방-폐쇄 원칙 (Open-closed principle)
- LSP : 리스코프 치환 원칙 (Liskov substitution principle)
- ISP : 인터페이스 분리 원칙 (Interface segregation principle)
- DIP : 의존관계 역전 원칙 (Dependenct inversion principle)
기존 코드 변경 없이 코드 확장하는 법
1. 다형성 활용
인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현 -> 기존 코드 변경 x
2. 스프링 활용
객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자 = 스프링
EX. 악셀 구현 -> 악셀은 앞으로 가야함 BUT, 뒤로 가게 구현 한다면?
컴파일 오류는 없음 -> BUT, 인터페이스 규약이 깨짐 -> 인터페이스 규약을 지켜줘야됨
EX. 자동차 인터페이스 -> 운전 인터페이스, 정비 인터페이스로 분리
인터페이스를 분리하면 정비 인터페이스 자체가 변해도 운전 인터페이스는 영향을 주지 않는다.
EX. 운전자가 자동차역할에 대해 잘 알아야지 k3, 테슬라 각각에 집중하면 운전이 힘들어 짐