결제 서비스사에서 Webhook으로 결제 완료 이벤트를 보내준다고 합니다. 그런데 가끔 주문이 두 개 생성된다는 버그 신고가 들어옵니다. 로그를 보니 동일한 결제 완료 이벤트가 두 번 수신됐습니다. 한편 API Gateway 앞단에서는 특정 IP가 갑자기 초당 100개 요청을 보내 서버가 느려지는 일도 생겼습니다. 두 문제 모두 API Gateway와 Webhook 설계를 이해하면 해결됩니다.
이 모듈에서는 API Gateway의 역할과 Nginx Rate Limiting 설정, Webhook 수신 요구사항과 멱등성 패턴, 지수 백오프 재시도 전략을 다룹니다.
- 1API Gateway가 서비스 앞에 위치하는 이유와 처리하는 공통 기능을 설명할 수 있다
- 2Nginx limit_req_zone으로 Rate Limiting을 설정하고 동작을 확인할 수 있다
- 3Webhook 수신 서버의 필수 요구사항(응답 시간, 멱등성, HTTPS)을 설명할 수 있다
- 4429 응답 시 지수 백오프 재시도 전략을 설계하고 구현할 수 있다
- 5Webhook 중복 수신을 멱등키(idempotency key)로 처리하는 방법을 적용할 수 있다
API Gateway의 역할
왜 API Gateway가 필요한가
마이크로서비스 환경에서 각 서비스가 인증, Rate Limiting, 로깅, CORS를 개별적으로 구현하면 코드 중복이 발생하고 정책 일관성이 깨집니다. API Gateway는 모든 외부 요청의 단일 진입점(Single Entry Point)으로, 이런 공통 관심사를 한 곳에서 처리합니다.
확대
API Gateway가 처리하는 공통 기능:
| 기능 | 설명 |
|---|---|
| 인증/인가 | JWT 검증, API Key 확인 → 유효하지 않으면 401/403 반환 |
| Rate Limiting | 클라이언트별 초당/분당 요청 수 제한 → 초과 시 429 반환 |
| 라우팅 | URL 경로 기반으로 적합한 백엔드 서비스로 프록시 |
| 로깅/추적 | 모든 요청/응답 기록, 분산 트레이싱 헤더 주입 |
| SSL Termination | HTTPS를 게이트웨이에서 종료, 내부는 HTTP |
| 요청 변환 | 헤더 추가/제거, 요청 본문 변환 |
서비스 구조:
확대
주요 API Gateway 제품 비교:
| 제품 | 특징 | 적합 상황 |
|---|---|---|
| Kong | 플러그인 기반, DB 또는 DB-less 모드 | 엔터프라이즈, 다양한 플러그인 필요 |
| AWS API Gateway | 완전관리형, Lambda 연동 용이 | AWS 환경, 서버리스 아키텍처 |
| Nginx | 가볍고 유연, 직접 설정 필요 | 단순 라우팅/Rate Limiting, 소규모 |
| Traefik | 컨테이너 친화적, 자동 서비스 디스커버리 | Kubernetes/Docker 환경 |
Rate Limiting — 남용 방지와 서버 보호
Nginx limit_req_zone으로 Rate Limiting 구현
Rate Limiting 없이 서비스를 운영하면 악의적인 요청이나 버그가 있는 클라이언트가 서버 자원을 독점합니다. Nginx의 limit_req_zone은 클라이언트별로 요청 속도를 제한하는 방식으로, 별도 Gateway 없이 Nginx만으로도 기본적인 보호가 가능합니다.
Nginx Rate Limiting 설정:
# /etc/nginx/nginx.conf 또는 /etc/nginx/conf.d/rate-limit.conf
http {
# -- Rate Limit Zone 정의 --
# $binary_remote_addr: 클라이언트 IP (바이너리 형식, 메모리 절약)
# zone=api_limit:10m: 'api_limit'이란 이름, 10MB 공유 메모리 (약 16만 IP 저장 가능)
# rate=10r/s: 초당 10개 요청 허용
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
# 로그인 같은 민감한 엔드포인트는 더 엄격하게
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m;
server {
listen 80;
# -- API 엔드포인트에 Rate Limiting 적용 --
location /api/ {
# burst=20: 순간적으로 20개까지 큐에 대기 허용
# nodelay: 큐 대기 없이 즉시 처리 (burst 초과분은 429)
limit_req zone=api_limit burst=20 nodelay;
limit_req_status 429; # 초과 시 반환할 상태 코드
proxy_pass http://backend;
}
# 로그인은 더 엄격하게
location /api/login {
limit_req zone=login_limit burst=3 nodelay;
limit_req_status 429;
proxy_pass http://backend;
}
# Rate Limit 초과 응답 커스터마이징
error_page 429 @rate_limit_exceeded;
location @rate_limit_exceeded {
default_type application/json;
return 429 '{"error":"too_many_requests","message":"요청 한도를 초과했습니다. 잠시 후 다시 시도하세요.","retry_after":1}';
}
}
}
지수 백오프 재시도 로직 (클라이언트 측):
import time
import requests
def call_api_with_retry(url, max_retries=5):
for attempt in range(max_retries):
try:
response = requests.get(url, timeout=10)
if response.status_code == 429:
# Retry-After 헤더가 있으면 그 시간만큼 대기
retry_after = int(response.headers.get('Retry-After', 0))
wait_time = retry_after if retry_after > 0 else (2 ** attempt)
print(f"Rate limited. Waiting {wait_time}s (attempt {attempt + 1})")
time.sleep(wait_time)
continue
return response
except requests.exceptions.Timeout:
wait_time = 2 ** attempt # 1, 2, 4, 8, 16초
print(f"Timeout. Waiting {wait_time}s (attempt {attempt + 1})")
time.sleep(wait_time)
raise Exception(f"API 호출 실패: {max_retries}회 재시도 초과")
Webhook 수신 구조
Webhook의 동작 방식과 수신 서버 요구사항
결제 서비스사에서 "Webhook이 응답이 없어 재전송하고 있다"는 연락이 왔습니다. 동시에 주문이 두 개씩 생성된다는 버그 신고도 들어옵니다. Webhook 수신 서버가 처리하는 데 3초씩 걸렸고, 그 사이 발신측이 재시도를 했습니다. "2초 내 응답"과 "멱등성"을 모르면 Webhook을 제대로 운영할 수 없습니다.
Webhook은 이벤트 주도 방식입니다. 우리가 외부 서비스에 "이 URL로 이벤트 보내줘"라고 등록하면, 이벤트(결제 완료, 배송 시작, SMS 발송 결과 등) 발생 시 외부 서비스가 우리 서버로 HTTP POST를 보냅니다.
Webhook 흐름:
확대
Webhook 수신 서버의 핵심 요구사항:
| 요구사항 | 이유 | 미충족 시 |
|---|---|---|
| 2초 내 응답 | 발신측 timeout 방지 | timeout → 실패로 판단 → 재시도 → 중복 이벤트 |
| 멱등성 | 재시도 시 중복 처리 방지 | 결제 두 번 처리, 이메일 두 번 발송 등 |
| HTTPS | 이벤트 데이터 암호화 | 대부분의 외부 서비스가 HTTPS만 허용 |
| 서명 검증 | 위조 요청 차단 | 공격자가 결제 완료 이벤트 위조 가능 |
멱등성 구현 패턴 (Node.js/Express 예시):
// webhook 수신 핸들러
const processedEvents = new Set(); // 실제로는 Redis나 DB 사용
app.post('/webhook/payment', async (req, res) => {
// 1. 즉시 200 OK 응답 (2초 제한 준수)
res.status(200).json({ received: true });
// 2. 이후 비동기로 실제 처리
const eventId = req.headers['x-event-id'] || req.body.event_id;
// 3. 중복 체크 (멱등성)
if (processedEvents.has(eventId)) {
console.log(`중복 이벤트 무시: ${eventId}`);
return;
}
// 4. 서명 검증 (발신측에서 제공하는 시크릿 사용)
const signature = req.headers['x-webhook-signature'];
const expectedSig = hmac('sha256', process.env.WEBHOOK_SECRET, JSON.stringify(req.body));
if (signature !== expectedSig) {
console.error('서명 불일치 — 위조 요청 차단');
return;
}
// 5. 처리 완료 기록
processedEvents.add(eventId);
// 6. 실제 비즈니스 로직 (비동기)
await processPaymentComplete(req.body);
});
확대
웹훅 이벤트 한 건이 수신·처리되는 순서 — POST 도착부터 ACK까지 6단계
위 요구사항 표가 "수신 서버가 무엇을 만족해야 하나"라면, 여기서는 이벤트 한 건이 어떤 순서로 흘러가며 각 실패가 어디서 드러나는지를 봅니다. 핵심은 순서입니다 — 검증한 뒤 빠르게 응답(ACK)하고, 무거운 처리는 그다음으로 미뤄야 타임아웃·재전송·부하가 한꺼번에 터지지 않습니다. 아래는 웹훅 POST 한 건이 우리 서버 안에서 지나는 6단계입니다.
[결제사] POST /webhook/payment (X-Signature · X-Event-ID · JSON)
│
① 수신 게이트웨이가 POST 접수 → 원문(raw body) 그대로 보존
│ → 파싱·재직렬화 전에 보존해야 서명이 맞음
│
② 서명 검증 같은 시크릿으로 raw body에 HMAC 재계산 → 상수시간 비교
│ 불일치 → 위조로 보고 거부(4xx), 이후 단계 안 감
│
③ 재전송·멱등 타임스탬프 허용오차(±N분) 확인 + 이벤트 ID 중복 조회
│ 이미 처리한 ID → 처리 건너뛰고 곧장 2xx
│
④ 큐 적재 검증 통과분을 메시지 큐에 넣음 (무거운 처리 분리)
│
⑤ ACK 2초 안에 2xx 반환 → 발신측 타임아웃·재전송 차단
▼
⑥ 비동기 처리 워커가 핸들러 실행 → 성공 시 이벤트 ID 저장(멱등 확정)
[내부 처리 완료]
각 단계에서 무슨 일을 하고, 어긋나면 어떤 증상인가:
| 단계 | 하는 일 | 여기서 어긋나면 |
|---|---|---|
| ① 수신·원문 보존 | POST를 받고 파싱 전 raw body를 보존 | 파싱 후 재직렬화(JSON.stringify)한 값으로 검증 → 정상 이벤트가 전부 서명 불일치 |
| ② 서명 검증 | 시크릿으로 raw body에 HMAC 재계산, 상수시간 비교 | 검증 생략·== 비교 → 위조 이벤트 통과 또는 타이밍 공격 노출 |
| ③ 재전송·멱등 | 타임스탬프 허용오차 + 이벤트 ID 중복 판별 | 멱등 없음 → 재전송된 결제 완료가 주문을 두 번 생성 |
| ④ 큐 적재 | 통과분을 큐에 넣어 무거운 처리를 분리 | 핸들러에서 동기로 무거운 작업(정산·메일) → 응답 지연 |
| ⑤ ACK | 2초 안에 2xx 반환 | 응답이 2초 초과 → 발신측 타임아웃 → 재전송 폭주(부하 악순환) |
| ⑥ 비동기 처리·기록 | 워커가 핸들러 실행 후 이벤트 ID 저장 | 처리 전에 ID를 먼저 확정 저장하면, 처리 실패분이 재전송돼도 멱등에 걸려 영영 처리 안 됨 |
즉 웹훅 사고는 대개 세 지점에서 납니다 — ①②의 서명(정상인데 전부 거부되면 raw body가 아니라 재조립본으로 검증한 것), ③의 멱등(주문 중복이면 이벤트 ID 기록이 빠진 것), ⑤의 응답 시간(재전송 폭주면 핸들러가 동기로 오래 걸린 것). 핵심 순서는 "검증 → 빠른 ACK → 비동기 처리"이고, 이 순서가 뒤집혀 무거운 처리를 ACK 앞에 두면 타임아웃·재전송·부하가 함께 터집니다. curl -w "%{time_total}"로 응답 시간을, 로그의 이벤트 ID 중복으로 멱등을 각각 확인하면 어느 단계인지 좁혀집니다.
실습 — Rate Limiting과 Webhook 테스트
현재 Nginx 설정에서 Rate Limiting 관련 지시어를 확인합니다.
# Nginx 전체 설정에서 Rate Limiting 설정 확인
nginx -T | grep limit_req
# limit_req_zone 정의와 limit_req 적용 위치 확인
nginx -T | grep -E "limit_req_zone|limit_req "
# Rate Limiting 동작 테스트 (빠르게 11개 요청 → 일부 429)
for i in $(seq 1 15); do
curl -s -o /dev/null -w "Request $i: %{http_code}\n" http://localhost/api/test
done
# 처음 10개는 200, 이후는 429 또는 503 (설정에 따라 다름)
nginx -T | grep limit_req- nginx -T | grep limit_req_zone으로 정의 위치와 rate 값을 먼저 확인 — rate=10r/s이면 초당 10요청 허용. burst 값이 없으면 초과 요청이 즉시 503으로 거부됨(burst 설정으로 순간 트래픽 허용 가능)
- 반복 요청 테스트에서 429가 나오면 rate limit 동작 확인 — 첫 10개 요청이 200이고 11번째부터 429면 정상. 모두 200이면 limit_req 지시자가 location 블록에 적용 안 된 것
- Nginx error.log에 "limiting requests"가 있고 429도 반환되는 조합이면 설정 완료 — 로그는 있는데 429가 안 나오면 return 429가 아닌 nodelay 옵션이 설정된 것으로 요청이 지연만 되고 거부 안 됨
nc(netcat)로 임시 수신 서버를 열고 Webhook 요청을 받아봅니다.
# 터미널 1: nc로 8888 포트 수신 대기
nc -l -p 8888
# 터미널 2: 별도 창에서 Webhook 발송 테스트
curl -X POST http://localhost:8888/webhook/test \
-H "Content-Type: application/json" \
-H "X-Event-ID: evt-001" \
-d '{"event":"payment.done","order_id":"ORD-001","amount":50000}'
# 터미널 1에서 수신된 HTTP 요청 전체 내용 확인:
# POST /webhook/test HTTP/1.1
# Host: localhost:8888
# Content-Type: application/json
# X-Event-ID: evt-001
# ...
# {"event":"payment.done","order_id":"ORD-001","amount":50000}
nc -l -p 8888- nc 터미널에 HTTP 요청 헤더가 표시됐는지 먼저 확인 — 아무것도 없으면 Webhook 발송 측이 우리 서버 IP/포트가 아닌 다른 주소로 보내는 것. 헤더 첫 줄에서 POST /endpoint HTTP/1.1 형식 확인
- X-Event-ID 헤더가 없으면 Webhook 발송 측 설정 누락 — 이벤트 ID가 없으면 중복 수신 시 멱등성 보장 불가. 실제 운영 서버는 이 ID를 DB에 저장해 중복 처리를 막아야 함
- 요청 본문 수신은 됐지만 Webhook 발송 측에 타임아웃 오류가 나면 — 수신 서버가 2초 내 응답하지 않은 것. 실제 처리 로직(DB 저장 등)은 비동기로 분리하고 즉시 200 OK를 먼저 반환해야 재시도 폭탄 방지
트러블슈팅
원인: 백엔드 서비스 프로세스는 살아있지만 응답이 지연되거나(응답 timeout 초과), keepalive 연결이 끊어진 상태에서 Gateway가 재연결하기 전에 요청이 들어온 경우입니다. 또는 백엔드가 Gateway의 IP에서 오는 연결을 방화벽으로 차단한 경우입니다.
# Gateway의 업스트림 에러 로그 확인
grep "upstream" /var/log/nginx/error.log | tail -20
# 출력 예: [error] upstream timed out (110: Connection timed out)
# [error] connect() failed (111: Connection refused)
# 백엔드 서버 직접 접속 테스트 (Gateway 우회)
curl -v http://192.168.10.11:8080/actuator/health
# → 200이면 백엔드는 정상, Gateway→백엔드 구간 문제
# Gateway 서버에서 백엔드로 TCP 연결 확인
nc -zv 192.168.10.11 8080
# Nginx proxy timeout 설정 확인 및 조정
nginx -T | grep -E "proxy_(connect|send|read)_timeout"
# 너무 짧으면 증가
# proxy_connect_timeout 10s;
# proxy_read_timeout 60s;
해결: proxy_read_timeout을 백엔드 응답 시간에 맞게 조정하고, upstream의 keepalive 설정을 추가합니다. 방화벽 문제라면 Gateway IP에서 백엔드 포트로의 inbound 규칙을 확인합니다.
원인: Webhook 수신 서버의 응답이 2초를 넘기는 경우 발신측이 timeout으로 판단하고 재전송합니다. 수신 서버가 응답을 보내기 전에 이미 처리를 시작했다면, 재전송 이벤트가 오면 동일 주문이 두 번 처리됩니다.
# 수신 서버 응답 시간 확인
curl -w "\nTime: %{time_total}s\n" -X POST http://localhost/webhook/payment \
-H "Content-Type: application/json" \
-d '{"event":"payment.done","order_id":"ORD-TEST"}'
# 2초 이상이면 발신측이 timeout으로 처리
# 애플리케이션 로그에서 중복 이벤트 확인
grep "ORD-001" /var/log/app/webhook.log
# 동일 order_id가 두 번 이상 나타나면 중복 처리 중
# 해결 방안 확인:
# 1. 응답을 먼저 보내고 처리는 비동기로 → 즉시 200 OK
# 2. 이벤트 ID를 DB나 Redis에 기록하여 중복 체크
# 예: Redis SETNX로 멱등키 설정 (이미 있으면 중복)
# redis-cli SET webhook:evt-001 1 NX EX 86400
# → (nil)이면 이미 처리된 이벤트
해결: Webhook 핸들러를 "즉시 200 응답 → 비동기 처리" 패턴으로 변경하고, 이벤트 ID를 처리 완료 후 DB 또는 Redis에 저장하여 중복 수신 시 건너뛰는 멱등성 로직을 추가합니다.
심화 — 서명은 붙였는데 전부 위조로 걸린다
심화: 웹훅 서명 검증의 실제 — 무엇에 서명했고, 무엇을 비교하는가
"서명 검증으로 위조를 막는다"는 한 줄은 쉽지만, 실제로 붙여 보면 정상 이벤트가 전부 막히거나 반대로 검증이 사실상 무력한 경우가 흔합니다. 서명이 정확히 무엇을 보증하고 어디서 어긋나는지를 알아야 합니다.
- 원문(raw body)에 대한 지문이다: 발신사는 공유 시크릿으로 자신이 보낸 본문 바이트에 HMAC(예: HMAC-SHA256)을 계산해 헤더(
X-Signature등)에 담습니다. 수신측이 같은 시크릿으로 같은 바이트에 다시 계산해 값이 같으면, 그 시크릿을 아는 발신자가 보냈고 내용이 변조되지 않았음이 보장됩니다. - 재직렬화하면 지문이 깨진다: 여기서 대부분 사고가 납니다. 프레임워크가 본문을 JSON 객체로 파싱한 뒤 우리가 그것을 다시 문자열로 만들어(
JSON.stringify) 서명을 계산하면, 키 순서·공백·유니코드 이스케이프가 원문과 달라져 지문이 어긋납니다. 발신자가 서명한 건 "그들이 보낸 원문"이지 "우리가 재조립한 것"이 아닙니다 — 반드시 수신 원문 바이트로 검증해야 합니다. - 비교는 상수시간으로: 서명 문자열을 일반
==로 비교하면 일치 길이에 따라 응답 시간이 미세하게 달라져, 이론상 한 바이트씩 맞춰가는 타이밍 공격이 가능합니다.hmac.compare_digest류의 상수시간 비교를 씁니다. - 서명만으로는 재전송을 못 막는다: 공격자가 과거의 정상 요청을 그대로 다시 쏘면 서명은 여전히 유효합니다. 그래서 서명 대상에 타임스탬프를 포함시키고, 수신측이 허용오차(예: ±5분) 밖이면 거부하며, 이벤트 ID로 멱등 처리를 더해야 재전송·중복까지 막힙니다.
정리하면 안전한 웹훅 검증은 "원문 바이트 + 상수시간 비교 + 타임스탬프 허용오차 + 멱등"의 조합이지, HMAC 한 줄이 아닙니다.
상황: 검증 코드를 추가한 뒤로 모든 웹훅이 서명 불일치로 401 처리됩니다. 발신사 대시보드에는 우리 응답이 실패로 찍혀 재전송이 쌓입니다. 시크릿도 문서대로 넣었고 알고리즘(HMAC-SHA256)도 맞습니다.
원인: 수신 프레임워크가 본문을 이미 JSON으로 파싱한 상태에서, 검증 코드가 그 객체를 JSON.stringify로 다시 문자열로 만들어 HMAC을 계산하고 있었습니다. 재직렬화 과정에서 공백·키 순서·유니코드 이스케이프가 발신 원문과 달라져, 같은 시크릿·같은 알고리즘인데도 지문이 어긋납니다. 검증 대상이 "원문"이 아니라 "재조립본"이었던 것입니다.
진단: 발신사 문서에서 "raw body 기준 서명"인지 확인합니다. 수신 시점의 원문 바이트 길이(Content-Length)와 우리가 재직렬화한 문자열의 길이를 로그로 대조하면 대개 다릅니다. 원문과 재조립본을 나란히 찍어 공백·이스케이프 차이를 눈으로 확인합니다.
해결: 해당 웹훅 라우트만 본문을 파싱 전에 원문으로 보존하도록 바꿉니다(예: express.raw({ type: 'application/json' })를 쓰거나 body-parser의 verify 콜백에서 rawBody를 저장). 그 원문 바이트로 HMAC을 계산하고, 비교는 상수시간 함수로 합니다. 재발·재전송 방지를 위해 타임스탬프 허용오차 검증과 이벤트 ID 멱등 처리를 함께 넣습니다.
실제 업무에서 이 지식이 쓰이는 상황:
결제 연동이나 배송 추적, SMS 발송 결과 수신 등 외부 서비스 연동은 대부분 Webhook으로 이루어집니다. 신입 개발자나 주니어 인프라 담당자가 가장 자주 실수하는 부분이 "2초 내 응답"과 "멱등성" 두 가지입니다.
Webhook 수신 서버 구성 체크리스트:
# 1. 응답 시간 확인 (2초 이내여야 함)
curl -w "응답시간: %{time_total}s\n" -X POST http://localhost/webhook/test \
-H "Content-Type: application/json" -d '{}'
# 2. HTTPS 설정 확인 (대부분 외부 서비스가 요구)
curl -vI https://our-server.com/webhook/payment 2>&1 | grep -E "SSL|TLS|Verify"
# 3. Webhook URL을 외부에서 접근 가능한지 확인
curl -m 5 https://our-server.com/webhook/payment
# Connection refused → 방화벽 또는 포트 미오픈
# 4. Rate Limiting 현황 확인
nginx -T | grep limit_req
API Gateway 장애 시 빠른 확인 순서:
# Gateway 상태
systemctl status nginx kong
# 최근 에러 로그
tail -50 /var/log/nginx/error.log | grep -E "upstream|timeout|502|504"
# 백엔드 직접 접속 테스트
curl http://백엔드서버:포트/health
API Gateway와 Webhook을 올바르게 구성하면 서비스 안정성이 크게 높아집니다.
명령어·단축키 빠른 참조
API Gateway의 Rate Limiting 확인과 Webhook 수신 테스트·장애 격리에 쓴 명령을 모았습니다. "예" 열의 조합을 그대로 써도 됩니다.
| 명령어/단축키 | 용도 | 자주 쓰는 예 |
|---|---|---|
nginx -T | 실행 중 Nginx 전체 설정 덤프 | nginx -T | grep -E "limit_req_zone|limit_req " |
curl -o /dev/null -w "%{http_code}" (반복) | Rate Limiting 동작 테스트(429 유발) | for i in $(seq 1 15); do curl -s -o /dev/null -w "%{http_code}\n" URL; done |
nc -l | 임시 수신 서버로 Webhook 원문 확인 | nc -l -p 8888 (다른 창에서 curl POST) |
curl -X POST -d | Webhook 발송 시뮬레이션 | curl -X POST -H "X-Event-ID: evt-001" -d '{"event":"payment.done"}' URL |
curl -w "%{time_total}" | 수신 서버 2초 응답 초과 여부 측정 | curl -w "%{time_total}s\n" -X POST -d '{}' URL/webhook |
nc -zv | Gateway→백엔드 TCP 연결 확인 | nc -zv 192.168.10.11 8080 |
curl -v (백엔드 직결) | Gateway 우회로 502 원인 격리 | curl -v http://192.168.10.11:8080/actuator/health |
grep upstream error.log | 502/504 업스트림 오류 추적 | grep "upstream" /var/log/nginx/error.log | tail -20 |
redis-cli SET ... NX EX | 멱등키로 중복 이벤트 차단 | redis-cli SET webhook:evt-001 1 NX EX 86400 ((nil)=이미 처리됨) |
curl -vI | Webhook URL의 HTTPS·TLS 확인 | curl -vI https://our-server.com/webhook 2>&1 | grep -E "SSL|TLS" |
systemctl status | Gateway 프로세스 상태 확인 | systemctl status nginx kong |
관련 모듈로 더 깊이:
- RESTful API 구조와 curl/Postman 테스트 실무 — Gateway가 라우팅하고 Webhook이 호출하는 REST API 설계 원리
- 써드파티 API와 공공 인프라 연계 실무 — Webhook 송신 측인 외부 기관 API 연계 실무
- Nginx 리버스 프록시와 로드밸런싱 설정 — Gateway의 핵심 기능인 라우팅·프록시를 Nginx로 구현하는 법
다음 모듈에서는 NICE 본인인증, SMS 게이트웨이, 전자서명 같은 외부 기관 API 연계 실무를 다룹니다.