운영 서버에서 NICE 본인인증 연동 테스트를 하는데 "연결 거부"가 납니다. 개발 서버에서는 됐는데 운영에서만 안 됩니다. 방화벽 담당자에게 물었더니 "Outbound 오픈 요청서 작성해서 주세요"라고 합니다. 무엇을 적어야 할지, 오픈 후에도 안 된다면 어떻게 점검해야 할지 막막합니다. 또 전자서명 연동에는 JKS 파일이 필요하다고 하는데 이게 뭔지도 모르겠습니다.
이 모듈에서는 외부 기관 API 연계의 전형적인 유형과 사전 점검 순서, JKS/TrustStore 개념, SMS/PG/인증 API 연계 운영 노하우를 다룹니다.
- 1외부 API 연계 전 방화벽 오픈 요청에 필요한 정보를 정확히 파악할 수 있다
- 2nc, openssl s_client, curl을 순서대로 사용해 외부 연결 문제를 단계별로 진단할 수 있다
- 3JKS(KeyStore)와 TrustStore의 역할 차이를 설명하고 오류를 해결할 수 있다
- 4SMS, PG, 본인인증 API 연계 시 반복되는 운영 이슈 패턴을 설명할 수 있다
- 5Circuit Breaker 개념과 외부 API timeout 설정이 서버 안정성에 미치는 영향을 설명할 수 있다
외부 연계 유형과 사전 준비
외부 기관 API 연계의 대표 유형
외부 API 연계는 "우리 코드를 짜는 것"이 아니라 "우리 서버가 외부 시스템과 신뢰를 맺는 것"입니다. 방화벽 오픈, 인증서 교환, IP 화이트리스트 등록처럼 인프라 레이어에서 먼저 해결해야 할 일들이 코드 작성보다 앞서 있습니다. 유형별로 요구사항이 다르기 때문에 어떤 종류의 연계인지 먼저 파악하지 않으면 준비해야 할 것을 빠뜨리게 됩니다.
확대
처음 공공기관 프로젝트에 투입됐을 때 "NICE 연동이 막혔습니다", "SignKorea JKS 파일이 필요하대요", "PG사에서 IP 화이트리스트 등록해달라고 합니다" 같은 요청이 동시에 들어옵니다. 각각 무엇을 해야 하는 작업인지, 사전에 무엇을 준비해야 하는지 모르면 연계 하나하나에서 막힙니다. 유형별로 요구사항이 다르기 때문에 먼저 어떤 종류의 연계인지 파악하는 것이 시작입니다.
공공기관이나 금융 프로젝트에서 자주 만나는 외부 연계 유형입니다. 각각 연계 방식과 준비 사항이 다릅니다. 처음 접하면 "왜 이렇게 복잡한가" 싶지만, 대부분은 보안 요구사항(신원 증명, 암호화, 감사 로그)에서 비롯됩니다.
주요 외부 연계 유형:
| 유형 | 대표 서비스 | 연계 방식 | 특이사항 |
|---|---|---|---|
| 본인인증 | NICE, KCB, KMC | HTTP API + 암복호화 | 암호화 키 관리, IP 등록 필요 |
| 전자서명 | SignKorea, CrossCert | HTTPS + mTLS (클라이언트 인증서) | JKS 인증서 관리 |
| PG(결제) | KG이니시스, NHN KCP | HTTPS API, Webhook | IP 화이트리스트, 테스트/운영 키 분리 |
| SMS/알림톡 | AWS SNS, 나이스정보통신, 카카오 | HTTPS REST API | API 키, 발신번호 사전 등록 |
| 공공 Open API | 행안부, 건강보험공단 등 | HTTPS + API Key | 서비스 신청 후 심사 과정 필요 |
| 파일 전송 | SFTP, AS2, VAN | TCP 22/4080 | 별도 방화벽 오픈, 인증서 교환 |
연계 전 체크리스트:
# 외부 기관에서 확인해야 할 정보
# - 운영 서버 IP/도메인 및 포트
# - 프로토콜 (HTTP/HTTPS, TCP)
# - 인증 방식 (API Key, 클라이언트 인증서, IP 화이트리스트)
# - 테스트 환경 계정/엔드포인트 별도 제공 여부
# 방화벽 오픈 요청 시 필요한 정보
# - 출발지: 우리 운영 서버 IP (WAS 서버들)
# - 목적지: 외부 API 서버 IP 또는 도메인
# - 목적지 포트: 443 (HTTPS), 80 (HTTP), 22 (SFTP) 등
# - 방향: Outbound (내부 → 외부)
# - 프로토콜: TCP
외부 API 연결 사전 점검 순서
nc → openssl → curl — 단계별 진단
외부 API 연결이 안 될 때 무작정 앱 로그만 보면 원인을 찾기 어렵습니다. 네트워크 계층부터 단계적으로 점검하면 어느 지점에서 막히는지 빠르게 특정할 수 있습니다.
확대
3단계 점검 순서:
# -- 1단계: TCP 연결 가능 여부 (nc) --
# 방화벽이 열렸는지, 서버가 포트를 열고 있는지 확인
nc -zv external-api.example.com 443
# 성공: Connection to external-api.example.com 443 port [tcp/https] succeeded!
# 실패: nc: connect to external-api.example.com port 443 (tcp) failed: Connection refused
# → 방화벽 미오픈 또는 서버가 포트를 닫은 상태
# 1단계 실패 시 → 방화벽 오픈 요청 또는 외부 기관에 서버 상태 확인
# 1단계 성공 시 → 2단계 진행
# -- 2단계: SSL/TLS 인증서 검증 (openssl s_client) --
# SSL 핸드셰이크가 정상인지, 인증서 체인이 완전한지 확인
openssl s_client -connect external-api.example.com:443 2>/dev/null \
| grep -E "Verify return code|issuer|subject|expire"
# 정상: Verify return code: 0 (ok)
# 실패 예: Verify return code: 21 (unable to verify the first certificate)
# → 중간 CA 인증서 누락, truststore 업데이트 필요
# 서버 인증서 만료일 확인
openssl s_client -connect external-api.example.com:443 2>/dev/null \
| openssl x509 -noout -dates
# notAfter=Nov 30 23:59:59 2026 GMT
# 2단계 실패 시 → SSL 인증서 문제 (아래 TroubleCase 참고)
# 2단계 성공 시 → 3단계 진행
# -- 3단계: HTTP 응답 확인 (curl) --
# 실제 API 응답 코드와 내용 확인
curl -m 10 -s -o /dev/null -w "%{http_code}" https://external-api.example.com/health
# 200: 정상
# 403: IP 화이트리스트 미등록 또는 API Key 오류
# 401: 인증 실패
# 000: 연결 자체 실패 (1단계로 되돌아가기)
# 응답 본문까지 확인
curl -m 10 -s https://external-api.example.com/health
# {"status":"ok"} 또는 에러 메시지
# 응답 시간 측정 (timeout 설정 기준)
curl -m 30 -w "\nDNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTotal: %{time_total}s\n" \
-s -o /dev/null https://external-api.example.com/health
JKS와 TrustStore — Java SSL 인증서 관리
KeyStore vs TrustStore — 헷갈리는 개념 정리
전자서명 API 연동 중 javax.net.ssl.SSLHandshakeException: PKIX path building failed 오류가 납니다. "TrustStore에 CA를 추가해야 한다"는 말을 들었는데, 이미 JKS 파일을 설정했습니다. KeyStore와 TrustStore가 다른 것인지 처음 접하면 혼란스럽습니다. 두 개념은 방향이 달라서, 어느 쪽이 문제인지 구분하지 못하면 엉뚱한 곳을 고치게 됩니다.
Java에서 SSL 인증서 관련 오류가 나면 KeyStore와 TrustStore 개념 혼동이 원인인 경우가 많습니다. 두 개념은 방향이 다릅니다. KeyStore는 "나의 인증서"(클라이언트가 서버에 제시), TrustStore는 "신뢰하는 CA 목록"(서버 인증서를 검증하기 위한)입니다.
확대
KeyStore vs TrustStore:
| 항목 | KeyStore (JKS) | TrustStore |
|---|---|---|
| 역할 | 나의 인증서와 개인키 보관 | 신뢰할 CA 인증서 목록 |
| 언제 필요 | mTLS (클라이언트 인증서 요구) | 자체 서명 인증서, 사설 CA |
| Java 옵션 | -Djavax.net.ssl.keyStore | -Djavax.net.ssl.trustStore |
| 기본값 | 없음 | JDK의 cacerts (공인 CA 기본 포함) |
JKS 관련 자주 쓰는 명령어:
# JKS 파일 내용 확인 (어떤 인증서가 들어있는지)
keytool -list -keystore client-cert.jks -storepass 비밀번호
# 출력: Alias name, Entry type, Certificate fingerprint
# PEM 인증서를 JKS로 변환 (외부 기관에서 PEM 발급 시)
# 1단계: PEM + 개인키 → PKCS12 변환
openssl pkcs12 -export \
-in client.crt \
-inkey client.key \
-out client.p12 \
-name myalias \
-passout pass:임시비밀번호
# 2단계: PKCS12 → JKS 변환
keytool -importkeystore \
-srckeystore client.p12 \
-srcstoretype PKCS12 \
-srcstorepass 임시비밀번호 \
-destkeystore client.jks \
-deststoretype JKS \
-deststorepass jks비밀번호
# TrustStore에 외부 CA 인증서 추가 (사설 CA 또는 중간 CA)
keytool -importcert \
-keystore truststore.jks \
-storepass trustpass \
-alias external-ca \
-file external-ca.crt \
-noprompt
# Java 앱 실행 시 JKS 사용 설정
java \
-Djavax.net.ssl.keyStore=/etc/ssl/client.jks \
-Djavax.net.ssl.keyStorePassword=비밀번호 \
-Djavax.net.ssl.trustStore=/etc/ssl/truststore.jks \
-Djavax.net.ssl.trustStorePassword=trustpass \
-jar app.jar
외부 API 호출의 생애
외부 API를 한 번 호출할 때 벌어지는 일 — 요청 준비부터 장애 격리까지 5단계
외부 API 호출은 코드에서 httpClient.post(url, body) 한 줄이지만, 그 안에서 인증 토큰·헤더 준비 → 호출 → 응답 처리(상태코드·페이징) → 재시도·타임아웃·레이트리밋 대응 → 장애 격리가 순서대로 일어납니다. 이 단계를 알면 401·429·타임아웃 같은 증상을 보고 어느 단계 문제인지 바로 짚을 수 있습니다. 앞 절의 nc→openssl→curl이 "연결이 되나"를 계층으로 봤다면, 여기서는 "호출 한 번이 어떻게 흘러가다 어디서 깨지나"를 봅니다.
[우리 서버] callExternalApi(payload)
│
① 요청 준비 (URL·메서드·헤더 / 인증 토큰·API 키·서명 부착)
│
② 호출 (connectTimeout 내 TCP·TLS 수립 → 요청 전송)
│
③ 응답 처리 (상태코드 분기 2xx/4xx/5xx, 페이징·부분 결과 조립)
│ → readTimeout 내 본문 수신
│
④ 재시도·레이트리밋 대응 (5xx·타임아웃만 backoff 재시도, 429는 Retry-After 존중)
│
⑤ 장애 격리 (연속 실패율 임계 초과 → Circuit Breaker OPEN → 즉시 fallback)
▼
[우리 서버] 결과 반환 또는 fallback (외부 장애가 우리로 전파되지 않음)
각 단계에서 무슨 일이 일어나고, 막히면 어떤 증상인가:
| 단계 | 하는 일 | 여기서 막히면 |
|---|---|---|
| ① 요청 준비 | URL·헤더에 인증 토큰·API 키·서명을 붙임 | 토큰 만료·키 오타 → 호출 시 401 Unauthorized / 서명·권한 부족 → 403 |
| ② 호출 | connectTimeout 안에 연결하고 요청 전송 | 포트·방화벽 미오픈 → Connection refused·연결 타임아웃(Outbound) / IP 화이트리스트 미등록 → 403 |
| ③ 응답 처리 | 상태코드로 분기하고 페이징·부분 결과를 조립 | 레이트리밋 → 429 Too Many Requests / readTimeout 초과 → Read timed out / 페이징 누락 → 일부만 처리(부분 실패) |
| ④ 재시도 | 일시 실패(5xx·타임아웃)만 backoff로 재시도 | 4xx까지 재시도 → 같은 실패 반복·자원 낭비 / 재시도 폭주 → 상대 서버에 부하 가중 |
| ⑤ 장애 격리 | 연속 실패율이 임계를 넘으면 회로를 열어 호출 차단 | 격리 없으면 외부 지연이 우리 스레드를 잠식 → 의존성 장애가 서비스 전체로 전파 |
즉 외부 API 오류를 볼 때 상태코드가 곧 단계 지도입니다 — 401·403은 ①(인증·권한·IP), Connection refused·타임아웃은 ②(네트워크·방화벽), 429는 ③(레이트리밋), Read timed out은 ③(응답 지연), 재시도해도 계속 실패면 ④⑤(의존성 장애)입니다. ⑤의 timeout과 Circuit Breaker를 자세히 봅니다.4xx는 재시도해도 소용없으니 즉시 실패로, 5xx·타임아웃만 backoff 재시도로 갈라야 하고, 외부가 오래 죽어 있으면 ⑤ Circuit Breaker로 우리 자원을 지킵니다. 아래에서 ④
Circuit Breaker — 외부 API 장애 격리
timeout 설정과 Circuit Breaker의 필요성
외부 API가 갑자기 느려지거나 응답을 하지 않을 때, 우리 서버가 함께 장애로 빠지는 것을 방지해야 합니다. timeout만으로는 부족하고, Circuit Breaker 패턴이 필요합니다.
timeout 설정의 중요성:
# 잘못된 예: timeout 없음 → 스레드 무기한 대기
curl https://external-api.example.com/payment
# 올바른 예: 적절한 timeout 설정
curl -m 10 https://external-api.example.com/payment
# 10초 내 응답 없으면 포기
# Java HttpClient timeout 설정 예시
# connection-timeout: 3초 (TCP 연결 수립)
# read-timeout: 10초 (응답 본문 수신)
Circuit Breaker 동작 원리:
확대
Resilience4j (Spring Boot) 설정 예시:
# application.yml
resilience4j:
circuitbreaker:
instances:
smsService:
failure-rate-threshold: 50 # 50% 실패 시 OPEN
wait-duration-in-open-state: 30s # 30초 후 HALF-OPEN 시도
sliding-window-size: 10 # 최근 10개 요청 기준
permitted-number-of-calls-in-half-open-state: 3
실습 — 외부 API 연결 사전 점검
TCP 연결부터 단계적으로 점검합니다. 실제 외부 API 서버 주소로 교체하여 사용합니다.
# 1단계: TCP 포트 연결 확인
nc -zv external-api.example.com 443
# 2단계: SSL 인증서 검증
openssl s_client -connect external-api.example.com:443 2>/dev/null \
| grep "Verify return code"
# 3단계: HTTP 응답 확인 (응답 코드 + 시간)
curl -m 10 -s -o /dev/null -w "%{http_code} (%{time_total}s)\n" \
https://external-api.example.com/health
nc -zv external-api.example.com 443- nc -zv external-api.example.com 443 결과부터 확인 — "succeeded!"이면 TCP 연결 가능. "Connection refused"는 서비스 미기동, "timed out"은 방화벽 차단(우리 서버 Outbound 미오픈 가능성)
- openssl s_client 결과에서 "Verify return code: 0 (ok)"이면 TLS 정상 — 번호가 18(self-signed), 19(chain 불완전), 20(인증서 없음) 등이면 JKS TrustStore에 해당 CA 인증서 추가 필요
- nc 성공하고 openssl도 정상인데 curl 응답이 401이면 인증 헤더 오류, 403이면 IP 허용 목록 미등록, 타임아웃이면 timeout 설정(보통 5~30초)이 외부 API 응답 시간보다 짧은 것
mTLS 연계 시 사용하는 JKS 파일의 인증서 정보를 확인합니다.
# JKS 파일 목록 및 만료일 확인
keytool -list -v -keystore /etc/ssl/client.jks -storepass 비밀번호 \
| grep -E "Alias|Valid|until"
# TrustStore에 등록된 CA 목록 확인
keytool -list -keystore /etc/ssl/truststore.jks -storepass trustpass \
| grep -E "Alias|trustedCertEntry"
# 인증서 만료 여부 빠른 확인
keytool -list -v -keystore /etc/ssl/client.jks -storepass 비밀번호 \
| grep "until" | while read line; do
echo "$line"
done
keytool -list -keystore /path/to/client.jks -storepass 비밀번호- keytool -list 출력에서 alias 이름을 먼저 확인 — 연계 기관이 요구하는 alias명과 대소문자까지 정확히 일치해야 함. 다르면 mTLS 핸드셰이크 시 인증서를 찾지 못해 연결 실패
- "Valid from" ~ "until" 날짜에서 만료일 확인 — 현재 날짜 기준으로 30일 이내면 교체 일정 수립 필요. 만료된 인증서는 SSL handshake failure 발생
- privateKeyEntry가 있어야 클라이언트 인증서 포함 — trustedCertEntry만 있으면 서버 인증서 검증용(TrustStore)이지 클라이언트 인증서(KeyStore)가 아님. mTLS에서는 두 용도의 JKS를 별도로 관리
트러블슈팅
원인: 우리 서버의 Outbound 방화벽이 막혀 있습니다. 개발 서버는 방화벽이 느슨하고 운영 서버는 엄격한 경우가 많아 개발에서는 됐는데 운영에서는 안 되는 전형적인 패턴입니다.
# 우리 서버에서 외부 API 서버로 직접 연결 테스트
nc -zv external-api.example.com 443
# 실패: nc: connect to external-api.example.com port 443 failed: Connection timed out
# → Outbound 방화벽 미오픈 확인 필요
# 방화벽 오픈 요청 정보 수집
dig +short external-api.example.com # 도메인 → IP 조회
# 여러 IP가 나오면 모두 화이트리스트 등록 요청
# 라우팅 경로 확인
traceroute external-api.example.com
# 어느 홉에서 막히는지 확인
# 방화벽 오픈 후 재테스트
nc -zv external-api.example.com 443
# 성공하면 다음 단계(SSL, HTTP) 점검
해결: 보안팀 또는 방화벽 담당자에게 Outbound 오픈 요청서를 제출합니다. 요청서에 포함해야 할 내용: 출발지 서버 IP, 목적지 IP(외부 API IP), 목적지 포트(443), 프로토콜(TCP), 방향(Outbound), 오픈 사유(서비스명 및 연계 목적).
원인: 외부 API 서버의 인증서 체인에서 중간 CA(Intermediate CA) 인증서가 변경됐는데 우리 서버의 TrustStore(cacerts 또는 커스텀 truststore.jks)가 업데이트되지 않았습니다. 외부 기관이 인증서를 갱신하면서 중간 CA가 달라진 경우에 자주 발생합니다.
# 현재 외부 서버의 인증서 체인 확인
openssl s_client -connect external-api.example.com:443 \
-showcerts 2>/dev/null | grep -E "BEGIN CERTIFICATE|subject|issuer"
# 출력에서 중간 CA 인증서 확인
# 체인이 완전하지 않으면: Chain: End Entity → (중간 CA 없음) → Root CA
# 정상 체인: End Entity → Intermediate CA → Root CA
# 중간 CA 인증서 추출 (2번째 인증서가 보통 중간 CA)
openssl s_client -connect external-api.example.com:443 \
-showcerts 2>/dev/null | awk '/BEGIN CERT/,/END CERT/' | \
awk 'BEGIN{n=0} /BEGIN CERT/{n++} n==2' > intermediate-ca.crt
# 추출한 중간 CA를 TrustStore에 추가
keytool -importcert \
-keystore /etc/ssl/truststore.jks \
-storepass trustpass \
-alias intermediate-ca-new \
-file intermediate-ca.crt \
-noprompt
# Java 기본 cacerts에 추가 (sudo 필요)
sudo keytool -importcert \
-keystore $JAVA_HOME/jre/lib/security/cacerts \
-storepass changeit \
-alias intermediate-ca-new \
-file intermediate-ca.crt \
-noprompt
# WAS 재시작 후 연결 테스트
sudo systemctl restart tomcat
curl -v https://external-api.example.com/health 2>&1 | grep -E "verify|Verify"
심화 — 서버 인증서는 멀쩡한데 mTLS만 끊긴다
심화: mTLS 핸드셰이크의 안쪽 — 클라이언트 인증서는 언제, 무엇으로 검증되나
앞에서 KeyStore(나의 인증서)와 TrustStore(신뢰하는 상대)를 나눴습니다. 그 둘이 실제 TLS 핸드셰이크의 어느 순간에 쓰이는지를 알면, "서버 인증서는 정상인데 mTLS만 실패"하는 장애를 정확히 짚을 수 있습니다.
- 핸드셰이크 순서: 클라이언트가 ClientHello를 보내면, 서버는 자신의 인증서와 함께 CertificateRequest(클라이언트 인증서를 내놓으라는 요구)를 보냅니다. 그러면 클라이언트는 자기 인증서(KeyStore의 것)를 제시하고, 개인키로 서명한 CertificateVerify로 "이 인증서의 주인이 나"임을 증명합니다.
- 검증은 서버 쪽에서 일어난다: 우리가 낸 클라이언트 인증서는 서버가 자기 신뢰 앵커로 검증합니다. 즉 우리 클라이언트 인증서를 발급한 CA를 서버가 신뢰해야 하고, 우리는 리프 인증서만이 아니라 중간 CA까지 이어지는 전체 체인을 제시해야 서버가 앵커까지 경로를 이을 수 있습니다.
- 여기서 실패하면 HTTP는 시작도 못 한다: 클라 인증서 체인이 불완전하거나, 우리 발급 CA를 서버가 안 믿거나, 인증서가 만료·alias 불일치로 실제 제시되지 않으면 서버는 핸드셰이크 단계에서
handshake_failure·bad_certificate로 연결을 끊습니다. 응답 코드(401/403) 이전, 즉 HTTP에 닿기도 전에 끊기는 것이 서버 인증서 문제(PKIX)와의 결정적 차이입니다. - 진단이 갈리는 지점:
openssl s_client로 클라 인증서 없이 접속하면 서버 인증서만 검증되어Verify return code: 0이 나올 수 있습니다. 그것은 "서버 인증서가 정상"일 뿐, 우리 클라 인증서가 받아들여지는지는 별개입니다 — 그래서 mTLS는 클라 인증서를 붙여 따로 재현해야 합니다.
정리하면 PKIX path building failed가 "상대(서버) 인증서를 내가 못 믿겠다(TrustStore)"라면, mTLS handshake_failure는 "내(클라) 인증서를 상대가 못 믿겠다(KeyStore 체인·발급 CA)"로 방향이 반대입니다.
상황: nc로 포트는 열려 있고, openssl s_client -connect host:443은 서버 인증서 검증 0 (ok)를 돌려줍니다. 그런데 클라이언트 인증서를 붙여 호출하는 실제 앱만 SSLHandshakeException·handshake_failure로 끊기고, HTTP 응답 코드는 구경도 못 합니다. 서버 인증서는 멀쩡한데 mTLS만 안 됩니다.
원인: 서버가 CertificateRequest로 우리 클라이언트 인증서를 요구하는데, 우리 쪽 제시가 서버 검증을 통과하지 못합니다. 흔한 경우는 (1) KeyStore(JKS)에 리프 인증서만 있고 중간 CA 체인이 빠져 서버가 신뢰 앵커까지 경로를 못 잇거나, (2) 우리 클라 인증서를 발급한 CA가 서버의 신뢰 목록에 없거나, (3) 인증서 만료·alias 불일치로 애초에 인증서가 제시되지 않은 것입니다. 셋 다 서버 쪽 검증 실패라 HTTP 이전 단계에서 끊깁니다.
진단: openssl s_client -connect host:443 -cert client.crt -key client.key -CAfile chain.pem로 클라 인증서를 붙여 재현합니다. peer did not return a certificate면 제시 자체가 안 된 것(alias·경로), alert handshake failure·certificate unknown이면 서버가 우리 발급 CA를 안 믿는 것입니다. keytool -list -v로 KeyStore에 privateKeyEntry와 리프+중간 CA 전체 체인이 있는지, 인증서 유효기간이 남았는지 확인합니다.
해결: KeyStore에 리프와 중간 CA를 모두 포함시킵니다 — PEM에서 만들 때 openssl pkcs12 -export에 전체 체인 파일을 넣어 체인이 딸려 가게 합니다. 인증서가 만료됐으면 갱신하고, 우리 발급 CA를 상대 기관 신뢰 목록에 등록해 달라고 요청합니다. openssl 재현에서 핸드셰이크가 성공하면 그 구성을 앱 JKS에 반영하고 WAS를 재시작합니다.
실제 업무에서 이 지식이 쓰이는 상황:
공공기관이나 금융 프로젝트에서 외부 연계 오류는 오픈 전에 가장 많이 발생하는 장애 유형입니다. 대부분은 방화벽 오픈 누락과 SSL 인증서 문제입니다.
새 외부 연계 추가 시 표준 절차:
# 1. 외부 기관에서 받아야 할 정보 목록 작성
# - 운영/테스트 엔드포인트 URL
# - IP 화이트리스트 등록 (우리 서버 IP 전달 필요)
# - API Key 또는 클라이언트 인증서 발급
# - 테스트 계정 (SMS 발송 수신번호, 결제 테스트 카드 등)
# 2. 방화벽 오픈 요청 (개발→운영 환경 모두)
# 3. 연결 사전 점검 (3단계: nc → openssl → curl)
nc -zv api.external.com 443
openssl s_client -connect api.external.com:443 2>/dev/null | grep "Verify return code"
curl -m 10 -s -o /dev/null -w "%{http_code}" https://api.external.com/health
# 4. 앱 연동 테스트 (테스트 환경 → 운영 환경 순서)
# 5. Circuit Breaker 및 timeout 설정 검토
SMS 발송 실패 시 빠른 점검:
# API 직접 호출로 응답 코드/메시지 확인
curl -X POST https://sms-api.example.com/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"to":"01012345678","message":"테스트"}'
# 응답: {"result":"error","code":"E401","message":"Invalid API Key"}
# → API Key 만료 또는 IP 화이트리스트 미등록 확인
외부 API 연계는 우리가 통제할 수 없는 외부 시스템에 의존하는 구간입니다. Circuit Breaker와 적절한 timeout으로 외부 장애가 내부 시스템으로 전파되는 것을 막는 것이 운영 안정성의 핵심입니다.
명령어·단축키 빠른 참조
외부 기관 API 연계에서 nc→openssl→curl 3단계 진단과 JKS/TrustStore 관리에 쓴 명령을 모았습니다. "예" 열의 조합을 그대로 써도 됩니다.
| 명령어/단축키 | 용도 | 자주 쓰는 예 |
|---|---|---|
nc -zv | 1단계 — L4 포트·방화벽 도달 확인 | nc -zv external-api.example.com 443 |
openssl s_client -connect | 2단계 — TLS 핸드셰이크·인증서 체인 검증 | openssl s_client -connect host:443 2>/dev/null | grep "Verify return code" |
openssl x509 -noout -dates | 서버 인증서 만료일 확인 | openssl s_client -connect host:443 2>/dev/null | openssl x509 -noout -dates |
openssl s_client -showcerts | 중간 CA 포함 인증서 체인 추출 | openssl s_client -connect host:443 -showcerts |
curl -m -w "%{http_code}" | 3단계 — HTTP 응답코드·시간 확인 | curl -m 10 -s -o /dev/null -w "%{http_code} (%{time_total}s)\n" URL |
keytool -list -v | JKS·TrustStore 내용·만료·alias 확인 | keytool -list -v -keystore client.jks -storepass PW | grep -E "Alias|until" |
keytool -importcert | TrustStore에 외부·중간 CA 추가(PKIX 해결) | keytool -importcert -keystore truststore.jks -alias ca -file ca.crt |
openssl pkcs12 -export | PEM+개인키 → PKCS12로 묶기 | openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 |
keytool -importkeystore | PKCS12 → JKS 변환 | -srckeystore client.p12 -srcstoretype PKCS12 -destkeystore client.jks |
dig +short | 방화벽 등록용 목적지 IP 조회 | dig +short external-api.example.com |
traceroute | 어느 홉에서 막히는지 경로 확인 | traceroute external-api.example.com |
관련 모듈로 더 깊이:
- 트래픽 제어와 이벤트 기반 연계 구조 — 외부 API 호출과 웹훅 수신을 게이트웨이로 통제하는 구조
- SAML/OAuth 기반 싱글사인온 구성과 장애 분석 — 본인인증·전자서명 기관과 맞닿는 SSO/OAuth 연계의 원리
- SMTP 메일과 SMS 게이트웨이 운영 실무 — SMS/메일 게이트웨이 연동을 알림 채널 관점에서 더 깊이
다음 모듈에서는 SAML과 OAuth 기반 SSO 연계 구성과 장애 분석을 다룹니다.