본문 바로가기

Node.js

Node.js Socket Programming (1)

이번 시리즈는 Node.js에서 TCP/UDP/Websocket등을 활용한 실시간 통신 구현방안에 대해 소개하고자 합니다. 최근에는 Restful API가 트렌드로 자리잡으면서 주로 HTTP기반으로 통신하며 주고받는 컨텐츠만 고려하도록 (Low Level단에서 벌어지는 일은 신경쓰지 않아도 되는)해주는 좋은 라이브러리들이 많이 있습니다.

 

TCP/IP, UDP를 직접 다루는것은 Low Level 작업으로 인식합니다. 하지만 레거시 시스템에서는 아직도 HTTP가 아닌 TCP/IP나 UDP기반의 Custom프로토콜을 정의하여 구현된 것이 대부분이고 이러한 장비나 시스템과 연동하기 위해서는 여전히 소켓 프로그램에 대한 기본 지식이 있어야 합니다. 기본개념에 대해서는 인터넷상에 좋은 자료들이 많이 있기 떄문에  여기서는 간략하게 설명드리겠습니다.

 

소켓 프로그램에서 가장 기본이 되는것은 소켓을 생성하는 일입니다.  소켓은 네트워크를 통해 두 컴퓨터 간의 통신을 가능하게 하는 논리적인 접점입니다. 유닉스시스템에서는 파일과 같이 소프트웨어가 접근할 수 있는 객체로 생성됩니다. 
Application이 네트워크를 통해 다른 프로그램과 통신하려는 경우 소켓을 생성하고 IP 주소 및 포트 번호에 Binding합니다. 그런 다음 소켓으로부터 데이터를 읽고 쓰면 OS 에서 네트워크 장치를 통해 데이터를 전달,수신하는 방식입니다.

 

Node.js기본적인 TCP,UDP패키지가 Built-in되어 있어 별도의 설치과정 없이 바로 사용이 가능합니다. 이제 간단한 에코 서버를 작성해 보도록 하겠습니다. 에코서버는 클라이언트에게 수신된 데이터 그대로 다시 돌려주는 서버를 말하며 예제로 많이 사용됩니다(실무에서는 거의 사용되지 않습니다.)

 

const net = require('net');

const server = net.createServer((socket) => {
  console.log('Client connected');

  socket.on('data', (data) => {
    console.log(`Received from client: ${data}`);

    // Echo back the data to the client
    socket.write(data);
  });

  socket.on('end', () => {
    console.log('Client disconnected');
  });
});

const port = 8080;
server.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});

 

'net' package는 TCP/IP통신을 위한 Node.js기본 내장 라이브러리입니다. net.createServer() 메서드는 TCP 서버를 생성하고 콜백 함수를 매개변수로 사용합니다. 이 콜백 함수는 새 클라이언트가 서버에 연결할 때마다 호출되어 해당 클라이언트에서 액션이 발생할때마다 콜백함수에 정의한 이벤트 리스너들이 호출됩니다.


위의 서버 코드에서 클라이언트가 연결될 때 로그를 출력후 데이터 및 종료 이벤트에 대한 이벤트 리스너를 설정합니다. data 이벤트는 클라이언트가 서버에 데이터를 보낼 때마다 발생하고 end 이벤트는 클라이언트가 연결을 끊을 때 발생합니다. 이 예제에서는 수신된 데이터를 화면에 출력후 socket.write() 메서드를 사용하여 클라이언트에 다시 전송합니다.

 

소켓을 생성 및 이벤트 리스너를 등록한 후 반드시 server.listen을 호출해야 합니다. listen함수는 서버에서 사용되며 클라이언트의 접속을 수신하라는 명령입니다. 여러 옵션을 지정할 수 있지만 클라이언트가 접속할 PORT번호는 반드시 지정되어야 합니다. 위 예제는 8080번에서 데이터 접속을 기다리고 있습니다.

 

echoserver.js파일에 위 코드를 작성후에 실행합니다.

 

C:\Users\****\myapp>node echoserver.js
Server listening on port 8080

 

텔넷 클라이언트를 이용한 확인방법

이제 TCP/IP클라이언트로 올바르게 동작하는지 확인해 보도록 하겠습니다. TCP/IP테스트 툴은 다양하진 않습니다. 가장 좋은건 telnet 클라이언트로 확인하는 방법입니다. Windows에 기본 패키지라 별도의 작업이 필요없다는 장점이 있습니다. 최근 버전의 Windows에서는 보안문제로 인해 기본 비활성화 상태입니다. 이것을 활성해 해주여야 합니다.

 

