diff --git a/keyword/chapter03/keyword.md b/keyword/chapter03/keyword.md new file mode 100644 index 0000000..148a6bd --- /dev/null +++ b/keyword/chapter03/keyword.md @@ -0,0 +1,263 @@ +- **SOLID원칙이란?** + + > 객체지향 프로그래밍에서 코드의 유지보수성, 확장성, 유연성을 높이기 위해 준수해야할 5가지 핵심 원칙 + > + + **[단일 책임 원칙 - Single Pesponsibility Principle]** + + - 하나의 클래스는 하나의 책임(기능)만 가져야 한다. + - 클래스가 변경되는 이유는 하나여야 한다. + + **[개방-폐쇄 원칙 - Open/Closed Principle]** + + - 기존 코드를 변경하지 않고, 확장할 수 있어야 한다. + - 새로운 기능 추가시 기존 코드를 수정하지 않고도 구현이 가능해야 한다. + + **[리스코프 치환 원칙 - Liskov Substitution Principle]** + + - 자식 클래스는 부모 클래스를 대체할 수 있어야 한다. + - 부모 클래스로 자식 클래스를 받을 수 있어야 한다. + - 하위 클래스가 상위 클래스의 기능을 변경하면 안 된다. + + **[인터페이스 분리 원칙 - Interface Segregation Principle]** + + - client가 사용하지 않는 인터페이스에 의존하지 않도록 해야한다. + - 하나의 큰 인터페이스보다는 여러 개의 작은 인터페이스로 분리하는 게 좋다**.** + + **[의존성 역전 원칙 - Dependency Inversion Principle]** + + - 상위 모듈(추상화)이 하위 모듈(구현)에 의존하는 것이 아니라, 하위 모듈이 상위 모듈에 의존해야한다. + - 의존성을 줄이기 위해 인터페이스를 활용한다. + + **[장, 단점]** + + - 장점: 확장성 향상, 유지보수 용이, 결합도 감소 + - 단점: 코드 복잡도 증가, 초기 개발 속도 저하 + + +- **DI란?** + + > 의존성 주입(Dependency Injection)으로, 외부에서 객체를 생성해 넣어주는 설계 패턴 + > + + **[의존성 - Dependency]** + + - 필요로 하는 것, 뭔가를 하기 위해 필요한 것 + + **[주입 - Injection]** + + - 외부에서 누군가 넣어주는 것 + + **[DI의 3가지 방식]** + + - **필드 주입** - 변수 위에 `@Autowired` 를 붙여 사용 + - 코드가 간단하지만, 필드가 `private` 라 순수 자바 단위 테스트가 불가하다. + + ```java + @Service + public class UserService { + + @Autowired + private UserRepository userRepository; + } + ``` + + - **setter 주입** - setter 매서드를 통해 주입 + - 런타임에 주입받아 중간에 의존성을 바꿀 수 있다. + + ```java + @Service + public class UserService { + + private UserRepository userRepository; + + @Autowired + public void setUserRepository(UserRepository userRepository){ + this.userRepository = userRepository; + } + } + ``` + + - **생성자 주입** + - `final`을 붙여 한 번 주입되면 바뀌지 않는다. + - 의존성 누락시 생성자에서 컴파일 오류를 발생시켜 누락을 방지한다. + - 롬복 라이브러리를 통해 `@RequiredArgsConstructor` 로 대체 + - `final`이 붙은 필드들이 인자로 들어가는 생성자 생성 + + ```java + @Service + public class UserService { + + private final UserRepository userRepository; + + public UserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + } + ``` + + +- **IoC란?** + + > 제어의 역전(Inversion of Control)으로, 코드의 주도권이 개발자에서 프레임워크나 컨테이너에 위임하는 sw 설계 원칙 + > + + > 개발자가 객체를 직접 `new` 로 생성하고 생명주기를 제어했지만, 이 역할을 프레임워크가 대신한다. + > + + **[요약된 흐름]** + + ```java + public class Customer { + + private final Pizza pizza; // 피자를 받을 준비만 + + // 생성자, 누군가 넣어줄 것을 기다림 + public Customer(Pizza pizza){ + this.pizza = pizza; + } + + public void eat(){ + pizza.eat(); + } + } + ``` + + 외부에서 넣어주는 피자를 그냥 먹기만 하면 된다. + + **[역전 - Inversion]** + + - 기존에는 app → 라이브러리 방향으로 호출 + - framework → app 방향으로 호출 + - 객체의 생명주기가 프레임워크로 넘어가, 흐름이 뒤집혔다고 하여 제어의 역전이라고 부른다. + + **[장, 단점]** + + - 코드 유연성이 높아진다. + - `new` 로 강한 의존 관계에선 의존 관계 변경을 위해 service 코드에 수정이 필요하다. + - 인터페이스를 통해 약한 의존 관계를 만들어, 의존 관계 변경시 service 코드 변경없이 수정 가능하다. + - 테스트가 용이해진다. + - Mock 객체를 주입하여 실제 동작 없이 테스트를 돌리기 용이하다. + - 코드 복잡도가 증가한다. + - 코드 흐름의 직관적인 파악이 어려워진다. + + +- **생성자 주입 vs 수정자, 필드 주입 차이는?** + + > 불변성과 순환참조, 테스트 용이 등의 장점으로 스프링에서 가장 추천하는 방식은 생성자 주입이다. + > + + **[필드 주입]** + + - 변수(필드) 바로 위에 `@Autowired` 를 붙여 사용한다. + - 코드가 간단하다. + - 외부에서의 변경이 어려워 단위 테스트 시, 가짜 객체를 넣기 힘들다. + + ```java + @Service + public class UserService { + + @Autowired + private UserRepository userRepository; + } + ``` + + **[Setter 주입]** + + - setter 매서드를 통해 의존성을 주입하는 방식이다. + - 변경될 수 있는 의존 관계에 사용한다. + - 매서드가 public이기에 수정이 가능하여 안정성이 떨어진다. + + ```java + @Service + public class UserService { + + private final UserRepository userRepository; + + public UserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + } + ``` + + **[생성자 주입]** + + - 생성자 호출 시 1번 초기화 하는 방식이다. + - `final` 키워드를 사용하여, 불변성을 보장한다. + - 의존성 누락시 생성자에서 컴파일 오류를 발생시켜 누락을 방지한다. + - 롬복 라이브러리를 통해 `@RequiredArgsConstructor` 로 대체 + - `final`이 붙은 필드들이 인자로 들어가는 생성자 생성 + + ```java + @Service + public class UserService { + + private final UserRepository userRepository; + + public UserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + } + ``` + + +- **AOP란?** + + > 관점 지향 프로그래밍(Aspect-Oriented Programming)으로, 핵심 모듈이 아닌 부가 기능을 분리하여 모듈화한다. + > + + > 즉, 핵심 비즈니스 로직에서 분리하여 재사용하겠다는 점 + > + + **[AOP의 주요 개념]** + + - Aspect: 흩어진 관심사를 모듈화한 것(주로 부가기능) + - Target: Aspect을 적용하는 곳 + - Advice: 실질적으로 어떤 일을 해야할 지에 대한 것, 실질적인 부가 기능을 담은 구현체 + - JointPoint: Advice가 적용될 위치, 끼어들 수 있는 지점 + - PointCut: JointPoint의 세부 스펙을 정의한 것 + + **[스프링 AOP 특징]** + + - 프록시 패턴 기반의 AOP 구현체 + - 스프링 빈에만 적용 가능 + - 모든 AOP 기능을 제공하는 것이 아닌 스프링 IoC와 연동하여 “중복 코드, 프록시 클래스 작성의 번거로움, 객체 사이의 복잡도 증가”에 대한 해결책 지원 + + +- **서블릿이란?** + + > 동적 웹페이지를 만들 때 사용되는 자바 기반의 웹 애플리케이션 프로그래밍 기술 + > + + 웹을 만들 때 다양한 Request와 Response가 있고, 이 요청과 응답에는 규칙이 존재한다. + + 개발자가 이러한 요청과 응답을 일일이 처리하는 게 아니라, 비즈니스 로직에만 집중할 수 있도록 도와주는 기술이 서블릿이다. + + 이러한 웹 요청과 응답의 흐름을 **간단한 매서드 호출**만으로 다룰 수 있게 해주는 기술이다. + + **[서블릿의 주요 특징]** + + - Client의 Request에 대해 동적으로 작동하는 웹 애플리케이션 컴포넌트다. + - HTML을 사용하여 Response한다. + - 자바의 스레드를 이용하여 동작한다. + - MVC 패턴에서의 컨트롤러로 이용된다. + - HTTP 프로토콜 서비스를 지원하는 HttpServlet 클래스를 상속받는다. + - UDP보다 속도가 느리다. + - HTML 변경시 Servlet을 다시 컴파일해야한다. + + **[동작 과정]** + + - `init()` + - 서블릿이 처음으로 요청될 때 초기화를 하는 매서드 + - 초기화된 서블릿은 싱글톤으로 관리된다. + - `service()` + - 서블릿 컨테이너가 요청을 받고 응답을 내려줄 때 필요한 매서드 + - HttpServelt 클래스의 doGet, doPost 같은 매서드들이 호출된다. + - `destroy()` + - 더 이상 사용되지 않는 서블릿 클래스는 주기적으로 서블릿 컨테이너가 매서드를 호출하여 제거한다. + + **[서블릿 생명주기]** + + - 서블릿도 자바 클래스이므로 실행하면 초기화부터 서비스 수행 후 소멸하기까지의 과정을 거친다. + + diff --git "a/mission/chapter03/images/\354\227\220\353\260\230_\355\224\274\354\226\264\353\246\254\353\267\260_\354\240\234\354\235\264\354\235\230_\354\233\214\355\201\254\353\266\201.png" "b/mission/chapter03/images/\354\227\220\353\260\230_\355\224\274\354\226\264\353\246\254\353\267\260_\354\240\234\354\235\264\354\235\230_\354\233\214\355\201\254\353\266\201.png" new file mode 100644 index 0000000..0d9f8d0 Binary files /dev/null and "b/mission/chapter03/images/\354\227\220\353\260\230_\355\224\274\354\226\264\353\246\254\353\267\260_\354\240\234\354\235\264\354\235\230_\354\233\214\355\201\254\353\266\201.png" differ diff --git a/mission/chapter03/mission.md b/mission/chapter03/mission.md new file mode 100644 index 0000000..b26e59d --- /dev/null +++ b/mission/chapter03/mission.md @@ -0,0 +1,41 @@ +### 워크북 캡쳐 + +![에반_피어리뷰_제이의_워크북.png](./images/에반_피어리뷰_제이의_워크북.png) + +### 워크북 리뷰 + + + + +# 미션 기록 +**[스프링 MVC 요청/응답 흐름]** + +1. DispatcherServlet: 입구 (Front Controller) + 1. 모든 HTTP 요청은 가장 먼저 DispatcherServlet이 받는다. +2. Handler Mapping: 길 찾기 + 1. DispatcherServlet이 Handler Mapping에게 `/login` 과 같은 요청을 어디서 처리하는 지 `@Controller` 코드들을 뒤져서 알려준다. +3. Handler Adapter: 대리 실행 + 1. 컨트롤러의 구현 방식이 각자마다 다를 수 있기에, Handler Adapter를 통해 컨트롤러의 매서드를 실제로 호출한다. +4. Controller: 비즈니스 로직 수행 + 1. 파라미터를 읽고, 서비스를 호출해서 DB 데이터를 가져오고, 결과를 담아 다시 Adapter에게 돌려준다. +5. View Resolver: 화면 찾기 또는 데이터 변환 + 1. HTML을 보여줄 때 + 1. View Resolver가 “어떤 HTML 파일을 보여줄지 찾아서 화면을 렌더링한다. + 2. API(JSON)을 보낼 때 + 1. `@ResponseBody`가 붙어있으면 HTML 대신 데이터를 JSON 형식으로 바로 변환 +6. Response: 최종 응답 + 1. 완성된 HTML이나 JSON 데이터가 DispatcherServlet을 거쳐 브라우저에게 전달된다. + +**[요약 흐름도]** + +- **Request** → (DispatcherServlet) +- **DispatcherServlet** → (Handler Mapping) : "어디로 갈까?" +- **DispatcherServlet** → (Handler Adapter) : "이 컨트롤러 실행해줘" +- **Controller** : "로직 처리 완료!" +- **DispatcherServlet** → (View Resolver) : "어떤 화면 보여줄까?" (API의 경우 생략) +- **Response** → 브라우저 완료