[2026] 파일 전송 프로토콜 완벽 가이드 | FTP·SFTP·FTPS·SMB·NFS·SCP 비교
이 글의 핵심
FTP, SFTP, FTPS, SMB/CIFS, NFS, SCP, rsync 등 파일 전송 및 공유 프로토콜의 동작 원리, 보안, 성능 비교. 실전 구현 예제와 프로덕션 배포까지 완벽 마스터.
들어가며: 파일 전송의 역사와 현대
”파일을 어떻게 안전하게 전송할까?”
서버에 파일을 업로드하거나, 팀원과 대용량 파일을 공유하거나, 백업을 원격 서버로 전송할 때 어떤 프로토콜을 사용하시나요? FTP는 오래되었지만 여전히 널리 사용되고, SFTP는 보안이 강화되었으며, SMB는 Windows 네트워크 공유의 표준입니다. 각 프로토콜마다 보안, 성능, 호환성이 다르며, 잘못 선택하면 데이터 유출이나 성능 저하가 발생합니다. 이 글에서 다루는 프로토콜:
- FTP (File Transfer Protocol)
- SFTP (SSH File Transfer Protocol)
- FTPS (FTP over SSL/TLS)
- SMB/CIFS (Server Message Block)
- NFS (Network File System)
- SCP (Secure Copy Protocol)
- rsync (Remote Sync)
실무에서 마주한 현실
개발을 배울 때는 모든 게 깔끔하고 이론적입니다. 하지만 실무는 다릅니다. 레거시 코드와 씨름하고, 급한 일정에 쫓기고, 예상치 못한 버그와 마주합니다. 이 글에서 다루는 내용도 처음엔 이론으로 배웠지만, 실제 프로젝트에 적용하면서 “아, 이래서 이렇게 설계하는구나” 하고 깨달은 것들입니다. 특히 기억에 남는 건 첫 프로젝트에서 겪은 시행착오입니다. 책에서 배운 대로 했는데 왜 안 되는지 몰라 며칠을 헤맸죠. 결국 선배 개발자의 코드 리뷰를 통해 문제를 발견했고, 그 과정에서 많은 걸 배웠습니다. 이 글에서는 이론뿐 아니라 실전에서 마주칠 수 있는 함정들과 해결 방법을 함께 다루겠습니다.
목차
1. FTP (File Transfer Protocol)
FTP란?
FTP는 1971년에 개발된 파일 전송 프로토콜로, TCP/IP 기반으로 클라이언트와 서버 간 파일을 주고받습니다.
FTP 동작 원리
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
sequenceDiagram
participant C as Client
participant CS as Control\nPort 21
participant DS as Data\nPort 20
C->>CS: USER username
CS-->>C: 331 Password required
C->>CS: PASS password
CS-->>C: 230 Login successful
C->>CS: PASV (Passive Mode)
CS-->>C: 227 Entering Passive Mode (IP,Port)
C->>DS: Connect to data port
C->>CS: LIST
CS->>DS: Send file list
DS-->>C: File list data
CS-->>C: 226 Transfer complete
C->>CS: RETR file.txt
CS->>DS: Send file data
DS-->>C: File content
CS-->>C: 226 Transfer complete
C->>CS: QUIT
CS-->>C: 221 Goodbye
FTP 모드
Active Mode (능동 모드)
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
flowchart LR
subgraph Client["Client\nIP: 192.168.1.100"]
CP["Control Port\nRandom: 50000"]
DP["Data Port\nRandom: 50001"]
end
subgraph Server["Server\nIP: 203.0.113.1"]
CS["Control Port\n21"]
DS["Data Port\n20"]
end
CP -->|1. Control Connection| CS
DS -->|2. Data Connection\nServer → Client| DP
style DS fill:#f96
style DP fill:#6cf
문제점: 클라이언트 방화벽이 서버의 연결을 차단할 수 있음
Passive Mode (수동 모드)
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
flowchart LR
subgraph Client["Client\nIP: 192.168.1.100"]
CP["Control Port\nRandom: 50000"]
DP["Data Port\nRandom: 50001"]
end
subgraph Server["Server\nIP: 203.0.113.1"]
CS["Control Port\n21"]
DS["Data Port\nRandom: 60000"]
end
CP -->|1. Control Connection| CS
DP -->|2. Data Connection\nClient → Server| DS
style DP fill:#6cf
style DS fill:#f96
장점: 클라이언트가 모든 연결을 시작하므로 방화벽 친화적
FTP 명령어
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# FTP 연결
ftp ftp.example.com
# 또는
ftp 203.0.113.1
# 로그인
Name: username
Password: ******
# 기본 명령어
ftp> ls # 디렉토리 목록
ftp> cd /path/to/dir # 디렉토리 이동
ftp> pwd # 현재 디렉토리
ftp> mkdir newdir # 디렉토리 생성
ftp> rmdir olddir # 디렉토리 삭제
# 파일 전송
ftp> get remote.txt # 다운로드
ftp> put local.txt # 업로드
ftp> mget *.txt # 여러 파일 다운로드
ftp> mput *.log # 여러 파일 업로드
# 전송 모드
ftp> binary # 바이너리 모드 (기본)
ftp> ascii # ASCII 모드
# 수동 모드
ftp> passive # Passive 모드 활성화
# 종료
ftp> bye
FTP 서버 구현 (Python)
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
def setup_ftp_server():
"""FTP 서버 설정"""
# 사용자 인증
authorizer = DummyAuthorizer()
# 사용자 추가 (username, password, homedir, perm)
authorizer.add_user("user", "12345", "/home/ftp", perm="elradfmw")
# 익명 사용자
authorizer.add_anonymous("/home/ftp/public", perm="elr")
# 핸들러 설정
handler = FTPHandler
handler.authorizer = authorizer
# 배너 설정
handler.banner = "Welcome to My FTP Server"
# Passive 모드 포트 범위
handler.passive_ports = range(60000, 60100)
# 서버 시작
server = FTPServer(("0.0.0.0", 21), handler)
# 연결 제한
server.max_cons = 256
server.max_cons_per_ip = 5
print("FTP Server running on port 21...")
server.serve_forever()
if __name__ == "__main__":
setup_ftp_server()
FTP 클라이언트 구현
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
from ftplib import FTP
import os
class FTPClient:
def __init__(self, host, username, password):
self.ftp = FTP()
self.ftp.connect(host, 21)
self.ftp.login(username, password)
print(f"✅ Connected to {host}")
def list_files(self, path='/'):
"""파일 목록 조회"""
self.ftp.cwd(path)
files = []
self.ftp.retrlines('LIST', files.append)
return files
def download_file(self, remote_path, local_path):
"""파일 다운로드"""
with open(local_path, 'wb') as f:
self.ftp.retrbinary(f'RETR {remote_path}', f.write)
print(f"✅ Downloaded: {remote_path} → {local_path}")
def upload_file(self, local_path, remote_path):
"""파일 업로드"""
with open(local_path, 'rb') as f:
self.ftp.storbinary(f'STOR {remote_path}', f)
print(f"✅ Uploaded: {local_path} → {remote_path}")
def download_directory(self, remote_dir, local_dir):
"""디렉토리 재귀 다운로드"""
os.makedirs(local_dir, exist_ok=True)
self.ftp.cwd(remote_dir)
for item in self.ftp.nlst():
local_path = os.path.join(local_dir, item)
remote_path = f"{remote_dir}/{item}"
try:
# 디렉토리인지 확인
self.ftp.cwd(remote_path)
self.ftp.cwd('..')
# 디렉토리면 재귀 호출
self.download_directory(remote_path, local_path)
except:
# 파일이면 다운로드
self.download_file(item, local_path)
def close(self):
self.ftp.quit()
print("✅ Connection closed")
# 사용 예시
client = FTPClient('ftp.example.com', 'user', 'pass')
client.list_files('/')
client.download_file('report.pdf', 'local_report.pdf')
client.upload_file('data.csv', 'remote_data.csv')
client.close()
FTP 보안 문제
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
flowchart TB
FTP[FTP 프로토콜]
subgraph Issues[보안 취약점]
I1["🔓 평문 전송\nID/PW 노출"]
I2["🔓 데이터 암호화 없음\n파일 내용 노출"]
I3["🔓 중간자 공격\nMan-in-the-Middle"]
I4["🔓 스니핑 가능\nWireshark로 캡처"]
end
subgraph Solutions[해결책]
S1["✅ SFTP 사용\nSSH 암호화"]
S2["✅ FTPS 사용\nTLS 암호화"]
S3["✅ VPN 터널링\n네트워크 암호화"]
end
FTP --> Issues
Issues --> Solutions
2. SFTP (SSH File Transfer Protocol)
SFTP란?
SFTP는 SSH 프로토콜 위에서 동작하는 파일 전송 프로토콜로, 모든 데이터가 암호화됩니다. FTP와 이름이 비슷하지만 완전히 다른 프로토콜입니다.
SFTP vs FTP
| 특성 | FTP | SFTP |
|---|---|---|
| 프로토콜 | 독립 프로토콜 | SSH 기반 |
| 포트 | 21 (제어), 20 (데이터) | 22 (단일) |
| 암호화 | ❌ 평문 | ✅ SSH 암호화 |
| 인증 | ID/PW | ID/PW, 공개키 |
| 방화벽 | 복잡 (2개 포트) | 간단 (1개 포트) |
| 속도 | 빠름 | 약간 느림 (암호화 오버헤드) |
SFTP 동작 원리
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
sequenceDiagram
participant C as Client
participant S as Server\nPort 22
C->>S: SSH 연결 요청
S-->>C: 서버 공개키
C->>S: 클라이언트 인증 (ID/PW 또는 키)
S-->>C: 인증 성공
Note over C,S: SSH 터널 내부에서 SFTP 세션
C->>S: SFTP 세션 시작
S-->>C: SFTP 프로토콜 버전
C->>S: SSH_FXP_OPENDIR /path
S-->>C: SSH_FXP_HANDLE (핸들)
C->>S: SSH_FXP_READDIR (핸들)
S-->>C: SSH_FXP_NAME (파일 목록)
C->>S: SSH_FXP_OPEN file.txt
S-->>C: SSH_FXP_HANDLE
C->>S: SSH_FXP_READ (핸들, offset, length)
S-->>C: SSH_FXP_DATA (파일 데이터)
C->>S: SSH_FXP_CLOSE (핸들)
S-->>C: SSH_FXP_STATUS OK
SFTP 명령어
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# SFTP 연결
sftp user@example.com
# 또는 포트 지정
sftp -P 2222 user@example.com
# 공개키 인증
sftp -i ~/.ssh/id_rsa user@example.com
# 기본 명령어
sftp> ls # 원격 디렉토리 목록
sftp> lls # 로컬 디렉토리 목록
sftp> cd /remote/path # 원격 디렉토리 이동
sftp> lcd /local/path # 로컬 디렉토리 이동
sftp> pwd # 원격 현재 디렉토리
sftp> lpwd # 로컬 현재 디렉토리
# 파일 전송
sftp> get remote.txt # 다운로드
sftp> put local.txt # 업로드
sftp> get -r remotedir # 디렉토리 다운로드
sftp> put -r localdir # 디렉토리 업로드
# 파일 관리
sftp> mkdir newdir # 디렉토리 생성
sftp> rmdir olddir # 디렉토리 삭제
sftp> rm file.txt # 파일 삭제
sftp> rename old.txt new.txt # 파일 이름 변경
# 권한 관리
sftp> chmod 644 file.txt # 권한 변경
sftp> chown user file.txt # 소유자 변경
# 종료
sftp> exit
SFTP 클라이언트 구현 (Python)
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
import paramiko
import os
from pathlib import Path
class SFTPClient:
def __init__(self, host, port, username, password=None, key_file=None):
"""SFTP 클라이언트 초기화"""
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
if key_file:
# 공개키 인증
private_key = paramiko.RSAKey.from_private_key_file(key_file)
self.ssh.connect(host, port, username, pkey=private_key)
else:
# 비밀번호 인증
self.ssh.connect(host, port, username, password)
self.sftp = self.ssh.open_sftp()
print(f"✅ Connected to {host}:{port}")
def list_files(self, remote_path='/'):
"""파일 목록 조회"""
return self.sftp.listdir(remote_path)
def download_file(self, remote_path, local_path):
"""파일 다운로드"""
self.sftp.get(remote_path, local_path)
print(f"✅ Downloaded: {remote_path} → {local_path}")
def upload_file(self, local_path, remote_path):
"""파일 업로드"""
self.sftp.put(local_path, remote_path)
print(f"✅ Uploaded: {local_path} → {remote_path}")
def download_directory(self, remote_dir, local_dir):
"""디렉토리 재귀 다운로드"""
os.makedirs(local_dir, exist_ok=True)
for item in self.sftp.listdir_attr(remote_dir):
remote_path = f"{remote_dir}/{item.filename}"
local_path = os.path.join(local_dir, item.filename)
if self._is_directory(item):
self.download_directory(remote_path, local_path)
else:
self.download_file(remote_path, local_path)
def upload_directory(self, local_dir, remote_dir):
"""디렉토리 재귀 업로드"""
try:
self.sftp.mkdir(remote_dir)
except IOError:
pass
for item in os.listdir(local_dir):
local_path = os.path.join(local_dir, item)
remote_path = f"{remote_dir}/{item}"
if os.path.isdir(local_path):
self.upload_directory(local_path, remote_path)
else:
self.upload_file(local_path, remote_path)
def _is_directory(self, item):
"""디렉토리 여부 확인"""
import stat
return stat.S_ISDIR(item.st_mode)
def close(self):
"""연결 종료"""
self.sftp.close()
self.ssh.close()
print("✅ Connection closed")
# 사용 예시
client = SFTPClient('example.com', 22, 'user', password='pass')
# 또는 공개키 인증
# client = SFTPClient('example.com', 22, 'user', key_file='~/.ssh/id_rsa')
files = client.list_files('/uploads')
print(files)
client.download_file('/uploads/report.pdf', 'local_report.pdf')
client.upload_file('data.csv', '/uploads/data.csv')
client.download_directory('/uploads/project', './project')
client.close()
SFTP 서버 설정 (OpenSSH)
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# /etc/ssh/sshd_config
# SFTP 서브시스템 활성화
Subsystem sftp /usr/lib/openssh/sftp-server
# SFTP 전용 사용자 생성
Match User sftpuser
ChrootDirectory /home/sftpuser
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
# 설정 적용
sudo systemctl restart sshd
3. FTPS (FTP over SSL/TLS)
FTPS란?
FTPS는 FTP에 SSL/TLS 암호화를 추가한 프로토콜로, HTTPS와 유사하게 보안 계층을 제공합니다.
FTPS 모드
Explicit FTPS (FTPES)
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
sequenceDiagram
participant C as Client
participant S as Server\nPort 21
C->>S: Connect (평문)
S-->>C: 220 Welcome
C->>S: AUTH TLS
S-->>C: 234 Proceed with negotiation
Note over C,S: TLS 핸드셰이크
C->>S: TLS ClientHello
S-->>C: TLS ServerHello, Certificate
C->>S: TLS Finished
Note over C,S: 암호화된 연결
C->>S: USER username (암호화)
S-->>C: 331 Password required
C->>S: PASS password (암호화)
S-->>C: 230 Login successful
포트: 21 (제어), 평문으로 시작 후 TLS로 업그레이드
Implicit FTPS
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
sequenceDiagram
participant C as Client
participant S as Server\nPort 990
Note over C,S: 처음부터 TLS 암호화
C->>S: TLS ClientHello
S-->>C: TLS ServerHello, Certificate
C->>S: TLS Finished
Note over C,S: 암호화된 FTP 세션
C->>S: USER username (암호화)
S-->>C: 331 Password required
C->>S: PASS password (암호화)
S-->>C: 230 Login successful
포트: 990 (제어), 처음부터 TLS 암호화
FTPS 클라이언트 (Python)
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
from ftplib import FTP_TLS
import ssl
class FTPSClient:
def __init__(self, host, username, password, implicit=False):
"""FTPS 클라이언트 초기화"""
if implicit:
# Implicit FTPS (포트 990)
context = ssl.create_default_context()
self.ftp = FTP_TLS(context=context)
self.ftp.connect(host, 990)
else:
# Explicit FTPS (포트 21)
self.ftp = FTP_TLS()
self.ftp.connect(host, 21)
self.ftp.login(username, password)
# 데이터 연결도 암호화
self.ftp.prot_p()
print(f"✅ Secure connection to {host}")
def download_file(self, remote_path, local_path):
"""파일 다운로드"""
with open(local_path, 'wb') as f:
self.ftp.retrbinary(f'RETR {remote_path}', f.write)
print(f"✅ Downloaded: {remote_path}")
def upload_file(self, local_path, remote_path):
"""파일 업로드"""
with open(local_path, 'rb') as f:
self.ftp.storbinary(f'STOR {remote_path}', f)
print(f"✅ Uploaded: {local_path}")
def close(self):
self.ftp.quit()
# 사용
client = FTPSClient('ftps.example.com', 'user', 'pass')
client.download_file('secure.pdf', 'local.pdf')
client.close()
4. SMB/CIFS (Server Message Block)
SMB란?
SMB는 Windows 네트워크 파일 공유 프로토콜로, Samba는 Linux에서 SMB를 구현한 오픈소스입니다.
SMB 버전 비교
| 버전 | 출시 | 주요 특징 |
|---|---|---|
| SMB 1.0 | 1984 | 레거시, 보안 취약점 다수 |
| SMB 2.0 | 2006 | 성능 개선, 파이프라이닝 |
| SMB 2.1 | 2010 | 대용량 MTU 지원 |
| SMB 3.0 | 2012 | 암호화, 멀티채널, RDMA |
| SMB 3.1.1 | 2015 | AES-128-GCM, 사전 인증 무결성 |
SMB 동작 원리
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
sequenceDiagram
participant C as Client
participant S as Server\nPort 445
C->>S: SMB Negotiate Protocol
S-->>C: SMB2/SMB3 지원 확인
C->>S: Session Setup (인증)
S-->>C: Session ID
C->>S: Tree Connect (\\server\share)
S-->>C: Tree ID
C->>S: Create (파일 열기)
S-->>C: File ID
C->>S: Read (File ID, offset, length)
S-->>C: File Data
C->>S: Write (File ID, offset, data)
S-->>C: Write Complete
C->>S: Close (File ID)
S-->>C: Close Complete
C->>S: Tree Disconnect
S-->>C: Disconnect OK
Samba 서버 설정
아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# Samba 설치 (Ubuntu/Debian)
sudo apt update
sudo apt install samba samba-common-bin
# Samba 사용자 추가
sudo smbpasswd -a username
# /etc/samba/smb.conf 설정
sudo nano /etc/samba/smb.conf
다음은 ini를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# /etc/samba/smb.conf
[global]
workgroup = WORKGROUP
server string = Samba Server
security = user
map to guest = Bad User
# SMB 버전 제한 (보안)
min protocol = SMB2
max protocol = SMB3
# 로깅
log file = /var/log/samba/%m.log
max log size = 50
# 성능 최적화
socket options = TCP_NODELAY IPTOS_LOWDELAY
read raw = yes
write raw = yes
# 암호화 (SMB 3.0+)
smb encrypt = desired
[public]
comment = Public Share
path = /srv/samba/public
browseable = yes
read only = yes
guest ok = yes
[private]
comment = Private Share
path = /srv/samba/private
browseable = yes
read only = no
valid users = @staff
create mask = 0660
directory mask = 0770
force group = staff
[homes]
comment = Home Directories
browseable = no
read only = no
create mask = 0700
directory mask = 0700
valid users = %S
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 디렉토리 생성 및 권한 설정
sudo mkdir -p /srv/samba/{public,private}
sudo chmod 755 /srv/samba/public
sudo chmod 770 /srv/samba/private
sudo chown -R root:staff /srv/samba/private
# Samba 서비스 재시작
sudo systemctl restart smbd
sudo systemctl enable smbd
# 방화벽 설정
sudo ufw allow 445/tcp
sudo ufw allow 139/tcp
SMB 클라이언트 (Python)
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
from smb.SMBConnection import SMBConnection
import tempfile
class SMBClient:
def __init__(self, host, username, password, domain='WORKGROUP', share_name='public'):
"""SMB 클라이언트 초기화"""
self.conn = SMBConnection(
username,
password,
'client_machine',
host,
domain=domain,
use_ntlm_v2=True,
is_direct_tcp=True
)
if not self.conn.connect(host, 445):
raise Exception("Connection failed")
self.share_name = share_name
print(f"✅ Connected to \\\\{host}\\{share_name}")
def list_files(self, path='/'):
"""파일 목록 조회"""
files = self.conn.listPath(self.share_name, path)
return [f.filename for f in files if f.filename not in ['.', '..']]
def download_file(self, remote_path, local_path):
"""파일 다운로드"""
with open(local_path, 'wb') as f:
self.conn.retrieveFile(self.share_name, remote_path, f)
print(f"✅ Downloaded: {remote_path}")
def upload_file(self, local_path, remote_path):
"""파일 업로드"""
with open(local_path, 'rb') as f:
self.conn.storeFile(self.share_name, remote_path, f)
print(f"✅ Uploaded: {local_path}")
def create_directory(self, path):
"""디렉토리 생성"""
self.conn.createDirectory(self.share_name, path)
print(f"✅ Created directory: {path}")
def delete_file(self, path):
"""파일 삭제"""
self.conn.deleteFiles(self.share_name, path)
print(f"✅ Deleted: {path}")
def close(self):
"""연결 종료"""
self.conn.close()
print("✅ Connection closed")
# 사용 예시
client = SMBClient('192.168.1.100', 'user', 'pass', share_name='shared')
files = client.list_files('/')
print(files)
client.download_file('/documents/report.pdf', 'report.pdf')
client.upload_file('data.csv', '/uploads/data.csv')
client.close()
Windows에서 SMB 공유 마운트
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# Windows (CMD)
net use Z: \\192.168.1.100\shared /user:username password
# Windows (PowerShell)
New-PSDrive -Name "Z" -PSProvider FileSystem -Root "\\192.168.1.100\shared" -Credential (Get-Credential)
# Linux (CIFS 마운트)
sudo apt install cifs-utils
sudo mount -t cifs //192.168.1.100/shared /mnt/shared -o username=user,password=pass
# 영구 마운트 (/etc/fstab)
//192.168.1.100/shared /mnt/shared cifs credentials=/etc/samba/credentials,uid=1000,gid=1000 0 0
# /etc/samba/credentials
username=user
password=pass
5. NFS (Network File System)
NFS란?
NFS는 Unix/Linux 환경에서 파일 시스템을 네트워크로 공유하는 프로토콜입니다. 로컬 파일 시스템처럼 투명하게 사용할 수 있습니다.
NFS 버전
| 버전 | 특징 |
|---|---|
| NFSv3 | UDP/TCP, Stateless, 널리 사용 |
| NFSv4 | TCP만, Stateful, 방화벽 친화적 (단일 포트 2049), ACL 지원 |
| NFSv4.1 | pNFS (병렬 NFS), 세션 관리 |
| NFSv4.2 | 서버 사이드 복사, 희소 파일 |
NFS 동작 원리
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
flowchart TB
subgraph Client[NFS Client]
App[Application]
VFS[VFS Layer]
NFSC[NFS Client]
end
subgraph Network[Network]
RPC[RPC/XDR]
end
subgraph Server[NFS Server]
NFSD[NFS Daemon]
FS[File System]
Disk[Disk]
end
App -->|read/write| VFS
VFS -->|NFS call| NFSC
NFSC -->|RPC| RPC
RPC -->|Network| NFSD
NFSD -->|I/O| FS
FS -->|Storage| Disk
NFS 서버 설정
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# NFS 서버 설치 (Ubuntu/Debian)
sudo apt install nfs-kernel-server
# 공유 디렉토리 생성
sudo mkdir -p /srv/nfs/shared
sudo chown nobody:nogroup /srv/nfs/shared
sudo chmod 755 /srv/nfs/shared
# /etc/exports 설정
sudo nano /etc/exports
다음은 bash를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# /etc/exports
# 형식: 공유경로 클라이언트(옵션)
# 특정 IP만 허용
/srv/nfs/shared 192.168.1.100(rw,sync,no_subtree_check)
# 서브넷 허용
/srv/nfs/shared 192.168.1.0/24(rw,sync,no_subtree_check)
# 읽기 전용
/srv/nfs/public 192.168.1.0/24(ro,sync,no_subtree_check)
# 여러 클라이언트
/srv/nfs/shared 192.168.1.100(rw,sync) 192.168.1.101(rw,sync)
# 옵션 설명:
# rw: 읽기/쓰기 허용
# ro: 읽기만 허용
# sync: 동기 쓰기 (데이터 무결성)
# async: 비동기 쓰기 (성능 향상, 위험)
# no_subtree_check: 서브트리 검사 비활성화 (성능)
# root_squash: root를 nobody로 매핑 (보안)
# no_root_squash: root 권한 유지 (위험)
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# exports 적용
sudo exportfs -ra
# 현재 공유 목록 확인
sudo exportfs -v
# NFS 서버 시작
sudo systemctl start nfs-kernel-server
sudo systemctl enable nfs-kernel-server
# 방화벽 설정
sudo ufw allow from 192.168.1.0/24 to any port nfs
NFS 클라이언트 마운트
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# NFS 클라이언트 설치
sudo apt install nfs-common
# 마운트
sudo mkdir -p /mnt/nfs/shared
sudo mount -t nfs 192.168.1.100:/srv/nfs/shared /mnt/nfs/shared
# 옵션 지정
sudo mount -t nfs -o rw,hard,intr,timeo=600 192.168.1.100:/srv/nfs/shared /mnt/nfs/shared
# 영구 마운트 (/etc/fstab)
192.168.1.100:/srv/nfs/shared /mnt/nfs/shared nfs defaults,_netdev 0 0
# 마운트 확인
df -h | grep nfs
mount | grep nfs
# 언마운트
sudo umount /mnt/nfs/shared
NFS 성능 최적화
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# /etc/fstab 최적화 옵션
192.168.1.100:/srv/nfs/shared /mnt/nfs/shared nfs rw,hard,intr,rsize=32768,wsize=32768,timeo=600,retrans=2,_netdev 0 0
# 옵션 설명:
# rsize=32768: 읽기 버퍼 크기 (32KB)
# wsize=32768: 쓰기 버퍼 크기 (32KB)
# hard: 서버 응답 없으면 무한 재시도 (데이터 무결성)
# soft: 타임아웃 후 에러 반환 (성능)
# intr: 인터럽트 가능
# timeo=600: 타임아웃 (0.1초 단위, 60초)
# retrans=2: 재전송 횟수
# _netdev: 네트워크 활성화 후 마운트
6. SCP와 rsync
SCP (Secure Copy Protocol)
SCP는 SSH를 사용하여 파일을 안전하게 복사하는 프로토콜입니다. 다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 기본 사용법
scp local.txt user@example.com:/remote/path/
# 원격 → 로컬
scp user@example.com:/remote/file.txt ./local.txt
# 디렉토리 복사 (재귀)
scp -r localdir/ user@example.com:/remote/path/
# 포트 지정
scp -P 2222 file.txt user@example.com:/path/
# 공개키 인증
scp -i ~/.ssh/id_rsa file.txt user@example.com:/path/
# 대역폭 제한 (KB/s)
scp -l 1024 large.zip user@example.com:/path/
# 압축 전송
scp -C large.tar user@example.com:/path/
# 진행률 표시
scp -v file.txt user@example.com:/path/
# 여러 파일
scp file1.txt file2.txt user@example.com:/path/
# 와일드카드
scp *.log user@example.com:/logs/
rsync (Remote Sync)
rsync는 효율적인 파일 동기화 도구로, 변경된 부분만 전송합니다. 다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 기본 사용법
rsync -avz localdir/ user@example.com:/remote/path/
# 옵션 설명:
# -a: archive (권한, 타임스탬프, 심볼릭 링크 유지)
# -v: verbose (진행 상황 표시)
# -z: compress (압축 전송)
# -h: human-readable (사람이 읽기 쉬운 크기)
# -P: progress + partial (진행률 + 중단된 전송 재개)
# --delete: 원본에 없는 파일 삭제 (동기화)
# 진행률 표시
rsync -avzP localdir/ user@example.com:/remote/path/
# 삭제 동기화
rsync -avz --delete localdir/ user@example.com:/remote/path/
# Dry-run (실제 전송 없이 테스트)
rsync -avzn localdir/ user@example.com:/remote/path/
# 특정 파일 제외
rsync -avz --exclude='*.log' --exclude='node_modules/' localdir/ user@example.com:/remote/
# SSH 포트 지정
rsync -avz -e "ssh -p 2222" localdir/ user@example.com:/remote/
# 대역폭 제한 (KB/s)
rsync -avz --bwlimit=1024 localdir/ user@example.com:/remote/
# 로컬 동기화
rsync -avz /source/ /destination/
# 백업 (타임스탬프 디렉토리)
rsync -avz --backup --backup-dir=/backup/$(date +%Y%m%d) /source/ /destination/
rsync 고급 사용
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 증분 백업 (하드링크 사용)
#!/bin/bash
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d_%H%M%S)
LATEST="$BACKUP_DIR/latest"
CURRENT="$BACKUP_DIR/$DATE"
rsync -avz --delete \
--link-dest="$LATEST" \
/source/ \
"$CURRENT/"
# 심볼릭 링크 업데이트
rm -f "$LATEST"
ln -s "$CURRENT" "$LATEST"
echo "✅ Backup completed: $CURRENT"
# 원격 서버 백업
#!/bin/bash
rsync -avz --delete \
-e "ssh -i ~/.ssh/backup_key" \
--exclude='*.tmp' \
--exclude='cache/' \
/var/www/ \
backup@backup-server.com:/backups/www/
# 양방향 동기화 (주의: 충돌 가능)
rsync -avz --delete /local/ user@remote:/remote/
rsync -avz --delete user@remote:/remote/ /local/
7. 프로토콜 비교
종합 비교표
| 프로토콜 | 포트 | 암호화 | 속도 | 사용 사례 | 장점 | 단점 |
|---|---|---|---|---|---|---|
| FTP | 21, 20 | ❌ | ⭐⭐⭐⭐⭐ | 레거시 시스템 | 빠름, 간단 | 보안 취약 |
| SFTP | 22 | ✅ SSH | ⭐⭐⭐⭐ | 안전한 파일 전송 | 보안, 방화벽 친화적 | 약간 느림 |
| FTPS | 21, 990 | ✅ TLS | ⭐⭐⭐⭐ | 레거시 FTP 보안 | FTP 호환 | 복잡한 방화벽 |
| SMB | 445 | ✅ (v3+) | ⭐⭐⭐⭐ | Windows 공유 | 권한 관리 강력 | Windows 중심 |
| NFS | 2049 | ✅ (v4+) | ⭐⭐⭐⭐⭐ | Linux 서버 공유 | 빠름, 투명 | Unix 중심 |
| SCP | 22 | ✅ SSH | ⭐⭐⭐ | 간단한 파일 복사 | 간단, 안전 | 동기화 불가 |
| rsync | 22, 873 | ✅ SSH | ⭐⭐⭐⭐⭐ | 파일 동기화, 백업 | 증분 전송, 효율적 | 초기 학습 곡선 |
보안 비교
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
flowchart TB
subgraph Insecure[🔓 암호화 없음]
FTP["FTP\n평문 전송"]
NFSv3["NFSv3\n기본 암호화 없음"]
end
subgraph Secure[🔒 암호화 지원]
SFTP["SFTP\nSSH 암호화"]
FTPS["FTPS\nTLS 암호화"]
SMB3["SMB 3.0+\nAES 암호화"]
NFSv4["NFSv4\nKerberos"]
SCP["SCP\nSSH 암호화"]
RSYNC["rsync over SSH\nSSH 암호화"]
end
style Insecure fill:#fcc
style Secure fill:#cfc
성능 비교 (벤치마크)
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#!/bin/bash
# 1GB 파일 전송 벤치마크
FILE="test_1gb.bin"
dd if=/dev/urandom of=$FILE bs=1M count=1024
echo "=== FTP ==="
time ftp -n <<EOF
open ftp.example.com
user username password
binary
put $FILE
bye
EOF
echo "=== SFTP ==="
time sftp user@example.com <<EOF
put $FILE
bye
EOF
echo "=== SCP ==="
time scp $FILE user@example.com:/tmp/
echo "=== rsync ==="
time rsync -avz $FILE user@example.com:/tmp/
echo "=== SMB ==="
time cp $FILE /mnt/smb/
echo "=== NFS ==="
time cp $FILE /mnt/nfs/
# 일반적인 결과 (1Gbps 네트워크):
# FTP: ~10초 (가장 빠름)
# NFS: ~12초
# SMB: ~15초
# rsync: ~18초 (압축 오버헤드)
# SFTP: ~20초 (암호화 오버헤드)
# SCP: ~22초
8. 실전 구현
시나리오 1: 자동 백업 스크립트
다음은 bash를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#!/bin/bash
# backup.sh - 일일 백업 스크립트
BACKUP_DATE=$(date +%Y%m%d)
SOURCE="/var/www"
REMOTE_HOST="backup.example.com"
REMOTE_USER="backup"
REMOTE_PATH="/backups/www"
LOG_FILE="/var/log/backup.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "Starting backup..."
# rsync로 증분 백업
rsync -avz --delete \
--exclude='*.tmp' \
--exclude='cache/' \
--exclude='node_modules/' \
--backup --backup-dir="$REMOTE_PATH/deleted_$BACKUP_DATE" \
-e "ssh -i /root/.ssh/backup_key -o StrictHostKeyChecking=no" \
"$SOURCE/" \
"$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/current/" \
2>&1 | tee -a "$LOG_FILE"
if [ ${PIPESTATUS[0]} -eq 0 ]; then
log "✅ Backup completed successfully"
# 원격 서버에서 7일 이상 된 백업 삭제
ssh -i /root/.ssh/backup_key "$REMOTE_USER@$REMOTE_HOST" \
"find $REMOTE_PATH/deleted_* -mtime +7 -delete"
log "✅ Old backups cleaned"
else
log "❌ Backup failed"
exit 1
fi
아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# crontab 등록
crontab -e
# 매일 새벽 2시 백업
0 2 * * * /usr/local/bin/backup.sh
시나리오 2: 파일 업로드 서버
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#!/usr/bin/env python3
"""
멀티 프로토콜 파일 업로드 서버
"""
import paramiko
from ftplib import FTP_TLS
import os
from pathlib import Path
class FileUploadServer:
def __init__(self, protocol='sftp', host='localhost', username='user', password='pass'):
self.protocol = protocol
self.host = host
self.username = username
self.password = password
self.client = None
if protocol == 'sftp':
self._connect_sftp()
elif protocol == 'ftps':
self._connect_ftps()
else:
raise ValueError(f"Unsupported protocol: {protocol}")
def _connect_sftp(self):
"""SFTP 연결"""
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(self.host, 22, self.username, self.password)
self.client = ssh.open_sftp()
print(f"✅ SFTP connected to {self.host}")
def _connect_ftps(self):
"""FTPS 연결"""
self.client = FTP_TLS()
self.client.connect(self.host, 21)
self.client.login(self.username, self.password)
self.client.prot_p()
print(f"✅ FTPS connected to {self.host}")
def upload_with_progress(self, local_path, remote_path):
"""진행률 표시 업로드"""
file_size = os.path.getsize(local_path)
uploaded = 0
def callback(data):
nonlocal uploaded
uploaded += len(data)
progress = (uploaded / file_size) * 100
print(f"\rUploading: {progress:.1f}%", end=')
with open(local_path, 'rb') as f:
if self.protocol == 'sftp':
self.client.putfo(f, remote_path, callback=lambda x, y: callback(b'))
elif self.protocol == 'ftps':
self.client.storbinary(f'STOR {remote_path}', f, callback=callback)
print(f"\n✅ Uploaded: {local_path} → {remote_path}")
def upload_directory(self, local_dir, remote_dir):
"""디렉토리 재귀 업로드"""
for root, dirs, files in os.walk(local_dir):
rel_path = os.path.relpath(root, local_dir)
remote_root = os.path.join(remote_dir, rel_path).replace('\\', '/')
# 디렉토리 생성
try:
if self.protocol == 'sftp':
self.client.mkdir(remote_root)
elif self.protocol == 'ftps':
self.client.mkd(remote_root)
except:
pass
# 파일 업로드
for file in files:
local_path = os.path.join(root, file)
remote_path = os.path.join(remote_root, file).replace('\\', '/')
self.upload_with_progress(local_path, remote_path)
def close(self):
"""연결 종료"""
if self.client:
self.client.close()
print("✅ Connection closed")
# 사용 예시
uploader = FileUploadServer('sftp', 'example.com', 'user', 'pass')
uploader.upload_with_progress('large_file.zip', '/uploads/large_file.zip')
uploader.upload_directory('./project', '/uploads/project')
uploader.close()
시나리오 3: 파일 동기화 데몬
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 함수를 통해 로직을 구현합니다, 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#!/usr/bin/env python3
"""
파일 변경 감지 및 자동 동기화
"""
import time
import subprocess
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class SyncHandler(FileSystemEventHandler):
def __init__(self, local_dir, remote_host, remote_user, remote_dir):
self.local_dir = local_dir
self.remote_host = remote_host
self.remote_user = remote_user
self.remote_dir = remote_dir
self.last_sync = 0
self.sync_interval = 5
def on_any_event(self, event):
"""파일 변경 감지"""
current_time = time.time()
if current_time - self.last_sync < self.sync_interval:
return
if event.is_directory:
return
print(f"📁 File changed: {event.src_path}")
self.sync()
self.last_sync = current_time
def sync(self):
"""rsync로 동기화"""
cmd = [
'rsync',
'-avz',
'--delete',
'--exclude=.git/',
'--exclude=node_modules/',
f'{self.local_dir}/',
f'{self.remote_user}@{self.remote_host}:{self.remote_dir}/'
]
try:
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
print("✅ Sync completed")
else:
print(f"❌ Sync failed: {result.stderr}")
except Exception as e:
print(f"❌ Error: {e}")
def main():
"""파일 감시 시작"""
local_dir = '/var/www/html'
remote_host = 'backup.example.com'
remote_user = 'backup'
remote_dir = '/backups/www'
event_handler = SyncHandler(local_dir, remote_host, remote_user, remote_dir)
observer = Observer()
observer.schedule(event_handler, local_dir, recursive=True)
observer.start()
print(f"👀 Watching {local_dir} for changes...")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
print("\n✅ Stopped watching")
observer.join()
if __name__ == "__main__":
main()
실전 시나리오
시나리오 4: Docker 컨테이너에서 SFTP 서버
다음은 dockerfile를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# Dockerfile
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
openssh-server \
&& rm -rf /var/lib/apt/lists/*
# SFTP 전용 사용자 생성
RUN useradd -m -d /home/sftpuser -s /bin/bash sftpuser && \
echo "sftpuser:password" | chpasswd && \
mkdir -p /home/sftpuser/uploads && \
chown root:root /home/sftpuser && \
chmod 755 /home/sftpuser && \
chown sftpuser:sftpuser /home/sftpuser/uploads
# SSH 설정
RUN mkdir /var/run/sshd && \
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config
# SFTP 전용 설정 추가
RUN echo "\n\
Match User sftpuser\n\
ChrootDirectory /home/sftpuser\n\
ForceCommand internal-sftp\n\
AllowTcpForwarding no\n\
X11Forwarding no\n\
" >> /etc/ssh/sshd_config
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
아래 코드는 yaml를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# docker-compose.yml
version: '3.8'
services:
sftp:
build: .
ports:
- "2222:22"
volumes:
- ./uploads:/home/sftpuser/uploads
environment:
- SFTP_USERS=user:pass:1001
restart: unless-stopped
아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# 빌드 및 실행
docker-compose up -d
# 연결 테스트
sftp -P 2222 sftpuser@localhost
시나리오 5: 멀티 프로토콜 파일 서버
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#!/usr/bin/env python3
"""
통합 파일 서버 (SFTP + FTPS + HTTP)
"""
import asyncio
from aiohttp import web
import paramiko
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import TLS_FTPHandler
from pyftpdlib.servers import FTPServer
import threading
class MultiProtocolFileServer:
def __init__(self, base_dir='/srv/files'):
self.base_dir = base_dir
def start_sftp_server(self):
"""SFTP 서버 시작"""
class SFTPServer(paramiko.ServerInterface):
def check_auth_password(self, username, password):
if username == 'user' and password == 'pass':
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
# SSH 서버 설정
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('0.0.0.0', 2222))
sock.listen(10)
print("✅ SFTP Server running on port 2222")
while True:
client, addr = sock.accept()
print(f"📥 SFTP connection from {addr}")
# 클라이언트 처리 (생략)
def start_ftps_server(self):
"""FTPS 서버 시작"""
authorizer = DummyAuthorizer()
authorizer.add_user("user", "pass", self.base_dir, perm="elradfmw")
handler = TLS_FTPHandler
handler.authorizer = authorizer
handler.certfile = '/etc/ssl/certs/server.crt'
handler.keyfile = '/etc/ssl/private/server.key'
handler.tls_control_required = True
handler.tls_data_required = True
server = FTPServer(('0.0.0.0', 990), handler)
print("✅ FTPS Server running on port 990")
server.serve_forever()
async def start_http_server(self):
"""HTTP 파일 다운로드 서버"""
async def download(request):
filename = request.match_info['filename']
filepath = os.path.join(self.base_dir, filename)
if not os.path.exists(filepath):
return web.Response(status=404, text="File not found")
return web.FileResponse(filepath)
app = web.Application()
app.router.add_get('/download/{filename}', download)
runner = web.AppRunner(app)
await runner.setup()
site = web.TCPSite(runner, '0.0.0.0', 8080)
await site.start()
print("✅ HTTP Server running on port 8080")
await asyncio.Event().wait()
def start(self):
"""모든 서버 시작"""
# FTPS 서버 (별도 스레드)
ftps_thread = threading.Thread(target=self.start_ftps_server, daemon=True)
ftps_thread.start()
# HTTP 서버 (asyncio)
asyncio.run(self.start_http_server())
if __name__ == "__main__":
server = MultiProtocolFileServer('/srv/files')
server.start()
시나리오 6: 파일 전송 모니터링
다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#!/usr/bin/env python3
"""
파일 전송 모니터링 및 알림
"""
import paramiko
import time
from datetime import datetime
import smtplib
from email.mime.text import MIMEText
class TransferMonitor:
def __init__(self, sftp_host, sftp_user, sftp_pass, watch_dir='/uploads'):
self.sftp_host = sftp_host
self.sftp_user = sftp_user
self.sftp_pass = sftp_pass
self.watch_dir = watch_dir
self.known_files = set()
def connect(self):
"""SFTP 연결"""
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(self.sftp_host, 22, self.sftp_user, self.sftp_pass)
self.sftp = ssh.open_sftp()
def check_new_files(self):
"""새 파일 확인"""
try:
files = set(self.sftp.listdir(self.watch_dir))
new_files = files - self.known_files
if new_files:
for file in new_files:
file_path = f"{self.watch_dir}/{file}"
stat = self.sftp.stat(file_path)
size = stat.st_size
mtime = datetime.fromtimestamp(stat.st_mtime)
print(f"📥 New file: {file} ({size} bytes) at {mtime}")
self.send_notification(file, size, mtime)
self.known_files = files
except Exception as e:
print(f"❌ Error: {e}")
def send_notification(self, filename, size, mtime):
"""이메일 알림"""
msg = MIMEText(f"""
새 파일이 업로드되었습니다.
파일명: {filename}
크기: {size:,} bytes
시간: {mtime}
경로: {self.watch_dir}/{filename}
""")
msg['Subject'] = f'[파일 업로드] {filename}'
msg['From'] = 'monitor@example.com'
msg['To'] = 'admin@example.com'
try:
with smtplib.SMTP('localhost', 25) as smtp:
smtp.send_message(msg)
print(f"✅ Notification sent for {filename}")
except Exception as e:
print(f"❌ Failed to send notification: {e}")
def monitor(self, interval=60):
"""주기적 모니터링"""
self.connect()
print(f"👀 Monitoring {self.watch_dir} every {interval}s...")
try:
while True:
self.check_new_files()
time.sleep(interval)
except KeyboardInterrupt:
print("\n✅ Monitoring stopped")
finally:
self.sftp.close()
# 사용
monitor = TransferMonitor('sftp.example.com', 'user', 'pass')
monitor.monitor(interval=60)
보안 베스트 프랙티스
1. 공개키 인증 설정
다음은 bash를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 클라이언트에서 키 생성
ssh-keygen -t ed25519 -C "backup@example.com"
# 또는 RSA
ssh-keygen -t rsa -b 4096 -C "backup@example.com"
# 공개키를 서버에 복사
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@example.com
# 또는 수동 복사
cat ~/.ssh/id_ed25519.pub | ssh user@example.com "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
# 서버에서 비밀번호 인증 비활성화
# /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
sudo systemctl restart sshd
2. Chroot Jail 설정
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# SFTP 사용자를 특정 디렉토리에 격리
# /etc/ssh/sshd_config
Match User sftpuser
ChrootDirectory /home/sftpuser
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
# 디렉토리 권한 (중요!)
sudo chown root:root /home/sftpuser
sudo chmod 755 /home/sftpuser
# 쓰기 가능한 하위 디렉토리
sudo mkdir /home/sftpuser/uploads
sudo chown sftpuser:sftpuser /home/sftpuser/uploads
sudo chmod 755 /home/sftpuser/uploads
3. 방화벽 설정
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# UFW (Ubuntu)
# SFTP (SSH)
sudo ufw allow 22/tcp
# FTPS (Explicit)
sudo ufw allow 21/tcp
sudo ufw allow 60000:60100/tcp
# FTPS (Implicit)
sudo ufw allow 990/tcp
# SMB
sudo ufw allow 445/tcp
sudo ufw allow 139/tcp
# NFS
sudo ufw allow 2049/tcp
# 특정 IP만 허용
sudo ufw allow from 192.168.1.0/24 to any port 22
성능 최적화
1. 대용량 파일 전송
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# rsync 최적화
rsync -avz \
--compress-level=1 \
--partial \
--progress \
--bwlimit=10000 \
--timeout=300 \
large_file.zip user@example.com:/path/
# SCP 압축 비활성화 (이미 압축된 파일)
scp -o "Compression no" archive.zip user@example.com:/path/
# 병렬 전송 (GNU Parallel)
find . -type f | parallel -j 4 scp {} user@example.com:/path/{}
2. 네트워크 튜닝
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# TCP 윈도우 크기 증가
sudo sysctl -w net.ipv4.tcp_window_scaling=1
sudo sysctl -w net.core.rmem_max=134217728
sudo sysctl -w net.core.wmem_max=134217728
sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 67108864"
sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 67108864"
# /etc/sysctl.conf에 영구 적용
net.ipv4.tcp_window_scaling = 1
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
3. SMB 성능 최적화
다음은 ini를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# /etc/samba/smb.conf
[global]
# 성능 최적화
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=131072 SO_SNDBUF=131072
read raw = yes
write raw = yes
max xmit = 65535
dead time = 15
getwd cache = yes
# SMB 3.0 멀티채널
server multi channel support = yes
# 비동기 I/O
aio read size = 16384
aio write size = 16384
문제 해결
문제 1: FTP Passive 모드 연결 실패
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 증상
ftp> ls
425 Failed to establish connection
# 원인: 방화벽이 데이터 포트 차단
# 해결: 서버에서 Passive 포트 범위 설정
# /etc/vsftpd.conf
pasv_enable=YES
pasv_min_port=60000
pasv_max_port=60100
# 방화벽 허용
sudo ufw allow 60000:60100/tcp
# 재시작
sudo systemctl restart vsftpd
문제 2: SFTP 권한 거부
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 증상
sftp> put file.txt
Couldn't open file "/file.txt": Permission denied
# 원인: Chroot 디렉토리 권한 문제
# 해결: 상위 디렉토리는 root 소유, 하위는 사용자 소유
sudo chown root:root /home/sftpuser
sudo chmod 755 /home/sftpuser
sudo chown sftpuser:sftpuser /home/sftpuser/uploads
sudo chmod 755 /home/sftpuser/uploads
문제 3: SMB 느린 전송 속도
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 증상: 10MB/s 이하의 느린 속도
# 원인 1: SMB 1.0 사용 (레거시)
# 해결: SMB 2/3 강제
# /etc/samba/smb.conf
min protocol = SMB2
max protocol = SMB3
# 원인 2: 작은 MTU
# 해결: MTU 확인 및 증가
ip link show eth0
sudo ip link set eth0 mtu 9000
# 원인 3: TCP 윈도우 크기
# 해결: 위 네트워크 튜닝 섹션 참고
문제 4: NFS Stale File Handle
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 증상
ls: cannot access '/mnt/nfs': Stale file handle
# 원인: NFS 서버 재시작 또는 네트워크 끊김
# 해결 1: 언마운트 후 재마운트
sudo umount -f /mnt/nfs
sudo mount /mnt/nfs
# 해결 2: 강제 언마운트
sudo umount -l /mnt/nfs
# 예방: hard 마운트 + intr 옵션
# /etc/fstab
192.168.1.100:/srv/nfs /mnt/nfs nfs hard,intr,timeo=600 0 0
프로토콜 선택 가이드
의사 결정 플로우차트
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
flowchart TD
Start[파일 전송 프로토콜 선택] --> Q1{용도는?}
Q1 -->|파일 전송| Q2{보안 필요?}
Q1 -->|파일 공유| Q3{OS는?}
Q1 -->|백업/동기화| RSYNC["✅ rsync\n증분 전송"]
Q2 -->|Yes| Q4{기존 인프라는?}
Q2 -->|No| FTP["⚠️ FTP\n레거시만"]
Q4 -->|SSH 있음| SFTP["✅ SFTP\n가장 안전"]
Q4 -->|FTP 있음| FTPS["✅ FTPS\nTLS 추가"]
Q4 -->|새로 구축| SFTP
Q3 -->|Windows| SMB["✅ SMB/CIFS\n네트워크 드라이브"]
Q3 -->|Linux| NFS["✅ NFS\n고성능"]
Q3 -->|혼합| SMB2["✅ SMB\n크로스 플랫폼"]
사용 사례별 추천
다음은 code를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
✅ 웹 호스팅 파일 업로드:
→ SFTP (보안) 또는 rsync (자동화)
✅ 팀 파일 공유:
→ SMB (Windows) 또는 NFS (Linux)
✅ 서버 간 백업:
→ rsync over SSH (증분 백업)
✅ 레거시 시스템 연동:
→ FTPS (FTP 호환 + 보안)
✅ 대용량 미디어 파일:
→ NFS (성능) 또는 SMB 3.0 (멀티채널)
✅ 간단한 파일 복사:
→ SCP (한 번만 전송)
✅ CI/CD 파이프라인:
→ rsync 또는 SFTP (자동화)
✅ 클라우드 스토리지 동기화:
→ rclone (S3, GCS, Azure 지원)
고급 주제
rclone (클라우드 스토리지)
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# rclone 설치
curl https://rclone.org/install.sh | sudo bash
# 설정
rclone config
# S3 동기화
rclone sync /local/path s3:bucket-name/path
# Google Drive
rclone sync /local/path gdrive:folder
# 양방향 동기화 (주의: 충돌 가능)
rclone bisync /local/path remote:path
# 암호화 래퍼
rclone sync /local/path crypt:encrypted-remote
SSHFS (SSH File System)
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# SSHFS 설치
sudo apt install sshfs
# 마운트
sshfs user@example.com:/remote/path /mnt/sshfs
# 언마운트
fusermount -u /mnt/sshfs
# 옵션
sshfs -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3 \
user@example.com:/remote /mnt/sshfs
WebDAV
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# WebDAV 서버 (Nginx)
location /webdav {
root /srv/webdav;
client_body_temp_path /tmp;
dav_methods PUT DELETE MKCOL COPY MOVE;
dav_ext_methods PROPFIND OPTIONS;
dav_access user:rw group:rw all:r;
auth_basic "WebDAV";
auth_basic_user_file /etc/nginx/.htpasswd;
create_full_put_path on;
client_max_body_size 0;
}
# 클라이언트 (Linux)
sudo apt install davfs2
sudo mount -t davfs https://example.com/webdav /mnt/webdav
정리
프로토콜 선택 체크리스트
다음은 code를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
📋 FTP
- [ ] 보안이 중요하지 않음
- [ ] 레거시 시스템과 호환 필요
- [ ] 최대 성능 필요
- [ ] 내부 네트워크만 사용
📋 SFTP
- [ ] 보안이 최우선
- [ ] SSH 인프라 있음
- [ ] 방화벽 친화적 필요
- [ ] 공개키 인증 사용
📋 FTPS
- [ ] 기존 FTP 인프라 유지
- [ ] TLS 암호화 추가
- [ ] 레거시 클라이언트 지원
📋 SMB/CIFS
- [ ] Windows 파일 공유
- [ ] 네트워크 드라이브 필요
- [ ] 권한 관리 중요
- [ ] Active Directory 통합
📋 NFS
- [ ] Linux 서버 간 공유
- [ ] 고성능 필요
- [ ] 투명한 파일 시스템 접근
- [ ] 내부 네트워크
📋 rsync
- [ ] 파일 동기화
- [ ] 증분 백업
- [ ] 대역폭 절약
- [ ] 자동화 스크립트
핵심 명령어 치트시트
다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# FTP
ftp ftp.example.com
ftp> get file.txt
ftp> put file.txt
# SFTP
sftp user@example.com
sftp> get file.txt
sftp> put file.txt
# SCP
scp file.txt user@example.com:/path/
scp user@example.com:/path/file.txt ./
# rsync
rsync -avz localdir/ user@example.com:/remote/
rsync -avz --delete localdir/ user@example.com:/remote/
# SMB 마운트
sudo mount -t cifs //server/share /mnt/smb -o username=user
# NFS 마운트
sudo mount -t nfs server:/export /mnt/nfs
참고 자료
- RFC 959 - FTP
- RFC 4253 - SSH Protocol
- SMB Protocol Documentation
- NFS RFC 7530
- Samba Documentation
- rsync Manual 한 줄 요약: 보안이 중요하면 SFTP, Windows 공유는 SMB, Linux 서버는 NFS, 백업은 rsync를 사용하되, 각 프로토콜의 특성을 이해하고 요구사항에 맞게 선택하세요.