출처: 이것이 취업을 위한 코딩테스트다 with 파이썬, 나동빈, 2021

강의: https://youtu.be/7C9RgOcvkvo?si=p-_dsBcTLy0K_6WN


스택 Stack

출처: GeeksforGeeks

Last-In First-Out

먼저 들어온 데이터가 나중에 나가는 선입후출 자료구조.

stack = []

stack.append(5) # push
stack.append(3)
stack.append(2)
stack.pop() # pop

print(stack) # [5, 3]

 

python에서 stack은 리스트로 구현할 수 있다.

  • 삽입: append(요소) # O(1)
  • 삭제: pop() # O(1)

큐 queue

출처: GeeksforGeeks

First-In First-Out

먼저 들어온 데이터가 먼저 나가는 선입선출 자료구조.

from collections import deque

queue = deque()

queue.append(5) # push
queue.append(3)
queue.popleft() # pop
queue.append(2)

print(queue) # [3, 2]

 

python에서 queue는 deque을 사용해서 구현한다.

삽입: append(요소) # O(1)

삭제: popleft() # O(1)

 

deque은 내부적으로 연결 리스트로 구현이 되어 있다.

따라서 삽입, 삭제가 O(1)으로 가능하다.

단 random access가 불가능하기에, 요소 접근에는 O(N)이 소요된다.

 

재귀 함수 Recursive Fuction

출처: inDepth.dev

재귀 함수란? 자기 자신을 다시 호출하는 함수.

 

재귀 함수는 반복문으로 동일하게 구현이 가능하다. 역도 그렇다.

코드의 길이는 짧아지지만, 인간에게 직관적이지 않으므로 신중하게 사용해야 한다.

 

문제 풀이에 활용하려면 종료 조건을 반드시 명시해야 한다.

종료 조건 없이 함수가 무한히 호출되면, stack overflow가 발생하기 때문.

import sys
sys.setrecursionlimit(10 ** 5)

 

python3는 기본적으로 재귀 깊이를 1,000으로 제한해 놓았다.

그러나 문제를 풀다보면 이 제한을 해제해야 하는 경우가 있다.

sys.setrecursionlimit()으로 이 제한을 늘려주자

 

재귀 깊이가 29945를 넘어가면 에러 발생

 

직접 해본 결과 재귀 깊이가 29945를 넘어가면, segmentation fault 에러가 발생한다.

프로그램이 메모리를 잘못 액세스 했을 때 발생하는 오류로, stack overflow를 원인으로 발생하는 오류 중 하나이다.

정해진 메모리 공간을 넘어가면, 다른 데이터를 건드릴 수 있기에 이를 방지하기 위한 에러이다.

 

실전에서는 재귀 깊이 제한을 10 ** 5 정도로 설정한 뒤에, 종료 조건을 반드시 작성하자.

 

예시1. 팩토리얼

def factorial_recursive(n)
    if n <=1 :
        return 1
    return n * factorial_recursive(n - 1)
    
# 0! == 1
# 1! == 1

 

예시2. 유클리드 호제법

def gcd(a, b)
    if a % b == 0 :
        return b
    else :
        return gcd(b, a % b)
        
# 성질: a와 b의 나머지가 r이라면, a와 b의 최대 공약수 == b와 r의 최대 공약수
# a, b의 대소 관계와 상관없이 동작한다.

 

DFS (Depth First Search)

출처: GeeksforGeeks

정의

깊이 우선 탐색.

그래프에서 깊은 부분을 우선적으로 탐색하는 알고리즘.

뼈대

def dfs(graph, v, visited):
    
    visited[v] = True # 현재 노드 방문 처리
    print(v, end = " ") # 방문한 노드를 순서대로 출력
    
    for i in graph[v]: # 인접한 노드를 모두 확인
        if not visited[v]: # 방문하지 않은 노드가 있다면
            dfs(graph, i, visited) # 재귀적으로 탐색

 

스택 혹은 재귀 함수를 이용한다.

  1. 탐색 시작 노드를 스택에 삽입 / 방문 처리
  2. 스택 최상단 노드에 방문하지 않은 인접한 노드가 하나라도 있으면, 그 노드를 스택에 넣고 방문 처리.
    방문하지 않은 인접한 노드가 없으면 스택 최상단 노드 꺼냄.
  3. 2번 과정을 수행할 수 없을 때 까지 반복

 

BFS (Breadth First Search)

출처: GeeksforGeeks

정의

너비 우선 탐색.

가까운 노드부터 우선적으로 탐색하는 알고리즘.

뼈대

from collections import deque

def bfs(graph, start, visited):
    
    queue = deque([start]) # deque에 시작 노드를 추가해서 초기화
    visited[start] = True # 현재 노드 방문 처리
    
    while queue: # 큐가 빌 때까지 반복
        v = queue.popleft() # 가장 먼저 들어온 노드를 제거 # 처음에는 시작 노드
        print(v, end = " ") # 순서대로 출력
        
        for i in graph[v]: # 인접한 노드를 모두 확인
            if not visited[i]: # 방문하지 않은 노드가 있다면
                queue.append(i) # 큐에 추가하고
                visited[i] = True # 방문 처리

 

큐를 이용한다.

  1. 탐색 시작 노드를 큐에 삽입 / 방문 처리
  2. 큐에서 노드 꺼내고 해당 노드의 인접 노드 중에서, 방문하지 않은 노드를 모두 큐에 삽입하고 방문 처리
  3. 2번 과정을 수행할 수 없을 때까지 반복

 

