Spring이란?
- 자바 오픈소스 프레임워크 중 하나이다.
- 스프링 컨테이너로 자바 객체를 관리하며 DI와 IoC를 통해 결합도를 낮출수 있다.
- AOP를 통해 공통 기능을 분리하여 관리할 수 있다.
Spring DI/IoC 동작방식
스프링 프레임워크는 느슨한 결합을 기반으로 동작한다. ioC 컨테이너를 통해 객체 간의 의존성을 주입하면서 느슨한 결합을 유지할 수 있다.
- 의존성 주입(Dependency Inject)
- 객체가 필요로 하는 의존성을 직접 생성하거나 참조하지 않고, 빈 설정 정보를 바탕으로 컨테이너가 자동으로 연결해주는 것
- 제어의 역전(Inversion Of Control)
- 개발자가 객체 간의 의존성을 관리하는 코드를 작성하는 것이 아닌, 프레임워크가 의존성 관리를 대신 수행하는 것
- 스프링 DI 과정
1) 스프링 컨테이너가 객체 생성을 위해 빈을 생성
2) 빈이 생성된 후, 스프링은 빈이 의존하는 다른 빈들을 찾아 의존성 주입 수행
3) 의존성 주입이 완료된 빈은 초기화됨
4) 빈이 더이상 필요하지 않으면 destory 메서드를 호출하여 빈을 종료한다.
AOP란
- 특정 로직을 기준으로 핵심적인 관점, 부가적인 관적으로 나누고 그 관점을 기준으로 각각 모듈화하는것
- 모듈화란 어떤 공통된 로직이나 기능을 하나의 단위로 묶는것을 의미
- 실행시간 측정, 트랜잭션, 로깅등이 AOP의 대표적인 예이다.
AOP 동작원리
- 스프링은 런타임 시점에 프록시를 생성해 준다.
JDK Dynamic Proxy 또는 CGLIB를 이용하여 프록시를 생성한다.
- JDK Dynamic Proxy
- 리플렉션을 통해 프록시 객체를 생성해주는 기능이다.
- 반드시 인터페이스의 구현체이어야 동작한다.
- CGLIB(Code Generator Libray)
- 클래스의 바이트 코드를 조작하여 프록시를 생성해준다.
- target class에 포함된 모든 메서드를 재정의하고 바이트 코드를 조작하여 프록시를 생성한다.
- 리플렉션이 아닌 바이트코드를 조작하기때문에 성능이 좋다.
의존성 주입 방법
- 생성자 주입:
- 생성자 호출시점에 딱 1번만 호출되는 것을 보장하며 불변, 필수 의존관계에 사용
- Setter 주입:
- 선택, 변경 가능성이 있는 의존관계에 사용되며 스프링빈을 선택적으로 등록 가능
- 필드 주입:
- @Autowired를 사용하는데 외부에서 변경이 불가능하여 테스트하기가 힘듦
- 주로 테스트코드에서 사용된다.
Bean이란?
- 스프링 컨테이너 안에 들어있는 객체로 필요할때 스프링 컨테이너에서 가져와 사용한다.
@Bean 어노테이션을 사용하거나 xml설정을 통해 일반 객체를 Bean으로 등록할 수 있다.
- Bean 생성 과정
1) 스프링 컨테이너 생성
2) 스프링 빈 생성
3) 의존 관계 주입
4) 초기화 콜백(@PostConstruct)
5) 사용
6) 소멸 전 콜백(@PreDestroy)
7) 종료
Bean의 Scope 설명
- 빈 스코프는 빈이 존재할 수 있는 범위를 뜻하며 싱글톤, 프로토타입, request, session, application 등이 있다.
- 싱글톤은 기본 스코프로 스크링 컨테이너 시작과 종료까지 유지되는 가장 넓은 범위의 스코프이다.
- 프로트타입은 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프이다.
@Bean과 @Component 차이
- @Bean:
- 외부 라이브러리를 Bean으로 등록하고 싶은 경우 사용
- 메서드 레벨에만 적용 가능
- @Component:
- 클래스 레벨에만 적용 가능
JPA N+1 문제 원인과 해결 방법
- N+1 이란 1번의 쿼리를 날렸을때 의도하지 않은 N번의 쿼리가 추가적으로 실행되는 것을 의미한다.
- 발생 원인은 연관관계를 가진 엔티티를 조회할 때 한 쪽 테이블만 조회하고 연결된 다른 테이블은 따로 조회하기 때문이다.
- Fetch Join이나 @EntityGraph사용시 예방할 수 있다.
JPA 영속성 컨텍스트란?
- 영속성 컨텍스트는 entity를 영구 저장하는 환경을 의미한다.
- 1차캐시, 동일성 보장, 쓰기지연, 변경감지(Dirty checking), 지연로딩 등의 이점이 있다.
- 쓰기지연: 실제 insert되야 할 쿼리를 모아뒀다가 flush 될때 쿼리가 나가는 기능
- 지연로딩: 연관 관계 매핑되어 있는 엔티티를 조회 시 우선 프록시 객체를 반환하고, 실제로 필요할 때 쿼리를 날려 가저오는 기능
Servlet이란?
- 서블릿은 클라이언트 요청을 처리하고, 그 결과를 다시 클라이언트에게 전송하는 Servlet 클래스의 구현 규칙을 지킨 자바프로그램이다.
- 서블릿을 사용하게 되면 웹 페이지를 동적으로 생성하여 클라이언트에게 반환해 줄 수 있다.
Servlet 동작방식
- 사용자가 URL을 입력하면 요청이 서블릿 컨테이너로 전송된다.
- 요청을 전송 받은 서블릿 컨테이너는 Http Request, HttpResponse 객체를 생성한다.
- 사용자가 요청한 URL이 어느 서블릿에 대한 요청인지 찾는다. 위 예제에서는 helloServlet을 찾게 된다.
- 서블릿의 service() 메소드를 호출한 후 클라이언트의 GET, POST 여부에 따라 doGet(), doPost() 메소드를 호출한다.
- 동적 페이지를 생성한 후 HttpServletResponse 객체에 응답을 보낸다.
- 클라이언트에 최종 결과를 응답한 후 HttpServletRequest, HttpServletResponse 객체를 소멸한다.
Servlet 생명주기
- 클라이언트 요청이 들어오면 서블릿 컨테이너는 서블릿이 메모리에 있는지 확인한다. 메모리에 없다면 init() 메소드를 호출하여 적재한다.
- 클라이언트 요청에 따라서 service() 메소드를 통해 요청에 대한 응답이 doGet(), doPost()로 분기한다.
- 서블릿 컨테이너가 서블릿에 종료 요청을 하면 destory() 메소드가 호출된다. 종료 시 처리해야 하는 작업은 destory() 메소드를 오버라이딩하여 구현하면된다.
- destory() 메소드가 끝난 서블릿 인스턴스는 GC에 의해 제거된다.
Servlet과 일반 자바 객체의 차이
- JVM에서 호출 방식은 서블릿과 일반 클래스 모두 같으나, 서블릿은 main() 메소드로 직접 호출되지 않고, 웹 컨테이너(Servlet Container)에 의해 실행된다
Servlet Container란?
- 서블릿 컨테이너는 구현되어 있는 Servlet 클래스의 규칙에 맞게 서블릿 객체를 생성, 초기화, 호출, 종료하는 생명 주기를 관리한다.
Servlet Container의 특징
- 개발자가 비즈니스 로직에 집중할 수 있도록 HTTP 요청 메시지 파싱, Content-Type 확인, HTTP 응답 메시지 생성 등 작업을 대신 처리 해준다.
- 서블릿의 생명 주기를 관리한다.
- 요청이 올 때마다 자바 스레드 하나를 생성하여 멀티 스레딩 처리를 한다.
Servlet Container의 동작 과정
- 웹 브라우저에서 웹 서버에 HTTP 요청을 보내면, 웹 서버는 받은 HTTP 요청을 WAS의 Web Server로 전달한다.
- WAS의 웹 서버는 HTTP 요청을 서블릿 컨테이너에 전달한다.
- 서블릿 컨테이너는 HTTP 요청 처리에 필요한 서블릿 인스턴스가 힙 메모리 영역에 있는지 확인한다. 존재하지 않는다면, 서블릿 인스턴스를 생성하고 해당 서블릿 인스턴스의 init() 메소드를 호출하여 서블릿 인스턴스를 초기화한다.
- 서블릿 컨테이너는 서블릿 인스턴스의 service() 메소드를 호출하여 HTTP 요청을 처리하고, WAS의 웹 서버에게 처리 결과를 전달한다.
- WAS의 웹 서버는 HTTP 응답을 앞 단에 위치한 웹 서버에게 전달하고, 앞 단의 웹 서버는 받은 HTTP 응답을 웹 브라우저에게 전달한다.
DispatcherServlet이란?
- DispatcherServlet은 표현 계층 전면에서 HTTP 프로토콜을 통해 들어오는 모든 요청을 중앙 집중식으로 처리하는 프론트 컨트롤러이다.
- DispatcherServlet은 Spring MVC의 핵심 요소 중 하나로, 클라이언트로부터 어떤 요청이 들어오면 서블릿 컨테이너가 요청을 받는다.
- 이후 공통 작업을 DipatcherServlet에 처리하고, 이외 작업은 적절한 세부 컨트롤러로 위임한다.
DispatcherServlet 동작과정 설명
- DispatcherServlet으로 클라이언트의 웹 요청이 들어온다.
- 웹 요청을 Handler Mapping에 위임하여 해당 요청을 처리할 Handler(Controller)를 탐색한다.
- 찾은 Handler를 실행할 수 있는 HandlerAdapter를 탐색한다.
- 찾은 Handler Adapter를 사용해서 Handler의 메소드를 실행한다.
- Handler의 반환 값은 Model과 View이다.
- View 이름을 ViewResolver에게 전달하고, ViewResolver는 해당하는 View 객체를 전달한다.
- DispatcherServlet은 View에게 Model을 전달하고 화면 표시를 요청한다. 이때, Model이 null이면 View를 그대로 사용하고, 그렇지 않으면 View에 Model 데이터를 렌더링한다.
- 최종적으로 DispatcherServlet은 View 결과(HttpServletResponse)를 클라이언트에게 반환한다.
Controller 1개는 어떻게 수십 만 개의 요청을 처리하는가?
- 톰캣은 하나의 프로세스에서 동작하고, 내부적으로 스레드 풀을 만들어서 HTTP 요청이 오면 스레드 풀에서 스레드 하나를 가져온다.
- 따라서 여러 요청이 오면, 각각 스레드를 생성하여 하나의 컨트롤러에 요청을 한다. 그러면, 컨트롤러는 요청에 맞게 로직을 수행하여 적절한 데이터를 반환한다.
- 이때 컨트롤러가 Thread-Safe하게 설계되었고, 싱글톤 빈으로 생성되었다면 안전하게 1개의 Controller 객체만으로 다중 요청을 처리할 수 있다.
MVC 패턴이란
- model, view, controller의 약자로 하나의 프로젝트를 구성할때 세가지의 역할로 구분한 패턴
- view 사용자가 보여주는 화면단을 의미
- model 애플리케이션쪽의 비즈니스 로직을 의미
- controller view와 model의 통신창구
Annotaion이란
- 코드사이에 주석처럼 쓰이며 특별한 의미, 기능을 수행하도록 하는 기술
Filter & Interceptor 차이
대상 | 필터 | 인터셉터 |
---|---|---|
관리 | 서블릿 컨테이너 | 스프링 컨테이너 |
스프링 예외처리 | X | O |
Request/Response 조작 여부 | O | X |
용도 | 공통된 보안 및 인증/인가 관련 작업<div> </div><div>모든 요청에 대한 로깅 또는 감사</div><div> </div><div>이미지/데이터 압축 및 문자열 인코딩</div><div> </div><div>Spring과 분리되어야 하는 기능</div> | 세부적인 보안 및 인증/인가 공통 작업<div> </div><div>API 호출에 대한 로깅 또는 감사</div><div> </div><div>Controller로 넘겨주는 정보의 가공</div> |
JPA란?
- 자바 ORM 기술에 대한 API 표준 명세로, 자바 개발자들이 객체와 관계형 데이터베이스를 매핑하는데 사용하는 프레임워크이다.
- JPA는 ORM을 사용하기 위한 인터페이스를 모아둔 것으로, 이를 구현한 구현체로는 Hibernate, EclipseLink, DataNucleus 등이 있다.
엔티티 매니저란?
- 엔티티 매니저는 영속성 컨텍스트를 생성하고, 관리한다.
- 엔티티 매니저는 데이터베이스와의 트랜잭션을 처리하며, 데이터베이스와의 연결을 담당한다.
영속성 컨텍스트란?
- 영속성 컨텍스트는 엔티티 매니저를 통해 접근할 수 있으며, 엔티티 매니저는 영속성 컨텍스트를 관리한다.