🐶〰️
이 글은 질문에 대한 답을 찾아 정리 해놓은 것으로 참고한 글들은 가장 아래 [📌출처] 에 링크 달아놓았습니다.
- HTTP
: Hyper Text Transfer Protocol서버/클라이언트 모델을 따라 데이터를 주고받기 위한 프로토콜
인터넷에서 하이퍼텍스트를 교환하기 위한 통신 규약으로 80번 포트를 사용하고 있다.
HTTP 서버가 80번 포트에서 요청을 기다리고, 클라이언트는 80번 포트를 통해 요청한다.애플리케이션 레벨의 프로토콜로 TCP/IP 위에서 동작한다.
HTTP는 상태를 가지지 않는 stateless 프로토콜이며 Method, Path, Version, Headers, Body 등으로 구성된다.암호화되지 않은 평문 데이터를 전송하는 프로토콜로 비밀번호와 같은 중요한 정보를 전송하면 제 3자가 정보를 조회할 수 있어 위험하다.
그래서 HTTPS가 등장하게 되었다.
- HTTPS
: Hyper Text Transfer Protocol SecureHTTP에 데이터 암호화가 추가된 프로토콜
443번 포트가 사용되며 네트워크 상에서 제 3자가 정보를 훔쳐볼 수 없도록 암호화를 지원한다.
HTTPS는 대칭키 암호화 방식과 비대칭키 암호화 방식을 모두 사용한다.
*
공개키
: 모두에게 공개 가능한 키
*개인키
: 나만 가지고 알고 있어야 하는 키
: HTTPS는 대칭키 암호화와 비대칭키 암호화를 모두 사용해 빠른 연산 속도와 안정성을 모두 얻는다.
Hand-Shaking 과정에서는 먼저 서버와 클라이언트간 세션키를 교환한다.
여기서 세션키는 주고받는 데이터를 암호화하기 위해 사용되는 대칭키이다.
데이터 간 교환에는 빠른 연산 속도가 필요하므로 세션키는 대칭키로 만들어진다.
처음 연결을 성립해 안전하게 세션키를 공유하는 과정에서 비대칭키가 사용된다.
이후 데이터를 교환하는 과정에서 빠른 연산 속도를 위해 대칭키가 사용된다.
- Header + Body 구성
- Header에는 URI, Request method, 여러 header 정보가 포함
- 사람이 읽을 수 있는 문자열 그대로 전송
- TCP 커넥션 이용 (3-way-handshake 사용)
- 커넥션 재사용
- 파이프라이닝 추가 (요청에 대한 응답이 끝나기 전 다음 데이터를 미리 요청)
...
사실 1.1보다 많은 (아래와 같은) 문제를 가짐
- 바이너리가 아닌 텍스트로 데이터를 전송
- TCP 사용
- 여전히 요청 데이터가 🔗동기적으로 진행 (1개 요청, 대기 .. 도착하면 그 다음 데이터 요청, 대기 ..)
- 헤더에 중복된 데이터
HTTP/3 프로토콜은 구글(Google)에서 주도하였으며 10년 전부터 인터넷 서비스 향상을 위해 웹 페이지 반응 속도 개선, TCP 성능 개선 등 다양한 표준화 연구 개발을 진행하였다.
그 후 여러 검증된 인터넷 서비스 개선 기술을 지속적으로 발표하는 동시에 HTTP-over-QUIC의 명칭을 HTTP/3로 바꾸었다.
*
QUID
: 2.0에서 TCP+TLS(3-Way-Handshake 과정)에 해당
보안 및 향상된 성능을 제공하는 UDP기반 전송 계층 프로토콜상당히 가볍고 성능과 보안성을 모두 고려해 설계
암호화된 전송을 통해 멀티 플렉싱된 스트림을 제공
: Representation State Transfer
자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든것을 의미한다.
1. HTTP URI를 통해 자원(resource)를 명시하고
2. HTTP Method(POST, GTE, PUT, DELETE)를 통해
3. 해당 자원에 대한 CRUD Operation을 적용하는 것
📌 Payload 페이로드
: 전송되는 데이터를 의미
데이터를 전송할 때 헤더와 메타 데이터, 에러 체크 비트 등과 같은 다양한 요소들을 함께 보내 데이터 전송의 효율과 안정성을 높이게 된다.
이때, 보내고자 하는 데이터 자체를 의미하는 것이 페이로드이다.
예를 들어 책을 택배로 보낸다고 생각해보자.
책이 페이로드이다. 책을 감싼 완충재와 송장, 박스 이것들은 부가적인 요소로 페이로드라고 할 수 없다.페이로드는 메시지 프로토콜 중 프로토콜 오버헤드와 원하는 데이터를 구별할 때 사용된다.
{ "status": "", "from": "", "to": "", "method": "", "data": { "username" : "dbsrud" } }
(status, from, to, method의 내용은 생략했다.)
여기서 data에 해당하는 부분만이 페이로드이다.
: REST 원리를 따르는 시스템
하지만 REST를 사용했다고 모두 RESTful한 것은 아니다.
REST API의 설계 규칙을 올바르게 지킨 시스템을 RESTful하다고 할 수 있다.
모든 CRUD 기능을 POST로 처리하는 API 혹은 URI 규칙을 지키지 않은 API는 REST API를 사용하였지만 RESTful하지 못한 시스템이라고 할 수 있다.
예전에 다른 분 포스트 보고 공부한건데 출처가 기억 안 남😢
: 프로세스 내 실행되는 여러 흐름의 단위
프로세스의 특정한 수행 경로
프로세스가 할당ㅂ다은 자원을 이용하는 실행의 단위라고 할 수 있다.
: 컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램
메모리에 올라와 실행되고 있는 프로그램의 인스턴스(독립적은 개체)
os로부터 시스템 자원을 할당받는 작업의 단위
라고 할 수 있는데 즉, 동적인 개념으로는 실행된 프로그램을 의미한다.
📌 IPC
: Inter-Process Communication
프로세스들 사이 서로 데이터를 주고받는 행위 또는 그에 대한 방법이나 경로
: 하나의 응용 프로그램을 여러개의 프로세스로 구성하여 각 프로세스가 하나의 작업(task)을 처리하도록 하는 것
Context Switching
: CPU에서 여러 프로세스를 돌아가며 작업을 처리하는데 이 과정을 Context Switching이라고 함): 하나의 응용 프로그램을 여러 개의 스레드로 구성하고 각 스레드로 하여금 하나의 작업을 처리하는 것
웹 서버가 대표적인 멀티 스레드 응용 프로그램
프로그램 여러 개(멀티 프로세스) vs 하나의 프로그램 안에서 여러 작업(멀티 스레드)
우선, 프로세스를 생성해 자원을 할당하는 시스템 콜이 줄어들기 때문에 자원의 효율성을 높일 수 있다.
멀티 프로세스일 때는 프로세스 간 Context switching시 단순히 CPU 레지스터 교체 뿐만 아니라 RAM과 CPU 사이의 캐시 메모리에 대한 데이터까지 초기화되므로 오버헤드가 크다.
하지만 스레드는 프로세스 내 메모리를 공유하기 때문에 독립적인 프로세스와 달리 스레드 간 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 줄어든다.
또한 처리 비용 감소되고 응답 시간이 단축된다.
프로세스 간 통신(IPC)보다 스레드 간 통신 비용이 적어 작업들 간의 통신 부담이 줄어든다. (스레드는 stack 영역을 제외한 모든 메모리를 공유하기 때문)
프로세스 간 전환 속도보다 스레드 간 전환 속도가 빠르다. (context switching시 스레드는 stack 영역만 처리하기 때문)
하지만 스레드 간 자원 공유는 전역 변수 (데이터 세그먼트)를 이용하므로 함께 상용할 때 충돌이 발생할 수 있다는 점을 주의해야 한다.
: Process Control Block
운영체제가 프로세스를 제어하기 위해 정보를 저장해 놓는 곳
즉, 프로세스의 상태 정보를 저장하는 자료구조
운영체제에서 프로세스는 PCB로 표현된다.
프로세스가 생성될 때마다 고유 PCB가 생성되고 프로세스가 완료되면 PCB도 함께 제거된다.
이는 프로세스 상태 관리와 Context Switching을 위해 필요하다.
OS에 따라 PCB에 포함되는 항목이 다를 수 있지만 일반적으로 포인터
, 프로세스 상태
, 프로세스 번호
, 프로그램 카운터
, 레지스터
, 메모리 제한
,열린 파일 목록
...이 있다.
OS는 빠르게 PCB에 접근하기 위해 프로세스 테이블을 사용해 각 프로세스의 PCB를 관리한다.
Transaction
: 쪼개질 수 없는 업무처리의 단위commit
: 모든 부분 작업이 정상적으로 완료되면 이 변경사항을 한번에 DB에 반영rollback
: 부분 작업이 실패하면 트랜잭션 실행 전으로 되돌림: 프로세스가 자원을 얻지 못해 다음 처리를 하지 못하는 상태
시스템적으로 한정된 자원을 여러 곳에서 사용할 때 발생
교착 상태는 한 시스템 내에서 다음 네 가지 조건이 동시 성립될 때 발생한다.
상호 배제(Mutual exclusion)
자원은 한 번에 한 프로세스만이 사용할 수 있어야 한다.
점유 대기(Hold and wait)
최소한 하나의 자원을 점유하고 있으면서 다른 프로세스에 할당되어 사용하고 있는 자원을 추가로 점유하기 위해 대기하는 프로세스가 있어야 한다.
비선점(No preemption)
다른 프로세스에 할당된 자원은 사용이 끝날 때까지 강제로 빼앗을 수 없어야 한다.
순환 대기(Circular wait)
프로세스의 집합 {P0, P1, ... Pn}에서 P0은 P1이 점유한 자원을 대기, P1은 P2가 점유한 자원을 대기 ... Pn-1은 Pn이 점유한 자원을 대기하며 Pn은 P0이 점유한 자원을 요구해야 한다.
: 프로세스 간 공유 자원을 접근하는 데 있어 문제가 발생하지 않도록 한 번에 하나의 프로세스만 이용해 다른 프로세스들의 접근을 제한하는 영역
상호 배제(Mutual Exclution) - 스핀락, 뮤텍스
: 하나의 프로세스가 임계 구역에 들어가 있다면 다른 프로세스는 들어갈 수 없어야 한다.
진행(Progress)
: 들어가려는 프로세스가 여러 개라면 어느 것이 들어갈지 결정해주어야 한다.
한정된 대기(Bounded Waiting)
: 다른 프로세스의 기아(Starvation)를 막기 위해 한 번 임계 구역에 들어간 프로세스는 다음번 임계 구역 접근에 제한이 생겨야 한다.
: 특정한 자원을 획득(Lock) 또는 해제(Unlock)를 통해 공유 자원에 대한 접근 권한을 관리하는 방법
권한을 획득하기 전까지 CPU는 무의미한 코드를 수행하는 Busy Waiting 상태로 대기하고 있다가 접근 권한을 얻게되면 내부 코드를 수행하고 종료 후 권한을 해제한다.
상태가 획득, 해제 뿐이기 때문에 공유 영역에서는 하나의 컴포넌트만 접근이 가능하다.
(획득, 해제의 주체는 동일해야 한다.)
하나의 작업이 빠르게 수행될 수 있다는 장점이 있지만, 선점 기간 동안에는 다른 프로세스의 작업이 지연될 수 있는 오버 헤드가 존재한다.
그래서 짧게 수행할 수 있는 작업에 주로 사용된다.
: MUTual EXclusion으로 상호 배제라고도 한다.
획득(Lock), 해제(Unlock) 상태가 있으며 스핀락과 같이 접근 권한을 획득할 때까지 BusyWating 상태에 머무르지 않고 Sleep 상태가 되며 Wakeup이 되면 권한 획득을 시도한다.
뮤텍스의 경우엔 Locking 메커니즘으로 오직 하나의 스레드만이 동일 시점에 뮤텍스를 얻어 임계 구역(Critical Section)에 접근할 수 있다.
(마찬가지로 획득, 해제의 주체는 동일해야 한다.)
: 스핀락과 뮤텍스와는 다르게 하나 이상의 스레드가 공유 자원에 접근할 수 있도록 함
(예전에 많이 사용되던 방식)
표현형은 정수로 표현하며 획득, 해제가 아닌, 값을 올리고 내리는 방식을 사용한다.
컴포넌트가 특정 자원에 접근할 때 semWait
이 먼저 호출되어 임계 구역에 들어갈 수 있는지 확인한다.
조건에 만족한다면 semWait
을 빠져나와 임계 구역에 들어가게 되고 이후 semSignal
이 호출되어 임계 구역을 빠져나오게 된다.
semWait
연산: 세마포어의 값을 감소시킴
만약 값이 음수가 되면semWait
을 호출한 스레드는 블록되지만 음수가 아니라면 스레드는 작업을 수행
semSignal
연산: 세마포어의 값을 증가시킴
만약 값이 양수가 아니라면semWait
연산에 의해 블록된 스레드들을wake
시킴
세마포어
의 경우 여러 개의 스레드가 접근할 수 있는 반면뮤텍스
는 오직 한 개의 스레드만 접근 가능세마포어
는 현재 수행 중인 스레드가 아닌 다른 스레드가 세마포어 해제를 할 수 있지만뮤텍스
의 경우 획득하고 해제하는 주체가 동일해야 함 (lock을 획득한 프로세스가 unlock까지)
: 상호배제 락에 의해 보호되는 일련의 루틴
락을 획득하기 전까지는 스레드에서 모니터에 속하는 어떤 루틴도 실행시킬 수 없다.
모니터 안 항상 하나의 프로세스만이 활성화 되도록 보장하여 프로그래머들은 동기화 제약 조건을 명시적으로 코딩하지 않아도 된다.
(자바 프로그램에서는 모니터에 대한 활용이 활발)
모니터는 세마포어 이후 프로세스 동기화 도구이다. 그리고 세마포어보다 고수준 개념을 담고있다.
- 공유자원 + 공유자원 접근함수로 구성
- 2개의 queues: 배터동기(
Mutual exclusiton queue
) + 조건동기(Conditional synchronization
)- 공유자원 접근함수에는 최대 한 개의 스레드만 진입 가능
➡️ 나머지 진입하지 못한 스레드들은 큐에서 대기 (Mutual exclusion queue
)- 진입 스레드가 조건 동기로 블록되면 새 스레드 진입 가능
➡️wait call
들어왔던 스레드는Conditional synchronization
에 갇히게 되고 새 스레드는 진입 가능해짐- 새 스레드는 조건동기로 블록된 스레드를 깨울 수 있음
➡️notify()
: 블록됨 스레드를 깨움- 깨워진 스레드는 현재 스레드가 나가면 재진입 가능
➡️ 하나의 스레드만 있을 수 있으므로 그 비워진 자리에 깨워진 스레드가 들어올 수 있게 됨
자바에서는 모든 객체가 모니터가 될 수 있다.
synchronization
키워드를 사용해 지정. 한 스레드에만 접근 가능.wait()
, notify()
, notifyAll()
메소드 사용
세마포어
에 비하여모니터
쪽이 공유자원에 접근할 수 있는 키의 획득과 해제를 모두 처리해 간단하다.
세마포어
는 직접 키 해제와 공유자원 접근 처리를 해주어야 한다.
💡 모니터(Monitor)에 대한 내용은 개념을 모두 이해해 정리하여 쓴 내용이 아니기 때문에 오류가 있을 수 있음
:
내용이 많아 게시물로 따로 정리해 링크 올려둘 것
: 전송 계층에서 데이터를 보내기 위해 사용하는 프로토콜
: Transmission Control Protocol
연결형 서비스를 지원하는 프로토콜
: User Datagram Protocol
비연결형 서비스를 지원하는 프로토콜
각각의 패킷이 다른 경로로 전송되어 독립적인 관계를 지닌다.
즉, 신뢰성보단 연속성이 중요한 서비스에 이용된다.
: 프로그램 전체가 메모리에 연속적으로 할당되어야 하는 관리 기법
: 프로그램의 일부가 서로 다른 주소 공간에 할당될 수 있도록 하는 기법
: 메모리 공간이 조각조각 나뉘게 되어 실제로는 사용 가능한 메모리가 충분한데도 불구하고 할당이 불가능한 상태
(내부 단편화, 외부 단편화)
이를 해결하기 위한 방안으로 Paging, Segmentation이 있다.
Segment
: 페이지 같은 개념이지만, 프로세스를 논리적 내용을 기반으로 나누어 메모리에 배치paging
은 고정 크기를 가짐segmentation
은 가변 크기를 가짐paging
은 내부 단편화 발생 가능segmentation
은 외부 단편화 발생 가능: 추가적인 쓰기 작업과 저장 공간을 활용하여 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조
인덱스를 활용하면 데이터를 조회하는 SELECT
이외에도 UPDATE
나 DELETE
의 성능이 함께 향상된다.
(UPDATE
나 DELETE
또한 해당 대상을 조회해야만 작업할 수 있기 때문)
index를 사용하지 않은 컬럼을 조회한다면 전체를 비교하여 탐색하는 Full Scan을 수행해야 하므로 처리 속도가 떨어진다.
더 자세한 내용은 🔗망나니개발자님 참고
B Tree는 밸런스 트리 (Balanced Tree)의 대표적인 예 중 하나이다.
밸런스 트리 Balanced Tree
: 트리의 노드가 한 방향으로 쏠리지 않도록, 노드 삽입 및 삭제 시 특정 규칙에 맞게 재정렬하여 왼쪽과 오른쪽 자식 양쪽 수의 밸런스를 유지하는 트리
➡️ 최악의 경우에도 O(logN)
해시 테이블은 O(1) 시간 복잡도를 가진다. (해시 충돌 등 최악의 경우에는 O(N)이 될 수 있지만 편균적으로는 O(1))
하지만 이 시간 복잡도는 단 하나의 데이터를 탐색하는 시간 에서 가질 수 있다.
즉, 간단히 1~10까지 저장되어 있을 때 3을 찾는 그런 상황에서만 가진다는 것이다.
분명히 그런 상황만 존재하는 것이 아니다.
3보다 크거나 같은 경우 를 탐색할 때와 같이 부등호가 들어가면 찾기 힘들어진다.
모든 값이 정렬되어 있지 않아 해시 테이블에서는 특정 기준보다 크거나 작은 값을 찾을 수 없다.
(찾을 수야 있지만 O(1)을 보장하지 않음)
그래서 O(1)의 시간 복잡도를 가진 해시 대신 B Tree를 사용하는 것이다.
Map
- key-value를 가진 집합
- 중복 허용 X ➡️ 하나의 key에 하나의 value
- jata.util 패키지에 여러 집합들을 사용하기 위한 여러 인터페이스와 클래스들이 정의되어 있음
HashMap
- Map interface를 implements(구현)한 클래스
- 중복 허용 X
- Map과 같이 key-value로 이루어짐
- key 또는 value 값으로 null 허용
- 순서 유지 X
List
- 배열이 가진 index라는 장점을 버리고 빈틈없는 데이터 적재라는 장점을 가짐
- 순서가 있는 데이터 모음
- 리스트에서의 인덱스 → 몇 번째 데이터인가
(배열에서의 인덱스는 유일무이 식별자)- 비어있는 원소 허용 X
- 순서를 보장하지 않아 cash hit 어려움
- 데이터 개수가 정해져 있고 자주 사용된다면 List보단 Array
Array
- 배열에서의 인덱스는 값에 대한 유일무이한 식별자
- 크기가 정해져있음
- 원소들의 인덱스 불변
- 인덱스를 활용한 빠른 조회 가능
- cache hit의 가능성이 커 성능에 도움
- 하지만 인덱스 값이 불면인 만큼 삭제된 원소의 공간이 그대로 남아 메모리 낭비 발생
Stack
- LIFO (Last In First Out, 후입선출)
- 스택의 구현은 Array 또는 Linked List
- 대표적으로 프로그램을 수행할 때 사용됨
(Main 프로그램에서 함수 A를 호출하면 Main 위에 A가 쌓이고, A 수행 중 B가 호출되면 A위 B가 스택처럼 쌓임)
Queue
- FIFO (First In First Out, 선입선출)
- 큐의 구현은 Array 또는 Linked List
- 여러 프로세스가 수행중일 때 새로운 프로세스가 수행되어야 하는 경우, 기존에 수행되던 프로세스 중 가장 먼저 메모리에 올라온 프로세스가 실행되고, 새로운 프로세스를 메모리에 올림 ➡️ 이런 경우 큐의 형태로 관리
종류가 너무 많아 링크 대체
해당 🔗링크에 Bubble
, Selection
, Insertion
, Quick
, Merge
, Heap
, Radix
, Counting
정렬이 정말 잘 정리되어 있으니 참고하기