WSL2 원격 개발 시 SSH 터널링으로 Tomcat 접속하기
WSL2에서 Tomcat을 띄웠지만 원격지 PC 브라우저에서 접속이 안 되는 경우, SSH 터널링으로 해결할 수 있습니다. ssh -N -L 8002:localhost:8002 username@server-ip로 SSH 터널을 열면 되며, SSH Config에 등록하면 한 줄로 접속 가능합니다.
이 가이드가 필요한 상황
JetBrains Gateway로 원격 WSL2에 접속해서 코드를 편집하고 Tomcat까지 띄웠는데, 정작 브라우저에서 내 웹 애플리케이션에 접속할 수 없는 상황이라면 이 가이드가 필요합니다.
처음 원격 개발 환경을 세팅하면 “Gateway로 코드는 잘 보이는데, 브라우저에서 내 Tomcat에 어떻게 접속하지?” 하고 막히는 순간이 옵니다. 이 문서는 그 순간을 위한 가이드입니다.
포트(Port)란?
문서에서 “8002번 포트”, “3306번 포트” 같은 말이 계속 나오니까 먼저 짚고 넘어가겠습니다.
컴퓨터를 아파트 한 동이라고 생각해보세요. IP 주소가 “아파트 주소"라면, 포트 번호는 **“호수(호실)”**입니다. 한 컴퓨터 안에서 웹 브라우저, Tomcat, DB 등 여러 프로그램이 동시에 네트워크를 쓰는데, “이 요청은 어떤 프로그램한테 가야 해?“를 구분해주는 게 바로 포트 번호입니다.
- 0번 ~ 65535번까지 총 65,536개
- 잘 알려진 번호들: 80(HTTP), 443(HTTPS), 22(SSH), 3306(MariaDB)
- Tomcat의 8002번은 프로젝트 설정에 따라 정해진 번호이며, 8080이나 9090 등으로 변경 가능
왜 하필 8002? Tomcat 기본 포트가 8080인데, 다른 서비스와 충돌하지 않도록 프로젝트에서 별도 포트를 지정한 것입니다.
SSH란?
SSH는 Secure Shell의 약자입니다. 한 마디로 “안전한 원격 접속 방법"입니다.
옛날에는 Telnet이라는 걸 썼는데, 비밀번호든 명령어든 전부 평문(날것 그대로) 네트워크에 흘러갔습니다. SSH는 모든 통신을 암호화해서 이 문제를 해결했습니다. Windows에도 기본 내장되어 있어서 별도 설치 없이 바로 사용할 수 있습니다.
SSH를 쓰는 핵심 이유는 보안도 있지만 실은 편의성 때문입니다. 방화벽 구멍을 여러 개 뚫거나 공유기 포트포워딩을 일일이 설정하는 것보다, SSH 터널 하나로 필요한 포트를 다 연결하는 게 훨씬 깔끔합니다.
상황 이해하기
일반적인 개발 환경에서는 내 PC에서 Tomcat을 띄우고 localhost로 바로 접속합니다. 그런데 원격 개발 환경에서는 구조가 다릅니다:
[원격지 PC (사무실)] ---Gateway(SSH)---> [서버 PC의 WSL2]
(브라우저) (Tomcat 실행 중)
JetBrains Gateway로 원격 WSL2에 접속해서 코드를 수정하고 Tomcat도 띄웠습니다. 여기까지는 문제없는데… 원격지 PC의 브라우저에서 서버 WSL2의 Tomcat에 접속할 수가 없습니다.
왜 안 될까? 원격지 PC 브라우저에서
localhost:8002를 입력하면, 그건 원격지 PC 자기 자신의 8002 포트를 찾는 것입니다. 서버에 있는 WSL2의 8002 포트가 아닙니다. 네트워크적으로 완전히 다른 컴퓨터이기 때문입니다.
SSH 터널링이란?
여기서 SSH 터널링이 등장합니다. 쉽게 비유하면:
비밀 통로를 하나 뚫는 것입니다. “내 PC의 8002번 문을 열면, SSH라는 비밀 통로를 통해서, 저 멀리 서버 WSL2의 8002번 문으로 연결되게 해줘"라고 하는 것입니다.
그래서 원격지 PC 브라우저에서 localhost:8002를 입력하면, 마치 내 PC에서 Tomcat이 돌고 있는 것처럼 느껴지지만, 실제로는 SSH 터널을 타고 서버 WSL2의 Tomcat까지 요청이 날아갑니다.
실제 명령어
원격지 PC에서 PowerShell 또는 CMD를 열고 다음 명령어를 실행합니다:
ssh -N -L 8002:localhost:8002 username@your-server-ip
SSH 포트가 기본값(22)이 아닌 경우에는 -p 옵션을 추가합니다:
ssh -N -L 8002:localhost:8002 username@your-server-ip -p {SSH포트}
-N옵션이란? “포트 포워딩만 할 거고, 원격 서버에서 명령어를 실행할 생각은 없어"라는 뜻입니다. 붙이지 않으면 원격 셸이 열려서 실수로 명령어를 칠 수 있습니다. 포트 포워딩 전용이면-N을 습관처럼 붙이는 게 좋습니다.
접속에 성공하면 (비밀번호 입력 후 커서가 멈춰 있으면 정상) 그 터미널 창을 닫지 말고 브라우저에서 http://localhost:8002로 접속하면 됩니다.
-N을 빼면 셸 프롬프트가 뜨고,-N을 넣으면 커서만 깜빡이며 대기합니다. 둘 다 터널은 정상 작동 중입니다.
명령어 상세 분석
처음에는 다들 헷갈리지만, 한 번만 이해하면 평생 써먹을 수 있습니다.
ssh -N -L {로컬포트}:{목적지호스트}:{목적지포트} {사용자}@{서버IP} -p {SSH포트}
| 부분 | 실제 값 | 설명 |
|---|---|---|
-N |
“원격 명령 실행 없이 포워딩만 해"라는 옵션 | |
-L |
“Local 포트 포워딩 할 거야"라는 옵션. L은 Local의 L | |
| 로컬포트 | 8002 |
내 PC(원격지)에서 열릴 포트. 브라우저에서 이 포트로 접속 |
| 목적지호스트 | localhost |
SSH 서버 입장에서의 localhost (내 PC가 아님!) |
| 목적지포트 | 8002 |
WSL2에서 Tomcat이 돌고 있는 포트 |
| 사용자@서버IP | username@server-ip |
WSL2에 접속하는 SSH 계정 정보 |
-p |
22 (기본값) |
SSH 접속 포트. 기본 22번이면 생략 가능 |
“목적지호스트가 왜 localhost야?” - 가장 많이 하는 질문
localhost가 헷갈릴 수 있습니다. “이미 원격 서버에 접속하는 건데 왜 목적지가 localhost지?” 싶은 거죠.
이건 SSH 서버 기준으로 생각해야 합니다. SSH로 서버 WSL2에 접속했으면, 그때부터 목적지호스트는 WSL2 입장에서 바라본 주소입니다. Tomcat은 WSL2 안에서 돌고 있으니까, WSL2 입장에서는 자기 자신 = localhost인 것입니다.
동작 흐름 (전체 그림)
요청이 어떻게 흘러가는지 그림으로 보겠습니다:
[원격지 PC 브라우저]
http://localhost:8002 <- "내 PC의 8002번 문을 두드린다"
|
v (로컬 8002 포트)
[SSH 터널] =================> [서버 WSL2] <- "비밀 통로를 타고 날아간다"
(암호화된 연결) |
v (localhost:8002)
[Tomcat] <- "Tomcat이 응답한다"
브라우저 요청이 SSH 터널이라는 암호화된 비밀 통로를 통해서 서버 WSL2의 Tomcat까지 안전하게 전달됩니다. 중간에 누가 패킷을 가로채도 암호화되어 있어서 내용을 볼 수 없습니다.
자주 하는 실수 & 해결법
1. 터미널 창 닫지 마세요!
SSH 터널은 그 터미널 세션이 살아있는 동안만 유지됩니다. 터미널 창을 닫으면 터널도 같이 끊어집니다. 브라우저에서 갑자기 안 되면 제일 먼저 터미널 창이 닫혔는지 확인하세요.
2. Gateway 연결과는 별개입니다
JetBrains Gateway도 SSH로 연결하는 건 맞습니다. 그런데 Gateway의 SSH 연결은 IDE용입니다. 포트 포워딩은 해주지 않습니다. SSH 터널은 별도로 직접 열어줘야 합니다.
3. 여러 포트가 필요할 때
Tomcat 말고 DB 포트(3306)나 다른 서비스 포트도 접속해야 할 때는 -L 옵션을 여러 번 씁니다:
ssh -N -L 8002:localhost:8002 -L 3306:localhost:3306 username@your-server-ip
localhost:8002는 Tomcat으로, localhost:3306은 DB로 연결되는 터널이 동시에 두 개 열립니다.
4. 서버 IP 주소가 바뀌었을 때
가정용 인터넷은 보통 유동 IP라서, 공유기 재부팅이나 통신사 사정으로 IP가 바뀔 수 있습니다.
DDNS로 해결 (추천): DDNS(Dynamic DNS)는 “IP가 바뀌어도 항상 같은 이름으로 접속할 수 있게 해주는 서비스"입니다. ipTIME 공유기라면 설정에 DDNS가 내장되어 있습니다.
ssh -L 8002:localhost:8002 username@mydev.iptime.org
수동 확인: DDNS 설정 전에는 서버 PC의 WSL2 터미널에서 curl ifconfig.me를 실행하면 현재 공인 IP를 확인할 수 있습니다.
5. 포트 번호가 이미 사용 중일 때
“Address already in use” 에러가 뜨면, 내 PC에서 이미 그 포트를 쓰고 있다는 뜻입니다.
누가 포트를 쓰고 있는지 찾기 (Windows PowerShell):
# 8002 포트를 점유 중인 프로세스 확인
netstat -ano | findstr :8002
결과 예시:
TCP 127.0.0.1:8002 0.0.0.0:0 LISTENING 12345
맨 뒤 숫자(12345)가 PID(프로세스 ID)입니다:
# 어떤 프로세스인지 이름 확인
tasklist | findstr 12345
# 해당 프로세스 강제 종료
taskkill /PID 12345 /F
더 빠른 방법: 로컬포트 번호를 바꿔버리면 됩니다.
ssh -N -L 8003:localhost:8002 username@your-server-ip
localhost:8003으로 접속하면 되니까 충돌 없이 바로 해결됩니다.
매번 명령어 치기 귀찮다면 - 자동화
방법 1: .bat 파일로 원클릭 실행
메모장에 이렇게 적고 ssh-tunnel.bat으로 저장해서 바탕화면에 두면, 더블클릭만으로 터널이 열립니다:
@echo off
echo SSH 터널 연결 중...
ssh -N -L 8002:localhost:8002 -L 3306:localhost:3306 username@your-server-ip
pause
pause를 넣은 이유는 에러가 나도 창이 바로 안 닫히게 하려는 것입니다.
방법 2: SSH Config 파일 (추천)
C:\Users\{사용자명}\.ssh\config 파일을 만들거나 열어서 작성합니다:
Host wsl-tunnel
HostName your-server-ip
User username
LocalForward 8002 localhost:8002
LocalForward 3306 localhost:3306
ServerAliveInterval 60
ServerAliveCountMax 3
그러면 긴 명령어 대신 이것만 입력하면 됩니다:
ssh wsl-tunnel
ServerAliveInterval 60은 60초마다 “나 살아있어” 신호를 보내서 네트워크 불안정으로 연결이 끊어지는 걸 방지합니다. ServerAliveCountMax 3은 3번 연속 응답이 없으면 그때 끊어라는 뜻입니다.
트러블슈팅 - 브라우저가 안 될 때
“갑자기 안 돼요!” 상황이 오면 당황하지 말고 이 순서대로 확인하세요:
브라우저 안 됨
-> SSH 터미널 창 반응 확인
-> 반응 없음: SSH 터널 끊김 -> 다시 연결
-> 반응 있음: Tomcat 확인 (ps, curl)
-> Tomcat 죽음 -> Tomcat 재시작
-> Tomcat 살아있음 -> 다른 원인 (URL 오타, 방화벽 등)
1단계: SSH 터널 상태 확인
SSH 터널을 열어둔 터미널 창을 확인합니다:
-N옵션 사용 시: 커서가 깜빡이며 대기 중이면 정상.Write failed: broken pipe에러가 나왔거나 창이 닫혔으면 끊어진 것-N없이 셸 접속 시: 셸 프롬프트가 떠있고 명령어 입력이 가능하면 정상.Enter를 쳐도 반응이 없으면 끊어진 것
끊어졌으면 그 터미널을 닫고 SSH 터널을 다시 열면 됩니다.
2단계: Tomcat 상태 확인
SSH 터널이 살아있는데 브라우저가 안 되면 Tomcat이 죽었을 가능성이 높습니다. 별도 터미널에서 WSL2에 SSH 접속 후 확인합니다:
# Tomcat 프로세스가 살아있는지 확인
ps aux | grep tomcat
# Tomcat 포트가 응답하는지 확인
curl -s -o /dev/null -w "%{http_code}" http://localhost:8002
curl 결과가 000이면 Tomcat이 죽은 것이고, 200이나 302면 Tomcat은 살아있는데 다른 문제입니다.
한 줄 요약: SSH 터널링 = “내 PC의 특정 포트를 원격 서버의 포트에 연결하는 암호화된 비밀 통로”
처음엔 명령어가 낯설겠지만, SSH Config 파일까지 세팅해두면 ssh wsl-tunnel 한 줄이면 끝입니다.