SFTP vs NFS — 실시간 I/O엔 왜 NFS인가
어느 인스턴스가 받아 둔 파일을 나중에 다른 인스턴스가 읽어야 했습니다. 로컬 디스크에 두면 받은 그 서버에서만 보이니, 한군데에 모아 두고 여러 대가 붙는 구조로 가야 합니다.
이때 SFTP 와 NFS 를 놓고 고민하게 됩니다. 둘 다 원격에 있는 파일을 다루고 붙고 나면 경로로 접근하는 것도 비슷해서, 처음에는 어느 쪽이든 되겠거니 싶습니다. 이미 SSH 로 들어가는 서버면 SFTP 는 따로 열 포트도 없으니 더 그렇습니다. 그런데 막상 실시간으로 읽고 쓰는 자리에 SFTP 를 끼우면 느려서 못 씁니다.
같은 원격 파일인데도 이렇게 갈리는 건 두 방식이 각각 어디서 도느냐 때문입니다. 하나는 유저 공간에서 돌고, 다른 하나는 커널 안에 들어가 있습니다.
SFTP — SSH 위의 전송 서브시스템
SFTP 는 별도 소프트웨어가 아니라 OpenSSH 에 내장된 서브시스템이고, 파일 전송 요청을 처리하는
것도 sshd 데몬입니다. 그래서 읽고 쓰는 동작이 유저 공간에서 요청-응답을 주고받는 일이
됩니다.
문제는 이 요청-응답에 매번 왕복이 한 번씩 든다는 겁니다.
클라이언트 서버
│── "파일 열어줘" ─────────▶│
│◀──────────── "OK" ────────│ 왕복 1번
│── "0~32KB 읽어줘" ───────▶│
│◀──────────── [32KB] ──────│ 왕복 1번
│── "32~64KB 읽어줘" ──────▶│
│◀──────────── [32KB] ──────│ 왕복 1번
게다가 단일 읽기·쓰기 요청이 보통 32KB 단위로 잘립니다(OpenSSH 기준). 큰 파일은 무조건 여러 번 나눠 요청해야 하고 조각마다 SSH 암호화 비용이 붙습니다. 파이프라이닝 (응답을 안 기다리고 요청을 미리 여러 개 보냄)으로 완화되지만, 라이브러리가 지원해야 하고 암호화 오버헤드는 그대로입니다.
NFS — 앱이 구분 못 하는 커널 파일시스템
NFS 는 커널 공간의 파일시스템이라, 마운트하고 나면 앱은 그게 원격인지 로컬 디스크인지 구분하지
못합니다. open/read/write 시스템콜을 그대로 쓰고, 원격과 주고받는 건 커널이 합니다. 매번
요청-응답을 유저 공간에서 주고받게 하는 SFTP 와는 근본이 다릅니다.
여기에 커널의 페이지 캐시까지 얹혀서, 한 번 읽은 블록은 메모리에 캐시되고 순차 접근이면 readahead 로 뒤쪽 블록을 미리 당겨 오니, 반복 접근·순차 접근에서 NFS 가 훨씬 유리합니다.
선택 기준 — 배치는 SFTP, 실시간은 NFS
배치성 전송이면 SFTP 가 맞습니다. 파일을 통째로 한 번 옮기는 용도라면 요청-응답 왕복이 몇 번 더 도는 게 문제가 안 되고, SSH 하나로 인증과 암호화가 같이 끝나는 것도 장점입니다. 반대로 앱이 원격 파일을 로컬처럼 계속 읽고 쓰는 실시간 I/O 라면 조각마다 왕복과 암호화가 붙는 SFTP 로는 못 버티니 NFS 를 씁니다.
NFS 도 결국 네트워크를 타니 왕복이 아예 없는 건 아닌데, 커널이 캐시하고 미리 당겨 오니 앱이 매번 그 왕복을 기다리지는 않습니다. 그러니 고를 때는 그 파일을 몇 번 만지는지부터 세어 보면 됩니다. 통째로 한 번 옮기고 끝이면 SFTP 고, 앱이 열어 둔 채로 계속 읽고 쓰면 NFS 입니다.
댓글 0