제5부 운영체제 다루기
5.2 SSH 원격 접속과 파일 전송
App Lab GUI 없이 UNO Q의 Debian 셸에 직접 들어가 작업하고 싶을 때 가장 실용적인 방법이 SSH다. 이 장은 계정·비밀번호 확인부터 mDNS 문제 대응, scp·rsync로 파일을 주고받는 법, 그리고 VS Code 같은 에디터로 원격 개발하는 워크플로우까지 다룬다.
5.2.1 접속 정보 — 계정과 비밀번호
UNO Q의 Linux 계정명은 항상 arduino로 고정돼 있다. 비밀번호는 고정된 기본값이 아니라 App Lab 최초 설정 과정에서 사용자가 직접 지정한다 — 공식 SSH 튜토리얼은 "보드 이름과 비밀번호만 알면 접속할 수 있으며, 이는 최초 설정 때 정해진다"고 설명한다. App Lab의 보드 설정 마법사는 Wi-Fi 연결 다음 단계로 "Linux 비밀번호 설정"을 반드시 거치게 하며, 이 비밀번호 없이는 SSH·Network Mode·SBC 모드 데스크톱 로그인이 모두 불가능하다.
⚠️ 표기: 아래 두 가지는 공식 자료 간에도 표현이 갈리므로 실기로 직접 확인하는 편이 안전하다.
- 보드를 재플래싱해 "공장 상태"로 되돌리면
arduino계정에 빈 비밀번호가 설정된다고 Arduino 스태프가 포럼에서 확인한 바 있다(로그인 시 별도 입력 없이 진행되며, 이후 최초 설정에서 새 비밀번호 지정이 강제됨). - 반면 ADB 튜토리얼 문서는 "App Lab으로 먼저 설정하지 않은 상태에서
adb shell을 실행하면 비밀번호를 요구할 수 있으며, 이때 비밀번호는arduino"라고 적고 있다.
두 설명이 정확히 같은 상태를 가리키는지는 확인 필요 — 실기에서 최초 부팅 직후(App Lab 설정 전) adb shell을 시도해 실제로 어떤 프롬프트가 표시되는지 직접 확인하고 진행하는 것을 권한다. 어느 쪽이든, App Lab의 최초 설정을 마치기 전에는 SSH 자체가 비활성 상태이므로 이 단계에서 SSH로 바로 들어갈 일은 없다.
5.2.2 SSH 클라이언트 준비
macOS·Windows 10+·Ubuntu는 모두 OpenSSH 기반 클라이언트를 기본 내장한다. 설치 여부만 확인하면 된다.
ssh -V
정상이면 아래와 비슷한 출력이 나온다.
OpenSSH_9.9p2, LibreSSL 3.3.6
만약 오래된 Windows(10 미만)나 커스텀 시스템이라 SSH가 없다면, Windows는 Chocolatey, macOS는 Brew, Ubuntu는 sudo apt install openssh-client openssh-server libressl-dev로 설치한다.
5.2.3 최초 연결과 mDNS 문제 대응
App Lab 최초 설정에서 Wi-Fi 자격 증명을 입력하면 SSH가 자동으로 활성화된다. 이 상태에서 접속한다.
ssh arduino@<boardname>.local # <boardname>을 실제 보드 이름으로 교체
처음 접속할 때 yes로 호스트 신뢰를 확인하고, 비밀번호를 입력하면 셸에 들어간다.
ssh [email protected]
5.2.3.1 mDNS가 막힌 네트워크
게스트 Wi-Fi, 회사망, VPN, 방화벽이 엄격한 네트워크에서는 <boardname>.local이 해석되지 않아 다음과 같은 에러가 날 수 있다.
ssh: connect to host <boardname>.local port 22: Connection refused
이럴 때는 IP 주소로 직접 접속한다. IP는 다음 중 하나로 확인한다.
- Arduino IDE 2(Zephyr 코어 설치 필요)
- Arduino CLI:
arduino-cli board list - 보드 셸에서 직접:
hostname -I(ADB나 SBC 모드로 먼저 들어가야 함)
ssh [email protected]
영구적으로 .local 이름을 쓰고 싶다면 컴퓨터의 /etc/hosts에 항목을 추가하는 방법도 있다(고급).
sudo nano /etc/hosts
# 파일 끝에 추가: <보드IP주소> <boardname>.local
5.2.3.2 재플래시 후 known_hosts 충돌
같은 IP의 보드를 예전에 한 번 접속한 적이 있는데 그사이 보드를 재플래시했다면, SSH 호스트 키가 바뀌어 접속이 거부된다. 오래된 키를 지운다.
ssh-keygen -R <보드IP주소>
또는 ~/.ssh/known_hosts를 직접 열어 해당 줄을 지운다.
5.2.4 scp로 파일 전송
파일 전송은 보드 안이 아니라 컴퓨터의 터미널에서 scp로 한다.
파일을 보드로 전송하기(push):
scp test-transfer.txt arduino@<boardname>.local:/home/arduino/
보드에서 파일을 가져오기(pull):
scp arduino@<boardname>.local:/home/arduino/test-transfer.txt ./
폴더 전체를 재귀적으로, 권한·시간 정보를 보존하며 옮기려면 -rp를 쓴다.
scp -rp "my-folder" arduino@<boardname>.local:/home/arduino/ArduinoApps/
scp -rp arduino@<boardname>.local:/home/arduino/ArduinoApps/my-folder ./
5.2.5 rsync로 증분 전송
scp는 매번 파일 전체를 다시 보낸다. 반복적으로 같은 폴더를 동기화한다면(예: 개발 중인 App 소스를 계속 수정하며 보드에 반영) 변경분만 전송하는 rsync가 더 효율적이다. 다만 이는 UNO Q 공식 문서에 등장하는 도구가 아니라 일반 Debian/Linux 관행을 그대로 적용하는 것이다 — 표준 Debian 패키지이므로 동작 자체는 신뢰할 수 있지만, UNO Q 쪽에 별도 최적화나 제약이 있는지는 확인하지 않았다.
보드에 rsync가 없다면 먼저 설치한다.
sudo apt install rsync
컴퓨터에서 보드로 폴더를 동기화한다(변경된 파일만 전송, 삭제된 파일도 반영하려면 --delete 추가).
rsync -avz --progress ./my-folder/ arduino@<boardname>.local:/home/arduino/ArduinoApps/my-folder/
-a(아카이브 모드: 권한·심볼릭 링크·시간 보존), -v(상세 출력), -z(전송 중 압축)의 조합이 흔한 기본값이다. 경로 끝의 슬래시(/) 유무에 따라 "폴더 자체를 복사"할지 "폴더 안 내용만 복사"할지가 달라지므로 rsync 매뉴얼(man rsync)로 한 번 확인해 두는 것을 권한다.
5.2.6 에디터로 원격 개발하기 — VS Code Remote-SSH
App Lab의 코드 에디터 대신 익숙한 로컬 에디터로 보드 위 파일을 직접 편집·실행하고 싶다면, VS Code의 Remote-SSH 확장 같은 표준 원격 개발 워크플로우를 그대로 쓸 수 있다. 이는 UNO Q 전용 기능이 아니라 SSH가 되는 어떤 Linux 머신에도 통하는 일반적인 방법이며, UNO Q 공식 문서에서 별도로 안내하지는 않는다.
대략의 흐름은 다음과 같다.
- VS Code에 "Remote - SSH" 확장을 설치한다.
~/.ssh/config에 별칭을 등록해 두면 편리하다.
Host uno-q
HostName <boardname>.local
User arduino
- VS Code 명령 팔레트에서 Remote-SSH: Connect to Host… →
uno-q선택. - 연결되면
/home/arduino/ArduinoApps/아래 프로젝트 폴더를 열어 보드 위 파일을 직접 편집·터미널 실행할 수 있다.
이 방식은 "보드 위에서 직접 편집·실행"하는 워크플로우다. 반대로 PC에서 크로스 컴파일한 바이너리를 보드로 배포해 실행하는 워크플로우(C++/Rust 툴체인, Docker 빌드 후 scp/rsync로 전달)는 개발 속도·재현성 면에서 다른 장점이 있다 — 이 방식은 6.3(Docker 기반 빌드와 SSH 원격 배포·디버깅)에서 자세히 다룬다.
5.2.7 로컬망 밖에서 접속하기 — 개관
지금까지 다룬 방법은 컴퓨터와 보드가 같은 로컬망에 있다는 전제였다. 외출 중이거나 보드가 다른 네트워크에 있을 때는 다음 방법들을 쓸 수 있으며, 공식 튜토리얼(Remote Access Options for UNO Q)이 자세히 다룬다.
- Tailscale + SSH: 보드와 컴퓨터에 각각 Tailscale을 설치하면 사설 VPN으로 묶여, 어디서든
ssh arduino@<tailscale-ip>로 접속할 수 있다. - xrdp: RDP 프로토콜로 그래픽 데스크톱까지 원격 접속.
sudo apt install xrdp dbus-x11 && sudo systemctl enable --now xrdp로 설치하며, USB 연결 시adb forward tcp:3389 tcp:3389로 ADB 터널링도 가능하다. - RustDesk: 더미 디스플레이 드라이버를 설정해 헤드리스 상태에서도 그래픽 원격 접속을 제공하는 서드파티 오픈소스 도구.
셋 다 SSH보다 설정이 더 필요하므로, 셸 작업만 목적이라면 Tailscale + SSH가 구성 부담이 가장 작다.
5.2.8 방화벽 뒤에서 — 필요한 포트와 도메인
기업망이나 IoT 전용망처럼 통제된 네트워크에서 App Lab·SSH가 안 된다면 아래를 확인한다.
| 포트 | 프로토콜 | 용도 |
|---|---|---|
| 5353 | UDP | mDNS — 로컬망에서 보드 자동 탐색 |
| 22 | TCP | SSH — Network Mode의 App 배포·관리 |
| 80 / 443 | TCP | 시스템 업데이트, Docker 이미지, API 데이터 |
| 123 | UDP | NTP — 시스템 시각 동기화 |
| 7000 | TCP | WebUI Brick 기본 포트(초기화 시 변경 가능) |
방화벽을 여는 것 외에, 아래 도메인에 대한 아웃바운드 접근도 필요하다: downloads.arduino.cc, apt-repo.arduino.cc, public.ecr.aws, github.com/raw.githubusercontent.com(그리고 Arduino Cloud를 쓴다면 app.arduino.cc, login.arduino.cc).
또한 캡티브 포털(로그인 페이지를 거치는 공용 Wi-Fi)은 App Lab Wi-Fi 설정 마법사가 지원하지 않는다. WPA2-Enterprise는 Debian OS 자체는 지원하지만 App Lab GUI 마법사로는 안 되고, 터미널에서 nmcli로 수동 설정해야 한다.
5.2.9 SSH 터널로 다른 서비스 보호하기
보드에서 웹 서버나 API 같은 서비스를 특정 포트(예: 8900)로 기동했는데 이를 인터넷에 직접 노출하고 싶지 않다면, 방화벽으로 포트를 막고 SSH 터널로만 접근을 허용하는 방식이 안전하다.
- 로컬호스트에서 오는 연결만 허용:
sudo iptables -A INPUT -i lo -j ACCEPT
- 외부에서 해당 포트로 직접 접근하는 것을 차단:
sudo iptables -A INPUT -p tcp --dport 8900 -j DROP
- 필요할 때만 SSH 터널로 접속:
ssh -L 9999:<보드IP>:8900 arduino@<보드IP>
이제 컴퓨터의 localhost:9999가 보드의 8900 포트로 암호화된 채널을 통해 연결된다.
5.2.10 엣지케이스 정리
- 접속이 계속 안 될 때: 최초 설정을 완료했는지부터 확인한다 — 완료 전에는 SSH 자체가 꺼져 있다.
arduino-app-cli system network-mode enable을 ADB 셸에서 실행하면 수동으로도 활성화할 수 있다(5.3에서 다시 다룬다). - 연결은 되는데 자꾸 멈출 때: 로컬 네트워크 문제일 가능성이 크다 — 컴퓨터와 보드가 정말 같은 서브넷에 있는지 확인한다.
- 보드 이름을 바꿨는데 예전 이름으로 접속을 시도할 때: App Lab Settings > Device Details에서 현재 보드 이름을 다시 확인한다(5.3).
- App Lab이 간헐적으로 Linux 비밀번호를 인식하지 못할 때: 커뮤니티 보고에 따르면 App Lab을 껐다 다시 켜면 대부분 해결된다 — 앱 자체의 일시적 버그로 보이며 공식 확인 사항은 아니다.
다음 5.3에서는 지금 익힌 접속 방법을 바탕으로, App Lab의 Remote Management 기능과 arduino-app-cli로 OTA 업데이트와 원격 관리를 실전으로 다룬다.