내부 통신을 UNIX 소켓 통신으로!

Hyunsoo Lim·2024년 3월 31일
0

장애 분석을 하며 TCP 병목이 문제가 될 수도 있다는 걸 알고 대안을 찾아보기 시작했다.

정확히는 Nextjs와 gunicorn 사이의 내부 통신에서의 병목이 문제였는데, TCP 통신 말고 다른 걸 쓰면 되지 않을까? 해서 나온 대안이 Unix 소켓 통신.

이를 위에 기존의 PORT 방식의 TCP 통신과 유닉스 소켓 방식을 비교해보면 다음과 같다.

PORT 방식

  1. gunicorn 을 8000 포트에 바인딩해서 띄우는 방식
  2. 포트 방식은 네트워크를 통해 외부/내부에서 엑세스 가능 == TCP/IP 네트워크 프로토콜을 사용
    a. 그래서 위의 그림 1을 보면 알겠지만, nginx 를 거쳐 gunicorn으로 요청을 보내는 CSR 과는 달리, SSR은 프론트엔드에서 http://localhost:8000/api/v1 을 이용해 gunicorn 으로 요청을 직접 보냄.
    b. http://12.34.56.78:8000/api/v1 같은 식으로 서버의 ip만 알면 외부에서도 접근 가능 == 보안상 위험
  3. 장점 : 설정이 쉬움.
  4. 단점 : 2-b에 언급한 보안. 그리고 SSR은 실제로는 내부 통신인데, 네트워크 스택을 정석대로 타야하니 오버헤드가 걸려 상대적으로 느림.

UNIX 소켓 방식

  1. gunicorn을 소켓 파일 /home/ubuntu/gunicorn.sock 을 바인딩해서 띄우는 방식
  2. 내부(호스트) 동일한 시스템 내에서 프로세스 간(ex. coco ↔ gunicorn) 통신을 위한 메커니즘
    a. 당연하게도 외부에서 http://12.34.56.78:8000/api/v1 같은 식으로 접근 못함 -> 프록시 서버(nginx)를 통해야…(axios는 조금 다를수도 있음. 아래에서 설명)
    b. IPC(Inter-Process Communication) 소켓이라고도 함.
    c. 내부 통신이라 http://12.34.56.78:8000/api/v1 에서 host에 해당하는 [12.34.56.78:8000](<http://12.34.56.78:8000/api/v1>) 부분은 아무렇게나 적어도(ex.naver.com) 괜찮음. 물론 http 를 https 로 하면 안 됨.
    d. 파일 시스템 기반 == 보안성 강화
  3. 장점 : 보안, 속도
  4. 단점 : 설정 어려움

개발 환경

  1. django 서버를 gunicorn이 아니라 runserver로 가볍게 띄움
  2. CSR 도 동일하게 8000 포트로 접근을 해야하는데 next.config.js 에서 rewrites 로 이를 해결하고 있음.

설정하는 데 유의점

  • axiosfetch 사이에 unix 소켓 통신 설정 방법이 다름.
    • axiossocketPath 설정만으로 사용 가능 (링크)
    • fetch 는 HTTP/HTTPS 프로토콜에만 사용되어 Unix 소켓 통신을 직접적으로 지원하지 않음.
      • WebSocket 을 쓰던가 (링크)
      • nginx 를 통해 유닉스 소켓과 통신하는 식으로 우회해야함.

후기

프론트엔드, 백엔드 구분이 되어 있지 않은 우리 팀 같은 문화가 아니었으면 세팅에 엄두도 못 냈을 것 같다.

하지만 22년 11월 입사 이후로 Next.js와 Svelte 코드도 꾸준히 봤고 이 작업을 하면서 관련 세팅도 다 뜯어보면서 기존에 환경변수가 잘못되어 있던 것도 발견하고 유닉스 소켓 세팅 자체는 성공적으로 POC를 했으나,

DB 커넥션 풀 세팅으로 문제는 해결되었고 axios 만 쓰는 Next.js와 달리, fetch 도 쓰는 스벨트 쪽 코드는 환경 설정이 복잡해져서, 굳이 필요없다는 판정을 받아 결국 해당 브랜치는 폐기했다...는 후문.

profile
잡식형 괴발자

0개의 댓글