동시성 문제를 해결하기 위해 cv, lock을 추가했죠. 이제는 다익스트리아가 도입한 세마포어에 대해 알아봅시다. 세마포어의 핵심은 다음과 같습니다 원자적 정수 변수: 세마포어 값은 중단 없이 한 번에 변경되어야 합니다. 카운팅 기능: 0 또는 1만 갖는 바이너리 세마포어(뮤텍스와 유사)와 0 이상의 정수 값을 가지는 카운팅 세마포어가 있습니다. 동기화: 자원이 없으면 프로세스는 대기(block)하고, 자원이 생기면 깹니다 세마포은 동시성을 관리하는 논리적 제어장치 또는 충돌을 방지하는 메커니즘입니다. Semaphores: A Definition 세마포어는 두 개의 루틴을 조작할 수 있는 정수 값을 가진 객체입니다. 초기 값이 동작을 결정하기 때문에 다른 루틴을 호출하여 상호작용이 생기기 전에 초기화가 필요합니다. ...
Operating Systems: Three Easy Pieces - Condition Variables
아쉽게도 lock만으로는 동시 프로그램을 구축하는 데 제약이 있습니다. 특히 스레드가 실행을 계속하기 전에 조건이 참인지 확인을 하고 싶어하는 경우가 많은 데, 이를 해결할 때 부족한점이 보이죠. 예를 들어 부모 스레드는 자식 스레드가 완료되었는 지 여부를 확인하고 싶을 수 있죠.(이를 join으로 부르기도 합니다.) import threading def child(): print("child") # XXX how to indicate we are done? def main(): print("parent: begin") t = threading.Thread(target=child) t.start() # XXX how to wait for child? print("parent: end") if __name__ == "__main__": main() 위 코드는 실행하면 아래처럼 부모가 먼저 끝날 수 있습니다. ...
Operating Systems: Three Easy Pieces - Lock-based Concurrent Data Structures
Lock을 다음 주제로 넘어가기 전에 일반 데이터 구조에 Lock을 얹어 쓰는 방법을 다룹니다. 모든 상황에 두루 통하는 방법을 찾기 어렵기 때문에 시나리오별로 나누어 살펴봅니다. 이번 챕터는 자료 구조라서 학습을 위해 파이썬(표준 라이브러리 threading)으로 같은 패턴을 옮겨 적습니다. Concurrent Counters 가장 단순한 데이터 구조 중 하나가 카운터입니다. 특정 값을 카운트하는 자료 구조로, 간단하게는 아래처럼 표현할 수 있습니다. class Counter: def __init__(self): self.value = 0 def increment(self): self.value += 1 def decrement(self): self.value -= 1 def get(self): return self.value 위 코드에 lock과 동시성을 추가해서 멀티스레드로 돌려봅시다. ...
Operating Systems: Three Easy Pieces - Locks
동시성 프로그래밍에서 일련의 명령을 원자적으로 실행하고 싶지만, 단일 또는 멀티 프로세스에서 멀티 스레드 환경을 도입시 프로세서에서의 인터럽트가 발생하기 때문에 그렇게 할 수 없죠, 그래서 이장에서 Lock을 도입하여 문제를 해결합니다. 해당 글에서도 c가 아닌 python으로 코드를 적습니다.(컨샙이나 이해부분을 위해 OSTEP를 보는 것이죠) 하지만 포인터 개념이 필요한 경우 c 코드를 참고합니다. Locks: The Basic Idea Lock의 기본 아이디어를 간단한 예제로 살펴보겠습니다. 잔고를 업데이트하는 코드입니다. 다음 명령어를 여러 스레드가 동시에 수행하면 스레드 컨텍스트 스위칭 타이밍에 따라 레이스 컨디션이 발생할 수 있습니다. (한 줄로 보여도 내부적으로는 값 읽기, 계산, 할당이 이뤄지는 복합적인 명령이기 때문입니다.) ...
Operating Systems: Three Easy Pieces - Thread API
교재에서는 c의 POSIX을 기반으로 진행되고 있고 Python을 공부 중이므로 Python의 threading로 해당 글을 진행합니다. threading 모듈은 OS의 저수준 스레딩 기능 위에 구축된 객체 지향 API로 Unix 계얼에서는 POSIX Thread(pthreads) 라이브러리를 기반으로 동작합니다. Thread Creation 파이썬에서는 threading.Thread 객체를 만들어 스레드를 생성합니다. 핵심은 “어떤 함수를 어떤 인자로 실행할지"를 스레드 객체에 넘기고, start()로 실행을 시작하는 흐름입니다. import threading def worker(name, count): for i in range(count): print(f"[{threading.current_thread().name}] {name}: {i}") # target: 새 스레드에서 실행할 함수 # args: target 함수에 전달할 인자 튜플 t1 = threading.Thread(target=worker, args=("A", 3), name="Thread-A") t2 = threading.Thread(target=worker, args=("B", 3), name="Thread-B") t1.start() t2.start() threading.Thread(...) 호출은 내부적으로 Thread.__init__(...) 인자와 매핑이 되죠죠 ...
Operating Systems: Three Easy Pieces - Concurrency: An Introduction
Process vs Thread 멀티 스레드는 하나의 Program Counter(PC)만 갖는 단일 스레드와 달리 각 스레드가 자신만의 Program Counter(PC)와 스택(Stack) 을 가집니다. 이로 인해 멀티 프로세스와 달리 다음 차이점들이 발생합니다. ※ Program Counter(PC): 다음에 실행할 명령어의 주소를 저장하는 레지스터 하나의 프로세스에 두 개의 스레드(T1, T2)가 있다고 가정해보면, T1에서 T2로 넘어갈 때 스레드 간 컨텍스트 스위치가 일어납니다. 이 과정은 프로세스 간 컨텍스트 스위치와 비슷하게 현재 실행 상태를 저장하고 다음 실행 상태를 복원한다는 점에서 유사합니다. ...
Django 6.0 Introduction Summary
서론 해당 글은 Laravel, Spring, Gin 등 다양한 프레임워크를 사용해 본 입장에서 Django를 살펴보며 정리한 메모입니다. Django 6.0 기준으로 Introduction은 다음과 같이 구성되어 있습니다. Django 훑어보기 빠른 설치 가이드 장고 앱 작성하기, part 1 ~ 8 심화 튜토리얼: 재사용 가능한 앱을 만드는 법 다음에 읽을 내용 장고에 처음으로 기여하기 Django 훑어보기 튜토리얼이 아닌 제목 그대로 Django의 동작 방식에 대해 설명하고 있습니다. Model 처음은 모델과 ORM(object-relational mapper)으로 시작하며, Django의 Model을 먼저 보여줍니다. Reporter와 Article로 모델 클래스의 관계를 다음처럼 표현합니다. 파이썬의 __str__ 매직 메서드로 모델 객체의 표시 형태도 지정합니다. ...
RFC 6749 — The OAuth 2.0 Authorization Framework
OAuth OAuth 2.0은 인증(Authentication) 자체보다 권한 부여(Authorization) 를 위한 프레임워크입니다. 즉, 제3자 애플리케이션이 리소스 소유자의 비밀번호를 직접 받지 않고도, 제한된 범위(scope)의 접근 권한을 얻도록 설계되었습니다. 네이버/카카오/구글 로그인에서 자주 보이는 흐름도 이 개념을 기반으로 하지만, “로그인(신원 확인)” 자체는 보통 OpenID Connect(OIDC) 같은 상위 프로토콜이 함께 쓰입니다. ※OpenID Connect(OIDC): OAuth 2.0 프로토콜을 기반으로, 웹과 모바일 앱에서 표준화된 방식으로 사용자의 신원을 확인(인증)하는 현대적인 인증 레이어입니다. OAuth가 널리 쓰이기 전에는 제3자 앱이 사용자 자격 증명을 직접 보관/전송하는 방식이 많았고, 이는 과도한 권한 부여와 자격 증명 유출 위험을 키웠습니다. OAuth 2.0은 이 문제를 “비밀번호 공유 없이 위임"하는 모델로 바꿉니다. ...
RFC 6454 — The Web Origin Concept
서론 서버가 교차 출처 요청을 아무 기준 없이 허용하면, 민감한 응답 데이터가 의도치 않게 노출될 수 있습니다, 브라우저는 Same-Origin Policy를 기본으로 적용하고, 서버는 CORS 헤더를 통해 특정 Origin에 한해 접근을 허용하는 방식으로 이를 대응합니다. Same-Origin Policy: 웹 브라우저가 보안을 위해 한 출처(Origin)에서 가져온 문서나 스크립트가 다른 출처의 리소스와 상호작용하는 것을 제한하는 핵심 보안 메커니즘 CORS: 브라우저가 다른 도메인(출처)의 서버 자원에 접근할 때, 보안상 제한(동일 출처 정책, SOP)을 해제하고 합법적으로 데이터를 공유하도록 서버가 허가해 주는 HTTP 응답 헤더 기반 메커니즘 Origin의 정의와 직렬화, 그리고 HTTP Origin 헤더를 규정한 RFC 6454를 정리합니다. Origin 개념을 이해하면 다른 출처 접근이 어떤 기준으로 허용/차단되는지, 그리고 이를 통해 서버 자원을 어떻게 보호하는지 명확하게 볼 수 있습니다. ...
RFC 9114 — HTTP/3
서론 HTTP/3는 구글에서 QUIC로 개발하였고 22년 6월에 RFC 9114로 표준화되며 HTTP/3로 변경되었습니다, 참고로 HTTP/3의 기반이 되는 QUIC는 새로운 전송 프로토콜로 RFC 9000으로 표준화되었죠. ※QUIC(Quick UDP Internet Connections): UDP 기반의 차세대 전송 프로토콜로, TCP를 쓰지 않아 TCP 수준의 HOL(head-of-line) 블로킹을 줄일 수 있음 HTTP/3의 필요성 QUIC를 사용함으로써 HTTP/2의 가장 큰 단점 몇 가지를 해결할 수 있습니다. 패킷 손실의 영향 감소: TCP는 순서대로 바이트를 넘기려고 해서, 중간에 패킷이 하나만 유실돼도 그 뒤 데이터 전체가 앱에 전달되기 전까지 막힙니다. HTTP/2는 여러 스트림의 프레임이 한 TCP 연결에 실려 보내지기 때문에 이런 막힘이 연결 위의 모든 스트림에 동시에 걸립니다. (TCP 수준의 HOL), QUIC는 스트림마다 손실·재전송을 처리하므로, 한 스트림에서 손실이 나도 다른 스트림이 전부 멈추지는 않습니다. ...