개발자가 Multi Thread 관련 코드는 고려하지 않아도 된다
Multi Thread 환경이므로 싱글톤 객체(Servlet, Spring Bean)는 주의해서 사용해야한다
→ ❗공유변수 사용 조심 또 조심❗
Thread는 Thread Pool에 보관 및 관리한다
Thread Pool에 생성 가능한 Thread 최대치를 관리한다. Tomcat은 최대 200개 기본 설정이 되어있다 (변경 가능)
✅ 장점
요청 마다 Thread를 생성하는 단점을 보완하였다
Thread가 미리 생성되어 있어서 Thread를 생성, 종료하는 비용이 절약된다 → 응답이 빠름
생성 가능한 Thread 최대치가 제한되어 있어서 많은 요청이 들어와도 안전하게 처리할 수 있다
❌ 단점
Thread Pool의 최대 Thread 수를 낮게 설정한다면 응답이 지연된다
최대 Thread 수가 너무 높으면 즉, 요청이 많아지면 리소스 부족으로 서버가 다운된다
네트워크 통신은 HTTP로 이루어진다
HTTP는 무상태 프로토콜이며 비연결성 특징을 가지고 있다
HTTP Message 구조
HTTP Method
상태코드
HTTP Header
HTTP API는 Restful 하게 설계해야 한다. 최소 성숙도레벨 2를 지켜야 한다
Servlet은 Java에서 Request, Response를 쉽게 다루게 해주는 객체이다
Servlet Container는 Servlet 객체를 싱글톤으로 관리한다
WAS는 다중 요청 처리를 위해 Multi Thread를 지원한다
SSR 방식은 서버에서 동적인 페이지를 완성하여 응답한것을 브라우저에서 화면을 출력한다
CSR은 HTTP API 통신으로 얻은 결과를 통해 브라우저에서 동적으로 화면을 출력한다
애플리케이션을 개발할 때 전체적인 구조(frame)를 잡기 위해 사용하는 것
기본적으로 프레임워크 내에서 사용하는 라이브러리들이 존재한다
개발을 진행하는 과정에서 필요한 기능을 구현하기 위해 사용하는 것
개발자들이 HTTP 요청을 만들고, 서버로부터의 응답을 확인하며, API의 기능을 테스트하고 디버깅할 수 있게 해준다
코드에 메타데이터를 추가할 수 있는 기능을 제공하며 주로 코드에 특별한 의미를 부여하거나, 컴파일러와 런타임에 특정 동작을 트리거하기 위해 사용된다
❗주석은 사람에게 정보를 제공하는 것이라면, 어노테이션은 특정 코드를 사용하는 프로그램에게 정보를 전달하는 것❗
어노테이션 정의
어노테이션은 @ 기호로 시작하며, 클래스, 메서드, 변수, 매개변수, 패키지 등에 추가할 수 있다
보일러 플레이트 코드를 줄여주는 라이브러리로 자동으로 보일러 플레이트 코드를 생성하여 코드의 가독성과 유지보수성을 높여준다
❗Lombok은 어노테이션 기반으로 동작하며, 주로 컴파일 시점에 소스 코드를 변환하여 필요한 메서드를 자동으로 생성한다❗
보일러 플레이트 코드(Boilerplate code)란?
getter/setter 메서드, 생성자, toString 메서드 등과 같이 반복적으로 작성되는 코드를 의미
Java Application Framework로 엔터프라이즈 애플리케이션 (대규모로 복잡한 비즈니스 프로세스와 데이터를 처리하는 애플리케이션) 개발에 주로 사용
Spring Framework 특징
애플리케이션의 다양한 구성 요소를 유연하게 연결하고 관리할 수 있도록 해준다
Spring Framework는 누구나 사용할 수 있는 오픈소스 이다
모듈화되어 있어 필요에 따라 특정 기능만 선택적으로 사용할 수 있다
❗Java언어의 가장 큰 특징인 객체 지향 언어의 특징을 살려낸 프레임워크❗이다
캡슐화
상속
추상화
다형성
❗Java와 유사한 문법 구조를 가진 Groovy기반의 스크립트 언어를 사용하며 다양한 소프트웨어를 빌드(Build)할 수 있는 유연한 빌드 자동화 도구❗
빌드(Build)
빌드 자동화 도구
Gradle 특징
1️⃣ 유연성
복잡한 빌드 시나리오를 처리할 수 있는 유연한 시스템을 제공한다
빌드 스크립트를 통해 다양한 빌드 작업을 정의하고, 필요한 경우 커스터마이징할 수 있다
2️⃣ 성능
Build Cache
빌드 결과물을 캐싱하여 재사용한다
라이브러리 의존성을 캐싱하여 재사용한다
점진적 빌드
마지막 빌드 호출 이후 변경된 부분만 빌드한다
변경되지 않은 부분은 캐시 결과를 검색해 재사용한다
데몬 프로세스
다음 빌드 작업을 위해 백그라운드에서 대기하는 프로세스
초기 빌드 이후부터는 빌드 실행 시 초기화 작업을 거치지 않는다
3️⃣ 멀티 프로젝트 빌드 지원
4️⃣ 설정 주입 방식
필요한 설정을 직접 프로젝트에 주입하는 방식이다
공통되는 정보는 묶어서 한번에 주입이 가능하다
프로젝트별로 설정을 다르게 주입할 수 있다
Groovy 기반 언어의 빌드 스크립트로 스크립트를 작성하면 소스 코드를 빌드하고, 라이브러리들의 의존성을 관리할 수 있다
1️⃣ 플러그인
2️⃣ 의존성 관리
프로젝트에서 사용하는 라이브러리나 패키지를 관리
의존성 설정 - 라이브러리를 추가하는 시점을 설정할 수 있다
3️⃣ repositories
Java를 사용한 웹 개발의 시초로, 서버에서 동적으로 콘텐츠를 생성하기 위해 사용되었다. 클라이언트의 요청을 받고, 그에 대한 응답을 생성하는 기본적인 구조를 제공했다
❌ 단점
JSP는 HTML 내에 Java 코드를 삽입할 수 있는 기술로, 웹 페이지를 더 쉽게 동적으로 생성할 수 있도록 도와주었다
❌ 단점
MVC 패턴이 도입되면서, UI, 비지니스 로직, 데이터를 분리하여 개발하는 방식이 등장했다
✅ 장점
❌ 단점
Struts, Spring 등의 MVC 프레임워크가 등장하며, 웹 애플리케이션 개발이 더욱 구조화되고 효율적으로 변했다
그중 Spring MVC는 단순하면서도 강력한 기능을 제공하여, Java 웹 개발의 표준으로 자리 잡게 되었다
중복적으로 설정해야 하는 부분들을 프레임워크로 자동화 했다
❌ 단점
Annotation을 통해 애플리케이션 설정의 복잡함을 줄여주었다
✅ 장점
Spring 프레임워크를 보다 쉽게 사용하도록 만든 도구로, 설정과 복잡한 초기 설정 작업을 자동화했다
✅ 장점
동적인 웹 페이지를 생성하기 위해 사용되는 도구이며 템플릿을 기반으로 정적인 부분과 동적인 데이터를 결합하여 HTML, XML 등의 문서를 생성하는 역할을 수행
➡️ 우리가 흔히 말하는 UI(User Interface)를 만들며, SSR(Server Side Rendering)에 사용된다
Servlet이나 JSP만으로 비지니스 로직과 View Rendering 까지 모두 처리하면 너무 많은 역할을 하게 되고 유지보수가 굉장히 어려워져서(책임이 너무 많음) 고안된 패턴
→ ❗백엔드 웹 기술의 역사 첫 번째❗
Web Application은 일반적으로 MVC(Model View Controller) 패턴을 사용
하나의 Servlet이나 JSP로 처리하던 것들을 Model, View, Controller 영역으로 나눈 것
→ ❗백엔드 웹 기술의 역사 두 번째❗
핵심 내용
View가 분리된 이유의 핵심은 변경이다
기획이 변하지 않는 이상 비지니스 로직과 View의 수정 원인은 별개로 발생한다
화면 구성에 수정이 발생하면 View만 변경
요구사항에 수정이 발생하는 경우 비지니스 로직 변경
➡️ 서로 연관이 없는 코드끼리 함께 존재할 필요가 없다. 완전히 분리하자
1️⃣ HTTP Request를 전달받아 파라미터를 검증
2️⃣ 비지니스 로직을 실행
3️⃣ View에 전달할 결과를 조회하여 Model 객체에 임시로 저장
1️⃣ View에 출력할 Data를 저장하는 객체
2️⃣ View는 비지니스 로직이나 Data 접근을 몰라도 되고 View Rendering에만 집중하면 된다 (책임 분리)
Model 객체에 담겨져 있는 Data를 사용하여 화면을 Rendering 한다
MVC 패턴을 적용한 JSP를 사용하게되면 화면을 그려내는 View 부분과 비지니스 로직을 실행하는 부분의 역할이 구분된다
→ ❗백엔드 웹 기술의 역사 세 번째❗
MVC 패턴이 적용되며 Controller와 View가 분리된다.
화면에 수정이 발생하면 화면(View)만 수정하고 로직에 수정이 발생하면 로직만 수정하면 된다
MVC 패턴을 적용 후 View의 역할은 필요한 데이터를 Model 에서 참조하여 화면을 그리는 역할만 수행하면 된다
하지만 Controller에 해당하는 부분은 여전히 문제를 가지고 있다
1️⃣ dispatcher.forward(request, response) View로 이동하는 forward가 항상 중복 호출된다
2️⃣ String path= “/WEB-INF/views/new-form.jsp” View의 path를 입력(중복 작업)한다
jsp 파일의 경로 혹은 이름이 바뀌면 해당 코드가 변경되어야 한다
JSP 이외의 확장자를 사용하려면 전체가 변경되어야 한다
3️⃣ HttpServletResponse 객체를 사용하는 경우가 적다 (JSP에서 모두 해결하기 때문)
4️⃣ 공통 기능이 추가될수록 Controller에서 처리해야 하는 부분들이 많아진다
모든 컨트롤러에서 공통으로 적용되는 기능을 의미
❌ 공통 기능으로 만들어놓은 Method 또한 항상 중복적으로 호출이 필요하다
Servlet(Controller)이 호출되기 전에 공통 기능을 하나의 Servlet에서 처리해주는 패턴
프론트 컨트롤러(Servlet) 하나에 모든 클라이언트측 요청이 들어온다
✅ 프론트 컨트롤러의 역할
1️⃣ 모든 요청을 하나의 프론트 컨트롤러가 받는다
2️⃣ 공통 기능을 처리한다
3️⃣ 요청을 처리할 수 있는 Controller를 찾아서 호출한다 (Controller Mapping)
4️⃣ 프론트 컨트롤러를 제외한 나머지 컨트롤러는 Servlet을 사용하지 않아도 된다
HttpServlet을 상속받거나, @WebServlet을 사용하지 않아도 된다❌ 프론트 컨트롤러 의문점
1️⃣ 공통 처리 로직에 모든 컨트롤러가 연결되기 위해서는 모든 컨트롤러가 return 하는 결과의 형태가 동일해야 한다
2️⃣ 하지만, Controller 마다 로직이나 응답해야하는 결과는 당연히 다르다 → 확장성, 유지보수성을 잃는다
3️⃣ 공통 로직에서 응답별로 퍼즐을 다시 하나하나 처리할 수 있으나 공통 부분의 책임이 너무 커지게된다
4️⃣ 컨트롤러에서 반환되는 결과가 달라지면 공통처리 부분의 변경 또한 불가피
다양한 컨트롤러(Handler)를 유연하게 만들기위해 어댑터 패턴을 도입
컨트롤러들은 동일한 인터페이스를 구현하도록 하고 해당 인터페이스와 공통 로직 사이에 어댑터를 두어 유연하게 만든다
❗서로 다른 인터페이스를 갖는 두 클래스를 연결해주는 패턴❗
어댑터 패턴 구조
1️⃣ 컨트롤러(Handler)는 비지니스 로직을 처리하고 알맞은 결과를 반환
2️⃣ 어댑터는 공통 로직과 컨트롤러(Handler)가 자연스럽게 연결되도록 한다
3️⃣ 프론트 컨트롤러는 공통으로 처리되는 로직을 수행
✅ 어댑터 패턴 장점
프론트 컨트롤러, 어댑터, 핸들러 모두 각자의 역할만 수행한다 (책임 분리)
새로운 컨트롤러(Handler)가 추가되어도 컨트롤러와 어댑터만 추가한다면 공통 로직의 변경이 발생하지 않는다
1️⃣ Servlet 사용
2️⃣ JSP 사용
3️⃣ MVC 패턴 사용
4️⃣ 프론트 컨트롤러 패턴 사용
공통 로직을 하나의 입구에서 처리하기 위해서 프론트 컨트롤러 패턴 적용
각각의 핸들러 호출 후 응답을 프론트 컨트롤러에 맞게 변형시켜야 하는 문제
5️⃣ Spring MVC 사용
프론트 컨트롤러 패턴, 어댑터 패턴이 모두 적용된 현재
우리가 사용하는 Spring을 이용한 Web Application 개발 방식에 사용됨
Spring은 MVC 패턴에 프론트 컨트롤러 패턴, 어댑터 패턴이 적용되어 있다
Spring은 MVC 패턴에 프론트 컨트롤러 패턴, 어댑터 패턴이 적용된 구조를 가지고 있다
→ ❗백엔드 웹 기술의 역사 네 번째❗

