질문 출처 : https://github.com/jjuyeon/Tech-Interview-Study/blob/main/spring/README.md
Spring
프레임워크
Spring Triangle
Enterprise Application 개발 시 복잡함을 해결하는 Spring의 3대 핵심 요소. 각각 IoC(DI), AOP, PSA 이다.
IoC (Inversion of Control, 제어의 역행)
객체지향 언어에서 프로그래머가 작성한 프로그램이 재사용 라이브러리의 흐름 제어를 받게되는 소프트웨어 디자인을 말한다. 전통적인 프로그래밍에서 흐름은 프로그래머가 작성한 프로그램이 외부 라이브러리의 코드를 호출해 이용하지만, 제어가 반대로 적용된 구조에서는 외부 라이브러리의 코드가 프로그래머가 작성한 코드를 호출하여 컨트롤 제어권과 Object간의 연결 관계를 결정한다. 설계 목적상 제어 반전의 목적은 다음과 같다.
- 작업을 구현하는 방식과 작업 수행 자체를 분리하여 모듈을 제작할 때 모듈과 외부 프로그램의 결합에 대해 고민할 필요 없이 모듈의 목적에 집중한다. 모듈을 바꾸어도 다른 시스템에 부작용을 일으키지 않는다.
- 객체 간의 관계가 느슨하게 연결된다. 원래는 런타임 후 실행하면서 필요한 객체를 만들어 사용하는데 제어 역행이 되면 사용될 객체들을 미리 만들어 둔 다음에 원할 때 사용한다.
IoC의 구현 방법에는 DL와 DI가 있다.
- DL (Dependency Lookup)
미리 만들어 둔 리소스나 객체를 컨테이너가 lookup context를 통해서 필요한 것을 얻는다. 찾은 객체를 필요한 타입으로 캐스팅해줘야하 한다.
- DI (Dependency Injection)
객체에 lookup 코드를 사용하지 않고 컨테이너가 직접 의존 구조를 객체에 설정할 수 있도록 지정해준다. 객체는 컨테이너의 존재 여부를 알 필요가 없으며 인터페이스에 의한 의존 관계만을 알고 있다. 관련글
세터 함수로 주입하는 Setter Injection과 생성자를 통해 주입되는 Constructor Injection로 나뉜다.
AOP (Aspect Oriented Programming, 관점 지향 프로그래밍)
문제를 해결하기 위한 핵심관심 사항과 전체에 적용되는 공통관심의 분리를 통해서 소프트웨어의 모듈성을 향상. 공통 모듈을 여러 코드에 쉽게 적용할 수 있다. 스프링은 자체적으로 프록시 기반의 AOP를 지원하므로 트랜잭션이나 로깅, 보안과 같이 여러 모듈에서 공통으로 필요로 하지만 실제 모듈의 핵심이 아닌 기능들을 분리하여 각 모듈에 적용이 가능하다.
PSA (Portable Service Abstraction, 서비스 추상화)
환경과 세부기술의 변경과 관계 없이 일관된 방식으로 기술에 접근할 수 있게 해주는 설계 원칙. 트랜잭션 추상화, OXM 추상화, 데이터 액세스의 Exception 변환 기능 등 기술적인 복잡함은 추상화를 통해 Low Level의 기술 구현 부분과 기술을 사용하는 인터페이스로 분리. 예를 들자면 데이터베이스에 관계없이 동일하게 적용할 수 있는 트랜잭션 처리방식을 설계하는 것이다.
POJO (Plain Old Java Object)
- Plain : component interface 또는 class를 상속받지 않는 특징(특정 framework에 종속되지 않는)
- Old : EJB(Enterprise JavaBeans) 이전의 java class를 의미
특정 프레임워크나 기술에 의존적이지 않는 자바 객체를 사용하는 방식이다. 특정 기술에 종속적이지 않기 때문에 생산성, 이식성이 향상된다. 테스트하기 용이하며 객체지향 설계를 자유롭게 적용할 수 있다.
스프링 컨테이너에 저장되는 자바 객체는 특정한 인터페이스를 구현 하거나, 클래스의 상속 없이도 사용이 가능하다. 일반적인 자바 객체를 칭하기 위한 별칭 개념이다.
그 외 특징
- MVC 웹 프레임워크 제공
- JDBC, JPA 연동, 선언적 트랜잭션 처리 등 DB 연동 지원
이 외에 자주 사용되는 프로젝트
- 스프링 데이터: JPA, 몽고DB, 레디스 등 다양한 저장소 기술을 지원
- 스프링 시큐리티: 인증/인가와 관련된 프레임워크, 웹/객체 접근 제어, DB/오픈 ID/LDAP 등 다양한 인증 방식, 암호화 기능을 제공
- 스프링 배치: 로깅/추적, 작업 통계, 실패 처리 등 배치 처리에 필요한 기본 기능을 제공
Spring MVC 구조 흐름
Spring MVC 구조의 핵심은 DispatcherServlet에 있다. 하지만 이 친구는 혼자서는 아무것도 하지 못해서 여러 친구들의 도움이 필요하다..
먼저 DispatcherServlet이 사용자의 요청을 수신한다. 그럼 이 요청을 처리할 수 있는 컨트롤러를 찾아야 하는데 얘는 누가 어떤 담당인지를 모른다! 그러면 HandlerMapping에게 문의하여 해당 요청의 담당자 컨트롤러 정보를 받고, 그 컨트롤러에게 찾아가 요청의 처리를 요구한다.
이때 (그림에는 누락됐지만) HandlerAdapter라는 빈이 또 필요한데, 이는 DispatcherServlet은 @Controller 어노테이션으로 구현한 컨트롤러뿐만 아니라 Controller, HttpRequestHandler 인터페이스를 구현한 컨트롤러/클래스를 동일한 방식으로 실행할 수 있게 만들어졌고, 그를 실제로 처리하는 것이 HandlerAdapter 빈이기 때문이다.
컨트롤러에서 Business Logic, DB Logic 등 모든 데이터 연산을 끝내고 ModelAndView 객체를 DispatcherServlet에게 넘겨준다. DispatcherServlet은 이 객체 안에 담긴 데이터(Model)를 전달해줘야 하는 뷰(View) 페이지를 찾아야 한다. 근데 문제는 컨트롤러가 뷰 페이지의 이름을 너무 축약해서(논리적 이름) 알려주기 때문에 DispatcherServlet는 또 혼란에 빠진다. 그러면 또 ViewResolver에게 찾아가서 이런 이름의 뷰를 아느냐 묻고, ViewResolver는 정확한 뷰의 위치를 가르쳐 준다. 그제서야 DispatcherServlet는 그 뷰 페이지로 찾아가서 자신이 받은 데이터(Model)를 전해준다. 그럼 View는 결과 정보를 사용하여 사용자에게 화면에 표시해준다.