✅ 한 것들
📝 CS 공부
- 인터넷에서 시험 관련 정보 모은 후 gpt에게 예상 문제 요청
- 인프런에서 샀던 면접 대비 자료에서 모르는 거 정리
C++
(0.1 + 0.2) == 0.3
십진 소수는 이진 부동소수점으로 정확히 표현할 수 없다.
실제로 저장되는 값 (대략)
0.1 ≈ 0.10000000000000000555
0.2 ≈ 0.20000000000000001110
0.3 ≈ 0.29999999999999998890
vitrual dispatch
struct B {
virtual void f(){ std::cout<<"B"; }
};
struct D : B {
void f() override { std::cout<<"D"; }
};
void g(B b){ b.f(); }
void h(B& b){ b.f(); }
int main(){
D d;
g(d);
std::cout<<" ";
h(d);
}
값으로 받으면 객체 슬라이싱 때문에 B로 인식돼서 B 출력
참조(포인터도 가능)로 받으면 virtual dispatch가 일어나 D 출력
예외 처리
- 예외가 던져지면 stack unwinding이 일어나 현재 함수에서 위로 올라가면서 지역 객체들의 소멸자 호출
- noexcept는 이 함수는 예외를 던지지 않겠다는 약속. 예외가 함수 밖으로 전파되면
std::terminate()가 호출되어 프로그램 강제 종료.
- c++은 언체크 예외만 있다. 체크 예외 : 함수가 어떤 예외를 던질 수 있는지 함수 시그니처에 명시.
- throw는 어떤 타입이든 던질 수 있다
바이트 패딩
32비트 CPU는 한 번에 4바이트,
64비트 CPU는 한 번에 8바이트를 읽을 수 있다. (대략)
메모리 주소가 마음대로면 주소 4+-1에 걸처져 있는 데이터 있을 때
메모리를 두 번 접근해야 읽을 수 있게 됨.
구조체/클래스 패딩은 구조체 안의 가장 큰 자료형의 크기로 정해짐.
구조체 안에 구조체가 들어가 있으면, 그 구조체 안에서 가장 큰 자료형의 크기로 정해짐.
struct S {
char a;
int b;
short c;
};
4바이트 정렬 예시
a는 1바이트. b 넣으려면 4바이트 정렬돼야 함. 3바이트 패딩.
b는 4바이트. 자기 타입 정렬에 맞으므로 넘어감.
c는 2바이트. 클래스 정렬 맞추기 위해 2바이트 추가.
최종 12바이트.
class C {
short a;
int b;
int c;
};
8바이트 정렬 예시 (가정)
a는 2바이트. b 넣으려면 4바이트 정렬돼야 함. 2바이트 패딩.
b는 4바이트. 자기 타입 정렬에 맞으므로 넘어감.
c는 4바이트. 클래스 정렬 맞추기 위해 4바이트 패딩 추가.
최종 16바이트.
알고리즘
재귀 함수의 장단점
- 장점 : 코드의 가독성을 높여준다
- 단점 : 메모리를 더 사용하고, 실행 시간이 더 느리다
정렬 알고리즘
선택 정렬
- 제일 작은 거 찾아서 맨 앞으로 보내는거 n번
- 찾는 연산은 원소만큼 N, 반복을 N, 최종 복잡도 O(n^2)
버블 정렬
- 2개씩 비교해서 자리 옮기는거 n번, n-1번 ...
- 연산 횟수 1부터 n까지 더하면 최고항 N^2, 최종 복잡도 O(n^2)
삽입 정렬
- 정렬 범위 1씩 확대하면서 새로 추가된 거 정렬될때까지 앞으로 보내기
- 원소 개수 N, 앞으로 보내기 N, 최종 복잡도 O(n^2)
병합 정렬
- 죄다 나눈 다음에 짝지어서 합치고 정렬 반복
- 합칠 때 정렬은 둘 중 작은 값 뽑아내기
- 원소의 개수만큼 비교하므로 N, 합치는 단계가 logN, 최종 복잡도 O(NlogN)
퀵 정렬
- 피벗 골라서 작은 값은 왼쪽, 큰 값은 오른쪽 반복
- 피벗 중간값 가까우면 : O(NlogN), 피벗 최대나 최소면 : O(N^2)
힙 정렬
- 최소 힙 최대 힙 구성해서 정렬
- O(NlogN)
자료구조
1e8 = 100000000
1e-8 = 0.00000001
레벨 순서(level-order)로 저장된 최소 힙
- heap은 완전 이진 트리 기반 자료 구조
- 부모 노드가 자식 노드보다 작음
- 배열에 level-order로 저장한다는 건 bfs 순서대로 저장한다는 뜻
[2, 3, 4, 5, 6, 7] 가 적절한 예시
운영체제
CPU 스케줄링
비선점형 스케줄링 : 작동 중인 프로세스 못 치움
선점형 스케줄링 : 운영체제가 프로세스한테서 CPU 뺏기 가능
- FCFS (First Com, First Served) : 선착순, 한 놈 때문에 다 느려질 수 있음
- SJF (Shortest Job First) : 가장 짧은 놈 먼저, 근데 그걸 어케 아는지가 문제
- 우선순위 : 오래된 작업 우선순위 높이는 등 기아 (Starvation) 문제 해결
- 라운드 로빈 : 동일한 할당 시간 부여
- SRTF (Shortest Remaining Time First) : 현재 실행 중인 프로세스 남은 시간 보다 짧은 놈 먼저, 근데 그걸 어케 아는지가 문제
- 다단계 큐 : 우선순위에 따라 큐를 나눔, 낮은 큐는 기아 발생 가능
- MLFQ (Multilevel Feedback Queue) : 낮은 큐에 있는것도 기다리면 승격
페이지 교체 알고리즘
- FIFO (First-In First-Out) : 가장 오래 전에 들어온 페이지를 교체. Belady's Anomaly(프레임 수 늘려도 페이지 폴트 늘어남) 발생 가능.
- OPT (Optimal) : 앞으로 가장 오랫동안 사용되지 않을 페이지 교체. 현실적으로 불가능.
- LRU (Least Recently Used) : 가장 오래 전에 사용된 페이지 교체.
- LFU (Least Frequently Used) : 사용 횟수가 가장 적은 페이지 교체. 예전에 많이 쓰고 지금은 안 쓰는 페이지도 남을 수 있음.
네트워크
Nagle 알고리즘
- 데이터 하나하나 쪼개서 보내지 말고 한꺼번에 보내는 알고리즘
- 데이터 보낸 후에 ACK 돌아오면 수신 측 Window size에 맞춰 데이터 보냄
IP 주소
-
IP : 어느 네트워크의 어느 호스트인지 나타내는 3계층 (네트워크 계층) 주소
-
IPv4 : 32비트. 점으로 구분된 10진수 4개로 표현 (10.20.1.130)
-
IPv6 : 128비트. 콜론으로 구분된 16진수 (2001:db8::1) 브로드캐스트(전부 전송)가 없고 멀티캐스트(그룹 전송) 사용.
-
네트워크 주소 : 서브넷의 가장 낮은 주소(호스트 비트가 모두 0). 라우팅 테이블에서 "그 서브넷 자체"를 가리킴
-
브로드캐스트 주소(IPv4) : 서브넷의 가장 높은 주소(호스트 비트가 모두 1), 같은 서브넷의 모든 호스트에게 보냄
-
사용 가능한 호스트 주소 : 2^(호스트 비트) - 2, 네트워크/브로드캐스트 2개 뺀 나머지
-
CIDR(Classless Inter-Domain Routing) : A/B/C 클래스 구분 없이 /27같은 prefix로 서브넷을 자유롭게 나누는 현재 표준 방식
서브넷
- 서브넷 : 큰 네트워크를 잘라 만든 논리적 네트워크
- 서브넷 마스크 : 네트워크 부분(1) / 호스트 부분(0)을 표시하는 32비트 값
/27이면 앞 27비트가 1, 뒤 5비트가 0 → 십진수 마스크는 255.255.255.224
TIME_WAIT
- TCP 연결이 정상적으로 종료(FIN/ACK 교환)된 후 마지막으로 FIN 보낸 쪽이 들어가는 상태
- 일정 시간 (보통 2MSL) 동안 기다린 다음에 소켓 닫음
- MSL = 네트워크에서 TCP 세그먼트가 살아남을 수 있는 최대 시간(보통 30초~2분 정도).
- 2MSL = 왕복 고려(송신 → 소멸, 재전송 가능성까지 포함)
전송 계층
- 혼잡 제어 (Congestion Control) : 네트워크 정보량 조절. ACK 오면 전송량 2배씩 늘리다 Time Out 발생하면 데이터 줄임.
- 흐름 제어 : ACK 받을 때만 다음 데이터 전송
- 오류 제어 : ACK를 못 받거나, 시간 내에 ACK 못 받거나, 데이터 중간에 손실되거나, 순서 바뀌거나, 훼손 되면 데이터 재전송
DNS 레코드
- A : 도메인 → IPv4 주소
- AAAA : 도메인 → IPv6 주소
- CNAME : 도메인 → 다른 도메인 이름 (같은 도메인에 A랑 같이 둘 수 없음)
- MX : 메일 서버
- NS : 이 도메인을 담당하는 네임 서버
데이터베이스
트랜잭션
- Dirty read : commit 안된 데이터 읽음
- Non-repeatable Read : 같은 행을 읽었는데 값이 달라짐
- Phantom Read : 같은 조건으로 두 번 읽었는데 새 행이 나타남
격리 수준
- Read Uncommitted : Commit이나 Rollback과 상관없이 다른 트랜잭션에서 조회 가능. Dirty Read 발생 가능.
- Read Committed : Commit된 변경만 읽을 수 있음. 조회하면 최신 커밋 스냅샷 갖고 옴. Non-repeatable Read 발생 가능.
- Repeatable Read : 읽은 행 락 걸어서 못 바꾸게 함. Phantom Read 발생 가능.
- Serializable : 트랜잭션을 하나씩 순서대로 실행한 것과 같게 보장. 성능 안 좋음.