가이드 · gmail api
제품 팀은 Gmail API를 어떻게 안전하게 구현해야 하나요?
Gmail API는 일반적인 이메일 전송용 자격 증명이 아니라 특정 Gmail 메일함에 대한 위임된 접근으로 구현하세요. 기능을 지원하는 가장 작은 OAuth 스코프를 선택하고, 인증 상태와 리프레시 토큰을 보호하고, 모든 메일함을 테넌트 단위로 유지하세요. 성숙한 인터넷 메시지 라이브러리로 메시지를 만들고, 반환된 Gmail 메시지 ID를 기록하고, Pub/Sub와 history 레코드로 변경 사항을 동기화하세요. 서비스 계정 가장(impersonation)은 Workspace 관리자가 결정할 사항으로 다루세요. 마지막으로 API 접수, 수신 서버로의 전달, 받은편지함 도달을 별개의 결과로 유지하세요.
코드를 작성하기 전에 메일함 모델 정하기
Gmail API는 사용자의 Gmail 메일함을 대상으로 동작합니다. 제품이 그 메일함을 읽거나, 라벨과 스레드를 정리하거나, 초안을 만들거나, 승인한 사용자 명의로 발송하거나, 메일함 변경 사항을 동기화해야 할 때 적합합니다. 이 권한은 검증된 제품 도메인에서 애플리케이션 이메일 API를 호출하는 것보다 훨씬 넓습니다. 먼저 정확한 메일함 작업과 접근을 허용하는 주체를 명시하세요. 사용자용 제품은 보통 연결된 Google 계정마다 OAuth 동의를 사용합니다. 내부 Google Workspace 자동화는 대신 관리자가 승인한 도메인 전체 위임을 사용할 수 있습니다. 영수증, 인증 링크, 알림 등 제품에서 발생하는 메시지를 회사가 통제하는 도메인에서 보내는 것이 유일한 요구 사항이라면 메일함 접근을 아예 피하고 트랜잭션 이메일 API를 검토하세요. 이 아키텍처 결정은 어떤 보안 제어나 동의 화면이 그 부담을 메우기 전에 불필요한 접근 자체를 줄여 줍니다.
실용적으로 가장 좁은 스코프로 승인받기
OAuth 클라이언트를 올바른 애플리케이션 유형으로 구성하고, 정확히 등록된 리디렉션 URI를 사용하고, 예측할 수 없는 state 값으로 승인 응답을 시작한 브라우저 세션에 묶으세요. 접근 권한은 사용자가 그것이 필요한 기능을 켤 때, 그 맥락에서 요청하세요. 발송 전용 연동에는 `https://www.googleapis.com/auth/gmail.send`가 메일함을 읽거나 수정하는 스코프보다 좁습니다. Google은 `gmail.send`를 민감한 스코프로, `gmail.readonly`, `gmail.compose`, `gmail.modify` 같은 스코프를 제한된 스코프로 분류합니다. 민감하거나 제한된 접근을 사용하는 공개 앱은 OAuth 검증이 필요할 수 있으며, 제한된 스코프 데이터를 서버 측에 저장하거나 전송하면 추가 보안 평가 요건이 적용될 수 있습니다. 오프라인 접근은 백그라운드 작업이 정말로 필요할 때만 요청하세요. 리프레시 토큰은 암호화하고, 각 토큰을 내부 테넌트 하나와 Google subject 하나에 연결하고, 브라우저 코드나 로그에 노출하지 말고, 로컬 자격 증명을 삭제하고 백그라운드 처리를 중단하는 검증된 연결 해제 경로를 제공하세요.
서비스 계정과 도메인 전체 위임 이해하기
서비스 계정은 애플리케이션 ID이지 그대로 끼워 넣을 수 있는 Gmail 받은편지함이 아닙니다. 그 자체로는 직원들의 메시지에 접근할 수 없습니다. Google Workspace 사용자 데이터에 접근하려면 슈퍼 관리자가 도메인 전체 위임을 통해 서비스 계정의 숫자 클라이언트 ID와 정확한 OAuth 스코프 목록을 명시적으로 승인해야 합니다. 그런 다음 애플리케이션이 지정한 사용자의 위임된 자격 증명을 요청하고, 각 API 호출은 승인된 스코프 안에서 그 사용자의 권한으로 동작합니다. 백그라운드 워커가 조용히 다른 메일함으로 바꾸지 못하도록 가장 대상 사용자를 작업 데이터와 감사 로그에 명시하세요. 성격이 크게 다른 워크로드에는 별도의 서비스 계정을 사용하고, 런타임이 관리형 자격 증명을 쓸 수 있다면 내려받을 수 있는 개인 키를 피하고, 도메인 전체 위임 권한을 정기적으로 검토하세요. 일반 소비자용 Gmail 계정에는 이런 조직 전체 위임을 부여할 Workspace 관리자가 없으므로, 그런 계정에는 사용자 OAuth 동의를 사용하세요.
통제와 감사 가능성을 잃지 않고 메시지 발송하기
Gmail은 base64url로 인코딩한 완전한 인터넷 이메일 메시지를 `users.messages.send`의 `raw` 필드로 받습니다. 제품은 초안을 만든 뒤 나중에 발송할 수도 있습니다. From, To, Cc, Bcc, Subject, Date, Message-ID, 텍스트, HTML, 첨부 파일 구조는 헤더 줄을 직접 이어 붙이지 말고 유지 관리되는 메시지 라이브러리로 생성하세요. 인코딩하기 전에 수신자와 콘텐츠를 검증하고, 헤더 인젝션을 거부하고, 명시적인 크기 제한을 두세요. Gmail을 호출하기 전에 제품 동작을 멱등하게 만드세요. 안정적인 애플리케이션 이벤트 키, 대상 메일함 subject, 발송 시도 상태를 저장합니다. 성공 응답을 받은 뒤에는 Gmail이 반환한 메시지 ID와 스레드 ID를 그 이벤트와 함께 저장하세요. 요청을 전송한 뒤 클라이언트가 타임아웃되면 메시지가 이미 접수되었을 수 있으므로 재시도하기 전에 메일함 상태를 조정하세요. 원래의 응답이 유실되었더라도 무작정 재시도하면 중복 이메일이 발생할 수 있습니다. 콘텐츠나 수신자에 승인이 필요하다면 초안 생성과 사람의 검토를 함께 사용하세요.
history 레코드로 메일함 변경 사항 동기화하기
서버 측 메일함 연동에서 Gmail watch는 Google Cloud Pub/Sub로 변경 신호를 게시합니다. 이 알림은 완전한 이메일 페이로드가 아니라 동기화를 시작하라는 신호입니다. watch 응답의 현재 history ID와 만료 시각을 저장하고, 알림에는 빠르게 확인 응답을 보내고, 마지막으로 성공적으로 커밋한 history ID부터 `users.history.list`를 호출해 메시지와 라벨의 변경 사항을 찾으세요. 기능에 필요한 메시지만 가져오고, 로컬 쓰기가 성공한 뒤에 체크포인트를 앞으로 옮기세요. 알림은 지연되거나 중복될 수 있으므로 메시지와 history 처리를 멱등하게 만드세요. Gmail은 메일함 watch를 최소 7일마다 갱신하도록 요구하고 매일 갱신을 권장합니다. 만료 전에 충분히 여유를 두고 갱신을 예약하고 실패 시 알림을 보내세요. 저장된 history ID가 Gmail에서 사용할 수 있는 범위를 벗어나면 API는 HTTP 404를 반환합니다. 이는 정의된 복구 경로로 다루세요. 유효하지 않은 history ID를 영원히 재시도하지 말고, 통제된 전체 동기화를 수행하고, 새 체크포인트를 만든 뒤 증분 처리를 재개하세요.
단계별 구현 및 검증 워크플로 사용하기
첫째, 기능이 메일을 보내는지, 읽는지, 수정하는지, watch하는지 문서화하고 각 작업을 필요한 최소 OAuth 스코프에 대응시키세요. 둘째, 개발용과 프로덕션용으로 Google Cloud 프로젝트나 OAuth 클라이언트를 분리하고 정확한 리디렉션 URI와 자격 증명 담당자를 지정하세요. 셋째, state 검증, 필요할 때만 사용하는 오프라인 접근, 암호화된 토큰 저장, 토큰 폐기, 테넌트 수준의 접근 검사를 갖춘 인증을 구현하세요. 넷째, 통제된 메일함으로 테스트하세요. 연결하고, 만료된 액세스 토큰을 갱신하고, 동의를 철회하고, 다시 연결하고, 한 번 발송하고, 모호한 타임아웃을 시뮬레이션하고, 중복 방지를 확인합니다. 다섯째, 수신도 다룬다면 Pub/Sub 권한을 프로비저닝하고, watch를 시작하고, history를 증분 처리하고, 오래된 체크포인트 복구를 강제로 실행하고, watch 갱신을 확인하세요. 여섯째, 사용자별 작업 큐, 상한이 있는 지수 백오프, 구조화된 오류 분류, 기본적으로 메시지 본문과 토큰을 제외하는 감사 로그를 추가하세요. 출시 전에 필요한 Google 검증과 보안 검토를 마치고, 정확한 데이터 사용 공개 문구를 게시하고, 자격 증명 교체와 사용자 데이터 삭제를 미리 연습하세요.
할당량, 재시도, 부분 실패에 대비하기
Gmail은 요청 수뿐 아니라 할당량 단위로 API 사용량을 측정합니다. Google의 할당량 페이지에는 프로젝트당 분당 1,200,000단위와 프로젝트당 사용자당 분당 6,000단위가 나열됩니다. `messages.send`, `drafts.send`, `watch`는 각각 100단위이고 메시지당 수신자 제한은 500명입니다. Gmail의 별도 사용자 발송 제한은 API, 웹, SMTP 클라이언트 전반에 여전히 적용됩니다. 게시된 제한을 비즈니스 로직에 하드코딩하지 말고 Cloud 콘솔과 최신 문서를 런타임 구성 입력으로 취급하세요. 메일함별 작업을 직렬화하거나 공정하게 큐잉하고, 동시성을 제한하며, 유한한 마감 기한과 지터가 있는 지수 백오프로 일시적 응답만 재시도하세요. 인증, 정책, 유효하지 않은 수신자, 잘못된 메시지 오류를 용량 문제처럼 재시도하지 마세요. multipart 배치는 연결 오버헤드를 줄이지만 각 내부 호출은 여전히 할당량을 소비하고 독립적으로 실패할 수 있습니다.
접수, 전달, 받은편지함 도달을 분리해 두기
`messages.send` 호출이 성공했다는 것은 Gmail이 승인된 API 요청을 접수하고 Gmail Message 리소스를 반환했다는 뜻입니다. 모든 수신자의 메일 서버가 메시지를 수락했다는 것을 증명하지 않으며, 수신 시스템이 메시지를 어떻게 분류했는지도 알 수 없습니다. 수신 서버로의 전달은 대상 시스템이 SMTP 책임을 수락했다는 뜻입니다. 받은편지함 도달은 기본 받은편지함, 프로모션, 격리, 스팸 같은 이후의 필터링 결과입니다. 따라서 Gmail의 메일함 API는 제품이 트랜잭션 메일의 전달, 반송, 스팸 신고 텔레메트리를 필요로 할 때 제공업체 이벤트 스트림을 대신할 수 없습니다. 조정을 위해 Gmail 메시지 ID를 보존하되, 별도의 증거가 전달을 뒷받침하지 않는 한 사용자에게 보이는 상태는 Gmail에서 발송됨 또는 접수됨으로 정확히 표현하세요. 인증, 예상 수신자, 콘텐츠 품질, 발송 행동, 대상 정책이 모두 이후 처리에 영향을 줍니다. API 응답은 수신자의 최종 메일함 폴더를 결정하거나 약속할 수 없습니다.
트랜잭션 이메일 API가 다른 용도에 맞는 경우 알아두기
제품에 스레드, 라벨, 초안, 메일함 동기화를 포함해 개인 또는 조직의 Gmail 메일함에 대한 승인된 액세스가 필요하면 Gmail API를 사용하세요. 트랜잭션 이메일 API는 다른 아키텍처에 맞습니다. 사용자 Gmail 메일함을 읽을 위임 권한 없이 조직이 제어하는 도메인에서 애플리케이션 트리거 메시지를 보냅니다. 경계가 명확하면 제품은 두 시스템을 모두 사용할 수 있습니다. 예를 들어 Gmail OAuth로 지원 에이전트의 연결된 메일함을 읽고, 별도로 검증된 트랜잭션 제공업체로 제품 영수증을 발송할 수 있습니다. 메일함 권한이 애플리케이션 전체 발송으로 새거나 트랜잭션 자격 증명이 사용자 Gmail을 읽지 못하도록 자격 증명, 동의, 메시지 저장소, 재시도 정책, 감사 기록을 분리하세요.
자주 묻는 질문
서비스 계정은 어떤 Gmail 메일함에나 접근할 수 있나요?
아니요. 서비스 계정은 Gmail 사용자 데이터 접근 권한을 자동으로 받지 않습니다. Google Workspace 슈퍼 관리자가 숫자 클라이언트 ID와 승인된 스코프에 도메인 전체 위임을 부여해야 하며, 그 후에 애플리케이션이 그 조직의 사용자를 명시적으로 가장합니다. 일반 소비자용 Gmail 계정에는 사용자 OAuth 동의를 사용하세요.
발송 전용 Gmail 연동은 어떤 OAuth 스코프를 요청해야 하나요?
먼저 `https://www.googleapis.com/auth/gmail.send`를 검토하세요. 이 스코프는 일반적인 메일함 읽기 권한을 부여하지 않고 사용자를 대신해 발송할 수 있게 합니다. 더 넓은 스코프를 요청하기 전에 제품 요구 사항 중 초안, 메시지 읽기, 라벨, 수정이 실제로 필요한 것이 없는지 확인하고, Google의 민감한 스코프 검증 규정을 고려하세요.
Gmail API 발송이 성공하면 메시지가 전달된 건가요?
아니요. Gmail이 승인된 API 작업을 접수하고 메시지 레코드를 반환했다는 것만 확인해 줍니다. 수신 서버의 수락과 받은편지함 도달은 이후의 별개 상태입니다. 다른 신뢰할 수 있는 신호가 그 결론을 뒷받침하지 않는 한 메시지를 전달됨으로 표시하거나 받은편지함 도달을 약속하지 마세요.
Gmail 푸시 알림에 새 메시지 전체가 들어 있나요?
아니요. Pub/Sub 알림은 메일함 상태가 바뀌었음을 알리며 동기화를 이어가는 데 쓰는 정보를 포함합니다. 애플리케이션은 저장해 둔 history ID부터 Gmail history를 조회하고, 필요한 메시지 데이터를 가져오고, 멱등하게 처리한 다음 체크포인트를 앞으로 옮겨야 합니다.
Gmail 메일함 watch는 얼마나 자주 갱신해야 하나요?
Google은 `watch`를 최소 7일에 한 번 호출하도록 요구하고 매일 갱신을 권장합니다. 반환된 만료 시각을 저장하고, 그보다 앞서 갱신하고, 실패를 모니터링하고, 갱신을 놓쳐도 데이터 공백이 조용히 무한정 생기지 않도록 대체 동기화 작업을 유지하세요.
팀은 언제 Gmail API 대신 트랜잭션 이메일 API를 써야 하나요?
조직이 통제하는 도메인에서 애플리케이션이 발생시키는 이메일이 목적이고 어떤 기능도 개인의 Gmail 메일함 접근을 필요로 하지 않는다면 트랜잭션 이메일 API를 사용하세요. 제품이 위임된 메일함의 메시지, 스레드, 라벨, 초안, 설정 또는 send-as 권한을 구체적으로 필요로 한다면 Gmail API를 사용하세요.
출처
- Gmail API 개요 — Google for Developers
- Gmail API 스코프 선택 — Google for Developers
- 서버 측 인증 구현 — Google for Developers
- 웹 서버 애플리케이션에서 OAuth 2.0 사용하기 — Google for Developers
- 서버 간 애플리케이션에서 OAuth 2.0 사용하기 — Google for Developers
- 이메일 메시지 만들기와 보내기 — Google for Developers
- Gmail API에서 푸시 알림 구성하기 — Google for Developers
- 클라이언트를 Gmail과 동기화하기 — Google for Developers
- Gmail API 사용량 한도 — Google for Developers
- Gmail API 오류 해결하기 — Google for Developers
- Google Workspace API 사용자 데이터 및 개발자 정책 — Google for Developers
- RFC 5322: 인터넷 메시지 형식(Internet Message Format) — RFC Editor
- RFC 5321: 단순 메일 전송 프로토콜(SMTP) — RFC Editor