DispatcherServlet
Spring의 프론트 컨트롤러
클라이언트 HTTP Request를 알맞게 파싱하고 클라이언트에게 알맞은 응답을 반환
핸들러 목록 정보를 알고있다
핸들러 어댑터 목록 정보를 알고있다
HandlerAdapter
자신이 처리할 수 있는 Handler인지 확인할 수 있는 기능(Method)이 필요하다
프론트 컨트롤러에서 요청을 위임받았을 때 핸들러에게 요청을 지시하는 기능이 필요하다
return 시 Handler로부터 전달받은 결과를 알맞은 응답으로 변환
Handler
View
Spring MVC의 프론트 컨트롤러는 Dispatcher Servlet(Servlet의 한 종류)이다
➡️ Spring MVC의 핵심 기능
Spring MVC는 DispatcherServlet 코드의 변경 없이 기능변경 및 확장이 가능
➡️ 기능들이 대부분 Interface로 만들어져 있기 때문
➡️ 인터페이스를 implements 하여 구현하면 내가 만든 클래스를 사용할 수 있다 (다형성)
Controller Interface를 implements 하여 구현하게되면 개발자가 원하는 Controller(Handler)를 사용할 수 있게 된다
@Component
Spring Bean에 등록하는 역할을 수행
Spring Bean은 애플리케이션의 구성 요소를 정의하는 객체
마치 Servlet이 Servlet Container에 등록되는 것과 같다
❗HandlerMapping, HandlerAdapter 모두 우선순위대로 조회한다❗
HandlerMapping 우선 순위 순서
1️⃣ RequestMappingHandlerMapping
우선순위가 가장 높다
Annotation 기반 Controller의 @RequestMapping에 사용
2️⃣ BeanNameUrlHandlerMapping
HandlerAdapter 우선 순위 순서
1️⃣ RequestMappingHandlerAdapter
@RequestMapping에서 사용2️⃣ HttpRequestHandlerAdapter
3️⃣ SimpleControllerHandlerAdapter
기존 방식에서 사용하는 Servlet과 가장 유사한 Handler

