> ## Content Index
> Fetch the complete content index at: https://mlog.me/llms.txt
> Use this file to discover other available public pages before exploring further.

# scp로 서버 파일을 내 PC에 가져오기: -P 포트·저장 경로·권한 오류 구분
- URL: https://mlog.me/scp-server-file-download-port-path-permission/
- Published: 2026-11-06T06:10:26.000Z
- Updated: 2026-11-06T06:10:26.000Z
- Description: scp로 서버 파일을 내 PC에 가져오는 명령을 정리합니다. -P와 -p, 명령 실행 위치, 폴더·공백 경로, Permission denied를 구분하고 다운로드 결과를 확인합니다.
- Author: mLog
- Tags: 서버·인프라, SSH, Linux

서버의 파일을 내 PC로 내려받으려면 **내 PC 터미널에서 원격 파일을 앞에, 로컬 저장 위치를 뒤에** 둔다. 접속 포트를 지정할 때는 `scp -P`처럼 대문자 `P`를 쓴다.

아래는 macOS·Linux의 Bash/zsh 계열 터미널에서 사용할 명령 예시다. `server.example.net`, `ubuntu`, `2222`, 키 파일과 원격 경로는 모두 설명용이다. 실제 접속에 사용하는 값으로 바꾼다. Windows PowerShell의 드라이브 경로 표기는 이 글의 범위에서 제외한다.

이 글의 오류와 전송 결과는 별도로 만든 Linux 로컬 시험 환경에서 확인했다. 개인 운영 서버나 Mac에서 같은 장애를 겪고 해결했다는 사례로 쓰지 않았다.

## 1\. 먼저 내 PC에 새 저장 폴더를 만든다

**같은 이름의 로컬 파일이 있으면 덮어쓸 수 있다.** 아래 예제는 매번 다른 임시 이름의 수신 폴더를 만들어 기존 파일과 섞이지 않게 한다. 생성된 폴더는 명령이 끝나도 남아 있다.

내 PC의 새 터미널 탭에서 실행한다.

```sh
mkdir -p "$HOME/Downloads" &&
dest=$(mktemp -d "$HOME/Downloads/scp-receive.XXXXXX") &&
scp -P 2222 -i "$HOME/.ssh/id_ed25519" \
  'ubuntu@server.example.net:/home/ubuntu/export/report.txt' \
  "$dest/" &&
printf '저장 위치: %s\n' "$dest"

```

`&&` 뒤의 명령은 앞의 명령이 성공했을 때만 실행된다. 마지막 저장 위치가 출력됐다면 그 폴더에서 `report.txt`를 확인한다. `dest` 변수는 이 명령을 실행한 셸에 있으므로, 아래 예제들도 같은 터미널 탭에서 이어서 사용한다.

키 파일은 서버의 공개키 파일이 아니라 **내 PC가 인증에 사용하는 개인키**다. 평소 SSH에서 다른 키 파일을 지정했다면 그 경로를 넣는다. 이미 SSH 설정 별칭을 사용한다면 뒤의 별칭 예제를 쓰면 된다.

명령은 다음 순서로 읽으면 된다.

- `-P 2222`: 원격 SSH 접속 포트.
- `-i ...`: 로컬 인증 키 경로.
- `ubuntu@server.example.net:/home/ubuntu/export/report.txt`: 가져올 원격 파일.
- `"$dest/"`: 내 PC에 만든 수신 폴더.

일반적인 `사용자@호스트:경로` 표기에서는 콜론 뒤가 파일 경로다. `호스트:2222:/경로`처럼 포트를 끼워 넣지 않는다. 이 글은 별도의 `scp://` URI 문법을 사용하지 않는다.

