반응형

스택 수열

티어 : Silver 3
시간 제한 : 2 초
메모리 제한 : 128 MB
알고리즘 분류 : 자료 구조, 스택

 

문제

스택 (stack)은 기본적인 자료구조 중 하나로, 컴퓨터 프로그램을 작성할 때 자주 이용되는 개념이다. 스택은 자료를 넣는 (push) 입구와 자료를 뽑는 (pop) 입구가 같아 제일 나중에 들어간 자료가 제일 먼저 나오는 (LIFO, Last in First out) 특성을 가지고 있다.

1부터 n까지의 수를 스택에 넣었다가 뽑아 늘어놓음으로써, 하나의 수열을 만들 수 있다. 이때, 스택에 push하는 순서는 반드시 오름차순을 지키도록 한다고 하자. 임의의 수열이 주어졌을 때 스택을 이용해 그 수열을 만들 수 있는지 없는지, 있다면 어떤 순서로 push와 pop 연산을 수행해야 하는지를 알아낼 수 있다. 이를 계산하는 프로그램을 작성하라.

 

입력

첫 줄에 n (1 ≤ n ≤ 100,000)이 주어진다. 둘째 줄부터 n개의 줄에는 수열을 이루는 1이상 n이하의 정수가 하나씩 순서대로 주어진다. 물론 같은 정수가 두 번 나오는 일은 없다.

 

출력

입력된 수열을 만들기 위해 필요한 연산을 한 줄에 한 개씩 출력한다. push연산은 +로, pop 연산은 -로 표현하도록 한다. 불가능한 경우 NO를 출력한다.

 

예제 입출력

 

힌트

1부터 n까지에 수에 대해 차례로 [push, push, push, push, pop, pop, push, push, pop, push, push, pop, pop, pop, pop, pop] 연산을 수행하면 수열 [4, 3, 6, 8, 7, 5, 2, 1]을 얻을 수 있다.

 


Algorithm

Stack 이용
1. 수열의 현재 숫자와 Stack의 마지막 값 비교
-> 수열의 현재 숫자까지 push()
-> 수열의 현재 숫자 == stack[-1]이면 pop()
-> 그외의 상황은 NO 출력

 

Code

import sys
input = sys.stdin.readline

n = int(input())
list_ = []
for _ in range(n):
    list_.append(int(input()))
    
pop_dict = {}
pop_dict = [False for _ in range(n+1)]

stack = []
flag = False # 불가능한 경우 True
answer = []
i = 0
num = 1
while i < len(list_):
    # stack 비어있으면 현재 값 append
    if not stack:
        stack.append(num)
        
    for j in range(num, list_[i] + 1):
        # pop dict에 없는 원소만 추가
        if not pop_dict[j]:
            stack.append(j)
            answer.append('+')
            num += 1

    if list_[i] == stack[-1]:
        pop_dict[stack[-1]] = True
        stack.pop()
        answer.append('-')
        i += 1
    else:
        flag = True
        break

# 출력
if flag:
    print('NO')
else:
    for i in answer:
        print(i)

메모리: 37084 KB
시간: 280 ms

반응형
반응형

OSI 7계층이란?

1. 개요

1.1. 두 대의 Computer가 통신하려면?

: 모든 File과 Program은 0과 1의 나열이므로 0과 1만 주고받을 수 있다.

 

두 대의 Computer를 전선 1대로 연결하면?

  • 1을 보낼 때는 +5V의 전기를 전선을 통해 흘려보낸다.
  • 0을 보낼 때는 -5V의 전기를 전선을 통해 흘려보낸다.

하지만 실제로는 잘 동작하지 않는다.

 

시간 당 전압을 나타내는 함수 (전자기파를 표현하는 함수)

주파수 = 1초당 진동한 횟수 [단위: 헤르츠(Hz)]

☞ 1초에 2번 진동했으므로 2Hz

 

불규칙한 전자기파의 경우 주파수 값이 하나로 고정되지 않는다.

☞ 파동이 진행되는 동안 주파수의 값이 계속 변한다.

전자기파 주파수 최솟값 = 1 Hz, 최댓값 = 10 Hz라고 가정했을 때 전선(전선 뿐 아니라 모든 매질)은 모든 주파수를 통과시킬 수 없다.

e.g., 어떤 전선이 5~8 Hz의 전자기파만 통과시킬 수 있다고 가정하면 위의 전자기파를 흘려보냈을 때 5~8 Hz인 신호만 통과해 엉뚱한 Data가 도착할 것이다.

 

1.2. Digital 신호의 전송

수직선과 수평선이 있는 전자기파는 항상 0 ~ 무한대 Hz의 주파수 범위를 가지며, 이런 전기 신호를 통과시킬 수 있는 전선을 없다.

그렇다면 어떻게 전송해야할까?

Digital 신호를 Analog 신호로 바꿔서 전송해야한다.

2. Physical Layer

