메뉴 닫기

소켓의 블럭킹(blocking)과 넌블럭킹(non-blocking), 그리고 비동기(asyncronous)

개발

얼마 전 업무의 일환으로 PHP 기반의 텔넷(telnet) 클라이언트 구현을 위한 클래스를 제작했다. PHP에서 제공되는 소켓 함수를 이용하여 제작했는데, 호스트 접근 오류에 대한 예외 처리를 어떻게 할 것인지 고민하다가 결국에는 소켓 접근 방식을 블럭킹 모드로 결정하고 타임아웃으로 예외가 처리되도록 개발하였다. 오히려 논블럭킹 모드보다 기능적으로 불편한 점도 없으면서, 코드는 심플해졌다.

 

소스 코드

아쉽게도 프로그램에 대한 전문적인 지식이 없는 독자들은 클래스가 무엇이며, 소켓에 블러킹은 또 뭔지, 타임아웃으로 예외를 처리한다는 것이 무엇인지 이해하기 어려울 수 있다. 그래서 오늘 이 글의 주제를 소켓 프로그램의 넌블러킹과 이를 이용한 비동기로 정했고, 이러한 프로그램의 로직이 어떻게 이뤄지는지 설명하고자 한다. 사실 이러한 주제에 대한 글은 인터넷에 차고 넘친다. 하지만, 글의 내용이 너무 전문적인 탓에 프로그래머도 이해하기 쉽지 않다. 즉, 이 글을 작성하는 목적은 프로그램은 몰라도 프로그래머와 항시 대화를 해야 하는 고충을 안고 있는 엔지니어나 상급자를 위한 것이다.

그럼, 본론으로 들어가 소켓 프로그램이 무엇인지 알아보자. 프로그램에서 소켓(socket)이란 특정 포트를 이용하여 데이터 송/수신을 가능하게 해주는 것을 의미한다. 실 예로 22번 포트는 SSH로 23번은 텔넷 포트로 알려져 있는데, 이 역시 소켓이 이용하는 포트로 목적이 미리 정해진 포트(well-known port)가 다 수 존재한다. 즉, 소켓 프로그램이란 `특정 포트를 이용하여 데이터를 송/수신함으로써 어떠한 목적을 이루기 위한 프로그램` 이라고 정의 할 수 있다. 이미 예상하고 있겠지만, FTP를 비롯하여 SSH, SMTP 등 포트를 이용한 대부분의 프로그램이 소켓 프로그램에 속한다.

 

아이디와 비밀번호 입력

이해를 돕기 위해 텔넷을 이용하여 서버에 접근을 해야 한다고 가정해보자. 텔넷 프로그램을 실행하여 서버에 접근을 시도하면 아마도 ID를 입력하라는 메시지가 출력될 것이고, 사용자는 아이디를 입력하고 엔터를 누를 것이다. 이와 같은 과정은 보이지 않는 곳에서 소켓을 통해 데이터 송/수신이 발생되었으며 그 결과를 사용자가 이해하기 쉬운 문자와 UI로 표현한 것이 바로 소켓 프로그램으로 대표적인 예가 바로 putty다.

putty는 매우 잘 만들어진 프로그램이지만, 가끔씩 서버에서 응답이 오지 않아 화면이 멈춰있는 현상이 발생되거나 네트워크 속도가 느린 탓인지 출력 결과가 한번에 나타나지 않고 조금씩 나뉘어서 나타나는 경우도 있다. 이러한 결과가 발생되는 이유는 프로그램이 소켓을 어떻게 이용(모드)하는가에 따라 그 결과가 다르게 나타나기 때문이다.

소켓을 블럭킹 모드로 사용하면 서버에서 보내는 응답이 완료 될 때까지 클라이언트는 수신을 종료하지 않고 대기한다. 이해하기 쉬운 예를 들면 다음과 같다.

대화(명령)를 하기 위해 상대방(호스트)에게 전화(소켓)를 걸었지만,
상대방이 아무말(응답)도 하지 않는 상황

혹은

어떤 질문(명령)을 메신저(소켓)로 친구(호스트)에게 했는데,
답변(응답)이 없는 상황

 

즉, putty를 사용하다가 서버에서 응답이 오지 않아 멈춘것 처럼 보이는 상황이 바로 이것이다. 보편적인 사람은 “여보세요!”를 반복하다가 상대방이 계속 응답을 하지 않으으면 전화(메신저)를 끊지만, 머리 나쁜 사람은 계속해서 “여보세요”를 외치고 있을지도 모른다. 이러한 이유로 프로그래머가 멍청하지 않다면 소켓을 이용하는 프로그램을 개발 할 때는 일정 시간 동안 응답이 없는 경우에 대한 예외를 처리하기 위하여 타임아웃 설정 기능을 포함 시킨다.

이러한 처리 방식이 소켓의 블럭킹 모드(이용)와 타임아웃 설정의 대표적인 방법이다. 아마도 여기까지 차분하게 읽은 독자는 이 글의 시작 부분에 언급했던 내용을 절반 정도는 이해 할 수 있을 것이다. 그렇다면 소켓의 다른 이용 방법인 논블럭킹 모드는 블럭킹 모드와 무슨 차이가 있는 것일까?

논블럭킹 모드는 블럭킹 모드에 비해 좀 더 유용한 소켓 이용 방법이라고 볼 수 있다. 그 이유를 이해하기 쉬운 예를 들면 다음과 같다.

대화(명령)를 하기 위해 상대방(호스트)에게 전화(소켓)를 걸고,
웹서핑을 하고 있다가 상대방(호스트)이 “여보세요”라고 말하면(콜백 혹은 트리거)
대화를 시작하는 상황

혹은

어떤 질문(명령)을 메신저(소켓)로 친구(호스트)에게 하고,
만화책을 보고 있다가 친구(호스트)가 답변(응답)을 시작하면 확인하는 상황

 

소켓을 이용하는 두 가지 방법의 결정적인 차이는 명령을 전달하고 그 응답을 실시간으로 기다리느냐(syncronous), 실시간으로 기다리지 않느냐(asyncronous)의 차이다. 논블럭킹 모드는 명령을 전달하고 응답이 올 때까지 다른 처리를 진행하다가 응답이 오는 신호(콜백 혹은 트리거)에 따라 동작되는 방식으로 비동기적인 구조를 가진다.

그러므로 여러 대의 서버에 동일한 명령을 수행하고 그 결과에 대한 응답을 각각 받을 수 있는 텔넷 프로그램을 만들어야 한다면, 소켓의 이용 방식은 논블럭킹 모드로 선택해야 할 것이다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다