https://mpjamong.tistory.com/125

 

Windows 10에서 텔넷(Telnet) 사용하는 방법

텔넷 서비스는 보안에 취약한 이유로 윈도우즈 10에서는 해당 서비스를 기본 설정으로 비활성합니다. 하지만, 테스트나 네트워크 작업에 필요한 경우 기본 설정을 변경함으로써 윈도우즈 10에서

mpjamong.tistory.com

잘 설명이 되어 있어 링크합니다.

 

설정을 완료후 새로운 Command창을 실해하여 아래와 같이 입력합니다. Windows기준입니다. 

 

telnet localhost 8080

 

접속이 성공하면 아무것도 출력되지 않는데 이는 실제로 텔넷 프로토콜을 주고받는게 아니라 서로 데이터 수신만 기다리고 있는 상태이기 때문에 그렇습니다. 키보드로 원하는 문자를 입력하면 반향되어 2개씩 출력되는것을 확인할 수 있습니다. 커맨드 창을 종료하면 접속이 종료되고 우리가 작성한 서버 코드의 end listener()가 호출되면서 접속이 해제됩니다. 오늘날의 텔넷 클라이언트는 필드에서 서버의 접속테스트로 많이 활용합니다.(원래 목적인 터미널 접속을 통한 원격제어는 SSH로 대체되어 있습니다.)

 

EchoClient

텔넷으로 간단하게 서버 동작유무를 테스트 해 볼수 있지만 아무래도 영 불편합니다. 테스트 하기 가장 좋은 방법은 서버의 통신 규약에 부합하는 클라이언트를 직접 제작하여 확인하는 것입니다. 위 에코서버는 별다른 프로토콜 규약 없이 단순 반향처리만 수행하지만 실제 필드에서는 서버와 클라이언트간 서로 프로토콜을 사전 정의후 해당 프로토콜규약에 따서 구현합니다. 프로토콜 정의에 대한 예제는 다음장에 소개드리도록 하겠습니다. 여기서는 Node.js로 간단한 에코 클라이언트를 제작해 보도록 하겠습니다.

 

const net = require('net');

const client = new net.Socket();

const port = 8080;
const host = 'localhost';

client.connect(port, host, () => {
  console.log(`Connected to server: ${host}:${port}`);

  // Send some data to the server
  client.write('Hello, server!');
});

client.on('data', (data) => {
  console.log(`Received from server: ${data}`);

  // Close the connection after receiving the response
  client.destroy();
});

client.on('close', () => {
  console.log('Connection closed');
});

 

Client역시 서버와 마찬가지로 net package를 이용합니다. net.Socket() 개체를 사용하여 새로운 소켓을 생성하고 접속할 서버의 IP, Port주소를 지정하여 서버에 연결합니다. 서버와 접속이 성공하면 CallBack이 호출되며 등록된 이벤트 리스너를 통해 데이터를 수신할 수 있습니다. (Node.js의  이벤트 드라이븐 방식의 처리는 C++/Java등의 타 언어에 비해 매우 직관적이고 편리합니다.)

data 이벤트는 서버가 클라이언트에 데이터를 보낼 때마다 발생하고, close 이벤트는 연결이 닫힐 때 발생합니다.

이 예제에서는 서버에 연결하고 client.write() 메서드를 사용하여 일부 데이터를 보냅니다. 서버로부터 응답을 받으면 데이터를 기록한 다음 client.destroy() 메서드를 사용하여 연결을 닫습니다.

 

echoclient.js에 위 코드를 작성하고 실행해 보도록 하겠습니다.

 

C:\Users\******\myapp>node echoclient.js
Connected to server: localhost:8080
Received from server: Hello, server!
Connection closed

 

서버로 보낸 메시지 "Hello, server!"가  반향되어 수신된것을 확인할 수 있습니다. 실행후 프로그램이 자동 종료되는데 Node.js기본적으로 더이상 등록된 이벤트 Loop가 발견되지 않으면 자동으로 프로세스가 종료되기 때문입니다. 웹서버나 TCP/IP소켓을 생성한 경우 내부적으로 이벤트 Loop가 등록됨으로 프로세스가 계속해서 실행되는 것이 그 증거입니다.

 

EchoServer/Client는 가장 기본적인 통신 프로그램입니다. 다음장에서는 실무에서 사용할 만한  좀더 복잡한 예제를 소개드리도록 하겠습니다.

 

읽어주셔서 감사합니다.