: 물리적으로 연결된 두 대의 Computer가 0과 1의 나열을 주고받을 수 있게 해주는 Module

  • Encoding : 0과 1의 나열(Digital 신호)을 Analog 신호로 바꾸어 전선으로 흘려보내는 것
  • Decoding : 들어온 Analog 신호를 0과 1의 나열(Digital 신호)로 해석하는 것

2.1. Encoding과 Decoding

 

2.2. 사용 예

: Physical Layer는 대부분 HardWare적으로 구성되어있다.

e.g., PHY 칩

 

참고

https://youtu.be/1pfTxp25MA8

 

반응형

'CS기술 지식 > 네트워크' 카테고리의 다른 글

[네트워크] OSI 7계층이란?  (0) 2022.03.20
[네트워크] RESTful이란?  (0) 2022.03.19
[네트워크] TCP vs UDP  (0) 2022.03.09
[네트워크] GET, POST 방식  (0) 2022.03.06
반응형

균형잡힌 세상

티어 : Silver 4
시간 제한 : 1 초
메모리 제한 : 128 MB
알고리즘 분류 : 자료 구조, 문자열, 스택

 

문제

세계는 균형이 잘 잡혀있어야 한다. 양과 음, 빛과 어둠 그리고 왼쪽 괄호와 오른쪽 괄호처럼 말이다.

정민이의 임무는 어떤 문자열이 주어졌을 때, 괄호들의 균형이 잘 맞춰져 있는지 판단하는 프로그램을 짜는 것이다.

문자열에 포함되는 괄호는 소괄호("()") 와 대괄호("[]")로 2종류이고, 문자열이 균형을 이루는 조건은 아래와 같다.

  • 모든 왼쪽 소괄호("(")는 오른쪽 소괄호(")")와만 짝을 이뤄야 한다.
  • 모든 왼쪽 대괄호("[")는 오른쪽 대괄호("]")와만 짝을 이뤄야 한다.
  • 모든 오른쪽 괄호들은 자신과 짝을 이룰 수 있는 왼쪽 괄호가 존재한다.
  • 모든 괄호들의 짝은 1:1 매칭만 가능하다. 즉, 괄호 하나가 둘 이상의 괄호와 짝지어지지 않는다.
  • 짝을 이루는 두 괄호가 있을 때, 그 사이에 있는 문자열도 균형이 잡혀야 한다.

정민이를 도와 문자열이 주어졌을 때 균형잡힌 문자열인지 아닌지를 판단해보자.

 

입력

하나 또는 여러줄에 걸쳐서 문자열이 주어진다. 각 문자열은 영문 알파벳, 공백, 소괄호("( )") 대괄호("[ ]")등으로 이루어져 있으며, 길이는 100글자보다 작거나 같다.

입력의 종료조건으로 맨 마지막에 점 하나(".")가 들어온다.

 

출력

각 줄마다 해당 문자열이 균형을 이루고 있으면 "yes"를, 아니면 "no"를 출력한다.

 

예제 입출력

 

힌트

7번째의 " ."와 같이 괄호가 하나도 없는 경우도 균형잡힌 문자열로 간주할 수 있다.

 


Algorithm