출처: 이것이 취업을 위한 코딩테스트다 with 파이썬, 나동빈, 2021

강의: https://youtu.be/2zjoKjt97vQ?si=VgYo4fBNuccHh7P5


그리디

chatGPT가 생각하는 그리디

정의

현재 상황에서 지금 당장 좋은 것만 선택하는 알고리즘.

정당성 분석이 선행되어야 한다.
--> 단순하게 가장 좋아보이는 것만 선택하면, 최적의 해를 구할 수 있는지?

 

실제로 유형을 모른 채로 문제를 만났을 때, 그리디 알고리즘을 사용해야 하는 근거는 다음과 같다.

 

1. 문제의 구조:

  • 최적 부분 구조: 작은 문제의 최적 해결책이, 전체 문제에도 적용될 수 있어야 함.

2. 선택의 기준:

  • 탐욕적: 현재 정보에 한해, 제일 좋은 것을 선택.
  • 단기적: 각 선택은 현재 정보만을 기반으로 이루어짐. 이전 혹은 미래의 선택을 고려하지 않음.
  • 불가역적: 선택이 이루어지고 나면, 이후의 과정에서 그 선택을 되돌릴 수 없음. 모든 선택은 최종 선택임.

 

1. 거스름 돈

큰 단위가 항상 작은 단위의 배수이므로 최적의 해를 보장한다.
예: [500, 400, 100]이라면, 큰 단위(500)가 작은 단위(400)의 배수가 아니므로, 그리디를 적용할 수 없다.

 

2. 1이 될 때까지

1빼기 보다, 나누기를 많이 하는 것이 대부분의 상황에서 유리하다.

현재 값이 2이상이면 나누는 것이 1 빼는 것보다 빠르게 조건을 달성할 수 있으니까.

n, k = map(int, input().split())

result = 0

