콘텐츠로 건너뛰기
Home » 스터디 » Page 5

스터디

Selector를 사용한 소켓 멀티플렉싱

소켓을 사용하여 간단한 서버를 만들 때에는 서버 소켓을 생성하고, 이를 특정한 네트워크 포트에 바인드한 다음, listen() 메소드를 사용해서 해당 포트로 들어올 수 있는 접속 대기열의 크기를 지정합니다. 그런 다음 해당 소켓의 accept() 메소드를 사용해서 클라이언트 소켓을 생성하고, 이 클라이언트 소켓을 통해 클라이언트가 보낸 요청을 읽고, 그에 대한 응답을 보내게 됩니다.

서버 소켓은 클라이언트가 접속할 때마다 ‘서버가 사용하는 클라이언트 소켓’을 따로 생성하고 실제 통신은 두 클라이언트 소켓 사이의 peer-to-peer 방식의 대화가 됩니다. 따라서 하나의 서버 소켓은 여러 클라이언트의 접속을 받을 수 있습니다.

만약 다중 접속을 허용하는 소켓 서버를 파이썬에서 구현한다면 가장 쉬운 방법은 스레드를 사용하는 것입니다. 클라이언트 소켓을 인자로 받는 핸들러 함수를 하나 작성하고, 서버 소켓의 accept() 메소드가 리턴하는 시점에 핸들러 함수에게 클라이언트 소켓을 주고 새로운 스레드에서 작동하도록 시작해주면 됩니다.

여기까지의 작동 모델은 ‘동기식 소켓’을 사용합니다. 동기식 소켓은 send(), recv(), accept() 등의 동작이 모두 블럭되는 소켓입니다. 따라서 스레드가 소켓의 입출력을 기다리는 동안에는 다른 일을 할 수가 없습니다. 그래서 서버 소켓과 클라이언트 소켓들이 동시에 작동할 수 없으니 스레드를 사용하는 것이겠죠.

소켓 라이브러리는 이와 다른 비동기 소켓을 지원하고 있습니다. 비동기 소켓은 소켓을 바인딩하기 전에 sock.setblocking(False)를 명시해서 블록킹 모드를 논블록킹으로 변경해줍니다. 이렇게 만들어진 비동기 소켓을 소켓 API만으로 사용할 수는 없습니다. Python How To 문서는 select.select() 를 사용할 것을 추천합니다만, 이는 문서가 오래되었음을 감안해야 하며 실제 파이썬 공식문서는 보다 고수준으로 설계되어 사용하기 쉬운 selectors 모듈을 쓸 것을 추천하고 있습니다.

이 글에서는 selectors 모듈을 사용하여, 단일 스레드에서 하나의 소켓 서버가 여러 클라이언트의 요청을 처리하는 멀티플렉싱을 어떻게 구현하는지 소개하며, 셀렉터 사용 방법에 대해서 살펴보겠습니다.

더 보기 »Selector를 사용한 소켓 멀티플렉싱

ZMQ 예제 – Poller를 사용하여 종료 시점을 동기화하기

하나의 ZMQ 소켓은 여러 포트에 바인드하거나 커넥트할 수 있어서, 1:N의 연결을 쉽게 구성할 수 있습니다. 하지만 어떤 경우에는 이 다중 접속이 두 개 이상의 소켓을 사용하는 경우도 있습니다. 이런 경우 두 개의 소켓을 동시에 듣는 방법이 필요합니다. ZMQ소켓의 recv() 메소드는 블럭킹 함수이기 때문에 2개 이상의 소켓 중 데이터가 들어온 소켓을 처리하기 위해서는 소켓만으로는 처리할 수 없습니다. ZMQ는 이런 상황에 사용할 수 있는 Poller라는 수단을 제공합니다.

더 보기 »ZMQ 예제 – Poller를 사용하여 종료 시점을 동기화하기

Asyncio – 네트워크 입출력을 위한 스트림

asyncio는 네트워크 입출력을 위한 스트림이라는 타입을 제공하고 있다. 스트림은 네트워크 연결을 만들거나(클라이언트의 connect 동작) 서버를 시작하고(서버의 bind/listen 동작) 연결이 생성되면 해당 연결을 처리하는 핸들러의 인자로 넘겨지게 된다. 비동기 코루틴인 각각의 핸들러는 이 스트림을 이용해서 데이터를 읽거나 전송할 수 있다.

입출력 스트림은 내부적으로 소켓을 감싸고 있으며, 노출되는 API를 통해서 소켓을 기다리고 읽고 쓰는 일련의 작업을 상당히 고수준의 레벨에서 제공해주고 있다.

더 보기 »Asyncio – 네트워크 입출력을 위한 스트림

파이썬 – 클래스를 사용하지 않기