Stack 이용
1. Stack을 생성
2. 문자가 ( 이거나 [ 인 경우 Stack에 추가, ) 이거나 ] 인 경우 stack의 마지막 원소가 ( 이거나 [ 인지 확인하고 맞으면 POP()
3. pop할 때 짝이 맞지 않으면 no
4. 스택에 원소가 남아있으면 no

 

Code

import sys
input = sys.stdin.readline

while True:
    words = input().rstrip()
    # 입력이 .이면 종료
    if words == '.':
        break
    
    stack = []
    flag = False # 균형이 맞으면 False, 균형이 맞지 않으면 True
    for word in words:
        # 문자가 (인 경우 소괄호 stack에 추가
        if word == '(':
            stack.append(word)
        elif word == ')': # 문자가 )인 경우 소괄호 stack에서 pop
            # stack의 마지막 원소와 짝이 맞으면 pop
            if stack and stack[-1] == '(': 
                stack.pop()
            # stack 비어있으면 no 출력
            else:
                flag = True
                break
                
        elif word == '[': # 문자가 [인 경우 대괄호 stack에 추가
            stack.append(word)
        elif word == ']': # 문자가 ]인 경우 대괄호 stack에서 pop
            # stack의 마지막 원소와 짝이 맞으면 pop
            if stack and stack[-1] == '[':
                stack.pop()
            # 대괄호 stack 비어있으면 no 출력
            else:
                flag = True
                break

    # flag가 True이거나 소괄호 stack과 대괄호 stack 중 비어있지 않은 리스트가 있으면 균형을 이루지 않는 문자열
    if flag or stack:
        print('no')
    # 소괄호 stack과 대괄호 stack에 아무것도 없으면 균형을 이루는 문자열
    elif not stack:
        print('yes')

메모리: 30864 KB
시간: 112 ms

반응형
반응형

1. OSI 7 Layer

: 국제 표준기구 ISO가 발표한 Network Model

 

1.1. Physical Layer(물리 계층)

: Bit 신호들을 전기 신호로 변환해 전송하는 Layer

물리 계층 자세한 설명 보러 가기

 

1.2. Data Link Layer(데이터 링크 계층)

: 동일한 Network 내에서의 전송을 담당하는 Layer

☞ Network 계층은 서로 다른 두 Network 간의 전송을 담당한다는 점에서 차이가 있다.

☞ 오류 제어, 흐름 제어를 제공한다.

Data Link Layer의 오류 제어
: 오류 Frame을 버린다.
☞ 오류 Data를 재전송함으로써 오류를 복구하는 Transport Layer의 오류 제어와 차이가 있다.

 

1.3. Network Layer(네트워크 계층)

: IP, 라우터 장비가 속한 계층으로 Data의 전송을 담당하는 Layer

☞ host에 IP 번호를 부여하고 도착지 IP까지의 최적의 경로를 찾는다.(Routing)

 

1.4. Transport Layer(전송 계층)

: 서로 다른 두 네트워크 간의 전송을 담당하는 Layer

☞ Segmentation, 흐름 제어, 오류 제어 등을 제공한다.

Segmentation
더보기

: 상위 계층의 Data를 받아 Segment라는 단위로 나누는 것

Computer A에서 Computer B로 100MB의 비디오를 전송하는 경우
Segment 과정이 없다면 사용자는 100MB의 비디오가 모두 로딩된 후 비디오를 볼 수 있다.
Segment 과정이 있다면 Segment라는 작은 단위로 나뉘어 비디오 일부분을 미리 볼 수 있다.

연결이 중간에 끊기는 경우 Segmentation을 하지 않으면 큰 Data가 날아가 손실률이 크다.

흐름 제어
더보기

: Data 전송량이 서로 다른 기기에서 전송량을 맞추는 것

 

Computer A : 50Mbps 처리

Computer B : 10Mbps 처리

Computer A가 Computer B에게 50Mbps씩 전송한다면 Computer B는 Computer A에게 전송량 낮춰달라고 요구

Computer A가 Computer B에게 5Mbps씩 전송한다면 Computer B는 Computer A에게 전송량 높여달라고 요구

 

전송량 변경을 요구하는 방법으로는 Stop&Wait, Sliding Window 등이 있다.

오류 제어
더보기

: 보낸 Data가 정확히 오류(손실)가 없는지 확인하고 오류가 있다면 해당 Data를 재전송

FEC, BEC, ARQ 등의 방식이 있다.

 

1.5. Session Layer(세션 계층)

: Session을 열고 닫는 기능 및 Session 복구를 지원하는 Mechanism의 Layer

Session 복구
Check Point를 통해 동기화한다.

Computer A에서 Computer B로 100MB의 Data를 전송하는 경우 (Check Point = 5MB)
48MB의 Data를 전송하는 도중에 연결이 끊기면 Check Point 덕분에 45MB부터 Session 재개가 가능하다.

 

1.6. Presentation Layer(표현 계층)

: Data의 변환, 압축, 암호화 등을 수행하는 Layer

더보기

Data의 변환이 왜 필요할까?

서로 다른 통신 기기 간 다른 Encoding을 사용할 수 있기 때문에 Data 변환이 필요하다.

 

1.7. Application Layer(응용 계층)

: 응용 프로세스를 직접 사용해 직접적인 응용 서비스를 수행하는 Layer

☞ HTTP, FTP, SMTP, Telnet 등과 같은 Protocol이 포함되어있다.

 

1.8. 전송 과정

 

2. TCP/IP Model

: OSI Model의 Presentation Layer, Session Layer가 Application Layer로 통합된 형태실제로 사용하는 Model

☞ OSI Model은 단지 Network를 묘사하기 위한 Model이다.

 

2.1. 전송 과정

 

① Transport Layer에서 TCP/UDP의 정보, Source Port, Destination Port 등의 정보를 Header에 넣어 Data 뒤에 붙이고 캡슐화한다.

 

② Network Layer에서 Source IP, Destination IP 등의 정보를 Header에 넣어 Segment 뒤에 붙이고 캡슐화한다.

 

③ Data Link Layer에서 Sorce MAC Address, 가장 가까운 Router의 MAC Address에 대한 정보를 Header에 넣어 Packet 뒤에 붙이고 캡슐화한다. 이 때 오류 제어를 위한 정보가 담겨있는 Trailer라는 정보도 함게 붙는다.

왜 Destination MAC Address가 아닌 Router의 MAC Address일까?
더보기

A는 처음에 B의 MAC Address를 알 수 없다. DHCP, ARP 등을 통해 Router의 IP를 MAC Address로 변환하고 Router에 대한 Destination MAC Address를 만들어 Header에 넣어준다.

 

④ Physical Layer에서 Frame을 전기 신호로 바꿔 Data를 전송한다.

 

⑤ Computer A에서 Switch로 Data를 전송한다.

☞ Decaptulation을 통해 L2 Header에 대한 정보를 살펴보고 Destination(Router) MAC Address를 확인한다.

 

⑥ Switch에서 Router로 Data를 전송한다.

☞ Decaptulation을 통해 L3 Header에 대한 정보를 살펴보고 Destination(Computer B) IP Address를 확인한다.

 

⑦ Router에서 Routing Table을 통해 Computer B의 MAC Address를 확인한다.

☞ L2 Header의 Destination MAC Address를 Update한다.

 

⑧ Router에서 Switch로 Data를 전송한다.

☞ Decaptulation을 통해 L2 Header에 대한 정보를 살펴보고 Destination(Computer B) MAC Address를 확인한다.

 

⑨ Switch에서 Cam Table을 통해 Computer B로 Data를 전송한다.

 

참고

https://youtu.be/Fl_PSiIwtEo

반응형

'CS기술 지식 > 네트워크' 카테고리의 다른 글

[네트워크] Physical Layer(물리 계층)란?  (0) 2022.03.23
[네트워크] RESTful이란?  (0) 2022.03.19
[네트워크] TCP vs UDP  (0) 2022.03.09
[네트워크] GET, POST 방식  (0) 2022.03.06
반응형

최소비용 구하기

티어 : Gold 5
시간 제한 : 0.5 초
메모리 제한 : 128 MB
알고리즘 분류 : 그래프 이론, 다익스트라

 

문제

N개의 도시가 있다. 그리고 한 도시에서 출발하여 다른 도시에 도착하는 M개의 버스가 있다. 우리는 A번째 도시에서 B번째 도시까지 가는데 드는 버스 비용을 최소화 시키려고 한다. A번째 도시에서 B번째 도시까지 가는데 드는 최소비용을 출력하여라. 도시의 번호는 1부터 N까지이다.

 

입력

첫째 줄에 도시의 개수 N(1 ≤ N ≤ 1,000)이 주어지고 둘째 줄에는 버스의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 그리고 셋째 줄부터 M+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가 주어진다. 그리고 그 다음에는 도착지의 도시 번호가 주어지고 또 그 버스 비용이 주어진다. 버스 비용은 0보다 크거나 같고, 100,000보다 작은 정수이다.

그리고 M+3째 줄에는 우리가 구하고자 하는 구간 출발점의 도시번호와 도착점의 도시번호가 주어진다. 출발점에서 도착점을 갈 수 있는 경우만 입력으로 주어진다.

 

출력

첫째 줄에 출발 도시에서 도착 도시까지 가는데 드는 최소 비용을 출력한다.

 

예제 입출력


Algorithm

dijkstra 알고리즘 - 힙
1. 입력으로 graph 구성
2. 다익스트라 알고리즘을 이용해 최단 경로 구하기

 

Code

import sys
import heapq

def dijkstra(start):
    queue = []
    
    # 첫 번째 위치 큐에 추가
    heapq.heappush(queue, (0, start))
    distance[start] = 0
    
    while queue:
        # queue에서 꺼내기
        dist, now = heapq.heappop(queue)
        
        # 이미 방문한 적 있는 도시이면 무시
        if distance[now] < dist:
            continue
        
        # 인접 노드 확인
        for next in graph[now]:
            # cost 계산 : 현재 node의 누적 거리 + 현재 노드에서 다음 노드까지의 거리
            cost = dist + next[0]
            # cost가 distance에 저장된 값보다 작으면 갱신
            if cost < distance[next[1]]:
                distance[next[1]] = cost
                heapq.heappush(queue, (cost, next[1]))
                
input = sys.stdin.readline
INF = 1e9

# 입력
N = int(input())
M = int(input())
graph = [[] for _ in range(N+1)]
distance = [INF] * (N+1)
for _ in range(M):
    start, end, cost = map(int, input().split())
    graph[start].append((cost, end))
start, end = map(int, input().split())

dijkstra(start)
print(distance[end])

메모리: 56088 KB
시간: 352 ms

반응형
반응형

최단경로

티어 : Gold 5
시간 제한 : 1 초
메모리 제한 : 256 MB
알고리즘 분류 : 그래프 이론, 다익스트라

 

문제

방향그래프가 주어지면 주어진 시작점에서 다른 모든 정점으로의 최단 경로를 구하는 프로그램을 작성하시오. 단, 모든 간선의 가중치는 10 이하의 자연수이다.

 

입력

첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1 ≤ K ≤ V)가 주어진다. 셋째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 뜻이다. u와 v는 서로 다르며 w는 10 이하의 자연수이다. 서로 다른 두 정점 사이에 여러 개의 간선이 존재할 수도 있음에 유의한다.

 

출력

첫째 줄부터 V개의 줄에 걸쳐, i번째 줄에 i번 정점으로의 최단 경로의 경로값을 출력한다. 시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다.

 

예제 입출력


Algorithm

dijkstra 알고리즘 - 힙
1. 입력으로 graph 구성
2. 다익스트라 알고리즘을 이용해 최단 경로 구하기

 

Code

import sys
import heapq

def dijkstra(start):
    queue = []
    # 첫 번째 노드 큐에 추가
    heapq.heappush(queue, (0, start))
    distance[start] = 0
    
    while queue:
        # 큐에서 꺼내기
        dist, now = heapq.heappop(queue)
        
        # 이미 방문한 노드는 무시
        if distance[now] < dist:
            continue
        
        # 인접 노드 확인
        for next in graph[now]:
            # cost 계산 = 현재 node의 거리 + 다음 node까지의 거리
            cost = dist + next[1]
            if cost < distance[next[0]]:
                distance[next[0]] = cost
                # 큐에 추가
                heapq.heappush(queue, (cost, next[0]))

INF = int(1e9)
input = sys.stdin.readline

V, E = map(int, input().split())
start = int(input())
graph = [[] for _ in range(V+1)]
distance = [INF] * (V+1)
for _ in range(E):
    u, v, w = map(int, input().split())
    graph[u].append((v, w))

dijkstra(start)
for i in range(1, V+1):
    if distance[i] == INF:
        print('INF')
    else:
        print(distance[i])

메모리: 66936 KB
시간: 700 ms

반응형
반응형

지름길

티어 : Silver 1
시간 제한 : 2 초
메모리 제한 : 128 MB
알고리즘 분류 : 다이나믹 프로그래밍, 그래프 이론, 다익스트라

 

문제

매일 아침, 세준이는 학교에 가기 위해서 차를 타고 D킬로미터 길이의 고속도로를 지난다. 이 고속도로는 심각하게 커브가 많아서 정말 운전하기도 힘들다. 어느 날, 세준이는 이 고속도로에 지름길이 존재한다는 것을 알게 되었다. 모든 지름길은 일방통행이고, 고속도로를 역주행할 수는 없다.

세준이가 운전해야 하는 거리의 최솟값을 출력하시오.

 

입력

첫째 줄에 지름길의 개수 N과 고속도로의 길이 D가 주어진다. N은 12 이하인 양의 정수이고, D는 10,000보다 작거나 같은 자연수이다. 다음 N개의 줄에 지름길의 시작 위치, 도착 위치, 지름길의 길이가 주어진다. 모든 위치와 길이는 10,000보다 작거나 같은 음이 아닌 정수이다. 지름길의 시작 위치는 도착 위치보다 작다.

 

출력

세준이가 운전해야하는 거리의 최솟값을 출력하시오.

 

예제 입출력


Algorithm

dijkstra 알고리즘 - 힙
1. 지름길을 입력 받아 graph 생성
    ➝ 도착 지점이 고속도로의 길이보다 큰 경우 graph에 추가하지 않음
2. 지름길이 아닌 길도 graph에 추가
    ➝ 중간에 끊겨있는 길도 같이 추가
3. D 위치의 최단 거리 출력

 

Code

import sys
import heapq

INF = int(1e9)
input = sys.stdin.readline

def dijkstra(start):
    queue = []
    
    # 첫 번째 칸으로 가는 최단 경로 0으로 설정
    heapq.heappush(queue, (start, 0))
    distance[start] = 0
    
    while queue:
        
        # 큐에서 꺼내기
        dist, now = heapq.heappop(queue)
        
        # 방문한 노드라면 무시
        if distance[now] < dist:
            continue
        
        # 인접 노드 확인
        for next in graph[now]:
            cost = dist + next[1]
            
            # cost가 인접노드까지 가는 데 최소 거리라면 갱신하고 큐에 추가
            if cost < distance[next[0]]:
                distance[next[0]] = cost
                heapq.heappush(queue, (cost, next[0]))
    

N, D = map(int, input().split())
graph = [[] for _ in range(D+1)]
distance = [INF] * (D+1)
for _ in range(N):
    start, end, length = map(int, input().split())
    # 도착 지점이 고속도로의 길이보다 큰 경우 graph에 추가하지 않음
    if end > D:
        continue
    graph[start].append((end, length))

    # 지름길이 아닌 길도 graph에 추가
    if (end, end - start) not in graph[start]:
        graph[start].append((end, end - start))
        
for i in range(D):
    # graph의 현재 INDEX에 다음 칸 까지의 거리 추가
    graph[i].append((i+1, 1))

dijkstra(0)
print(distance[-1])

메모리: 32928 KB
시간: 72 ms

반응형
반응형

1. REST(REpresentational State Transfer)

: Network Resource(자원)를 정의하고 처리하는 방법을 설명하는 일련의 원칙을 기반으로 하는 Architecture Style

☞ Client와 Server가 Data를 주고받는 방식에 대해 정리한 원칙이 있고 그 원칙을 기반으로하는 Architecture Style을 REST라고 한다.

☞ HTTP의 장점을 최대한 활용할 수 있는 Architecture로 REST의 원칙은 HTTP를 잘 활용하기 위한 원칙으로 볼 수 있다.

 

REpresentational(표현)  State(상태)  Transfer(전달)

자원(Resource)의 표현을 이용해 상태(정보) 전달

                 HTTP URI                                        HTTP Method

 

2. RESTful

: REST라는 Architecture Style의 제약조건을 모두 만족하는 System은 RESTful하다고 말할 수 있다.

 

3. URI 구조

: Collection과 Document의 조합으로 구성되며 동사를 사용하지 않는다.

  • Collection : Table 전체
    ☞ 일반적으로 객체들의 집합이므로 복수 명사 사용
  • Document : 행 하나 (객체)
    ☞ 집합 중 객체를 구분할 수 있는 값
더보기

/cources/front

/cources/back

/cources/front/crews/jjyoung

 

 

4. HTTP Method

: REST API에서 Resource(자원)에 대한 행위를 표현하기 위해 사용된다.

CRUD(데이터 처리 방법) HTTP Method
Create POST
Read GET
Update PUT / PATCH
Delete DELETE

 

4.1. Read(조회) - GET

<!-- 해당 Collection에 대한 전체 정보 -->
GET /cources
<!-- Document의 정보 조회 -->
GET /cources/front

 

4.2. Create(생성) - POST

<!-- backend coach 집합에 jjyoung라는 닉네임을 가진 코치 개체 생성 -->

POST /courses/back/coaches
<!-- body에 생성할 내용을 담음 -->
body {nickname: jjyoung}

 

4.3. Update(수정) - PUT

<!-- frontend coach 집합 중 첫 번째 코치 닉네임을 jjyoung로 수정 -->

PUT /courses/front/coaches
<!-- 수정할 내용을 body에 담음 -->
body {id: 1, nickname: jjyoung}

 

4.4. Delete(삭제) - DELETE

<!-- frontend crew 집합 중 jjyoung 삭제 -->
DELETE /courses/front/crews/jjyoung

 

5. REST Arichtecture의 제약 조건

5.1. Client - Server

: Client가 Server에게 Request를 보내고 Server가 Client에게 Response를 보내는 구조로 Server와 Client의 역할이 분리되어있다.

  • Server : API 제공과 제공된 API를 이용해 비즈니스 로직을 처리하거나 저장
  • Client : 사용자 인증이나 컨텍스트(세션, 로그인 정보) 등을 관리

 

5.2. Stateless(무상태성)

: Client와 Server의 통신에는 상태가 없어야하며 모든 요청은 필요한 정보를 담고 있어야 한다.

☞ Client가 두 가지 요청을 보냈을 때 두 번째 요청 시 Server는 Client의 첫 번째 요청의 내용을 모르므로 두 번째 요청시에도 필요한 모든 정보를 담고 있어야 한다.

 

5.3. Cache

: 일반적인 서비스에서 60 ~ 80% 가량의 Transaction이 Select와 같은 조회성 트랜잭션이며 GET은 얼마든지 호출해도 매번 같은 결과를 만들어내므로(Idempotent) 캐싱이 가능하다.

 

5.4. Uniform Interface

 

5.4.1. Identification of Resources
: 자원은 유일하게 식별 가능해야하며 Resource가 하나 이상의 유일한 특정 주소인 URI로 식별되어야 한다.
☞ 아직 POST Method로만 Request를 보내기 때문에 URI나 Request Body로 어떤 동작을 할 지 알려줘야 한다.

 

5.4.2. Manipulation of Resources through Representation
: HTTP Method로 표현(CRUD)을 담아야 한다.
☞ 안전한 Operation과 안전하지 않은 Operation 간의 강한 분리를 제공해야 한다.

HTTP Method Idempotent Safe
GET O O
HEAD O O
PUT O X
POST X X
DELETE O X
PATCH X X
더보기

Idempotent : 같은 요청을 여러 번 하더라도 그 결과가 동일함
Safe : 자원을 변경하지 않음

 

5.4.3. Self-Descriptive Messages
: Message를 스스로를 설명해야한다.

☞ 요청 작업 완료 및 응답 이해가 가능하도록 충분한 정보들을 HTTP Method, Status Code, Header 등을 활용해 전달해야 한다.

더보기

HTTP Status Code

: 발생한 에러의 종류를 Communication하기 위해 상태 코드 사용

Level 200 (Success) Level 400 Level 500
200 : OK 400 : Bad Request 500: Internal Server Error
201 : Created 401 : Unauthorized 501: Not Implemented
203 : Non - Autheoritative 403 : Forbidden 502 : Bad Gateway
204 : No Content 404 : Not Found 503 : Service Unavailable
  409 : Conflict 504 : Gateway Timeout
    599 : Network Timeout

 

5.4.4. Hypermedia As the Engine Of Application State(HATEOAS)

: Hyperlink를 통해 Application의 상태가 전이되어야 한다.

☞ HTTP Response에 다음 Action이나 관계되는 Resource에 대한 HTTP Link를 함께 Return한다.

☞ 장점 : 요청 URI가 변경되더라도 Client는 Server에서 동적으로 생성된 URI를 사용함으로써 Client는 URI 수정에 따른 코드를 변경하지 않아도 된다.

 

5.5. Layered System

: 계층으로 구성이 가능해야 한다.

☞ Server는 다중 계층으로 구성될 수 있으나 Client 입장에서는 계층에 상관 없이 Server만 호출하면 된다.

e.g., 순수 비즈니스 로직을 수행하는 Server, 사용자 인증, 암호화(SSL), 로드 밸런싱 등을 하는 계층을 추가하거나 PROXY, 게이트웨이 같은 중간 매체 사용 가능

 

5.6. Code-On-Demand(Option)

: Server가 Network를 통해 Client에 Program을 전달하면 그 Program이 Client에서 실행될 수 있어야 한다.

e.g., JavaScript를 사용해 Server에서 Program 전달하면 Client에서 동적으로 실행 가능하다.

 

6. Richardson Maturity Model

Glory of REST
Level 3 : Hypermedia Controls
Level 2 : HTTP Verbs
Level 1 : Resources
Level 0 : The Swamp of POX

 

6.1. Level 0 : The Swamp of POX

: POX(Plain Old XML)를 주고받는 단순한 RPC Style System

☞ HTTP를 RPC 기반의 원격 통신을 위한 터널링 Mechanism으로 사용된다.

충족된 제약 조건 : Server-Client, Stateless, Layered System, Manipulation of Resources through Representation

RPC(Remote Procedure Call, 원격 프로시저 호출)
: 별도의 원격 제어를 위한 코딩 없이 다른 주소 공간에서 함수나 프로시저를 실행할 수 있게 하는 프로세스 간 통신 기술 (= Client가 Server에 있는 Program을 실행하기 위해 사용하는 통신 기술)
☞ RPC를 이용하면 개발자는 실행 Program이 로컬 위치에 있든 원격 위치에 있든 동일한 코드를 이용할 수 있다.
☞ Client가 Server에게 Message를 보내 Program을 실행시키고 Server에서는 그 Program의 결과를 Client에게 전송

예제

더보기

1. Client - 2022년 3월 19일 회의실 1의 예약되지 않은 시간대를 알아내는 요청

POST /appointmentService HTTP/1.1
[various other headers]

<openSlotRequest date = "2022-03-19", mittingroom = "1"/>

 

2. Server - 2022년 3월 19일 회의실 1의 예약되지 않은 시간대를 알려주는 응답

HTTP/1.1 200 OK
[various other headers]

<openSlotList>
    <slot start = "1600", end = "1700">
        <meetingroom = "1"/>
    </slot>
    
    <slot start = "1900", end = "2100">
        <meetingroom = "1"/>
    </slot>
</openSlotList>

 

3. Client - 19시 ~ 21시 회의실을 예약하는 요청

POST /appointmentService HTTP/1.1
[various other headers]

<appointmentRequest>
    <slot meetingroom = "1", start = "1900", end = "2100"/>
    <bookingperson = "졍"/>
</appointmentRequest>

 

4.1. Server - 예약 성공

HTTP/1.1 200 OK
[various other headers]

<appointment>
    <slot meeingroom = "1", start = "1900", end = "2100"/>
    <bookingperson = "졍"/>
</appointment>

 

4.2. Server - 예약 실패

HTTP/1.1 200 OK
[various other headers]

<appointmentRequestFailure>
    <slot meetingroom = "1", start = "1900", end = "2100"/>
    <bookingperson = "졍"/>
    <reason> Slot Not Available </reson>
</appointmentRequestFailure>

 

6.2. Level 1 : Resources

: Resource를 도입해 모든 요청을 단일 서비스 End Point로 보내는 것이 아니라 개별 Resource(meetingroom, slot 등)와 통신한다.

☞ Level 0에서는 모든 요청이 appointmentService라는 단일 서비스 End Point로 보내졌다.

충족된 제약 조건 : Identification of Resources

예제

더보기

1. Client - 2022년 3월 19일 회의실 1의 예약되지 않은 시간대를 알아내는 요청

POST /meetingrooms/1 HTTP/1.1
[various other headers]

<openSlotRequest date = "2022-03-19"/>

 

2. Server - 2022년 3월 19일 회의실 1의 예약되지 않은 시간대를 알려주는 응답

HTTP/1.1 200 OK
[various other headers]

<openSlotList>
    <!-- Slot id를 이용해 resource 만듦 -->
    <slot id = "1234", meetingroom = "1", start = "1600", end = "1700"/>
    <slot id = "5678", meetingroom = "1", start = "1900", end = "2100"/>
</openSlotList>

 

3. Client - 19시 ~ 21시에 회의실 1을 예약하는 요청

POST /slots/5678 HTTP/1.1
[various other headers]

<appointmentRequest>
    <bookingperson = "졍"/>
</appointmentRequest>

 

4. Server - 예약 완료

HTTP/1.1 200 OK
[various other headers]

<appointment>
    <slot id = "5678", meetingroom = "1", start = "1900", end = "2100"/>
    <bookingperson = "졍"/>
</appointment>

 

6.3. Level 2 : HTTP Method

: HTTP Method를 사용할 수 있으며 Level 0, 1에 비해 HTTP의 사용법에 가능한 가깝게 사용한다.

충족된 제약 조건 : Manipulation of Resources through Representation, Self-Descriptive Messages, Cache

예제

더보기

1. Client - 2022년 3월 19일 회의실 1의 예약되지 않은 시간대를 알아내는 요청

 GET /meetingrooms/1/slots?date=20220319&status=open HTTP/1.1
 HOST : https://techcourse.woowahan.com/

 

2. Server - 2022년 3월 19일 회의실 1의 예약되지 않은 시간대를 알려주는 응답

HTTP/1.1 200 OK
[various other headers]

<openSlotList>
    <slot id = "1234", meetingroom = "1", start = "1600", end = "1700"/>
    <slot id = "5678", meetingroom = "1", start = "1900", end = "2100"/>
</openSlotList>

 

3. Client - 19시 ~ 21시에 회의실 1을 예약하는 요청

POST /slots/5678 HTTP/1.1
[various other headers]

<appointmentRequest>
    <bookingperson = "졍"/>
</appointmentRequest>

 

4.1. Server - 예약 완료

HTTP/1.1 201 Created
Location : slots/5678/appointment
[various other headers]

<appointment>
    <slot id = "5678", meetingroom = "1", start = "1900", end = "2100"/>
    <bookingperson = "졍"/>
</appointment>

 

4.2. Server - 예약 실패

HTTP/1.1 409 Conflict
[various other headers]

<openSlotList>
    <slot id = "5678", meetingroom = "1", start = "1900", end = "2100"/>
    <bookingperson = "졍"/>
</openSlotList>

 

6.4. Level 3 : Hypermdedia Controls

: HATEOAS를 도입해 Client가 Server로부터 어떤 요청을 할 때, 요청에 필요한 URI를 응답에 포함시켜 반환한다.

☞ Client가 전적으로 Server와 동적인 상호작용이 가능하다.

충족된 제약 조건 : HATEOAS

예제

더보기

1. Client - 2022년 3월 19일 회의실 1의 예약되지 않은 시간대를 알아내는 요청

 GET /meetingrooms/1/slots?date=20220319&status=open HTTP/1.1
 HOST : https://techcourse.woowahan.com/

 

2. Server - 2022년 3월 19일 회의실 1의 예약되지 않은 시간대를 알려주는 응답

HTTP/1.1 200 OK
[various othe headers]

<openSlotList>
    <slot id = "1234", meetingroom = "1", start = "1600", end = "1700">
        <link rel = "linkrels/slot/book", uri = "slots/1234"/>
    </slot>
    
    <slot id = "5678", meetingroom = "1", start = "1900", end = "2100">
        <link rel = "linkrels/slot/book", uri = "slots/5678"/>
    </slot>
</openSlotList>

 

3. Client - 19시 ~ 21시에 회의실 1을 예약하는 요청

POST /slots/5678 HTTP/1.1
[various other headers]

<appointmentRequest>
    <bookingperson = "졍"/>
</appointmentRequest>

 

4. Server - 예약 완료

HTTP/1.1 201 Created
Location : https://techcourse.woowahan.com/slots/5678/appointment
[various other heads]

<appointment>
    <slot id = "5678", meetingroom = "1", start = "1900", end = "2100"/>
    <bookingperson = "졍"/>
    <link rel = "/linkrels/appointment/cancel", uri = "/slots/5678/appointment"/>
    <link rel = "self", uri = /slots/5678/appointment"/>
    ...
    <link rel = "/linkrels/help", uri = "/help/appointment"/>
</appointment>

 

7. 결론

  • REST는 Software Architecture의 한 형식이다.
  • REST Architecture는 여러 개의 제약 조건을 가지고 있다.
  • REST Architecture의 제약 조건을 모두 만족하는 System을 RESTful한 System이라고 한다.
  • HTTP Method, Status Code를 용도에 맞게 써야하고, HTTP HeaderLink를 신경쓰면 RESTful한 Service를 설계할 수 있다.

 

참고

https://youtu.be/xY7cpMuWh4w

https://youtu.be/NODVCBmyaXs

반응형

'CS기술 지식 > 네트워크' 카테고리의 다른 글

[네트워크] Physical Layer(물리 계층)란?  (0) 2022.03.23
[네트워크] OSI 7계층이란?  (0) 2022.03.20
[네트워크] TCP vs UDP  (0) 2022.03.09
[네트워크] GET, POST 방식  (0) 2022.03.06

+ Recent posts