[쇼핑몰 프로젝트] 파일 디스크립터와 웹소켓

대원·2025년 2월 8일

쇼핑몰

목록 보기
10/13

파일디스크립터와 웹소켓

배경

서버 운영체제로 널리 활용되는 OS 중 하나로 리눅스를 꼽을 수 있습니다. 예를 들어 AWS 같은 클라우드 서비스에서 EC2 인스턴스를 생성할 때, 기본적으로 리눅스를 사용하는 경우가 많습니다.

리눅스에는 ‘파일 디스크립터(File Descriptor, FD)’라는 중요한 개념이 있습니다. 이 글에서는 리눅스 파일 디스크립터가 무엇인지 간단히 살펴보고, 네트워크 I/O가 많은 프로그램, 특히 웹소켓을 사용할 때 어떤 부분을 주의해야 하는지 알아보겠습니다.

리눅스 파일디스크립터

  • 리눅스의 ‘파일 디스크립터’는 유닉스(혹은 리눅스 계열 이하 리눅스로 통일함)에서 프로세스가 File을 관리할때 사용하는 개념이자 인터페이스입니다.
  • 리눅스는 모든 객체, 디렉토리, 파이프, 소켓, 등등을 ‘파일’로 관리합니다.
  • 리눅스 시스템에서 프로세스가 ‘파일’에 접근할때 ‘파일 디스크립터’를 통해 접근하여 읽기/쓰기 등의 작업을 수행합니다.
    • 마치 테이블의 인덱스와 같은 기능을 수행합니다.

기본적으로 할당되는 파일디스크립터는 3개가 있습니다.

  • 표준입력
    • 0을 할당
  • 표준출력
    • 1을 할당
  • 표준에러
    • 2를 할당

리눅스에서 FD를 확인하는 법

  • FD를 확인할 프로세스의 PID 확인
    • ps -ef | grep {}

  • 해당 PID의 FD를 확인
    • ls -al /proc/{pid}/fd

FD의 관리의 중요성

리눅스에서 모든 것은 파일로 관리된다고 하였습니다. 반대로 말하면 파일은 곧 자원이고 FD값이 크고 많을수록 메모리 부하가 생기게 됩니다. 즉 ,커넥션마다 파일 디스크립터뿐 아니라 서버의 메모리 버퍼와 CPU 등을 소모하게 됩니다.

프로세스가 fd를 제대로 정리하지 않는다면, fd leak이 발생해서 memory leak과 비슷한 현상이 생기게 됩니다. 프로세스가 열 수 있는 fd값은 환경에 따라 다르고 기본적으로 fd값은 0부터 할당되지만, 0,1,2는 공통적으로 사전에 표준입출력 등으로 정의되어있습니다.

따라서 File 입출력이 잦은 프로그램이라면 fd leak을 관리하는게 중요합니다.

다시 한 번 말하지만, 여기서 말하는 ‘파일’이란 우리가 일반적으로 윈도우/맥을 이용하며 사용하는 ‘파일’ 체계라기보다는, 리눅스계열의 모든 자원관리 등은 ‘파일’이라는 객체를 통해서 관리됩니다.

따라서 우리가 직관적으로 떠올려지는 ‘파일’이라기보다는 파일, 네트워크소켓, 파이프, 메세지 큐 등 모든 것을 포함합니다.

그렇기 때문에 네트워크 요청을 많이 처리하는 프로그램도 결국 내부적으로 fd를 할당하고 해제하는 과정이 반복해서 수행됩니다.

참고로 리눅스 서버 내에서 파일 디스크립터(fd)를 확인하는 방법 및 증량하는법 등은 아래와 같습니다.

  • 파일 디스크립터 한계값 확인
    • ulimit -n

  • 최대 fd개수 증가 방법
    • ulimit -n 10000-

  • 시스템 전체 file descriptor 개수 확인
    • cat /proc/sys/fs/file-nr

그렇다면, 네트워크 I/O가 중요한 작업이 무엇이 있을까요?
좀 더 자세히 이야기 해보자면, 네트워크 I/O가 높은 비중을 차지하는 것이 무엇이 있을까요?

네트워크 I/O가 높은 비중을 차지하는 작업

웹 애플리케이션, 마이크로서비스, 실시간 스트리밍, 채팅 서버 등 대부분의 서버 사이 통신은 네트워크를 통해 이뤄집니다. 결과적으로 다음과 같은 작업에서 네트워크 I/O가 특히 큰 비중을 차지하게 됩니다.

