[삽질 일기] 온프레미스 서버에서 숨겨진 NCP Private DB 뚫기: 위대한 점프서버와 SSH 터널링
오늘도 평화롭게 코딩을 하고 있었다. 로컬 개발 환경에서는 잘 돌아가던 코드를 **온프레미스 서버(사내 물리 서버)**에 배포하는 순간, 평화는 깨졌다.
Connection timed out: connect...
빨간색 에러 로그가 화면을 가득 채웠다. 아... 서버가 DB를 못 찾는다. 알고 보니 내가 사용하려는 NCP(Naver Cloud Platform)의 데이터베이스가 Private Subnet에 숨어 있었던 것이다. 외부(온프레미스)에서는 당연히 접근 불가능한 '성역'에 있었던 셈.
오늘은 이 철벽같은 Private DB에 온프레미스 서버가 접속할 수 있도록 **점프서버(Bastion Host)**를 이용해 길을 뚫어준 과정을 기록으로 남긴다.
1. 문제 상황: 너는 닿을 수 없는 곳에
상황은 이랬다.
- 내 서버: 회사 전산실에 있는 온프레미스 서버 (외부 인터넷망)
- DB: NCP 클라우드 내부의 Private Subnet에 위치 (공인 IP 없음, 사설 IP만 존재)
Private DB는 보안상 외부 인터넷과 차단되어 있다. 내 온프레미스 서버가 아무리 문을 두드려도, NCP의 보안 그룹(ACG)과 네트워크 구조상 절대 닿을 수 없는 구조였다.

그림처럼 내 요청은 방화벽 앞에서 가로막혀 갈 곳을 잃고 타임아웃만 뱉고 있었다.
2. 해결책: 점프서버(Jump Server) 소환
이 문제를 해결하려면 **"다리"**가 필요하다. NCP 내부의 Public Subnet(외부와 통신 가능)에 있는 서버 하나를 섭외했다. 우리는 이걸 점프서버(Jump Server) 또는 **배스천 호스트(Bastion Host)**라고 부른다.
- 점프서버는 **공인 IP(Public IP)**가 있어서 내 온프레미스 서버가 접속할 수 있다.
- 점프서버는 같은 VPC 내부에 있어서 Private DB와 통신할 수 있다.
즉, "온프레미스 -> 점프서버 -> Private DB" 순서로 데이터를 토스해주면 된다. 이걸 기술적으로 구현하는 방법이 바로 **SSH 터널링(Tunneling)**이다.

3. 실전: SSH 터널링 뚫기 (따라해보자)
이제 온프레미스 서버의 터미널을 열고 터널을 뚫어보자. 원리는 간단하다. "내 서버의 특정 포트(예: 9999)로 들어오는 신호를 점프서버를 통해 저쪽 DB 포트(1433)로 보내줘!" 라고 명령하는 것이다.
준비물
- 점프서버 접속 정보: 공인 IP, 계정 ID, PEM 키 파일 (또는 비밀번호)
- 타겟 DB 정보: Private IP (사설 IP), 포트 번호 (MSSQL은 보통 1433)
SSH 터널링 명령어 (리눅스/맥 터미널)
온프레미스 서버에서 아래 명령어를 입력한다.
ssh -N -L [로컬포트]:[DB_Private_IP]:[DB_포트] -i [PEM키경로] [점프서버계정]@[점프서버_Public_IP]
예시 상황
- 내 서버에서 사용할 포트: 9999 (아무거나 빈 거 쓰면 됨)
- DB Private IP: 192.168.1.50
- DB 포트: 1433 (MSSQL)
- 점프서버 IP: 203.0.113.10
- 점프서버 계정: root
- 키 파일: key.pem
실제 명령어 입력
ssh -N -L 9999:192.168.1.50:1433 -i ./key.pem root@203.0.113.10
옵션 설명 (이게 중요함!)
- -L (Local Port Forwarding): 가장 중요한 옵션. "로컬 포트를 리모트 호스트로 연결해라"라는 뜻.
- 구조: 내_컴퓨터_포트:최종_목적지_IP:최종_목적지_포트
- -N: "명령어 실행하지 마". 터널링만 연결하고 쉘 접속은 안 하겠다는 뜻이다. 이걸 안 쓰면 점프서버 터미널로 들어가져 버린다. (백그라운드에서 조용히 길만 열어둠)
- -i: 접속에 필요한 인증 키 파일 경로.
4. 코드 수정: 이제 DB는 '로컬'에 있다
터널링이 성공했다면(에러 없이 커서가 깜빡이거나 멈춰있으면 성공), 이제 내 온프레미스 서버 입장에서 Private DB는 마치 내 컴퓨터의 9999번 포트에 있는 것과 같다.
따라서 애플리케이션(Java/Python 등)의 DB 설정 파일(application.yaml 등)을 수정해야 한다.
수정 전 (직접 접속 시도 - 실패)
spring:
datasource:
url: jdbc:sqlserver://192.168.1.50:1433;... # Private IP로 직접 가려니 실패
수정 후 (터널링 경유 - 성공)
spring:
datasource:
url: jdbc:sqlserver://localhost:9999;... # 내 서버의 9999로 보내면 터널 타고 DB로 감!
핵심 포인트: 호스트는 localhost(또는 127.0.0.1), 포트는 내가 -L 옵션 맨 앞에 적었던 9999를 써야 한다.
5. 오늘의 교훈
- 보안은 불편하다, 하지만 이유가 있다: DB를 Private Subnet에 두는 건 보안의 기본이다. 불편하다고 Public으로 열어버리면 해킹 맛집이 된다.
- SSH는 만능이다: 단순히 원격 접속 도구인 줄 알았는데, 네트워크 길을 뚫어주는 터널링 기능은 정말 강력하다.
- 점프서버 관리를 잘하자: 점프서버가 털리면 내부망이 다 털리는 거다. 점프서버 보안 그룹(ACG) 설정도 빡빡하게 해야 한다.
오늘의 삽질 끝! 다음엔 이 터널링을 매번 명령어로 치기 귀찮으니 AutoSSH로 서비스 등록하는 걸 해봐야겠다.
'에러, 문제 해결' 카테고리의 다른 글
| Next.js와 AI 3D 아바타 연동기 렌더링 최적화 - 문제 고민 (0) | 2026.04.12 |
|---|---|
| 실시간 AI 아바타 대화 서비스 최적화 - Saas를 적절하게 활용 (0) | 2026.04.12 |
| 서버 중단 현상 - MSSQL 동시성 락 문제 (0) | 2026.03.02 |
| NCP 공공 클라우드 - On-Premise AI 서버와 Cloud DB 연동 (0) | 2026.03.02 |
| 분산된 의료 장비의 다운 원인 찾기 - heartbeat (1) | 2026.01.17 |