while True:
    target = (n // k) % k # n과 가장 가까우면서 작은 k로 나누어 떨어지는 수
    result += (n - target) # 어차피 1씩 빼면서 target까지 가야한다. 그것을 한 번에.
    
    n = target # 1씩 빼서 target까지 도착했다고 치고
    
    if n < k: # 나누는 수보다 작아지면 탈출
        break
        
    result += 1
    n //= k # while을 한 번 반복할 때마다, k로 한 번씩 나누는 셈

result += (n - 1) # 더 이상 나눌 수 없는 상태이므로, 1씩 빼서 1에 도착할 때까지 횟수
print(result)

 

3. 곱하기 혹은 더하기

피연산자가 1 또는 0이 아니라면 항상 곱하기가 유리하다.

 

4. 모험가 길드

배열을 정렬하고, 작은 값부터 임시 그룹에 추가하며, 조건을 만족하는 즉시 마을을 떠나면 최적의 해를 구할 수 있다.

 

그리디 알고리즘을 적용해야 하는지 헷갈릴 수 있다.

그리디 알고리즘 선택 근거를 다시 생각해보자.

 

1. 문제의 구조: [1]인 경우와 [1, 2, 3]인 경우, 모두 같은 풀이를 적용할 수 있다.

2. 선택의 기준: [1]인 경우와 [1, 2, 3]인 경우, 탐욕적으로 선택해도 최적의 해가 나온다. 각 선택은 단기적이고 불가역적이다. 

 

 

구현

chatGPT가 생각하는 구현

 

정의

풀이를 떠올리는 것은 쉽지만 소스 코드로 옮기기 어려운 문제

  1. 알고리즘은 간단한데 코드가 지나칠 정도로 길어짐
  2. 실수 연산을 다루고, 특정 소수점 자리까지 출력해야 함
  3. 문자열을 다룸
  4. 적절한 라이브러리를 찾아서 사용해야 함

 

1. 상하좌우

방향 벡터를 사용한 문제.

행렬의 시작 부분인 (0, 0)이 좌상단 임을 기억할 것.

 

2. 시각

h = int(input())

count = 0

for i in range(h + 1):
    for j in range(60):
        for k in range(60):
            if "3" in str(i) + str(j) + str(k): # 이렇게 하면 쉽다.
                count += 1

print(count)

 

완전 탐색.

하루는 86,400초이므로 완탐을 하기에 무리 없다.

파이썬은 1초에 2,000만 번 정도 연산을 수행할 수 있다고 생각하기.

 

3. 왕실의 나이트

8방향 벡터.

 

4. 문자열 재정렬

data = input()
result = []
value = 0

for x in data:
    if x.isalpha(): # 문자면 True 아니면 False # isNumeric()도 있음
        result.append(x)
    else:
        value += int(x)

result.sort()

if value != 0: # 숫자가 없을 경우 표시하면 안 되니까
    result.append(str(value))

print("".join(result)) # 리스트의 원소를 합쳐서 문자열로 만드는 방법

 

 

<애플리케이션의 구조>

클라이언트-서버 구조

클라이언트-서버 구조

애플리케이션 계층은 클라이언트 - 서버의 구조를 갖는다.

클라이언트는 요청하고, 서버는 응답한다.

 

서버:

  • 24시간 켜져 있음.
  • 영구적인 IP 주소
  • 확장을 위한 데이터 센터가 있음

클라이언트:

  • 서버와 통신
  • 항상 켜져있지 않고, 간헐적으로 통신
  • 동적인 IP 주소
  • 클라이언트와 클라이언트가 직접적으로 통신하지 않는다. (이것은 P2P)

P2P 구조

P2P 구조

서버가 항상 켜져있을 필요는 없다.

임의의 엔드 시스템(peer)끼리 직접 통신한다.

중앙 서버가 없기 때문에 확장이 더 쉽다. 중앙 서버의 장애가 전체 시스템에 영향을 끼치지 않는다.

반대로 중앙 집중 관리를 하지 않기에, 보안 문제가 발생하기 쉽다.

 

<애플리케이션 계층의 통신 방식>

통신 방식

프로세스 간의 통신은 Socket을 통해 이루어진다.


프로세스: 하나의 호스트 내에서 실행 중인 프로그램

 

하나의 호스트 내에서, 프로세스 간에 통신하는 것을 Inter Process Communication, IPC라고 한다.

다른 호스트 간에, 통신을 하는 것은 message를 주고 받음으로써 이루어진다.

이때 OS가 제공하는 인터페이스인 Socket을 통해 통신한다.

 

하나의 기기는 여러 개의 소켓을 가질 수 있다.

하나의 소켓은 여러 개의 프로세스를 가질 수 있다.

 

기기 간의 통신은 반드시 소켓에서 일어난다. 이 연결은 유일하다.

따라서 대략적인 통신 과정은 다음과 같다.

[출발 프로세스a ---> 출발 소켓A] ===> [목적지 소켓B ---> 목적지 프로세스b]

 

출발 소켓이 목적지 소켓을 찾기 위해서는 Socket 인터페이스 주소 == IP 주소가 필요하다.

목적지 소켓 내에서 목적지 프로세스를 찾기 위해서는 포트 번호가 필요하다.

 

어떤 기기든, 웹 서버 프로세스의 포트 번호는 80번이다.

 

애플리케이션 계층의 요구사항

애플리케이션 별 요구사항

 

애플리케이션은 데이터 무결성, 빠른 응답 속도, 많은 처리량, 보안성을 요구한다.

그러나 이 모든 것을 맞춰줄 수는 없다.

 

예컨대 e-mail 앱은 데이터 무결성이 중요하다. 그러나 반드시 응답 속도가 빠를 필요는 없다.

반면 실시간 영상은 데이터가 몇 프레임 정도 손상되어도 크게 지장 없다. 하지만 응답 속도는 가능한 한 빨라야 한다.

 

TCP / UDP

기능 TCP UDP
연결 형태 연결형 서비스. 송신자와 수신자 간에 연결 설정 후 통신 비연결형 서비스. 연결 설정 없이 데이터 그램을 직접 전송
reliable 높음. 중복 제거, 오류 검출 및 재전송 메커니즘 제공 낮음. 중복 제거 없음, 오류 검출 및 재전송 없음
in-order 데이터의 순서가 보장됨. 송신된 순서대로 데이터가 도착. 데이터의 순서가 보장되지 않음.
flow-control 있음. 네트워크 혼잡 시 데이터 전송 속도 조절 없음. 어떠한 흐름 제어도 적용되지 않음
congestion-control 있음. 네트워크의 혼잡 상태를 감지하고 데이터 전송량을 조절 없음. 네트워크 혼잡에 대응하지 않음
속도 UDP보다 느림. 연결 설정, 오류 검사 및 제어 메커니즘 때문 TCP보다 빠름. 최소한의 오버헤드만을 가짐
사용 사례 신뢰성 있는 데이터 전송이 필요한 경우 (웹 페이지 로딩, 이메일, 파일 전송 등) 실시간 통신이 필요한 경우 (스트리밍, 온라인 게임, VoIP 등)
헤더 크기 20바이트 기본. 옵션에 따라 더 길어질 수 있음 8바이트. 고정된 크기로 매우 경량
오류 검사 헤더와 데이터 모두에 대한 체크섬을 통한 오류 검사 및 수정 가능 헤더와 데이터에 대한 체크섬을 통해 오류 검사만 제공. 오류 수정은 제공하지 않음

 

TCP / UDP는 Transport 계층 프로토콜이 제공하는 서비스이다.

현재는 애플리케이션 계층에 대해 배우고 있지만, 후술한 HTTP에 대해서 설명하기 위해 간단하게 짚고 넘어가자.

 

TCP는 reliable, in-order, flow-control, congestion-control의 특징을 갖고 있다. 기능이 많은 대신 무겁고 느리다.

UDP는 그런 거 없다. 대신 가볍고 빠르다.

애플리케이션 별 사용하는 프로토콜

 

상술했듯이 애플리케이션마다 요구 사항이 다르다.

따라서 사용하는 전송 계층의 프로토콜도 다르다.

 

Web

사용자가 보는 웹 페이지는 object로 구성되어 있다.

object는 HTML 파일, JPEG 이미지, Audio 파일 등이 될 수 있다.

 

개발자가 보는 웹 페이지는 base HTML-file로 되어있다.

HTML은 referenced objects(객체의 주소)를 포함하고 있다.

따라서 주소(URL)를 통해 객체를 연결하고, 연결된 객체를 가져와서 보여주는 것이다.

 

HTTP

HTTP의 구조

HTTP의 통신 과정

Hyper Text Transfet Protocol.

이 프로토콜은 클라이언트의 request와 서버의 response로 이루어진다.

 

HTTP는 TCP를 기반으로 동작한다.

데이터의 reliability를 보장할 수 있지만, UDP에 비해 비싼 비용을 내야한다.

 

TCP로 통신을 하기 위해서는, 최초 request 메시지 이전에 TCP Connection이 이루어져야 한다.

이때 request & response 이후 Connection의 연결 지속 여부에 따라, Persistent와 Non-Persistent로 나뉜다.

 

HTTP는 Stateless한 특징을 갖는다.

request & response 이후에, 클라이언트와 서버는 서로에 대한 어떤 정보도 기억하지 않는다.

 

 HTTP 통신 소요 시간

HTTP 통신에 소요되는 시간

 

RTT는 Round Trip Time의 약자로, request & response가 한번 이루어지는 시간을 뜻한다.

1. TCP 통신을 위해서는 최초 TCP Connection 과정이 필요하다. (1 RTT)

2. request & response가 이루어진다. (1 RTT)

2-1. 데이터를 전송하는 시간이 소요된다. (transmission time)

 

Non-persistent의 경우, 데이터 전송 시마다 2 RTT + transmission time이 소요된다.

Persistent의 경우, 데이터 전송 시마다 1 RTT + transmission time이 소요된다.

 

HTTP 메시지의 구조

1. request / 2. response

HTTP request / response 메시지의 구조는 위와 같다.

위는 데이터를 제외한 헤더에 대한 내용이다.

 

response message에서 status line을 주목할 만하다.

응답의 상태를 나타낸다.

 

쿠키

서버가 만든 쿠키~ 클라이언트 위해 구웠지~

 

1. 웹 브라우저가 아마존에 접속하려고 함

2. http request를 생성하기 전에, 클라이언트의 로컬 디스크에서 아마존에 대한 쿠키가 있는지 살펴봄

3. 없으면 평범한 request를 생성해서 요청. 있으면 해당 정보를 포함해서 요청.

4. 아마존은 데이터베이스에서 클라이언트의 쿠키 정보를 확인함. 없으면 새로 생성해서 set-cookie: 일련번호 형태로 전송. 있으면 해당 상태에 적절한 응답.

5. 클라이언트는 이것을 로컬에 저장

6. 2~4의 과정을 반복

 

쿠키는 HTTP의 stateless 특징이 갖는 약점을 보완한다.

 

캐시 (proxy server)

프록시 서버의 구조

프록시 서버는 클라이언트와 원천 서버 사이에 위치하는 또다른 서버이다.

클라이언트의 요청을 대신하여 원천 서버의 리소스에 접근한다.

 

1. 캐싱

  • 프록시 서버는 자주 요청되는 웹 페이지나 파일을 로컬에 저장(캐싱)한다.
  • 이후 같은 요청이 들어올 경우, 프록시 서버는 인터넷에 다시 접속하지 않고 캐시된 데이터를 제공함으로써 응답 속도를 향상.

2. 보안

  • 프록시 서버는 내부 네트워크와 인터넷 사이의 중간자 역할을 하며, 외부의 불법적인 접근으로부터 내부 네트워크를 보호.
  • 또한, 내부 네트워크의 IP 주소를 숨기고 프록시 서버의 IP 주소로 대체하여 보안성을 높임.

3. 접근 제어

  • 프록시 서버를 통해 특정 웹 사이트나 서비스에 대한 접근을 제어.
  • 예를 들어, 관리자는 특정 사이트에 대한 접근을 차단하거나, 사용자 권한에 따라 인터넷 사용을 제한할 수 있음.

4. 익명성

  • 사용자가 프록시 서버를 통해 인터넷에 접속하면, 사용자의 실제 IP 주소가 숨겨지고 프록시 서버의 IP 주소가 사용됨.
  • 이를 통해 사용자의 익명성을 보장할 수 있습니다.

5. 로드 밸런싱

  • 여러 대의 프록시 서버를 사용하여 네트워크 트래픽을 분산시킬 수 있음.
  • 이는 서버에 대한 부하를 줄이고, 서비스의 가용성과 성능을 향상.

장점

빠르다. 행복한 클라이언트.

할 일이 줄어든다. 행복한 서버.

외부 네트워크로 나가는 트래픽이 줄어든다. 행복한 로컬 네트워크.

받는 돈이 줄어든다. 슬픈 KT.

받는 돈이 줄어든다. 슬픈 AT&T.

 

단점

캐싱의 근본은 자주 참조되는 데이터의 복사본을 프록시 서버에 두는 것.

원본이 바뀌었을 때는 일관성 문제가 발생.

 

캐싱의 예 (링크의 이용률이 오버 되는 상황)

로컬 웹 캐시(프록시 서버)를 설치하면 해결

 

LAN의 가용량에는 여유가 있고, 링크의 가용량이 부족한 상황

1. 케이블을 확장 설치

2. 캐싱 서버를 설치 (일반적으로 더 저렴한 해결책, 효과도 좋다.)

Conditional GET

Conditional GET의 예시

 

요청을 보낼 때 Conditional GET을 사용하면, 캐싱의 데이터 일관성 문제를 해결할 수 있다.

if-modified-since: <date> 이후로 수정이 되었는지 묻는 파라미터를 추가하여,

수정이 되지 않았다면 Not Modified를, 수정이 되었다면 새로운 데이터를 전달함으로써, 프록시 서버의 데이터를 갱신한다.

 

DNS

DNS란?

Domain Name System.

인터넷에서 도메인 이름을 IP 주소로 변환하는 시스템.

본격적인 HTTP 통신 이전에 준비 작업이다.

사용자가 웹 브라우저에 도메인 이름을 입력하면, DNS는 그것을 IP 주소로 변환하여 웹 서버에 접근할 수 있게 한다.

 

DNS의 계층화

DNS의 구조

 

DNS 테이블을 끝도 없이 채워나가다 보면 2가지 문제점을 만난다.

1. 중앙 집중으로 single point of failure 발생

2. 무거워져서 느려짐.

 

따라서 그림과 같이 분산화와 계층화를 한다.

다음과 같은 구성 요소로 이루어져 있다.

 

1. Root Name Server

  • 인터넷의 DNS 시스템에서 최상위에 위치
  • 전 세계에 걸쳐 13개의 루트 네임 서버가 존재
  • 이 서버들은 전체 DNS 조회 과정의 시작점 역할
  • 최상위 도메인(TLD)에 대한 요청을 받으면, 해당 TLD를 관리하는 네임 서버의 주소를 제공.

2. TLD (Top-Level Domain) Server

  • TLD 서버는 도메인 이름의 최상위 부분(예: .com, .net, .org 등)을 관리.
  • 각 TLD는 자신의 네임 서버를 가지며, 이 네임 서버는 해당 TLD에 등록된 모든 도메인의 정보를 관리.
  • 특정 도메인 이름에 대한 조회를 받으면, 그 도메인 이름을 관리하는 권한 있는(Authoritative) 네임 서버의 주소를 제공.

3. Authoritative Name Server

  • 권한 있는 네임 서버는 특정 도메인에 대한 최종적인 권한을 갖는다.
  • 해당 도메인의 모든 서브 도메인을 포함한 상세한 DNS 정보(예: IP 주소, 메일 서버)를 제공.

 

DNS 조회 과정

1. iterated query / 2. recursive query

  1. 사용자가 웹 브라우저에 도메인 이름을 입력.
  2. 사용자의 컴퓨터는 로컬 DNS 서버에 도메인 이름에 대한 IP 주소를 요청.
  3. 로컬 DNS 서버가 해당 정보를 캐시에 가지고 있지 않은 경우, 루트 네임 서버에 조회를 요청.
  4. 루트 네임 서버는 해당 도메인의 TLD 서버 주소를 제공.
  5. TLD 서버는 도메인의 권한 있는 네임 서버 주소를 제공.
  6. 권한 있는 네임 서버는 최종적으로 도메인 이름에 대한 IP 주소를 제공.
  7. IP 주소 정보는 로컬 DNS 서버를 거쳐 사용자의 컴퓨터에 전달되고, 이를 통해 사용자의 컴퓨터는 웹 서버에 접속한다.

도메인 레코드

도메인 레코드

A타입과 NS타입이 중요하다.

DNS 데이터를 관리하기 위해서 보통 A, NS 타입의 데이터를 관리한다.

타입 name value
A타입 호스트 이름 IP 주소
NS타입 도메인 호스트 이름(해당 도메인을 관리하는 authoritative server)

 

DNS의 프로토콜

DNS는 UDP를 사용한다.

1. 데이터의 크기가 매우 작다. 따라서 에러 발생 가능성도 작고, 손실의 리스크가 적다.

2. DNS는 본격적인 HTTP 통신 이전에 준비 과정이다. 따라서 간단할수록 좋다.

 

Socket 프로그래밍

소켓이란?

소켓의 구조

상술하였듯이, 소켓은 OS에서 제공하는 인터페이스이다.

애플리케이션 계층의 프로세스와, 통신 계층을 연결한다.

프로세스 간의 통신은 소켓을 통해서 이루어진다. (내부는 IPC 소켓, 외부는 네트워크 소켓)

 

하나의 기기는 여러 개의 소켓을 갖는다. (IP 주소로 찾는다.)

하나의 소켓은 여러 개의 프로세스를 갖는다. (포트 번호로 찾는다.

소켓은 특정 IP 주소 & 포트 번호의 조합에 바인딩 되어 있다.

 

소켓의 분류

타입에 따라 다른 소켓의 구조 (1. TCP: SOCK_STREAM / 2. UDP: SOCK_DGRAM)

 

소켓은 전송 계층의 프로토콜에 따라 2개의 분류로 나뉜다.

TCP는 SOCK_STREAM, UDP는 SOCK_DGRAM이다.

각 특징은 프로토콜의 그것을 따른다.

 

TCP: Socket 함수의 구조

TCP 소켓을 통해 통신이 이루어지는 과정

socket()

int socket(int domain, int type, int protocol);

소켓을 생성하는 함수.

type 파라미터를 통해 SOCK_STERAM / SOCK_DGRAM을 정한다.

socket file descriptor(일종의 id) or -1를 리턴한다.

bind()

IP 주소와 포트 번호를 바인딩하는 함수.

int bind(int sockfd, struct sockaddr* myaddr, int addrlen);

myaddr: 서버의 IP 주소와 포트 번호

listen()

해당 소켓으로 request를 받을 수 있도록, 연결에 대한 준비 상태로 만드는 함수

int listen(int sockfd, int backlog);

backlog: request 데이터를 담을 buffer의 사이즈를 결정한다.

accept()

해당 소켓으로 연결 준비를 마치는 함수. 이때부터 연결까지 blocking.

int accept (int sockfd, struct sockaddr* cliaddr, int* addrlen);

cliaddr: 클라이언트의 IP 주소와 포트 번호

 

새로운 소켓 id를 return한다.

이것을 이후 write(), read() 통신에서 사용한다.

connect()

연결을 시작하는 함수.

클라이언트 측에서 요청한다.

close()

연결을 종료하는 함수.

클라이언트와 서버 양측에서 종료해야 연결이 끊긴다.

 

UDP: 소켓 함수의 구조

UDP: 소켓 함수의 구조

상대적으로 단순한 구조를 갖고 있다.

따로 Connection 과정이 없는 것이 특징이다.

 

 

 

 

 

 

참조

컴퓨터네트워크 - 이석복, 한양대학교, 2018-1: http://www.kocw.net/home/search/kemView.do?kemId=1312397

자료: https://gaia.cs.umass.edu/kurose_ross/ppt.php

프로그램(Program)

  • 정의:
    • 프로그램은 저장 매체에 저장되어 있는, 실행 가능한 명령어(instruction)의 집합.
    • 이러한 명령어들은 컴퓨터가 수행해야 할 작업을 정의.
    • 프로그램은 일반적으로 하드 드라이브, SSD, USB 드라이브 등의 비휘발성 메모리에 저장.
  • 특징:
    • 프로그램은 정적인 성격.
    • 즉, 실행되고 있지 않을 때는 단순히 코드의 모음으로 존재.
    • 프로그램은 사용자나 다른 프로그램에 의해 실행될 때까지 변경되지 않고 그 상태를 유지.

프로세스(Process)

  • 정의:
    • 프로세스는 실행 중인 프로그램.
    • 컴퓨터에서 프로그램이 실행되면, 운영체제는 해당 프로그램의 코드와 데이터를 메모리에 로드하고, 이를 프로세스라는 실행 단위로 관리.
    • 프로세스는 운영체제에 의해 할당된 자원(메모리, CPU 시간, 입출력 장치 등)과 함께 실행.
  • 특징:
    • 프로세스는 동적인 성격.
    • 프로세스는 실행 상태, 대기 상태, 종료 상태 등 다양한 상태를 가지며, 시스템 자원을 소비하며 작업을 수행.
    • 각 프로세스는 고유한 프로세스 식별자(PID)를 가지고, 독립된 메모리 영역(주소 공간)에서 실행.

프로그램 VS 프로세스

  • 저장 위치와 형태: 프로그램은 디스크와 같은 저장 매체에 정적으로 저장되어 있지만, 프로세스는 메모리에 동적으로 존재.
  • 실행 상태: 프로그램은 실행되기 전의 코드와 데이터의 집합이지만, 프로세스는 실제로 실행 중인 프로그램을 의미.
  • 자원 사용: 프로세스는 실행되면서 CPU 시간, 메모리 공간, 입출력 장치 등의 시스템 자원을 사용. 반면, 프로그램은 자원을 사용하지 않고 저장 매체에 정적으로 존재.
  • 운영체제의 역할: 운영체제는 프로세스의 생성, 스케줄링, 관리를 담당. 프로그램은 사용자가 실행을 요청할 때 프로세스로 변환.

<TCP/IP 4계층 / OSI 7계층>

TCP/IP 4 계층과 OSI 7 계층의 비교
호스트 간의 통신 과정; OSI 7계층 기준이며, 상위 3개 항목을 묶어보면 TCP/IP 4계층과 같다.

 

해당 강의는 네트워크의 통신 과정을 TCP/IP 4계층을 기준으로 설명한다.

따라서 이 시리즈 역시 TCP/IP 4계층을 중심으로 정리할 예정이다.

 

 

 

<네트워크의 구조>

네트워크 구조

네트워크 구조는 크게 다음의 3가지로 나뉜다.

- 네트워크 엣지 (network edge)

- 네트워크 코어 (network core)

- 접근 네트워크와 물리 매체 (access networks and physical media)

 

네트워크 엣지

네트워크 엣지

 

Connection-oriented service.

엔드 시스템 간의 데이터 교환이 목적.

handshaking(connection): 데이터 교환 전에 준비하는 단계

 

TCP

- transmission control protocol [RFC 793] (전송 제어 프로토콜)

- reliable, in-order byte-stream data transfer: 메시지가 손실되지 않을 것이 보장, 보낸 순서대로 통신

- flow control: receiver의 수용량을 초과하지 않도록 조절

- congestion control: 네트워크 통신 상태를 고려하여 조절

- 인터넷의 프로토콜

- 애플리케이션에서 사용하는 경우: HTTP (WWW), FTP (file transfer), Telnet (remote login), SMTP (email)

 

Connectionless service

엔드 시스템 간의 데이터 교환이 목적 (위와 동일)

 

UDP

- User Datagram Protocol [RFC 768]

- unreliable data transfer

- no flow control

- no congestion control

- 애플리케이션에서 사용하는 경우: streaming media, teleconferencing, lnternet telephony

 

네트워크 엣지의 종류

엔드 시스템(호스트)

  • 애플리케이션 프로그램을 실행한다.
  • 예: 웹, 이메일

클라이언트/서버 모델

  • 클라이언트 호스트가 24시간 켜져있는 서버 측으로 서비스를 요청하고, 응답받는다.
  • 예: 웹 브라우저/서버, 이메일 클라이언트/서버

피어 투 피어 모델

  • 전용 서버 사용을 최소화하고, 사용자 간 직접적인 연결을 중심으로 데이터를 공유한다.
  • 예: Skype, BitTorrent, KaZaA

 

네트워크 코어

네트워크 코어

네트워크의 중심부.

높은 처리 능력으로 여러 네트워크 엣지를 연결하는, 라우터 광대역 전송 링크로 구성되어 있다.

데이터 패킷의 전송과 라우팅이 주로 이루어진다.

데이터를 전송하는 방식은 circuit switching, packet-switching으로 나뉜다.

 

Circuit Switching

Circuit Switching

엔드 시스템 간의 통신이, 하나의 전용 회선을 할당 받아 수행된다.

출발지 시스템에서 목적지 시스템으로 가는 경로가 유일하다.

다른 네트워크와 회선을 공유하지 않는다.

연결이 되고 나면 다음과 같은 특징을 얻는다.

- 빠른 속도를 보장

- 손실 가능성도 적음

- packet의 헤더와 같은 정보가 필요 없음

- 순차적으로 전송

 

그러나 회선을 예약하는데 매우 복잡하여 시간이 오래 걸린다.

점유 중인 회선에서 통신을 하고 있지 않다면, 회선이 낭비된다.

 

Packet Switching

Packet Switching

송신할 데이터를 packet이라는 단위로 쪼개서 전송한다.

인터넷에서 사용하는 데이터 전송 방식.

 

Circuit Switcing과 다르게, 여러 개의 시스템이 하나의 회선을 공유할 수 있으므로, 다중화(Multiflexing)를 통해 회선의 효율을 높인다.

다중화에는 FDM, TDM, STDM과 같은 방식이 있다.

 

Packet 전송이 딜레이 되는 4가지 이유

1. nodal processing

  • 비트 에러를 검사
  • 출력 링크를 결정
  • 해결 방법: 라우터의 성능 개선

2. queueing

  • 출력 링크에서 순서가 올 때까지 대기
  • 라우터의 혼잡도에 따라 대기 시간이 결정
  • 큐의 크기보다 더 많은 데이터가 들어오면, 패킷이 유실된다. (인터넷 환경에서 패킷 유실의 90% 이상이 여기에서 발생)
  • 해결 방법: 어렵다. 사용자가 몰리는 정도에 따라 다르다.

3. Transmission delay

  • 패킷은 데이터(비트)의 집합이므로, 하나의 패킷이 라우터를 완전히 빠져나가는 데에 시간이 걸린다.
  • 첫 번째 비트부터 마지막 비트까지 링크로 올라가, 전송이 시작되는 시간을 의미한다.
  • R = link bandwidth (bps)
  • L = packet length (bits)
  • 총 소요 시간: L/R
  • 해결 방법: 케이블의 대역폭을 확장한다.

4. Propagation delay

  • 마지막 비트까지 링크에 올라가서, 다음 라우터에 도달하는 데에 소요되는 시간
  • 데이터는 빛의 속도로 움직인다.
  • d = 링크의 물리적 길이
  • s = 데이터가 전파되는 속도
  • 총 소요 시간: d/s
  • 해결 방법: 어렵다. 빛의 속도를 더 줄일 수는 없다. 링크의 물리적 길이는 쉽게 개선하기 어렵다.

 

접근 네트워크와 물리 매체

접근 네트워크는 엔드 시스템을 네트워크 코어에 연결하는 역할을 한다.

이러한 네트워크는 사용자의 위치(예: 가정, 기업, 이동 중)에 따라 다양한 형태로 구성된다.

가정: DSL이나 케이블 모뎀을 통한 광대역 접속

기업: 고속 이더넷 접속

이동 중: 무선 접속 네트워크(예: 4G, 5G)

 

물리 매체는 네트워크 상에서 데이터를 전송하는 데 사용되는 물리적인 수단을 말한다.

구리선, 광섬유 케이블, 무선 링크 등이 포함된다.

 

 

 

참고

컴퓨터네트워크 - 이석복, 한양대학교, 2015-2: http://www.kocw.net/home/cview.do?mty=p&kemId=1169634

https://community.fs.com/article/tcpip-vs-osi-whats-the-difference-between-the-two-models.html

호스트

네트워크에 연결된 컴퓨터나 장치.

컴퓨터, 스마트폰, 태블릿, 서버 등 네트워크를 통해 데이터를 송수신하는 모든 장치를 포괄.

네트워크 상에서 고유한 IP 주소를 가지고 있으며, 다른 컴퓨터나 장치와 통신 가능.

(== 네트워크 호스트는 네트워크 주소가 할당된 네트워크 노드이다.)

(== 네트워크 호스트는 정보 리스소, 서비스, 애플리케이션을 네트워크 상의 사용자나 기타 노드에 제공할 수 있다.)

 

모든 서버는 호스트이지만, 모든 호스트가 호스트인 것은 아니다.

네트워크에 연결이 된 모든 장치는 호스트의 자격이 있는 반면, 다른 장치(클라이언트)로부터 연결을 수락하는 호스트만 서버가 될 수 있다.

 

호스팅

서버 컴퓨터의 전체 또는 일정 공간을 이용할 수 있도록 임대해 주는 서비스.

사용자가 직접 서버를 구입하고 운영할 필요 없이 호스팅 업체가 미리 준비해 놓은 서버를 빌려 사용하는 형식.

 

웹호스팅은 웹사이트의 파일과 데이터를 저장하는 서비스.

이를 통해 인터넷에 연결된 누구나 웹사이트에 접근 가능.

웹호스팅 제공 업체는 서버의 유지 관리, 보안, 백업 등을 관리.

 

서버 호스팅은 전체 서버를 임대하여, 사용자의 웹사이트, 애플리케이션, 데이터베이스 등을 호스팅.

고객이 서버의 전체 자원을 독점적으로 사용 가능.

 

클라우드 호스팅은 여러 연결된 서버의 네트워크를 사용하여 웹사이트나 애플리케이션을 호스팅.

필요에 따라 자원을 쉽게 확장하거나 축소할 수 있음.

 

공유 호스팅은 여러 웹사이트가 하나의 서버 자원을 공유하는 가장 기본적인 호스팅 형태.

비용이 저렴하지만, 다른 웹사이트의 트래픽이 많을 경우, 자신의 웹사이트 성능에 영향.

 

가상 사설 서버(VPS) 호스팅은 하나의 물리적 서버를 여러 가상 서버로 분할하여, 각각 독립된 서버 환경을 제공.

공유 호스팅과 전용 서버 호스팅의 중간 형태로, 사용자에게 더 많은 컨트롤과 자원을 제공.

 

로컬

특정 컨텍스트나 범위 내에서 접근이나 사용이 이루어지는 장치나 자원.

'로컬 컴퓨터'는 현재 사용자가 직접 작업하고 있는 컴퓨터.

'로컬 네트워크'는 사용자의 장치가 연결된 직접적인 네트워크.

로컬 장치 ∈ 호스트

 

프로그램

실행 가능한 소프트웨어의 모든 형태.

 

애플리케이션

최종 사용자에게 특정 작업을 수행하는 데 도움을 주는 소프트웨어.

일반적으로 사용자 인터페이스를 포함.

 

클라이언트 / 서버

네트워크 상의 두 가지 주요 컴퓨터 유형.

이들의 관계는 요청(request)과 응답(response)의 패턴을 따름.

 

클라이언트는 서비스나 데이터에 대한 요청을 하는 장치나 프로그램.

예를 들어, 웹 브라우저는 웹 페이지를 요청하는 클라이언트의 일종.

 

서버는 이러한 요청을 받아 처리하고, 필요한 데이터나 서비스를 클라이언트에게 제공하는 장치나 프로그램.

예를 들어, 웹 서버는 웹 페이지를 호스팅하고, 클라이언트의 요청에 응답하여 해당 페이지를 제공.

 

 

 

참고

https://ko.wikipedia.org/wiki/%ED%98%B8%EC%8A%A4%ED%8A%B8_(%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC)

https://eine.tistory.com/entry/64%EB%B9%84%ED%8A%B8-32%EB%B9%84%ED%8A%B8-CPU%EC%99%80-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC

 

64비트 32비트 CPU와 운영체제 에 대하여

제가 학부생때 많이 햇갈리던 개념이 있는데요, 64bit 운영체제, 32bit 운영체제, 64bit CPU, 32bit CPU 과 같은 개념들이었습니다. 제가 알고 있는 개념들로 어느정도 나름 알기쉽게 정리를 해 보도록 하

eine.tistory.com

 

위 글을 참고해서 작성했습니다.

원글의 퀄리티가 훨씬 우수하지만, 정리하는 차원에서 작성했습니다.


 

무슨 뜻임?

워드 사이즈가 32비트 혹은 64비트 라는 뜻이다.

워드 사이즈가 뭔가? 컴퓨터의 데이터 기본 처리 단위이다.

(하나의 기계어 명령어나 연산을 통해, 메모리에서 레지스터에 옮겨 놓거나, ALU로 데이터를 조작할 수 있는, 데이터 단위이다.)

 

레지스터는 뭔가? CPU에 있는 작지만 아주 빠른 기억 장치이다.

ALU는 뭔가? arithmetic and logical unit. CPU에 있는 산술 논리 장치이다.

 

CPU? 운영체제?

시스템, 머신, CPU, 운영체제, ...

용어가 혼용되어서 헷갈린다.

 

보통은 CPU == 시스템 == 머신 == 컴퓨터 이다.

그러니까 32비트 컴퓨터라고 하면, CPU의 레지스터 크기가 32비트인 것을 말한다.

따라서, 해당 컴퓨터는 한 번에 처리할 수 있는 데이터 양이 32비트이다.

이것은 하드웨어의 개념이다.

컴퓨터를 조립할 때, 32비트 CPU를 박아넣었으면, 바꿀 수 없는 것이다.

 

32비트 운영체제도 있다.

이것은 소프트웨어의 개념이다.

따라서 32비트 CPU를 박아넣은 컴퓨터에, 32비트 운영체제 혹은 64비트 운영체제를 설치할 수 있는 것이다.

동작은 장담할 수 없다.

 

출처:&nbsp;아인스트라세의 SW 블로그

 

x86? x64?

컴퓨터 아키텍쳐를 지칭하는 용어이다.

 

x86은 32비트 CPU에 적용되는 아키텍쳐이다.

x32가 아니라 x86인 이유는, 인텔 8086에 적용된 아키텍쳐이기 때문이다. 그냥 외우면 된다.

한 번에 32비트(4바이트)의 데이터를 처리하고, 최대 4GB(≈ 2^32)의 메모리 주소 공간에 직접 접근할 수 있다.

 

x64는 64비트 CPU에 적용되는 아키텍쳐이다.

한 번에 64비트(8바이트)의 데이터를 처리하고, 이론상 2^64까지의 메모리 주소 공간에 직접 접근할 수 있다.

 

 

 

참고

https://ko.wikipedia.org/wiki/%EC%9B%8C%EB%93%9C_(%EC%BB%B4%ED%93%A8%ED%8C%85)

+ Recent posts