OpenSSH의 [scp 공식 매뉴얼](https://man.openbsd.org/scp?ref=mlog.me)은 원본과 대상의 표기, `-P`, `-i` 등의 옵션을 설명한다.

## 2\. 서버에 로그인한 창에서 실행하면 내 PC로 오지 않는다

`로컬`은 항상 내 노트북이라는 뜻이 아니다. **지금 scp 프로세스를 실행하는 컴퓨터**다.

예를 들어 서버에 SSH로 로그인한 상태에서 다른 서버의 파일을 `.`으로 받으면, 파일은 그 SSH 세션이 실행 중인 서버의 현재 디렉터리에 놓인다. 내 PC의 다운로드 폴더로 보내라는 의미는 없다.

먼저 명령 실행 위치를 확인한다.

```sh
hostname
pwd

```

서버 셸을 보고 있다면 내 PC에서 새 터미널 탭을 여는 편이 명확하다. SSH 세션에서 `exit`해 로컬 셸로 돌아올 수도 있지만, 중첩해서 접속했다면 한 번의 `exit`만으로 내 PC가 아닐 수 있다. 다시 호스트와 경로를 확인한다.

이번 재현에서는 클라이언트의 작업 디렉터리를 별도 폴더로 바꾸고 목적지에 `.`을 넣었다. 받은 파일은 실제로 그 폴더에 생성됐다. 전송이 성공했는데 파일을 못 찾는다면, 서버 파일을 다시 지우거나 재전송하기 전에 **scp를 실행한 컴퓨터와 목적지 경로**부터 찾자.

## 3\. SSH의 -p와 scp의 -P를 구분한다

같은 서버를 대상으로 해도 포트 옵션 표기는 다르다.

```sh
# 로그인 또는 원격 명령: 소문자 p
ssh -p 2222 -i "$HOME/.ssh/id_ed25519" ubuntu@server.example.net

# 파일 다운로드: 대문자 P
scp -P 2222 -i "$HOME/.ssh/id_ed25519" \
  'ubuntu@server.example.net:/home/ubuntu/export/report.txt' "$dest/"

```

`scp -p`는 포트 설정이 아니다. 원본의 수정·접근 시각과 파일 모드 비트를 보존하는 옵션이다. 따라서 `scp -p 2222 ...`로 바꿔 쓰면 기대한 포트 지정이 되지 않는다. 이 차이는 [ssh 매뉴얼](https://man.openbsd.org/ssh?ref=mlog.me)과 [scp 매뉴얼](https://man.openbsd.org/scp?ref=mlog.me)에서 확인할 수 있다.

같은 서버에 자주 접속한다면 내 PC의 `~/.ssh/config`에 별칭을 추가할 수 있다. 기존 파일을 통째로 덮어쓰지 말고 해당 호스트 블록을 추가하거나 수정한다.

```sshconfig
Host sample-server
    HostName server.example.net
    User ubuntu
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

```

그러면 다음처럼 쓸 수 있다.

```sh
ssh sample-server
scp sample-server:/home/ubuntu/export/report.txt "$dest/"

```

`IdentitiesOnly yes`는 설정한 인증 키를 중심으로 사용하도록 제한해, 에이전트가 제공하는 다른 키가 섞이는 상황을 줄인다. `IdentityFile`은 여러 개가 누적될 수 있으므로 “이 줄 하나면 반드시 키 하나만 사용한다”는 의미로 해석하지 않는다.

실제로 선택된 설정은 서버에 접속하지 않고 확인할 수 있다.

```sh
ssh -G sample-server |
  awk '$1 ~ /^(hostname|user|port|identityfile|identitiesonly)$/ {print}'

```

`ssh -G`는 설정을 보여 주는 명령이지 접속 성공 검사 자체는 아니다. 별칭과 설정 우선순위는 [ssh\_config 공식 문서](https://man.openbsd.org/ssh%5Fconfig?ref=mlog.me)를 기준으로 확인한다.

## 4\. 폴더와 공백 경로는 각각 처리한다

### 폴더는 -r을 추가한다

```sh
scp -r -P 2222 -i "$HOME/.ssh/id_ed25519" \
  'ubuntu@server.example.net:/home/ubuntu/export/bundle' "$dest/"

```

여기서는 이미 존재하는 `dest` 폴더 아래에 `bundle`을 받는 예시다. 이번 시험에서는 `bundle/nested/data.txt`와 `bundle/.hidden`까지 복사되는 것을 확인했다. 같은 디렉터리에 `-r` 없이 요청했을 때는 다음 오류로 종료됐다. `<LAB>`만 시험용 임시 경로를 대신한 표시다.

```text
scp: download <LAB>/remote/bundle/: not a regular file

```

`-r`은 디렉터리를 재귀 복사하며, 공식 문서상 탐색 중 만난 심볼릭 링크도 따라간다. 링크가 섞인 운영 폴더를 무조건 통째로 받기보다 전송하려는 파일 범위를 먼저 확인한다. 실제로 사용 중인 DB 데이터 디렉터리를 복사하는 것을 일관된 DB 백업으로 간주해서도 안 된다.

### 공백이 있으면 경로를 하나의 인자로 묶는다

```sh
scp -P 2222 -i "$HOME/.ssh/id_ed25519" \
  'ubuntu@server.example.net:/home/ubuntu/export/report 01.txt' \
  "$dest/report 01.txt"

```

이 예제는 현재 OpenSSH의 기본 SFTP 방식과 로컬 셸의 인용 처리를 전제로 한다. 이번 시험에서도 공백이 포함된 원격 파일과 로컬 파일명을 따옴표로 묶어 전송했고 내용이 일치했다.

OpenSSH는 [9.0 릴리스](https://www.openssh.org/txt/release-9.0?ref=mlog.me)부터 scp의 기본 전송 방식을 SFTP로 바꿨다. 예전 SCP 프로토콜용으로 따옴표를 겹겹이 넣은 예제를 그대로 붙이면 오히려 실패할 수 있다. 먼저 `ssh -V`와 자신의 `man scp`를 확인한다. `-O`는 예전 SCP 프로토콜로 전환하는 옵션이지 모든 경로 오류의 해결책이 아니다.

## 5\. Permission denied는 어느 단계에서 났는지 본다

### 인증 단계에서 막힌 경우

`Permission denied (publickey)`처럼 파일 경로를 열기 전 인증이 거절된다면, 파일 권한을 변경하기 전에 **대상 호스트·계정·포트·키**가 평소 SSH와 같은지 대조한다.

```sh
ssh -v -p 2222 -i "$HOME/.ssh/id_ed25519" \
  ubuntu@server.example.net 'id -un'

```

서버의 공개키 인증 정책 자체를 점검해야 한다면 [SSH 비밀번호 차단과 root 로그인 정책](https://mlog.me/server-security-check-ssh-password-root-login/)으로 이어서 확인할 수 있다. 파일을 받기 위해 비밀번호 인증이나 root 로그인을 새로 열 필요부터 있다고 가정하지 않는다.

### 접속은 됐지만 원격 파일을 읽지 못한 경우

이번 시험에서는 합성 파일의 읽기 권한을 제거하자 인증 이후 다음 오류가 발생했다.

```text
scp: remote open "<LAB>/remote/unreadable.txt": Permission denied

```

셸 사용도 허용된 서버라면 같은 계정으로 파일과 상위 경로를 확인한다.

```sh
ssh -p 2222 -i "$HOME/.ssh/id_ed25519" ubuntu@server.example.net \
  'ls -ld /home/ubuntu/export; ls -l /home/ubuntu/export/report.txt'

```

파일 읽기 권한뿐 아니라 상위 디렉터리를 통과할 수 있어야 한다. ACL 등 추가 접근 정책도 원인이 될 수 있다. 로컬에서 `sudo scp`를 붙여도 원격 계정이 자동으로 sudo 사용자가 되지는 않는다.

필요한 자료가 관리자 전용 위치에 있다면 서버 관리 절차에 따라 **전송이 허용된 파일만** 해당 계정이 읽을 수 있는 별도 내보내기 폴더로 준비한다. 오류를 없애려고 운영 데이터 폴더 전체에 `chmod -R 777`이나 소유권 변경을 적용하지 않는다.

### 파일이 없거나 로컬 저장 위치가 잘못된 경우

이번에 존재하지 않는 원격 파일을 요청했을 때는 다음 오류가 나왔다.

```text
scp: <LAB>/remote/missing.txt: No such file or directory

```

이 문구만 보고 항상 서버 파일이 없다고 단정하면 안 된다. 실제 메시지에 나온 경로가 원격 원본인지 로컬 대상인지 읽어야 한다. 대소문자, 절대 경로, 로컬 폴더 존재 여부를 확인한다. 초기 확인에서는 원격 홈 축약이나 와일드카드보다 **파일 하나의 절대 경로**를 지정하면 비교할 항목이 줄어든다.

`Connection refused`나 시간 초과는 파일 경로를 바꿀 단계보다 앞선 연결 문제다. 평소 SSH가 도달하는 주소와 포트를 먼저 확인한다. 반대로 SSH 로그인은 되는데 `subsystem request failed`가 나온다면 서버의 SFTP 제공 여부나 제한 정책을 관리자에게 확인한다. 이 오류는 이번 실험에서 재현한 항목은 아니다.

### 서버 신원 경고는 인증 오류와 분리한다

처음 접속할 때 표시되는 호스트 키 지문은 신뢰할 수 있는 별도 경로의 서버 지문과 대조한다. 기존 호스트 키가 바뀌었다는 경고는 일반적인 파일 권한 오류가 아니다. 서버 재설치 등 정당한 변경인지 확인하기 전에는 호스트 검증을 끄거나 `known_hosts` 전체를 삭제해서 넘기지 않는다. [ssh\_config의 호스트 키 검증 규칙](https://man.openbsd.org/ssh%5Fconfig?ref=mlog.me#StrictHostKeyChecking)을 기준으로 판단한다.

## 6\. 다운로드 성공과 백업 성공을 구분한다

첫 예제의 `scp`가 성공하면 수신 폴더를 확인한다.

```sh
ls -l "$dest/report.txt"

```

중요한 완료 파일은 원본과 수신본의 SHA-256도 비교할 수 있다. 전송·해시 계산 중 바뀌지 않는 파일을 대상으로 한다.

```sh
# 원격 Linux에 GNU sha256sum이 있는 경우
ssh -p 2222 -i "$HOME/.ssh/id_ed25519" ubuntu@server.example.net \
  'sha256sum /home/ubuntu/export/report.txt'

# 내 PC에 shasum이 있는 경우
shasum -a 256 "$dest/report.txt"

```

양쪽 출력의 파일 경로가 아니라 해시 값을 비교한다. Linux 클라이언트에서는 `sha256sum "$dest/report.txt"`를 써도 된다. 각 도구의 입력·검증 방식은 [GNU sha256sum 매뉴얼](https://manpages.debian.org/trixie/coreutils/sha256sum.1.en.html?ref=mlog.me)과 [shasum 문서](https://perldoc.perl.org/shasum?ref=mlog.me)에서 확인할 수 있다.

이번 합성 파일 전송에서는 원본과 다운로드 파일의 바이트 및 SHA-256 일치를 확인했다. 이것은 파일 전송 결과를 검증한 것이며, DB나 애플리케이션을 복원할 수 있다는 보장은 아니다. 백업 아카이브를 받는 상황이라면 [Ghost·MySQL 백업 무결성 점검](https://mlog.me/ghost-mysql-backup-integrity-check/)의 내용 확인·복원 검증도 별도로 이어 간다.

Tailscale의 Taildrop으로 보낸 파일을 찾는 중이라면 scp의 목적지 폴더 규칙과 섞지 말자. 그 경우는 [Ubuntu Taildrop 수신함에서 파일 가져오기](https://mlog.me/tailscale-taildrop-ubuntu-file-receive-inbox/)가 해당 절차다.

## 검증 환경과 확인 범위

2026-11-06, Debian 13.6 / Linux x86\_64 / OpenSSH 10.0p2 Debian-7+deb13u4에서 확인했다. `127.0.0.1`에만 바인딩한 임시 sshd와 합성 파일을 사용했고, 생성한 서버 키를 별도 known\_hosts에 미리 등록해 검증했다. 기존 SSH 설정과 사용자 서버는 변경하지 않았다.

10개 검증 항목은 SSH 키 인증, 비표준 포트를 지정한 파일 다운로드, `-r` 없는 폴더 전송 실패, 하위·숨김 파일을 포함한 폴더 복사, 공백 경로, `.` 목적지, 없는 원본, 원격 읽기 권한 거부, 같은 이름의 대상 덮어쓰기, SSH 별칭의 유효 포트·키 설정이다. 예상 실패 사례도 예상한 오류로 끝났을 때 검증 통과로 계산했다.

테스트 종료 후 임시 서버를 중지하고 시험용 키와 파일을 정리했다. macOS 실기기, 실제 OCI 회선, 회사망, Windows PowerShell, 구형 SCP 프로토콜, 중단된 대용량 전송의 재개는 시험하지 않았다. 내려받기 전에 **내 PC에서 실행하는지, 포트와 계정이 맞는지, 원본을 읽을 수 있는지, 받을 폴더가 맞는지**를 확인하는 것이 이 글의 적용 범위다.

아래 ZIP에는 재현 코드와 실행 결과가 들어 있다. 시험 환경과 제한 사항은 README에서 함께 확인할 수 있다.

[scp 서버 파일 다운로드 재현 코드격리된 Linux·OpenSSH 환경의 10개 검증 코드와 실행 결과. 운영 서버·macOS 실기기 검증과는 구분합니다.scp-server-download-repro-20261106.zip6 KBdownload-circle](https://mlog.me/content/files/2026/11/scp-server-download-repro-20261106.zip "Download")