Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4주차/수콩] 워크북 제출합니다. #57

Merged
merged 2 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
301 changes: 301 additions & 0 deletions keyword/chapter04/keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@

# DI
## 의존관계

---

- 한 객체에서 다른 객체를 생성하거나, 다른 객체의 메서드를 호출하는 관계
- 객체를 사용하기 위해 다른 객체가 필요한 경우 두 객체는 의존관계라고 표현함
- 의존 관계 = 변경에 의해 영향을 받는 관계

## 의존 객체를 구하는 방법

---

### **객체 내에 의존 객체를 직접 생성하기**

- 프로그래밍 과정에서는 쉬운 방법이지만, 유지 보수 관점에서는 효율적이지 못함
- 의존 객체가 수정되면 의존 객체를 생성하는 모든 객체에서 수정이 필요

### **외부에 의존 객체를 생성하고, 의존 객체를 전달하기(의존성 주입 = DI)**

- 의존 객체가 수정되더라도, 변경할 곳이 의존 객체를 생성하는 부분에 집중됨.
- 객체 사이의 결합도를 낮출 수 있음

## 의존성 주입 방식

---

### **생성자를 통한 주입**

- 객체의 생성자에서 의존할 대상을 주입받으며, 객체 생성 이후 의존성은 변경되지 않음
- 객체를 생성하는 시점에 모든 의존 객체가 주입되므로 완전한 상태의 객체를 사용할 수 있음
- 객체의 의존성이 변하지 않으므로, 객체의 상태는 일관되게 유지됨
- 생성자 코드를 확인해야만 의존 객체를 알 수 있으며, 의존 객체가 많아지면 생성자의 코드가 복잡해짐

### **setter 메서드를 통한 주입**

- 객체가 생성된 후, setter 메서드를 통해 의존할 대상을 주입받으며, 객체가 생성된 후에도 의존성은 변경될 수 있음
- 객체 생성 이후에도 의존성을 변경할 수 있으므로 유연하게 객체를 설정할 수 있음
- 메서드 이름을 통해 주입되는 의존성을 확인할 수 있음
- 완전하지 않은 객체가 생성된 후 setter 메서드를 통해 의존성을 주입되므로 객체를 사용하는 시점에서 예외가 발생할 수 있음

### 필드를 통한 주입

- 필드에 @Autowired를 붙여 의존 객체를 자동으로 주입 받음
- @Autowired를 추가하는 것 만으로 의존성이 주입되므로 코드가 간결해짐
- 외부에서 변경이 불가능 → 테스트가 어려울 수 있음
- DI 프레임워크가 있는 환경에서만 사용할 수 있는 방식
- 클래스 내부에서 직접 의존성을 주입받으므로 결합도가 높아짐

### **생성자 주입 VS setter 메서드 주입**

→ 최근 스프링을 포함한 DI 프레임워크에는 생성자를 이용한 주입 방식이 권장됨

**불변성 측면**

- 대부분의 의존 관계 주입은 한 번 일어나면 애플리케이션이 종료될 때까지 변경할 일이 없고, 오히려 대부분의 의존관계는 변하면 안 됨.
- setter 메서드를 사용하면 해당 메서드를 public으로 설정해야 하므로 변경이 가능하여 안전성이 낮음.
- 생성자 주입 방식은 객체를 생성할 때 딱 1번만 호출되므로 이후에 호출되는 일이 없어 안전함

**누락의 측면**

- 프레임워크를 사용하면 의존성 주입에 누락이 생길 시 오류가 발생하지만, 순수 자바 단위 코드로 테스트를 하면 누락이 생겨도 오류가 발생하지 않고, Exception이 발생함
- 생성자 주입을 사용하면 주입 데이터를 누락했을 때 컴파일 오류가 발생하며, IDE에서 바로 어떤 값을 필수로 주입해야 하는지 알 수 있음 (생성자 방식만 해당)
- 컴파일 시점에서 발생한 오류를 해결하는 것이 런타임 시점에 발생한 오류를 해결하는 것 보다 좋음.

**final 키워드**

- 생성자 주입 방식은 final 키워드를 사용할 수 있기 떄문에, 생성자에서 의존성 주입 누락이 발생하면 컴파일 시점에 막을 수 있음.

**순환참조**

- 순환 참조: A 객체가 B객체를 참조하고 B객체가 A객체를 다시 참조하는 것
- 필드 주입과 setter 메서드 주입은 런타임 시점에 의존성이 주입되므로 오류 없이 실행되다가 해당 코드를 실행하는 시점이 되면 문제가 발생함
- 생성자 주입 방식은 BeanCurrentlyInCreationException이 발생하게 되어 컴파일 시점에 문제를 알 수 있음


# IoC

## IoC란?

---

- Inverse of Control(제어의 역전)의 약자로, 필요한 객체를 직접 생성해서 관리하지 않고 외부에서 관리하는 객체를 가져와 사용하는 것
- 외부에서 의존성을 주입하므로 객체 간의 결합도를 낮춤
- 의존 객체의 수정이 필요하더라도 외부에서 의존성을 주입하는 부분만 수정하면 됨
- DI는 IoC를 구현하는 방식 중 하나이며, DI로 객체 간의 결합도를 낮추고, 코드의 유연성을 높임

