원격 호스트로 파일 전송하기

웹 개발자가 백엔드 또는 프론트엔드 코드를 작성하고 서버를 실행할 수 있는 애플리케이션 빌드 파일과 프론트엔드 코드를 실행할 수 있도록 빌드된 에셋 파일들을 하나의 시스템으로써 배포하기 위해서 백엔드 개발자 또는 서버 엔지니어가 구성해놓은 인프라 환경에 있는 리눅스 서버에 파일을 전송해야 합니다. 조직 또는 시스템에 대한 인프라 구성에 따라서 여러가지 방식으로 빌드 파일을 전송할 수 있는데 개인적인 경험을 토대로 원격 호스트에 빌드 파일을 전달하는 방법에 대해서 정리하려고 합니다.

TL;DR

웹 개발자 또는 서버 엔지니어가 원격 호스트에 파일을 전송하기 위해서는 SCP 또는 SFTP 명령어를 사용할 수 있으며 클라우드 서비스에서 제공하는 S3와 같은 서비스를 통해서도 외부 인터넷으로 접속이 불가능한 환경에서도 파일을 가져올 수 있습니다.

SCP

SCP 명령어는 SSH 프로토콜을 사용하여 파일을 전송하는 방법으로써 SSH 접속이 가능한 리눅스 서버로 파일을 복사하기 위해서 사용됩니다.

PS C:\Users\Mambo\docker\nginx.conf> ls

    디렉터리: C:\Users\Mambo\docker\nginx.conf

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----    2022-02-22  오전 6:49:27                static
-a----    2022-02-22  오전 6:49:27       19245297 demo-0.0.1-SNAPSHOT.jar
-a----   2022-02-22  오후 11:26:45            473 docker-compose-local.yaml
-a----   2022-02-22  오후 11:05:42            573 docker-compose.yaml
-a----   2022-02-22  오후 11:26:28            241 localhost+3-key.pem
-a----   2022-02-22  오후 11:26:28           1318 localhost+3.pem
-a----    2022-05-21  오전 8:13:15           3017 nginx-local.conf
-a----   2022-02-22  오후 11:05:40           2896 nginx.conf
-a----    2022-02-22  오전 6:49:27           2036 README.md
-a----    2022-02-22  오전 6:49:27           1436 server.crt
-a----    2022-02-22  오전 6:49:27            246 server.key

# SCP 명령어를 사용해서 로컬 컴퓨터에 있는 파일을 원격 호스트로 전송합니다.
PS C:\Users\Mambo\docker\nginx.conf> scp ./demo-0.0.1-SNAPSHOT.jar ubuntu@192.168.0.18:/home/ubuntu/java/
ubuntu@192.168.0.18's password:
demo-0.0.1-SNAPSHOT.jar                                                                                                                        100%   18MB  44.0MB/s   00:00

제 로컬 컴퓨터에는 가상 환경 머신을 통해서 실행해놓은 우분투 리눅스(192.168.0.18)이 준비되어있으며 위와 같이 demo-0.0.1-SNAPSHOT.jar 라는 빌드 파일이 존재하여 이것을 SCP 명령어를 사용해서 원격 호스트의 사용자 홈 경로 하위의 java라는 폴더에 복사하였습니다.

SFTP

일반적으로 FTP 프로토콜을 사용하여 서버와 클라이언트 간의 파일 전송을 수행하는데요. 실무에서는 SFTP를 사용하며 터미널 명령어보다는 파일질라(FileZilla)와 같은 GUI를 제공하는 FTP 클라이언트를 사용하는 편입니다. SFTP는 서버와 클라이언트 방식이므로 SCP의 단일 명령어로 파일을 전송했던 것과 다르게 대화형 명령어를 사용하여 파일을 전송할 수 있습니다.

PS C:\Users\Mambo\docker\nginx.conf> sftp ubuntu@192.168.0.18
ubuntu@192.168.0.18 password:
Connected to ubuntu@192.168.0.18.
sftp> lls

 C:\Users\Mambo\docker\nginx.conf 디렉터리

2022-02-27  오전 10:59    <DIR>          .
2022-02-27  오전 10:59    <DIR>          ..
2022-02-22  오전 06:49        19,245,297 demo-0.0.1-SNAPSHOT.jar
2022-02-22  오후 11:26               473 docker-compose-local.yaml
2022-02-22  오후 11:05               573 docker-compose.yaml
2022-02-22  오후 11:26               241 localhost+3-key.pem
2022-02-22  오후 11:26             1,318 localhost+3.pem
2022-05-21  오전 08:13             3,017 nginx-local.conf
2022-02-22  오후 11:05             2,896 nginx.conf
2022-02-22  오전 06:49             2,036 README.md
2022-02-22  오전 06:49             1,436 server.crt
2022-02-22  오전 06:49               246 server.key
2022-02-22  오전 06:49    <DIR>          static
              10개 파일          19,257,533 바이트
               3개 디렉터리  51,521,728,512 바이트 남음

