Skip to content
Open
120 changes: 120 additions & 0 deletions Database/인덱스를 사용하는 이유(장단점).md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# 인덱스를 사용하는 이유(장단점)
## 요약
> 인덱스는 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조입니다.
> 사용 시 테이블 조회 속도를 높여 DB 성능을 향상시키며, Full Scan하지 않아 시스템 부하를 줄여줍니다.
> 하지만 항상 정렬된 상태로 유지해야하기에 추가적인 쓰기작업이 필요하며 이를 저장하기 위한 저장공간이 필요합니다. 때문에 잘못 사용할 경우 성능 저하의 역효과를 발생시킵니다.


## 인덱스(Index)란?
- 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조.
- 추가적인 쓰기 작업과 저장공간을 활용
-> 이를 관리하기 위해 DB에 ~~약 10%에 해당하는~~ 저장공간 필요
- **PK는 자동으로 Index가 생성됨** -> NHN 기출
![인덱스 구조](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Database/index_structure.png?raw=true)

> 인덱스 없이 조회하면 모든 튜플(레코드)를 검색하지만 인덱스를 사용한다면 인덱스를 탐색하고 일치할 시에 해당 튜플로 데이터를 검색. -> 속도 **up**


## 인덱스를 사용하는 이유
- 인덱스 테이블은 데이터들이 정렬되어 있음! -> **정렬과 연관지어 기억하자**

### 조건 검색 Where 절의 효율성
- 인덱스 테이블은 데이터들이 정렬되어 저장되어 있기 때문에 해당 조건(where)에 맞는 데이터를 빠르게 찾아낼 수 있음

### 정렬 Order by 절의 효율성
- 이미 정렬되어 있기 떄문에 order by에 의한 Sort과정을 피할 수 있음

### MIN, MAX의 효율적인 처리 가능
- MIN값과 MAX값을 레코드의 시작값과 끝 값 한 건씩만 가져오면 되기에 Full Scan보다 효율적


## 인덱스의 장단점
### 장점
- 테이블을 조회하는 속도와 그에 따른 성능을 향상
- 전반적인 시스템의 부하를 줄임(Full Scan을 안해서)

### 단점
- 인덱스를 관리하기 위해 DB의 ~~약 10%에 해당하는~~ 추가적인 저장공간 필요
- 인덱스를 관리하기 위해 추가 작업 필요
- 잘못 사용할 경우 성능 저하의 역효과 발생


## 인덱스 관리
- Index를 항상 **최신의 데이터를 정렬된 상태로 유지**해야 원하는 값을 탐색 할 수 있음
- INSERT, UPDATE, DELETE(데이터 추가, 수정, 삭제) 수행 시 정렬 필요! -> 부하**UP**
- INSERT, UPDATE, DELETE 시 추가적인 연산 필요
-> 부하를 최소화하기 위해 데이터 삭제라는 개념에서 **인덱스를 사용하지 않는다** 라는 작업으로 대신함
- INSERT : 새로운 데이터에 대한 인덱스 추가
- DELETE : 삭제하는 데이터의 인덱스를 사용하지 않는다는 작업 진행
- UPDATE : 기존의 인덱스를 사용하지 않음 처리, 갱신된 데이터에 대한 인덱스 추가


## 인덱스 생성 전략
- 조건절에 자주 등장하는 컬럼(호출 빈도가 높음)
- 같거나 크고, 작음으로 자주 사용되는 컬럼(where 또는 order by에서 쓰이는 컬럼)
- 중복되는 데이터가 최소한인 컬럼(분포도가 좋다 = 데이터가 서로 다르고 넓게 퍼져 있다)
- 조인 조건으로 자주 사용되는 컬럼


## 인덱스 자료구조
### 해시테이블
- key : 데이터(= 컬럼의 값)
- value : 데이터의 위치
- 장점
- 빠른 데이터 탐색에 유용
- 시간 복잡도 O(1)
- 단점
- 등호 연산에만 특화
- DB는 부등호(>, <) 연산이 많아서 **사용 부적합**
![인덱싱_해쉬](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Database/indexing_hash.png?raw=true)

## B+ Tree
- 대부분의 DB 인덱싱 자료구조
- 특징
- 리프노드에만 인덱스와 함께 데이터를 갖고있고, 나머지 노드들은 인덱스만을 가짐
- 리프노드들은 연결리스트로 이루어짐 -> 탐색이 0번노드부터 일어나는 연결리스트에 비해 시간 효율이 좋음!(log2(N))
- 데이터 노드의 크기는 인덱스 노드와의 크기와 같지 않아도 됨
- 예시
- 인덱스
![인덱싱_B+Tree1](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Database/indexing_b%2Btree1.jpeg?raw=true)