## Spring의 IoC 컨테이너

---

- 개발자가 제어해야 하는 요소들을 Spring IoC 컨테이너가 대신하는 것
- Spring IoC 컨테이너가 객체(Bean)를 생성하며, 의존성을 구성하고 결합하며 생명 주기를 관리함
- Bean Factory : 스프링 컨테이너의 최상위 인터페이스로, 빈의 생성과 관리를 담당함
- ApplicationContext: BeanFactory에서 상속받은 Bean의 관리 및 검색 기능에 부가기능을 추가한 컨테이너

## Spring IoC 컨테이너의 객체 관리

---

### Bean

- Spring IoC 컨테이너에서 관리하는 객체
- 생성된 Bean 객체를 바탕으로 컨테이너가 의존성 관계를 관리함

### Bean의 정의

- **암시적 정의 :** @Component를 통해 컨테이너가 자동으로 스캔하여 빈으로 등록
- **명시적 정의 :** 설정파일에 @Configuration을 작성하고 @Bean을 이용하여 빈으로 직접 등록


# 프레임워크와 API의 차이

## 프레임워크

---

- 개발자가 사용할 코드의 틀(구조)을 제공하며, 프로젝트의 구조 및 흐름을 제어하는 프로그램
- 프레임워크만으로 실행되는 것이 아닌, 프레임워크에 의존하여 개발자가 기능을 추가하는 방식으로 사용

**장점**

- 기본 틀이 제공되므로 개발 시간을 줄일 수 있음
- 공통적으로 적용되는 체계이기 때문에, 타인이 만든 코드를 이해하기 쉽고, 유지보수에 용이함

**단점**

- 기본적인 틀의 구조와 사용방법을 익혀야하므로 학습 시간이 많이 필요함
- 프레임워크의 제작자가 만든 구조에서 크게 벗어날 수 없으므로 개발 자유도가 낮음

## API

---

- 서로 다른 소프트웨어 시스템 간의 상호작용을 할 수 있도록 연결해주는 인터페이스이자 매개체
- 실제 개발 시 여러 컴포넌트를 합쳐 개발을 하고 각각의 컴포넌트는 API를 가짐.
즉, API는 컴포넌트를 사용하기 위한 규약이라고 할 수 있음.

**역할**

- 서버와 데이터베이스에 대한 출입구 역할로, 허용된 경우에만 데이터베이스 접근을 허용
- 애플리케이션과 기기가 원활히 데이터를 주고받을 수 있도록 돕는 역할로, 통신을 도움
- 모든 접속을 표준화하하여 기계나 운영체제에 관계없이 조건이 맞으면 동일한 엑세스를 줌

**장점**

- API를 사용하면 기능을 새롭게 개발하기 보다 이미 만들어진 API를 활용하여 개발 시간을 단축할 수 있음
- API는 모든 접속을 표준화하며 다양한 플랫폼, 언어 간의 호환성을 제공함
- API를 활용하면 기능을 모듈화하여 사용할 수 있으므로, 향후 기능을 추가하거나 변경할 때 유연하게 대처할 수 있음

**단점**

- API의 단일 진입점인 API gateway는 해커의 타겟 대상이 될 수 있음.
-

## 프레임워크와 API의 차이

---

**목적**

- 프레임워크의 목적은 개발자가 사용할 틀을 제공하여 개발 프로세스를 단순화 하는 것
- API의 목적은 소프트웨어 시스템 간의 통신을 가능하게 하고, 기능이나 데이터를 외부에서 접근할 수 있도록 하는 것

**제어**

- 프레임워크는 개발자가 아닌, 프레임워크가 직접 애플리케이션의 흐름을 관리하며, 개발자가 필요한 부분을 구현함
- API는 특정 기능을 호출할 수 있는 방법을 제공하며, 개발자가 직접 구현해야 하는 로직이나 구조는 포함되지 않음


# AOP

## AOP

---

- Aspect Oriented Programming의 약자로 여러 객체에서 공통으로 사용할 수 있는 기능을 분리하고 모듈화하여 코드의 재사용성을 높이는 프로그래밍 기법

**장점**

- 핵심기능과 부가(공통)기능을 분리하지 못했던 객체지향프로그래밍을 보완하고, 비지니스 로직이 명확해져 가독성이 향상됨
- 공통기능과 관련된 코드를 한 곳에서 수정할 수 있으므로 유지보수가 용이함
- 코드가 간결해지고, 유연성과 확장성이 증가함

**단점**

- AOP의 적용으로 코드의 흐름이 복잡해질 수 있고, 이로 인해 디버깅이 어려워질 수 있음
- 효율적이지 못한 AOP 설계는 프로그램의 성능을 낮출 수 있음

### AOP 적용 시점

---

**컴파일 타임**

- 컴파일 타임에 AOP 적용이 이루어지는 방식으로 AOP 프레임워크를 사용하여 코드를 컴파일할 때 관점이 적용됨
- 가장 강력하고 정교한 AOP 구현을 제공하지만, 코드 변경과 컴파일이 필요함

