Microsoft Graph 검증 핸드셰이크 완벽 이해하기
By Mirko Peters ·
팟캐스트 동반 블로그에 다시 오신 것을 환영합니다! 이번 글에서는 Microsoft Graph 변경 알림과 웹후크의 기술적 동작 원리를 깊이 살펴보겠습니다. 웹후크 구독을 설정했는데 이벤트가 단 한 건도 발생하지 않은 경험이 있다면, 여러분만 그런 것이 아닙니다. 죽은 Graph 웹후크의 대부분은 검증 핸드셰이크 단계에서 실패합니다. 애플리케이션이 처음으로 구독을 생성하려 할 때 Microsoft Graph는 엔드포인트가 살아 있고, 트래픽을 수신할 수 있으며, 올바르게 구성되어 있는지 확인하기 위해 테스트 요청을 보냅니다. 이 중요한 단계를 놓치거나 불필요한 부하를 추가하면 구독이 활성화되지 않고, 업무에 필수적인 트리거가 왜 동작하지 않는지 궁금해지게 됩니다.
Automatically translated with AI from the original post. Read the English original
팟캐스트 동반 블로그에 다시 오신 것을 환영합니다! 이번 글에서는 Microsoft Graph 변경 알림과 웹후크의 기술적 동작 원리를 깊이 살펴보겠습니다. 웹후크 구독을 설정했는데 이벤트가 단 한 건도 발생하지 않은 경험이 있다면, 여러분만 그런 것이 아닙니다. 죽은 Graph 웹후크의 대부분은 검증 핸드셰이크 단계에서 실패합니다. 애플리케이션이 처음으로 구독을 생성하려 할 때 Microsoft Graph는 엔드포인트가 살아 있고, 트래픽을 수신할 수 있으며, 올바르게 구성되어 있는지 확인하기 위해 테스트 요청을 보냅니다. 이 중요한 단계를 놓치거나 불필요한 부하를 추가하면 구독이 활성화되지 않고, 업무에 필수적인 트리거가 왜 동작하지 않는지 궁금해지게 됩니다.
이 장애물을 확실하게 극복할 수 있도록 검증 핸드셰이크의 정확한 요구 사항, 엔드포인트 보안 방법, 견고한 복원력 구현, 구독 수명 주기 관리를 차례로 살펴보겠습니다. 탄탄한 Microsoft Graph 웹후크 인프라를 구축하는 데 필요한 모든 내용을 함께 알아봅시다.
주요 내용
- 웹후크 검증 함정: 핸드셰이크 실패로 Graph가 첫 번째 이벤트를 보내지 않는 이유.
- 보안 엔드포인트: JWT 대상(audience) 및 범위(scope) 검사를 철저히 거쳐 실제로 Graph의 요청을 수락하는 방법.
- 복원력 기초: 제한 시간, 백오프 전략, 자동 재시도를 유발하는 상태 코드 식별.
- 수명 주기 상태 관리: 구독이 만료되기 전에 갱신하고, 끊어진 연결을 감지하며, 조기에 알림을 받는 방법.
가장 중요한 주의점: 검증 핸드셰이크
Microsoft Graph API에 새 구독 요청을 제출할 때는 알림 URL을 반드시 제공해야 합니다. Graph는 구독을 저장하고 활성화하기 전에, 해당 URL로 validationToken이라는 쿼리 문자열 또는 본문 매개 변수가 포함된 HTTP GET 또는 POST 요청을 보냅니다. 대부분의 개발자가 여기서 실수합니다.
- Graph는 고유한 validationToken 문자열이 포함된 요청을 엔드포인트로 보냅니다.
- 코드는 응답 본문에 정확히 같은 문자열로 응답해야 합니다. 특히 JSON 래퍼, HTML 서식, 끝에 붙는 줄 바꿈 문자가 없어야 합니다.
- 5초 이내에 빠르게 응답해야 합니다. 네트워크 지연, HTTP 리디렉션, 인증 미들웨어 검사, 본문 가공은 모두 구독을 즉시 실패하게 만듭니다.
최소 예시(의사 코드):
Request: GET /webhook?validationToken=abc123
Response: 200 OK
Body: abc123
Content-Type: text/plain핸드셰이크를 성공시키기 위한 실용 팁:
- 검증 요청만을 위한 짧은 단락(short-circuit) 코드 경로를 구현하세요. 데이터베이스를 거치지 않고, 무거운 인증 검사를 건너뛰며, 로깅 부담도 없애십시오.
- 웹 애플리케이션 방화벽(WAF) 또는 콘텐츠 전송 네트워크(CDN)가 검증 경로에서 Microsoft Graph IP 주소와 사용자 에이전트를 허용하도록 설정하세요.
- 검증 루틴은 기본적인 상태 확인(health check)처럼 다루십시오. 가볍고, 즉각적이며, 완전히 막힘없이 동작해야 합니다.
엔드포인트 보안(신뢰와 토큰)
검증 핸드셰이크가 성공하고 구독이 활성화되면, 이제 보안에 주의를 기울여야 합니다. 웹후크를 수신하도록 엔드포인트를 여는 것은 외부 트래픽을 아키텍처 안으로 들이는 것과 같으므로, 신뢰와 검증이 무엇보다 중요합니다.
- 유효하고 신뢰할 수 있는 SSL/TLS 인증서를 갖춘 HTTPS를 필수로 적용하세요. 암호화되지 않은 HTTP 트래픽은 절대 허용하지 말고, 취약한 암호화 방식은 반드시 비활성화하십시오.
- 수신되는 모든 알림 페이로드에 대해 Authorization 베어러 토큰을 검증하세요.
- Microsoft의 공식 JSON 웹 키 세트(JWKS)에 대해 암호화 서명을 검증하십시오.
- 토큰 발급자(issuer), 대상(audience, 애플리케이션 ID와 일치하는지 확인), 대상 테넌트, 만료 시간을 확인하십시오.
- 수정 대상 리소스에 필요한 애플리케이션 범위(scope)와 역할(role)을 강제로 적용하십시오.
- 최소 권한 원칙을 지키세요: 구독에 실제로 필요한 권한만 부여하십시오. 단일 사이트나 사서함 권한으로 충분한 경우에는 테넌트 전체 액세스를 요청하지 마십시오.
- 내부적으로 헤더를 제거하거나 기본 설정에서 Authorization 헤더를 숨기는 웹 프레임워크에 주의하십시오. 미들웨어가 수신된 헤더를 항상 그대로 유지하는지 반드시 확인하십시오.
견고한 복원력과 재시도
네트워크 장애는 언제든 발생하고, 클라우드 서비스도 일시적으로 불안정해질 수 있으며, 다운스트림 처리 큐가 간혹 과부하에 걸릴 수도 있습니다. 이런 순간에 엔드포인트가 Microsoft Graph에 어떻게 응답하느냐에 따라 통합 환경이 안정적으로 유지될지, 아니면 무너질지가 결정됩니다.
- 반환 코드는 매우 중요합니다:
- 200 OK 또는 202 Accepted는 알림이 정상적으로 전달되고 수신되었음을 Graph에 알려줍니다.
- 503, 504, 429 상태 코드는 서비스가 일시적으로 사용할 수 없음을 Graph에 알려 전달을 재시도하도록 합니다. 이러한 코드는 신중하게 사용하고, 시스템이 무한정 반복되지 않도록 하십시오.
- 4xx 상태 코드(예: 400, 401, 403)는 Graph에서 영구적인 실패로 간주합니다. 즉, 재시도 없이 알림을 즉시 폐기합니다.
- 일시적인 다운스트림 오류를 처리하려면 지수 백오프를 구현하고, 실패한 페이로드는 나중에 다시 처리할 수 있도록 데드레터 큐에 안전하게 저장하십시오.
- 모든 항목을 로깅하십시오: 요청 ID, 구독 ID, 처리 지연 시간, HTTP 상태 코드, 실행 중 발생한 예외를 모두 기록합니다.
안티패턴과 모범 사례 비교:
- ❌ 고정된 3회 재시도를 사용하고, 페이로드를 조용히 버리며, 로컬에 아무것도 저장하지 않는 방식.
- ✅ 지능형 백오프를 적용하고, 전용 데드레터 저장소를 두며, 선제적 알림을 설정하고, 완전한 멱등성을 고려하여 설계한 재처리 작업을 운영하는 방식.
구독 수명 주기 관리 (만료되지 않도록 관리)
수명이 무기한인 다른 생태계의 웹훅과 달리, Microsoft Graph 구독은 만료 기간이 매우 짧습니다. 리소스 유형에 따라 보통 몇 시간에서 길어야 며칠 정도입니다. 구독 수명 주기를 적극적으로 관리하지 않으면 주말 사이에 통합 환경이 조용히 중단될 수 있습니다.
- Graph 구독은 만료 기간이 짧으므로, 견고한 자동 갱신 메커니즘을 구축해야 합니다.
- 만료 시점보다 충분히 앞서 갱신을 자동화하고, 권한 변경이나 관리자 동의 취소로 인해 갱신이 실패하면 알림이 발생하도록 구성하십시오.
- 안심하고 운영하려면 상태 모니터링이 필수입니다. 다음 항목을 추적하십시오:
- 구독 ID별로 그룹화한, 시간당 수신된 알림 수.
- 실패율과 엔드포인트가 반환한 주요 HTTP 상태 코드의 분포.
- Graph가 웹훅을 전송한 시점부터 워커가 이를 처리하기까지의 전체 전달 지연 시간.
- 수신된 데이터 구조에 필요한 필드가 모두 포함되어 있는지 확인하는 페이로드 무결성 검사.
구현 체크리스트
- 라우트 설계
/webhook/validate→ 검증 토큰을 즉시 그리고 깔끔하게 반환합니다./webhook/notify→ 인증을 처리하고, 페이로드를 파싱하며, 메시지를 큐에 넣고, 수신 사실을 신속하게 응답합니다.
- 보안
- HTTPS만 사용하고, JWT를 엄격하게 검증(발급자, 대상, 만료 시간)하며, 최소 권한의 앱 역할을 적용합니다.
- 성능
- 작업을 비동기로 큐에 넣고 무거운 처리는 백그라운드 워커에 맡겨 알림에 빠르게 응답하십시오.
- 안정성
- 503/504/429 오류에 적절한 백오프 전략을 적용하고, 데드레터 저장소를 유지하며, 재처리 작업을 구축하십시오.
- 관찰 가능성
- Application Insights 또는 Log Analytics를 활용하여 포괄적인 메트릭, 추적 정보, 실행 가능한 알림을 확보하십시오.
- 수명 주기
- 예약된 갱신 작업을 구현하고, TTL(Time-to-Live)이 낮을 때 경고하도록 알림을 설정하십시오.
- 운영
- 만료된 구독을 처리하기 위한 문서화된 런북을 유지하고, 구독별 상태 지표를 보여주는 대시보드를 관리하십시오.
빠른 자가 점검 (10분 감사)
- 웹훅 엔드포인트가 1초 미만으로
validationToken을 정상적으로 반환할 수 있습니까? - 모든 알림 요청마다 JWT의 발급자, 대상, 테넌트를 철저히 검증하고 있습니까?
- 페이로드를 신속하게 큐에 넣고 200/202 상태 코드를 반환하고 있습니까, 아니면 엔드포인트가 무거운 비즈니스 로직을 처리하느라 차단되고 있습니까?
- 일시적인 내부 문제가 발생했을 때 400번대 오류 대신 503 또는 429 상태 코드를 올바르게 반환하고 있습니까?
- 실시간 알림과 함께 자동 갱신 작업을 실행하고 계십니까?
- 시스템의 각 구독별로 최근 24시간 전송 그래프를 바로 확인할 수 있습니까?
자주 하는 실수와 해결 방법
- 검증 응답에 프레임워크가 JSON 래퍼를 추가합니다. 해결하려면 라우트가 객체 직렬화 없이 순수 텍스트 본문만 반환하도록 하십시오.
- 리버스 프록시나 API 게이트웨이 때문에 Authorization 헤더가 누락됩니다. 해결하려면 들어오는 모든 헤더를 애플리케이션으로 전달하도록 프록시를 명시적으로 구성하십시오.
- 편의를 위해 전역 권한을 사용합니다. 해결하려면 권한 범위를 개별 사이트나 사서함으로 엄격히 제한하고, 가능한 경우 Resource-Specific Consent(RSC)를 활용하십시오.
- 콜드 스타트로 인해 지연 시간이 5초를 넘습니다. 해결하려면 서버리스 함수를 미리 워밍업하거나 웹 앱을 전용 프리미엄 호스팅 요금제에서 호스팅하십시오.
- 주말 동안 조용히 만료됩니다. 해결하려면 매일 갱신을 예약하고, 구독의 TTL(유효 기간)이 24시간 아래로 떨어질 때마다 자동 알림을 설정하십시오.
Microsoft Graph 검증 핸드셰이크와 변경 알림 파이프라인을 익히려면 세심한 주의가 필요하지만, 그 결실은 놓치는 일이 없는 탄력적이고 견고한 통합입니다. 이 주제를 자세히 다룬 관련 팟캐스트 에피소드에서 더 많은 전문가 조언을 들어 보시기 바랍니다: Fix Microsoft Graph Change Notifications and Webhooks. 오늘부터 이러한 전략을 적용해 더 이상 죽은 웹훅으로 고생하지 마십시오!