- B+ Tree
![인덱싱_B+Tree2](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Database/indexing_b%2Btree2.jpeg?raw=true)

> BTree : 모든 노드에 데이터를 담음
> 리프노드 : 자식이 없는 노드. 잎이라고도 함
> B+ Tree 알고리즘에 대해서는 추후 정리할 예정입니다.



## TMI : 결합 인덱스
- 두 개 이상의 컬럼을 합쳐서 인덱스를 만드는 것
- 단일 컬럼으로는 분포도가 나쁘지만, 여러 개의 컬럼을 합친다면 좋은 분포도를 가지며, where절에서 and 조건에 많이 사용되는 컬럼을 결합 인덱스로 생성함

### 결합 인덱스 컬럼 생성 전략
- where절에서 and 조건으로 자주 결합되고, 결합할 시 분포도가 좋아지는 컬럼
- 다른 테이블과 조인의 연결고리로 자주 사용되는 컬럼
- order by에서 자주 사용되는 컬럼
- 하나 이상의 키 컬럼 조건으로 같은 테이블의 컬럼들이 자주 조회될 때

### 예시
- 결합 인덱스 생성 예시
`create index emp_pay_idx on emp_pay(급여년월, 급여코드, 사원번호);`
- 결합 인덱스 사용 예시
```
select * from emp_pay where 급여년월 = '202107';
select * from emp_pay where 급여년월 = '202107' and 급여코드 = '정기급여';
select * from emp_pay where 급여년월 = '202107' and 급여코드 = '정기급여' and 사원번호 = '20210401';
```

> 단 급여코드만을 검색할 때는 결합 인덱스의 첫 번째 컬럼인 급여년월의 조건식이 없기 때문에 결합 인덱스로 조회하지 않음! -> 급여년월, 급여코드, 사원번호의 순서대로 조회
- 결합 인덱스 효율성 감소
1. LIKE 검색 : 2021%같이 검색할 경우 2021에 해당하는 모든 급여코드, 정기급여로 생성된 결합 인덱스를 조회해서 B*Tree에서 조회하기 어려움
2. 결합 인덱스 칼럼 순서(이하 급여년월(1), 급여코드(2), 사원번호(3) 컬럼을 숫자로 말하겠습니다)
- 1, 3 / 2 / 2, 3 / 3 으로 조회할 경우 결합 인덱스 순서대로 조회하지 않아서 Full Scan이 발생합니다