보통 객체 지향 언어를 설명할 때, 객체 지향의 기본적인 개념으로 클래스를 언급하는 경우가 많습니다. 그리고 자바나 C++ 등의 언어에서도 어떤 현실의 문제를 해결할 때, 그에 맞는 클래스부터 설계하는 방식으로 접근하기도 하지요. 파이썬 역시 객체지향 컨셉이 주가 되는 언어이며, 당연하게도 사용자가 직접 원하는 클래스를 정의하여 사용할 수 있습니다. 실제로 파이썬의 모든 것이 객체이기도 하지요.

그럼에도 불구하고 몇몇 특수한 경우를 제외하면 사실 파이썬에서 클래스를 직접 만들어서 사용하는 방식을 그리 권장하고 싶지는 않습니다.

더 보기 »파이썬 – 클래스를 사용하지 않기

(Swift) Float 타입 사용법

Float 타입은 32비트 부동 소수점 숫자를 다루기 위해 제공되는 기본 타입이다. 64비트 정밀도를 가지는 Double 타입도 제공된다.


지수(exponent)와 가수(significand)에 대해

컴퓨터에서 사용하는 부동소수점 숫자는 기본적으로 근사값이다. 모두들 알다시피 컴퓨터는 내부적으로 모든 데이터를 이진수로 표현한다. 정수나 자연수에 있어서 진법은 특정한 값을 표시하는데 있어서 필요한 숫자의 개수만 달라지지만 소수점 이하의 값에 대해서는 그 사정이 다르다. 먼저 10진수 13을 생각해보자. 13은 10 + 3 이며 이를 10을 밑으로 하는 다항식으로 쓰면 1 \times 10^1 + 3 \times 10^0 의 꼴로 표현된다. 같은 식으로 이 값을 이진수로 표현하면 1011(2)가 되는데, 이 표현은 다시 이는 1\times2^3 + 0\times2^2 + 1\times2^1 + 1\times2^0 이라는 의미이다.

더 보기 »(Swift) Float 타입 사용법

multipart/form-data 타입의 HTTP 메시지 구성 방법

파일 업로드를 구현할 때, 클라이언트가 웹브라우저라면 폼을 통해서 파일을 등록해서 전송하게 됩니다. 이때 웹브라우저가 보내는 HTTP 메시지는 Content-Type 속성이 multipart/form-data로 지정되며, 정해진 형식에 따라 메시지를 인코딩하여 전송합니다. 이를 처리하기 위한 서버는 멀티파트 메시지에 대해서 각 파트별로 분리하여 개별 파일의 정보를 얻게 됩니다.

만약 서버사이드가 이러한 방식으로 동작할 때, 웹브라우저처럼 파일을 멀티파트 메시지로 만들어서 업로드하는 것을 별도의 앱에서 구현하려면 어떻게해야 할까요? 그 방법을 알기 위해서 멀티파트 http 메시지가 어떻게 생겼는지를 살펴보면 거기에 해답이 있을 것 같습니다. 먼저 http 메시지의 구조를 보겠습니다.

더 보기 »multipart/form-data 타입의 HTTP 메시지 구성 방법

Codable

많은 프로그래밍 작업은 데이터를 어딘가로 전달하는 것과 관련된다. 네트워크를 통해서 전송하거나, 디스크와 같은 영구 저장소로 전달하여 기록할 수도 있다. 프로그램이 실행시간에 사용하는 데이터는 그 필요와 목적에 맞게 구조화되고 각 단위가 연결되어 입체적인 그래프를 형성하기도 하지만, 전달과정에서 만큼은 일렬로 늘어선 비트의 연속체가 되어야 한다. 따라서 필연적으로 어떤 데이터가 유용성을 가지려면 직렬화 될 수 있어야 하고 그 반대로 역직렬화도 가능해야 한다.

이러한 직렬화 / 역직렬화와 관련하여 Foundation은 오래전부터 NSCoding 이라는 기술을 보유하고 있었다. 이는 간단하게 가장 기본이 되는 몇 가지 타입이 인코딩이 가능하다면, 각 객체의 속성을 키-값 쌍으로 묶어서 인코딩할 수 있다는 가정하에 일반적으로 사용될 수 있는 임의의 타입의 데이터까지 간단하게 확장할 수 있는 기술이다. (물론, 현재도 쓰인다. 단 보안상의 문제로 NSSecureCoding으로 대체되었다.)

더 보기 »Codable

오일러 프로젝트 84

이번 문제는 문제가 길고 복잡하기 때문에 풀이 위주로 갑니다.

모노폴리 시뮬레이터를 작성하고 여러 차례 돌리면서 각 칸에 방문한 횟수를 늘려나간다. 정해진 횟수를 돈 다음, 각 칸에 도달했던 횟수를 계산해본다. 먼저 모노폴리 시뮬레이터를 작성해보자.

더 보기 »오일러 프로젝트 84