HandlerMapping 으로 핸들러 조회
HandlerAdapter 조회
HandlerAdapter 실행
반환된 ModelAndView 객체를 알맞은 View로 전달하기 위해 DispatcherServlet에서 ViewResolver를 호출하여 View 정보를 설정하는 역할을 수행

Spring Boot를 사용하면 개발에 필요하여 자동으로 등록되는 ViewResolver들이 있다
Slf4j는 인터페이스이고 그 구현체로 Logback같은 라이브러리를 선택
→ 실제 개발에서는 Spring Boot가 기본으로 제공하는 Logback을 대부분 사용
Annotation 기반의 Spring에서 Controller(Handler)를 만들 때 사용하는 어노테이션
1️⃣ @Controller
→ Template Engine인 Thymeleaf, JSP 등을 사용하는 경우
2️⃣ @RestController
응답할 Data가 있는 경우에 사용
현재는 대부분 @RestController를 사용하여 API가 만들어진다 (Restful API)
return 값으로 View를 찾는것이 아니라 HTTP Message Body에 Data를 입력

@Target(ElementType.Type)
@Retention(RetentionPolicy.RUNTIME)
@Document
@Component
Spring Bean에 등록
싱글톤으로 관리

@Controller에 @ResponseBody가 결합된 어노테이션
@RestController는 ❗@Controller와 달리 각 메서드마다 @ResponseBody를 추가하지 않아도 된다❗
1️⃣ @Component

Spring Bean에 등록하는 역할을 수행
@Indexed - 클래스가 컴포넌트 스캔의 대상으로 Spring Bean에 더 빠르게 등록되도록 도와준다
2️⃣ @Target
3️⃣ @Retention

4️⃣ @Documented

특정 URL로 Request를 보내면 들어온 요청을 Controller 내부의 특정 Method와 Mapping 하기 위해 사용
Client로부터 요청이 왔을 때 어떤 Controller가 호출될지 Mapping하는것은 단순히 URL로 Mapping 하는것이 아니라 여러가지 요소(URL, Method 등)를 조합하여 Mapping한다

➡️ ❗Spring Framework에서 HTTP 요청을 처리하는 메서드를 매핑하는 데 사용되는 어노테이션❗
주로 컨트롤러 클래스에서 사용되어, 특정 URL 패턴에 대한 요청을 해당 메서드로 전달할 수 있게 해준다
예) @RequestMapping을 사용하여 GET, POST, PUT, DELETE 등의 다양한 HTTP 메서드에 맞는 요청을 처리할 수 있다
깔끔하게 잘 정리된 요약본 감사합니다!