- 출처
- [Database 인덱스(index)란? - MangKyu’s Diary](https://mangkyu.tistory.com/96)
- [DB 데이터베이스 인덱스(Index) 란 무엇인가?](https://coding-factory.tistory.com/746)
- [자료구조 그림으로 알아보는 B+Tree](https://velog.io/@emplam27/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-B-Plus-Tree)
61 changes: 61 additions & 0 deletions Network/SSL_HandShake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# SSL HandShake
## HTTP
### 정의
- HyperText Transfer Protocol
- 웹 브라우저와 웹서버, 애플리케이션 및 IoT 등과 데이터를 주고 받기 위한 프로토콜

### 특징
- Stateless
- 클라이언트의 상태를 저장하지 않음 -> 때문에 클라이언트가 이전에 했던 요청에 따라 반응이 달라지지 않는다!
- 여러 대의 서버가 어떤 요청에 따라 동일한 응답을 하기 때문에 서버 확장이 가능!
- Connectionless
- 연결을 유지하지 않음
- 연결을 유지할 경우 지속적인 리소스가 사용됨!
- 클라이언트 - 서버 구조
- 클라이언트의 요청이 있을 때 서버가 응답하는 단반향 통신
- 대부분의 파일 형식 전송 가능
- 거의 모든 파일 형식을 HTTP 통신을 이용해 전송 가능

## HTTPS
### 정의
- 안전한 통신을 위해 HTTP 통신에 암호화를 적용
- SSL(Secure Socket Layer) / TLS(Transport Layer Security) 전송 기술 사용
- TCP, UDP와 같은 일반적인 인터넷 통신에 **안전한 계층(Layer)**를 추가

### 대칭키 암호화 방식
![대칭키 암호화](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Network/%E1%84%83%E1%85%A2%E1%84%8E%E1%85%B5%E1%86%BC%E1%84%8F%E1%85%B5%20%E1%84%8B%E1%85%A1%E1%86%B7%E1%84%92%E1%85%A9%E1%84%92%E1%85%AA.png?raw=true)

### 공개키 암호화 방식(비대칭키 암호화 방식)
![비대칭키 암호화](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Network/%E1%84%87%E1%85%B5%E1%84%83%E1%85%A2%E1%84%8E%E1%85%B5%E1%86%BC%E1%84%8F%E1%85%B5%20%E1%84%8B%E1%85%A1%E1%86%B7%E1%84%92%E1%85%A9%E1%84%92%E1%85%AA.png?raw=true)


### 순서
1. TCP, UDP 연결
2. SSL HandShake
3. 데이터 통신

### SSL HandShake
1. 클라이언트 - 클라이언트가 먼저 서버에 접속(Client Hello)
2. 웹서버 - 웹서버 인사 응답, 클라이언트에 정보 전달(Server Hello)
3. 클라이언트 - 웹서버의 인증서 확인, 웹서버의 공개키 획득
4. 웹서버의 공개키로 Premaster Secret을 암호화해서 전달(Premaster Secret : 브라우저와 웹서버의 난수로 생성된 일련의 값)
5. 웹서버의 개인키로 Premaster Secret 복호화
- 클라이언트, 웹서버 모두 일련의 과정을 거쳐서 Premaster Secret으로 Master Secret을 생성
- Master Secret으로 세션키 생성
6. SSL handshake 종료 및 HTTPS 시작
![SSL Handshake](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Network/SSL%20HandShake.png?raw=true)

### HTTPS를 적용하면 완벽 보안?
- HTTPS는 웹에서 보안을 적용하기 위한 가장 기본적인 단계
- HTTPS는 전달 구간에 대한 보안, 중간 서버를 해커가 침투하면 내용은 고스란히 유출
- HTTPS를 적용하면서 종단간 암호화 기술(E2EE : End-to-End Encryption) 적용하는 것이 일반적인 추세
> E2EE?
> - 일반적으로 E2EE가 적용되지 않는다면 발신원과 수신원 사이 중간서버에서 데이터는 암호화되지 않은 채로 저장되거나 잔류됨
> - E2EE를 적용할시 발신원의 정보가 **암호화된 채 그대로** 중간 서버를 거쳐 수신원에게 전달

## 출처
- [HTTPS를 위한 SSL/TLS 핸드 셰이크 작동원리](https://brunch.co.kr/@sangjinkang/38)
- [(CS) TLS/SSL Handshake란](https://hanjungv.github.io/2017-11-07-1_CS_SSL/)
- https://hanamon.kr/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-http-http%EB%9E%80-%ED%8A%B9%EC%A7%95-%EB%AC%B4%EC%83%81%ED%83%9C-%EB%B9%84%EC%97%B0%EA%B2%B0%EC%84%B1/
- [Network HTTP란 무엇인가?](https://surprisecomputer.tistory.com/54)
- [SSL이란 무엇인가 :: 매일의 공부 기록](https://study-recording.tistory.com/11)
Binary file added Spring/.DS_Store
Binary file not shown.
153 changes: 153 additions & 0 deletions Spring/생성자 주입을 사용해야하는 이유.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# 생성자 주입을 사용해야하는 이유
# 요약
- [객체의 불변성 확보](bear://x-callback-url/open-note?id=B5467B00-E1D6-4C5B-8FA4-83B1A3B2975E-1500-00000B9786F1BC1D&header=1.%20%EA%B0%9D%EC%B2%B4%EC%9D%98%20%EB%B6%88%EB%B3%80%EC%84%B1%20%ED%99%95%EB%B3%B4)
- [테스트 코드 작성 용이](bear://x-callback-url/open-note?id=B5467B00-E1D6-4C5B-8FA4-83B1A3B2975E-1500-00000B9786F1BC1D&header=2.%20%ED%85%8C%EC%8A%A4%ED%8A%B8%20%EC%BD%94%EB%93%9C%EC%9D%98%20%EC%9E%91%EC%84%B1)
- [final키워드 작성으로 실수를 줄이고 Lombok과의 연계가 좋다](bear://x-callback-url/open-note?id=B5467B00-E1D6-4C5B-8FA4-83B1A3B2975E-1500-00000B9786F1BC1D&header=3.%20final%20%ED%82%A4%EC%9B%8C%EB%93%9C%20%EC%9E%91%EC%84%B1%20%EB%B0%8F%20Lombok%EA%B3%BC%EC%9D%98%20%EA%B2%B0%ED%95%A9)
- [순환 참조 에러를 사전에 방지한다](bear://x-callback-url/open-note?id=B5467B00-E1D6-4C5B-8FA4-83B1A3B2975E-1500-00000B9786F1BC1D&header=4.%20%EC%88%9C%ED%99%98%20%EC%B0%B8%EC%A1%B0%20%EC%97%90%EB%9F%AC%20%EB%B0%A9%EC%A7%80)


# 1. 객체의 불변성 확보
- 대부분 의존 관계 주입은 애플리케이션 종료시점까지 변하면 안됨!
- Setter를 열어두는 것은 좋은 설계 방법이 아님(누군가 실수로 변경할 수 있음)
-> OCP(Open/closed principle) 위배
- 생성자 주입은 생성 시 딱 1번만 호출됨으로 불변하게 설계할 수 있음
- final 키워드 설정 가능(불변임으로)


# 2. 테스트 코드의 작성
## 생성자 주입이 아닐 경우
- 필드 주입을 사용한다면 테스트 환경은 실제 코드의 DI 프레임워크 위에서 동작하지 않고, 순수한 자바 코드로 동작 -> **Null Point Exception 에러 발생, 테스트 하는 것이 불가능**

### 실제 코드
```
@Service
public class UserServiceImpl implements UserService {

@Autowired
private UserRepository userRepository;

public UserRepository getUserRepository() {
return userRepository;
}
}
```

### 테스트 코드
```
public class UserServiceTest {
@Test
public void injectionTest() {
UserService userSerivce = new UserServiceImpl();
UserRepository ur = userService.getUserRepository();
System.out.println(ur);
}
```

> DI 프레임워크가 없는 순수한 자바 코드 테스트임으로 의존 관계 주입이 누락되어 UserRepository가 null인 NPE발생

- 위의 문제를 해결하기 위해선 Setter를 사용하면 되지만**, 싱글톤 패턴을 해칠 수 있다.** 또한 수정자 주입과 다를 바가 없으면서 수정자 주입 역시 **OCP 위배**한다는 문제가 있음

> OCP(Open/closed principle) : 개방-폐쇄 원칙, 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다.


## 생성자 주입일 경우
- 의존 관계 주입이 누락될 경우 **컴파일 오류**가 발생
- 어떤 값을 필수로 주입해야하는 지 확실하게 알 수 있음!

### 실제 코드
```
@Service
public class UserServiceImpl implements UserService {

private UserRepository userRepository;

@Autowired
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}

public UserRepository getUserRepository() {
return userRepository;
}
}
```

### 테스트 코드
```
public class UserServiceTest {
@Test
public void injectionTest() {
UserService userSerivce = new UserServiceImpl();
UserRepository ur = userService.getUserRepository();
System.out.println(ur);
}
```

> 컴파일 오류 발생 : `java: constructor UserServiceImpl in class (패키지명).UserServiceImpl cannot be applied to given types; required: (패키지명).UserRepository`


# 3. final 키워드 작성 및 Lombok과의 결합
## final 키워드 작성
- 생성자 주입은 final 키워드 사용 가능
-> 값 설정 누락 시 컴파일 시점에 오류 발생
- 누락된 의존성 확인이 빠름!

## Lombok과의 결합
- `@RequiredArgsConstructor`
-> final이 붙은 필드(변수)를 모두 모아 생성자를 자동으로 생성
- 필드 주입보다 더 간결한 코드!

> **최종 코드**
```
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

private final UserRepository userRepository;
}
```


# 4. 순환 참조 에러 방지
## 필드 or 수정자 주입의 경우
- 예시 (닭은 알을 낳고, 알은 닭으로 부화하고)
```
@Component
public class Chicken {
@Autowired Egg egg;

public void layEgg() {
egg.hatch();
}
}
```

```
@Component
public class Egg {
@Autowired Chicken chicken;

public void hatch() {
chicken.layEgg;
}
}
```

> 두 메소드는 서로를 순환하며 호출하다가, 메모리에 CallStack이 쌓여 StackOverFlow 에러를 발생

## 생성자 주입의 경우
- 애플리케이션 구동 시점(객체 생성 시점)에 컴파일 오류를 발생시켜 순환 참조 에러를 방지

```
Description: The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| chicken defined in file [(경로)/Chicken.class]
↑ ↓
| egg defined in file [(경로)\Egg.class]
└─────┘
```

> 생성자 주입의 컴파일 에러가 오류 잡기 좋다..

## 출처
- [스프링 핵심 원리 - 기본편 - 인프런 | 강의](https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard)
Loading