**로드 타임**

- 로드 타임에 AOP 적용이 이루어지는 방식으로 클래스 로더가 클래스를 로드하는 시점에 관점이 적용됨
- 컴파일 이후에도 수정 없이 AOP를 적용할 수 있어 편리하지만, 클래스 로더에 종속적임

**런타임**

- 런타임에 AOP 적용이 이루어지는 방식으로 프록시 기반 AOP 프레임워크를 사용하여 런타임 에 프록시 객체를 생성한 후 관점이 적용됨
- 가장 유연하며, 동적인 AOP 구현이 가능하지만, 프록시 생성 오버헤드가 발생할 수 있음

## 스프링의 AOP

---

- 스프링은 프록시 패턴 기반의 AOP 구현체를 이용하여 AOP를 지원함.
- 스프링 빈 객체만 AOP를 적용할 수 있음

**프록시 객체**

- 다른 객체에 대한 접근을 제어하거나 기능을 추가하기 위해 중간에 위치한 대리 객체
- 실제 객체(target)의 메서드 호출을 가로채 추가적 기능으로 감쌀 수 있음
→ 원래 객체에 직접 접근하는 것처럼 느껴짐
- 실제 객체를 필요할 때까지 생성하지 않음으로써 자원 사용을 최적화 함

**Aspect**

- 흩어진 관심사를 묶어서 모듈화 한 것

**Advice**

- 실질적인 부가기능을 담은 구현체
- Joint Point에서 실행

**Join Point**

- Advice 가 적용될 위치, 끼어들 수 있는 지점, 메서드 진입 지점 등 적용하는 곳에 대한 정보

**Point Cut**

- Joint Point를 표현하는 표현식

**target**

- Advice가 적용되는 대상 = 핵심 기능을 담고 있는 객체


# 서블릿

## Servlet

---

- 웹 애플리케이션에서 클라이언트(웹 브라우저)의 요청을 동적으로 처리하고 결과를 반환해주는 서버 측에서 실행되는 자바 프로그램을 말함
- HTTP 프로토콜을 기반으로 작동함

**동작과정**

1. 클라이언트가 url을 입력하면 HTTP Request가 Servlet Container로 전송
2. 요청을 전송받은 Servlet Container가 HttpServletRequest, HttpServletResponse 객체를 생성
3. web.xml을 기반으로 사용자가 요청한 URL에 해당하는 Servlet 찾기
4. 해당 Servlet에서 service() 메소드 호출 후, 클라이언트의 GET, POST 여부에 따라 doGet() 또는 doPost() 호출
5. doGet() 또는 doPost() 메소드가 동적 페이지를 생성한 뒤, HttpServletResponse 객체에 응답을 전송
6. 응답 후 HttpServletRequest, HttpServletResponse 소멸

## Servlet Container

---

- 서블릿을 관리해주는 컨테이너
- 웹 서버가 요청을 받으면 서블릿 컨테이너에 요청을 전달하고, 요청을 처리할 수 있는 서블릿에 처리를 위임하는 방식
- 클라이언트의 요청을 받아주고 응답할 수 있게, 웹서버와 소켓으로 통신
- 톰캣이 대표적인 서블릿 컨테이너

**서블릿 컨테이너의 역할**

- **웹 서버와의 통신**

서블릿과 웹 서버가 쉽게 통신할 수 있도록 함. 통신에 필요한 기능을 API로 제공하여 복잡한 과정을 생락하고 비지니스 로직에만 집중할 수 있도록 도움.

- **서블릿 생명주기 관리**

서블릿 클래스 로딩 후 인스턴스화,초기화 메소드 호출, 요청에 따른 적절한 서블릿 메소드 호출을 담당함. 서블릿 클래스 소멸 시 가비지컬렉션을 진행함.

- **멀티스레드 지원 및 관리**

요청이 들어올 때마다 새로운 자바 스레드를 생성하며, HTTP 메소드 실행 후 자동으로 스레드가 소멸함. 서버가 스레드를 관리하므로 스레드의 안정성이 보장됨.

## 스프링의 Dispatcher Servlet

---

- 서블릿 컨테이너의 가장 앞단에서 HTTP 프로토콜로 들어오는 모든 요청을 먼저 받아 적합한 컨트롤러에 위임해주는 Front Controller

**동작 방식**

1. 웹 브라우저가 DispatcherServlet에 요청을 전송함
2. DispatcherServlet이 HandlerMapping 빈 객체에 컨트롤러 검색을 요청
3. DispatcherServlet이 HandlerAdapter 빈 객체에 컨트롤러 객체의 요청 처리를 위임함
4. HandlerAdapter 빈 객체가 컨트롤러의 알맞은 메서드를 호출해서 요청을 처리하고, 결과를 ModelAndView로 변환하여 리턴함
5. DispatcherServlet이 ViewResolver를 이용해 결과를 보여줄 View를 검색함
6. DispatcherServlet이 최종 응답 HTML을 웹 브라우저에 리턴함

Loading