1 HTTP 요청/응답 처리

웹 서버가 클라이언트의 요청을 받았다가 다시 응답을 보내는 전 과정을 통틀어 네트워크 I/O가 핵심입니다.

2 웹소켓(WebSocket) 통신

실시간으로 양방향 통신을 유지해야 하므로, 소켓 연결을 지속적으로 관리합니다.

3 대규모 API 트래픽 처리

여러 외부 서비스(예: 결제 서비스, SNS API 등)와의 연동이 많은 환경에서는 수많은 네트워크 연결이 발생합니다.

4 스트리밍 서비스

음악, 동영상 스트리밍은 대량의 데이터를 네트워크로 전송하므로 I/O 사용량이 매우 높습니다.

현대 웹 기반 서비스의 대부분은 네트워크 위에서 돌아가며, 그 과정에서 FD가 끊임없이 생성되고 소멸합니다. 그렇기 때문에 특히 FD를 관리하는 것이 중요합니다.

4번은 도메인과 밀접하게 연관된 것이고 3번 항목의 경우 ‘규모’와 연관되어 있습니다. 프로토콜과 관련되어 생각하자면 1번과 2번 항목의 차이점을 비교하면서 생각해볼 필요가 있습니다. (특히 저의 경우엔 웹소켓을 통해서 채팅 서비스를 간단히 구현해봤기 때문에 1,2번의 차이가 중요하게 생각되었습니다.)

즉, HTTP 프로토콜과 웹소켓을 사용할때 있어서 파일 디스크립터를 관리하는데 주의해야할점이 무엇이 있을까요?

HTTP vs. 웹소켓: 파일 디스크립터와 리소스 관리 유의점

  1. 프로토콜 특성: Stateless vs. Stateful
    • HTTP:
      • 대표적으로 ‘Stateless’ 프로토콜입니다.
      • 클라이언트가 요청을 보내고 서버가 응답한 뒤에는 소켓 연결이 종료되는 형태가 일반적입니다.
      • 이처럼 요청/응답이 끝나면 FD(파일 디스크립터)가 해제되므로, 장시간 연결을 유지할 필요가 없습니다.
    • 웹소켓:
      • ‘Stateful’한 방식으로 서버와 클라이언트 간에 실시간 양방향 통신을 가능하게 합니다.
      • 연결이 한 번 맺어지면 유지되는 기간 동안에는 FD가 계속 점유됩니다.
      • 연결이 많아질수록 서버에서 관리해야 할 FD가 크게 증가합니다.
  2. FD 누적과 관리 포인트
    • HTTP는 요청을 주고받은 뒤 연결을 끊으므로 FD가 빠르게 해제됩니다.
    • 웹소켓은 연결을 지속해서 유지하므로, 단일 서버에서 동시에 수많은 연결을 담당하게 되면 FD 사용량이 기하급수적으로 늘어납니다.
    • 서버에서 설정한 FD 한계를 초과하면 “Too many open files” 오류가 발생할 수 있으며, 이때 단순히 FD만 문제가 되는 것이 아니라 CPU나 메모리 같은 자원도 함께 소모됩니다.
  3. OOM(Out Of Memory) 연관성
    • 웹소켓은 장시간 연결로 인해 FD 외에도 네트워크 버퍼, CPU, 메모리 같은 추가 자원을 상시 사용하게 됩니다.
    • 동시에 접속하는 연결이 많아질수록, 자원 점유는 더욱 가중됩니다.
    • 특정 한계를 넘어가면 서버가 OOM(Out Of Memory)에 직면할 수 있으며, 서비스 장애로 이어질 위험이 높습니다.

종합해보자면, HTTP기반 통신과 달리 웹소켓이 지속적으로 연결 상태를 유지하는 특성을 지니고 있기 때문에, 서버 입장에서는 웹소켓을 사용할때 더 많은 주의를 기울여야할 것으로 보입니다.

그렇다면 Application Level에서 웹소켓을 사용할때 OOM을 방지하기 위해 서버측에서 준비해줄 수 있는 것은 무엇일까요?

다음 글에서는 현재 본인의 토이프로젝트를 기준으로 무엇을 어떻게 적용할 수 있을지 생각해보겠습니다.

profile
고민하고 공부하는 사람

0개의 댓글