# java 폴더로 이동한 후 파일을 복사합니다.
sftp> cd java
sftp> put demo-0.0.1-SNAPSHOT.jar
Uploading demo-0.0.1-SNAPSHOT.jar to /home/ubuntu/java/demo-0.0.1-SNAPSHOT.jar
demo-0.0.1-SNAPSHOT.jar                                                                                                                        100%   18MB  68.8MB/s   00:00

로컬 컴퓨터에서 명령어를 수행하기 위해서 로컬(l)이 붙은 lls를 먼저 실행하여 로컬 컴퓨터에서 바라보는 경로를 확인하고 원격 호스트에 대한 명령어를 수행해서 파일을 복사했습니다. 그러면 SCP 명령어가 있는데도 불구하고 SFTP 프로토콜을 별도로 사용하는 이유는 무엇일까요?

SFTP 프로토콜을 별도로 사용하는 이유에 대해서는 자세히 모릅니다. 다만, 개인적인 실무 경험을 토대로 이야기해보자면 배스천 호스트에 대한 SSH 접속 시 OTP로 2FA 인증을 요구하며 배스천 호스트에 대한 명령어 수행을 기록하기 위해서 SCP 명령어와 같이 인터랙션 세션이 아닌 직접 명령어를 수행하는 것은 제한되어 있을 수 있습니다.

    =============================================================
=====================================================================

 /#######                        /##     /##
| ##__  ##                      | ##    |__/
| ##  \ ##  /######   /####### /######   /##  /######  /#######
| #######  |____  ## /##_____/|_  ##_/  | ## /##__  ##| ##__  ##
| ##__  ##  /#######|  ######   | ##    | ##| ##  \ ##| ##  \ ##
| ##  \ ## /##__  ## \____  ##  | ## /##| ##| ##  | ##| ##  | ##
| #######/|  ####### /#######/  |  ####/| ##|  ######/| ##  | ##
|_______/  \_______/|_______/    \___/  |__/ \______/ |__/  |__/


=====================================================================
    =============================================================
Verification code: ******
This bastion supports interactive sessions only. Do not supply a command

이와 같은 인프라 환경에서는 SFTP 서버에 업로드되는 파일들은 배스천 호스트의 특정 경로에 마운트되어 SSH 접속을 수행한 후 SCP 명령어를 사용해서 실제 리눅스 서버로 파일을 전달할 수 있습니다. SFTP 명령어에 대한 더 자세한 내용을 알고싶은 경우 How To Use SFTP to Securely Transfer Files with a Remote Server를 참고하면 좋습니다.

S3

요즘에는 IDC와 같은 온프레미스 환경보다는 AWS와 같은 클라우드 서비스 환경에 인프라를 구성하는 경우가 많습니다. AWS 에서는 S3라는 스토리지 서비스를 제공하는데 S3 버킷에 대한 권한을 가지는 IAM의 자격증명을 사용해서 쉽게 파일을 업로드할 수 있고 EC2 인스턴스 역할에 S3 버킷에 대한 접근 권한을 부여해놓으면 EC2 인스턴스 내에서도 S3 명령어를 사용해서 파일을 가져올 수 있습니다.

# 로컬 컴퓨터에 있는 파일을 S3 버킷에 복사합니다.
aws s3 cp demo-0.0.1-SNAPSHOT.jar s3://mambo.kr/java/ --profile mambo

# EC 인스턴스 내에서 S3 버킷에 있는 파일을 복사합니다.
aws s3 cp s3://mambo.kr/java/demo-0.0.1-SNAPSHOT.jar ./

현재 조직에서는 퍼블릭 액세스가 불가능한 버킷에 도메인 인증서 또는 일부 데이터베이스에 대한 패치 스크립트 등을 업로드하고 리눅스 서버에 접속하여 해당 파일들을 복사하여 사용하고 있습니다. 퍼블릭 액세스가 가능하도록 설정된 버킷에 파일을 업로드해두면 조직의 외부로 파일을 공유해야할 때 HTTP 엔드포인트를 전달할 수 있으므로 다양하게 활용할 수도 있습니다.

이처럼 원격 호스트에 파일을 전송하는 방법은 인프라 구성에 따라서 다양하게 사용해야할 수 있습니다. IT 분야가 어려운 이유는 생각보다 다양한 부분에 대해서 정답이라는 방식이 없기 때문에 개발자마다 조직에서 어떠한 방식을 취하느냐에 따라 다양한 경험을 할 수 있다는 것에 있습니다.

감사합니다.