728x90
1. 등장 배경
EJB(Enterprise Java Bean)
- 엔터프라이즈급 어플리케이션 개발을 단순화하기 위해 발표한 스펙
- 비즈니스 객체들을 관리하는 컨테이너를 만들어서 필요할 때마다 컨테이너로부터 객체를 받는 식으로 관리하면 효율적이겠다 라는 것에서 탄생
- 기능은 좋지만 복잡한 스펙으로 개발의 효율성이 떨어지고 EJB를 돌릴 서버가 따로 필요한 단점이 있음
- 즉 현실에서의 반영이 어려움
POJO(Plain Old Java Object)
- 특정 프레임워크나 기술에 의존적이지 않은 자바 객체
- 종속적이지 않기 떄문에 생산성, 이식성 향상
EJB가 제공하는 서비스를 지원해 줄 수 있는 프레임워크가 등장하며 EJB 없이 만들어졌다.
2. Spring Framework
스프링 프레임워크란?
스프링 프레임워크는 자바 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크이다.
스프링 프레임워크 구조
위의 그림은 Spring 삼각형이라고 부르며 Spring의 핵심이다.
그림처럼 POJO를 기반으로 IoC/DI, PSA, AOP 개념들이 삼각형을 이루고 있어서 스프링 삼각형이라고 부른다.
POJO는 위에서 말했으니 생략
IoC/DI
IoC(Inversion of Control -> 제어의 역행)
- 메소드나 객체의 호출작업을 개발자가 결정하는 것이 아니라 외부에서 결정되는 것을 의미
- 객체의 의존성을 역전시켜 객체 간의 결합도를 줄이고 유연한 코드를 작성할 수 있게 하여 가독성 향상, 코드 중복 방지, 유지 보수를 편하게 할 수 있음
- 객체의 생성을 Container에 위임하여 처리하는 것
- 스프링이 실행될 때 모든 의존성 객체를 다 만들어주고 필요한 곳에 주입시켜 줌으로써 Bean들은 Singleton 패턴의 특징을 가지며 이런 제어의 흐름을 개발자가 조작하는 것이 아니라 스프링에게 맡겨 작업을 처리함
- 이런 IoC의 구현 방법 중 하나가 DI임
Container
- 객체의 생성, 사용, 소멸에 해당하는 라이프사이클 담당
- 라이프사이클 관리, Dependency 객체 제공, Thread 관리, 기타 애플리케이션 실행에 필요한 환경 제공 등의 기능
- 비즈니스 로직 외에 부가적인 기능들에 대해서는 독립적으로 관리되도록 하기 위해 필요함
- 서비스 객체를 사용하기 위해 각각 Factory, Singleton 패턴을 직접 구현하지 않아도 됨
IoC Container
- 객체의 생성, 관계설정, 사용, 제거 등의 작업을 코드 대신 독립된 컨테이너가 담당
- 모든 객체가 아니라 Bean으로 등록된 객체만 담당(어노테이션이나 xml 파일에 설정된 것들)
- Bean으로 등록하기 위해 @Bean, @Controller, @Service 등의 여러 어노테이션들이 있고 해당 어노테이션이 달린 클래스들은 Bean으로 등록됨
- Bean으로 등록되고 IoC Container로부터 인스턴스들을 받아온다면 그 인스턴스들은 항상 같은 객체일 것이기 때문에 메모리 효율성이 좋고 이미 컨테이너 안에 미리 만들어놓은 하나의 객체를 사용하기 때문에 런타임 시에 성능 최적화에도 유리함 → 싱글톤 패턴이 적용되는 것임
- 컨트롤러나 서비스가 매 번 새로 생길 필요는 없으니 위의 어노테이션을 붙여주거나 xml파일에 을 이용해서 빈으로 등록해 주어 한 번 만들어놓고 요청이 들어올 때마다 등록한 것을 사용하는 것임
- 특히 내가 느끼기엔 JSP에서 DB 연결, 관리를 항상 내가 코드로 해줬지만 정해진 틀에 따라 작성만 한다면 내가 연결을 시작하고 끊는 작업이 없고 어떤 데이터를 뽑아올지 작성만 하는 부분에서 bean의 생성, 관계설정, 사용 및 제거의 IoC 개념이 와닿았음 → 결국 이런 작업들이 컨테이너에 위임되며 핵심 비즈니스 로직에만 더 집중할 수 있음
- 컨테이너가 나 대신(코드 대신) 객체에 대한 제어권을 가지고 있어 IoC라고 부름
- 이런 이유로 스프링 컨테이너를 IoC 컨테이너라고 부르기도 함
- IoC를 담당하는 컨테이너에는 BeanFactory, ApplicationContext가 있음
Spring DI Container
- Spring DI Container가 관리하는 객체를 Bean이라 함
- Bean들의 생명주기(Life-Cycle)를 관리하는 의미로 BeanFactory라고 함 → Bean의 생성,조회,반환 관리기능
- BeanFactory에 여러 컨테이너 기능을 추가한 것을 ApplicationContext라고 함
- ApplicationContext = BeanFactory + Spring의 각종 부가 서비스
DI(Dependency Injection → 의존성 주입)
- 다른 프레임워크와 차별화되어 제공하는 의존 관계 주입 기능으로 객체를 직접 생성하는게 아니라 외부에서 생성한 후 주입 시켜주는 방식
- 각 객체마다 new를 해서 생성해주는 것이 아니라 이미 생성된 것을 setter, constructor를 통해 사용
- 외부에서 생성된 객체들을 조립 시키는 방식으로 생각
- 예시로 자동차를 만들 때 차체에 필요한 바퀴를 차를 만들 때마다 new로 생성하는게 아니라 이미 만들어진 바퀴를 필요에 따라 갖다 껴버리는 방식
- DI를 통해서 모듈 간의 결합도가 낮아지고 유연성이 높아짐
Bean 설정
- XML 파일로 관리했지만 규모가 커지면 번거로워서 Annotation을 활용
- @Component → 태그와 같은 역할
- 더 정확히 구분하기 위해 얘를 상속받아 @Service, @Repository를 사용
- @Autowired → 주입하려고 하는 객체의 타입이 일치하는 객체를 자동으로 주입
- 필드,생성자, setter(여기에 사용하면 기본 생성자 있어야함)주입에 사용
AOP(Aspect Oriented Programming → 관점 지향 프로그래밍)
- 관점지향에서 공통적으로 처리해야 하는 작업을 공통관심사항, 반드시 처리해야 하는 작업을 핵심관심사항 이라고 함
- 이런 관점을 기준으로 각각 모듈화하겠다는 의미
- 중복되는 메소드들이 핵심 관심 사항을 선택해서 각각에 적용시키는 것
- css 선택자 처럼 클래스 이름이나 아이디에 해당하는거 여러개 골라서 너네들은 이 공통 관심사항을 실행해라 이런 의미임
Spring MVC
MVC(Model-View-Controller)
- 어플리케이션의 확장을 위해 Model, View, Controller 세가지 영역으로 분리
- 컴포넌트의 변경이 다른 영역 컴포넌트에 영향을 미치지 않아 유지보수성이 좋다
- 컴포넌트간의 결합성이 낮아 프로그램 수정이 용이하여 확장성이 뛰어나다
- 장점
- 화면과 비즈니스 로직을 분리해서 작업, 영역별로 개발하여 확장성이 뛰어남 → 신기술을 도입할 때 유리하다
- 표준화된 코드를 사용하므로 공동작업이 용이하고 유지보수성이 좋음
- 단점
- 초보자가 이해하기 어렵고 개발과정이 복잡해 초기 개발속도가 늦음
Spring MVC 요청 흐름
Dispatcher Servlet (Front Controller)
- 모든 클라이언트의 요청을 전달받음 → Front Controller
- 컨트롤러는 사용자와 직접 통신하는 유일한 컴포넌트라서 이렇게 세분화 한 것
- Controller에게 클라이언트의 요청을 전달 및 리턴 한 결과를 View에 전달하여 알맞은 응답 생성
- web.xml 파일에 Dispatcher Servlet 객체가 선언되어 있고 톰캣이 이걸 보고 읽어서 알게 됨
- 특정 경로에 대한 모든 요청을 내가 정의한 Dispatcher Servlet이 받도록 하는 설정이 여기에 정의되어 있음
- servlet-context.xml에 어떤일을 해야하는지 정의되어 있고 여기서 특정 패키지를 스캔하고 있기 때문에 이를 바탕으로 추가된 컨트롤러가 Handler Mapping이 읽는 것
HandlerMapping
- 클라이언트의 요청 URL을 어떤 Controller가 처리할지를 결정
- URL과 요청 정보를 기준으로 어떤 핸들러 객체(컨트롤러)를 사용할지 결정하는 객체
Controller
- 클라이언트의 요청을 처리한 뒤 Model을 호출하고 결과를 DispatcherServlet에게 알려줌
- 처리한 데이터 및 화면에 대한 정보를 보유한 객체인 ModelAndView를 리턴함 → ModelAndView는 어떤 데이터를 어디로 보내줄지 알려주는 객체임
ViewResolver
- Controller가 리턴 한 뷰 이름을 기반으로 Controller의 처리 결과를 보여줄 View를 결정
- 파일 경로나 확장자가 중복되니 여기서 결정함 → jsp파일, html파일이 어디 있는지 알려주는 것임
View
- Controller의 처리결과를 보여줄 응답화면을 생성
JSP와의 비교?
- 기존의 servlet 상속, doGet, doPost 메소드나 request, response 객체가 모두 사라짐 → POJO → 종속적이지 않음
Spring 전체 흐름 정리
- Server를 실행하면 톰캣에서 xml, cnofig 파일 드응ㄹ 찾아서 읽고 context 설정이 되어 있는 것을 읽어서 메모리에 올림
- pom.xml이 읽히고(여러 사용할 라이브러리들) 다음으로 web.xml 파일이 읽히며 여기서 context loader listener가 root-context.xml 파일을 첫 번째로 읽음
- root-context.xml 파일은 웹이 아닌 녀석들을 읽음 → DB 정보를 읽음
- 동시에 Dispatcher Servlet이 읽음
- Dispatcher Servlet은 뭘 하는지 모르기 때문에 servlet-context.xml 이라는 웹에 관련된 설정 파일을 읽혀주게 함.
- 1,2 과정이 끝나면 톰캣이 실행되며 하는 일이 끝나고 이후 클라이언트로부터 오는 요청을 처리함
- 클라이언트가 URL로 요청을 보내면 Dispatcher Servlet이 해당 요청을 받고 이 요청을 받을 수 있는지 Handler Mapping에 있는지 물어봄
- 요청 처리가 가능하다면 Controller의 어떤 메소드를 찾아가야하는지 알게되며 Dispatcher Servlet은 해당 Controller에게 일을 시킴
- Controller는 해당 메소드에서 Service를 호출하고 DAO에게 일을 시켜 필요한 데이터를 리턴받음(Model)
- Controller는 Dispatcher Servlet에게 Model과 View를 리턴함 → ModelAndView 리턴
- Dispatcher Servlet은 ModelAndView를 가지고 ViewResolver에게 어디로 가야하는지 물어봄
- ViewResolver는 경로와 확장자를 붙이는 설정이 있기 때문에 어느 View page로 가야하는지 알 수 있고 이를 반환함
- Dispatcher Servlet은 해당 페이지를 클라이언트에게 응답함
Spring Boot는 여기서 화면부분이 사라진 것이므로 View와 관련된 작업들이 없어지고 바로 데이터를 응답하는 방식이다.
즉 전체적인 흐름은 똑같이 흘러간다.
728x90
'Java > Spring(Boot)' 카테고리의 다른 글
Transactional 몰랐던 부분(신기해서 적어봄) + Transaction과 아닌 부분 나누기 (0) | 2023.03.21 |
---|---|
JPA와 ORM (0) | 2023.02.18 |
이해 안돼서 다시 정리하는 IoC/DI (0) | 2023.02.07 |
Spring Annotation 정리 (0) | 2023.02.03 |