Gmail 문의 메일을 Google Apps Script로 구글시트에 자동 정리하는 흐름

Gmail 검색 조건으로 문의 메일을 찾고, 필요한 정보를 구글시트에 기록한 뒤 처리 완료 표시까지 자동화하는 흐름입니다.


Gmail로 들어오는 문의 메일을 매번 열어 보고, 보낸 사람과 제목을 복사해서 구글시트에 붙여넣는 일은 생각보다 시간이 많이 듭니다. 하루에 몇 건이면 괜찮지만, 문의가 꾸준히 쌓이면 누락, 중복 기록, 처리 상태 혼선이 생기기 쉽습니다.


Google Apps Script를 사용하면 Gmail에서 특정 조건에 맞는 메일을 검색하고, 날짜·보낸 사람·이메일·제목·본문 일부를 Google Sheets에 자동 저장할 수 있습니다. 여기에 처리 완료 라벨까지 붙이면 이미 기록한 메일을 다시 저장하지 않도록 관리할 수 있습니다.


Gmail 자동화로 줄일 수 있는 반복 업무

이번 자동화는 고객 문의, 제휴 문의, 견적 요청, 신청 메일처럼 일정한 형식으로 들어오는 메일을 구글시트에 정리하는 데 적합합니다. 메일함에서 하나씩 확인하던 일을 줄이고, 시트에서 접수 현황을 한눈에 볼 수 있게 만드는 것이 핵심입니다.


수동 작업 자동화 후 효과
문의 메일 검색 Gmail 검색 조건으로 자동 조회 확인 시간 단축
보낸 사람·제목 복사 Apps Script가 메일 정보 추출 입력 실수 감소
구글시트에 붙여넣기 행 단위로 자동 저장 누락 방지
처리 여부 기억 처리 완료 라벨 적용 중복 저장 방지

오늘 만들 자동화 흐름

Gmail 검색부터 구글시트 저장과 처리 완료 라벨 적용까지 이어지는 자동화 단계

Gmail 검색, 메일 정보 추출, 구글시트 저장, 처리 완료 라벨 적용 순서로 이어지는 자동화 흐름입니다.


전체 흐름은 단순합니다. Gmail에서 문의 메일을 검색하고, 각 메일의 기본 정보를 가져온 뒤, Google Sheets에 저장합니다. 저장이 끝난 메일에는 Gmail 라벨을 붙여 다음 실행 때 다시 처리되지 않게 합니다.


자동화 흐름
Gmail 검색 → 메일 정보 추출 → 구글시트 기록 → 처리 완료 라벨 적용 순서로 움직입니다. 처음에는 수동 실행으로 결과를 확인하고, 문제가 없을 때 시간 기반 트리거를 연결하는 방식이 안전합니다.


이 방식이 잘 맞는 경우

메일 제목에 “문의”, “제휴”, “견적”, “신청” 같은 단어가 자주 들어가거나, 특정 발신자·라벨·기간을 기준으로 메일을 구분할 수 있다면 적용하기 좋습니다. 반대로 문의 메일 형식이 너무 다양하면 처음부터 넓은 조건으로 자동화하기보다 Gmail 라벨을 먼저 정리한 뒤 시작하는 편이 좋습니다.


Google Apps Script를 처음 다룬다면 기본 개념을 먼저 확인한 뒤 실습하면 이해가 더 쉽습니다. 구글시트 중심의 기초 흐름은 Google Apps Script 자동화 입문: 구글시트 반복 작업 줄이는 법에서 이어서 볼 수 있습니다.


준비물

별도 서버나 유료 자동화 도구 없이 Google 계정 안에서 시작할 수 있습니다. 다만 Gmail과 구글시트의 개인 데이터에 접근하므로 처음 실행할 때 권한 승인이 필요합니다.


준비물 용도 확인할 점
Gmail 문의 메일 검색 검색 조건을 좁게 설정
Google Sheets 메일 정보 저장 시트 ID 확인
Google Apps Script Gmail과 Sheets 연결 권한 승인 필요

구글시트 컬럼 만들기

먼저 Google Sheets에서 새 스프레드시트를 만들고, 첫 번째 행에 컬럼명을 넣습니다. 자동화는 이 컬럼 순서에 맞춰 데이터를 저장하므로 처음부터 단순하게 시작하는 것이 좋습니다.


수집일시 | 메일날짜 | 보낸사람 | 이메일 | 제목 | 본문요약 | 메일ID | 처리상태

여기서 메일ID는 중복 저장을 막는 기준으로 사용합니다. 같은 제목의 문의가 여러 번 들어올 수 있으므로 제목만으로 중복 여부를 판단하면 안 됩니다. Gmail 메시지의 고유 ID를 함께 저장해야 나중에 같은 메일이 반복 기록되는 문제를 줄일 수 있습니다.


Apps Script 코드 작성

구글시트 상단 메뉴에서 확장 프로그램 → Apps Script를 열고 아래 코드를 붙여넣습니다. 코드에서 SPREADSHEET_IDGMAIL_SEARCH_QUERY만 자신의 환경에 맞게 바꾸면 됩니다.


const SPREADSHEET_ID = '여기에_구글시트_ID를_입력하세요';
const SHEET_NAME = '문의메일';
const DONE_LABEL_NAME = '자동정리완료';
const GMAIL_SEARCH_QUERY = 'subject:문의 newer_than:7d -label:자동정리완료';

function saveInquiryEmailsToSheet() {
  const sheet = getOrCreateSheet_();
  prepareHeader_(sheet);

  const existingIds = getExistingMessageIds_(sheet);
  const doneLabel = getOrCreateGmailLabel_(DONE_LABEL_NAME);

  const threads = GmailApp.search(GMAIL_SEARCH_QUERY, 0, 30);
  const rows = [];

  threads.forEach(thread => {
    const messages = thread.getMessages();

    messages.forEach(message => {
      const messageId = message.getId();

      if (existingIds.has(messageId)) {
        return;
      }

      const from = message.getFrom();
      const email = extractEmail_(from);
      const subject = message.getSubject();
      const mailDate = message.getDate();
      const plainBody = message.getPlainBody();
      const summary = plainBody.replace(/\s+/g, ' ').trim().slice(0, 200);

      rows.push([
        new Date(),
        mailDate,
        from,
        email,
        subject,
        summary,
        messageId,
        '시트 저장 완료'
      ]);

      existingIds.add(messageId);
    });

    thread.addLabel(doneLabel);
  });

  if (rows.length > 0) {
    sheet.getRange(sheet.getLastRow() + 1, 1, rows.length, rows[0].length).setValues(rows);
  }
}

function getOrCreateSheet_() {
  const spreadsheet = SpreadsheetApp.openById(SPREADSHEET_ID);
  let sheet = spreadsheet.getSheetByName(SHEET_NAME);

  if (!sheet) {
    sheet = spreadsheet.insertSheet(SHEET_NAME);
  }

  return sheet;
}

function prepareHeader_(sheet) {
  const headers = ['수집일시', '메일날짜', '보낸사람', '이메일', '제목', '본문요약', '메일ID', '처리상태'];
  const firstRow = sheet.getRange(1, 1, 1, headers.length).getValues()[0];

  const hasHeader = firstRow.some(value => value !== '');
  if (!hasHeader) {
    sheet.getRange(1, 1, 1, headers.length).setValues([headers]);
    sheet.setFrozenRows(1);
  }
}

function getExistingMessageIds_(sheet) {
  const lastRow = sheet.getLastRow();

  if (lastRow < 2) {
    return new Set();
  }

  const messageIdColumn = 7;
  const values = sheet.getRange(2, messageIdColumn, lastRow - 1, 1).getValues();

  return new Set(values.flat().filter(String));
}

function getOrCreateGmailLabel_(labelName) {
  const existingLabel = GmailApp.getUserLabelByName(labelName);

  if (existingLabel) {
    return existingLabel;
  }

  return GmailApp.createLabel(labelName);
}

function extractEmail_(fromText) {
  const match = fromText.match(/<(.+?)>/);

  if (match && match[1]) {
    return match[1];
  }

  return fromText;
}

구글시트 ID 찾는 방법

구글시트를 열면 주소창에 긴 URL이 보입니다. 그중 /d//edit 사이에 있는 값이 스프레드시트 ID입니다.


https://docs.google.com/spreadsheets/d/여기가_스프레드시트_ID입니다/edit

Gmail 검색 조건 설정하기

자동화의 정확도는 Gmail 검색 조건에서 결정됩니다. 조건이 너무 넓으면 필요 없는 메일까지 저장되고, 너무 좁으면 실제 문의 메일을 놓칠 수 있습니다. 처음에는 최근 7일 또는 30일처럼 기간을 제한한 뒤 테스트하는 것이 좋습니다.


검색 조건 예시 사용 상황
제목 기준 subject:문의 문의 제목이 일정할 때
발신자 기준 from:example.com 특정 서비스 알림 메일 정리
라벨 기준 label:문의 Gmail 필터로 미리 분류할 때
기간 기준 newer_than:7d 최근 메일만 처리할 때
제외 조건 -label:자동정리완료 이미 처리한 메일 제외

예를 들어 제휴 문의만 저장하고 싶다면 아래처럼 바꿀 수 있습니다.


const GMAIL_SEARCH_QUERY = 'subject:제휴 newer_than:30d -label:자동정리완료';

문의 라벨이 붙은 메일만 정리하고 싶다면 Gmail 필터를 먼저 만든 뒤 아래처럼 사용할 수 있습니다.


const GMAIL_SEARCH_QUERY = 'label:문의 newer_than:30d -label:자동정리완료';

중복 저장을 방지하는 방법

Gmail 자동화에서 가장 흔한 문제는 같은 메일이 여러 번 시트에 저장되는 것입니다. 이를 막으려면 최소 두 가지 장치를 함께 쓰는 것이 좋습니다.


1. 메일ID를 시트에 저장하기

코드에서는 message.getId()로 Gmail 메시지 ID를 가져와 시트의 메일ID 컬럼에 저장합니다. 다음 실행 때 이미 저장된 ID인지 확인하므로 같은 메시지가 다시 기록될 가능성을 줄일 수 있습니다.


2. 처리 완료 라벨 붙이기

저장이 끝난 스레드에는 자동정리완료 라벨을 붙입니다. Gmail 검색 조건에 -label:자동정리완료를 넣어 두면 이미 처리된 스레드를 다시 검색하지 않습니다.


주의할 점
라벨은 스레드 단위로 붙고, 메일ID는 메시지 단위로 저장됩니다. 문의가 같은 스레드 안에서 계속 오가는 업무라면 최신 답장까지 모두 저장할지, 첫 문의만 저장할지 기준을 정한 뒤 코드를 조정하는 것이 좋습니다.


자동 실행 트리거 설정하기

코드가 정상 작동하는지 먼저 수동으로 실행해 본 뒤 자동 실행 트리거를 설정합니다. Apps Script 화면 왼쪽의 시계 모양 트리거 메뉴에서 새 트리거를 추가하면 됩니다.


  1. 실행할 함수 선택: saveInquiryEmailsToSheet
  2. 이벤트 소스 선택: 시간 기반
  3. 시간 기반 트리거 유형 선택: 분 단위, 시간 단위, 일 단위 중 선택
  4. 실행 간격 선택: 처음에는 1시간마다 또는 하루 1회 권장
  5. 저장 후 권한 승인: Google 계정으로 접근 권한 확인

문의가 많지 않은 블로그, 소규모 서비스, 개인 업무라면 5분마다 실행할 필요는 없습니다. 너무 잦은 실행은 할당량 문제를 만들 수 있으므로 업무량에 맞춰 간격을 조정하는 것이 좋습니다.


자주 나는 오류와 해결 방법

처음 실행할 때 오류가 나더라도 대부분은 권한, 시트 ID, 검색 조건, 실행량 문제입니다. 아래 순서대로 확인하면 원인을 좁히기 쉽습니다.


오류 상황 주요 원인 해결 방법
권한 승인 화면이 뜸 Gmail·Sheets 접근 권한 필요 계정 확인 후 권한 승인
시트를 찾을 수 없음 스프레드시트 ID 오류 /d//edit 사이 값 재확인
메일이 저장되지 않음 검색 조건이 너무 좁음 Gmail 검색창에서 조건 먼저 테스트
같은 메일이 반복 저장됨 메일ID 컬럼 누락 또는 라벨 미적용 메일ID 저장 여부와 라벨명 확인
실행 시간이 길어짐 검색 결과가 너무 많음 기간 제한과 검색 개수 축소

권한·개인정보 주의점

Gmail 자동화는 개인 메일함의 내용을 읽어오는 작업입니다. 따라서 업무용 계정과 개인 계정을 구분하고, 시트 공유 범위를 최소화하는 것이 좋습니다. 특히 고객 이메일, 문의 내용, 전화번호, 계약 관련 문구가 포함될 수 있다면 공유 권한을 더 신중하게 설정해야 합니다.


  • 개인 Gmail보다 업무용 Gmail 또는 전용 문의 계정에서 먼저 테스트합니다.
  • 구글시트 공유 대상은 실제로 처리해야 하는 사람으로 제한합니다.
  • 본문 전체를 저장하기보다 필요한 일부 요약만 저장합니다.
  • 퇴사자, 외부 협력자, 임시 계정의 접근 권한을 정기적으로 확인합니다.
  • 민감한 정보가 포함되는 업종이라면 내부 보관 기준에 맞춰 컬럼을 줄입니다.

처음 적용할 때의 기준
자동화는 넓게 시작하는 것보다 작게 시작하는 편이 안전합니다. 최근 7일, 제목에 문의가 포함된 메일, 최대 30개 처리처럼 범위를 제한한 뒤 결과가 맞는지 확인하고 확장하는 흐름이 좋습니다.


Make나 n8n과 비교하면 언제 Apps Script가 좋을까

Apps Script는 Gmail과 Google Sheets 안에서 끝나는 자동화에 잘 맞습니다. 별도 도구에 계정을 연결하지 않아도 되고, 간단한 JavaScript 코드만으로 구글 서비스끼리 연결할 수 있기 때문입니다.


반면 여러 외부 서비스와 연결하거나, 화면에서 노드를 조립하며 흐름을 관리하고 싶다면 Make나 n8n이 더 편할 수 있습니다. RSS, API, 웹훅, 데이터 변환이 섞이는 자동화라면 Make 자동화 예시: RSS 글을 구글시트에 자동 저장하는 법처럼 노코드 도구를 함께 비교해 보는 것도 좋습니다.


공식 자료로 더 확인하기

Gmail과 Google Sheets 자동화는 계정 권한, 실행 트리거, 서비스별 메서드의 영향을 받습니다. 실제 업무에 적용하기 전에는 공식 문서에서 Gmail 검색, 시트 저장, 자동 실행 기준을 확인하는 것이 좋습니다.


GmailApp 공식 문서

Apps Script에서 Gmail 메일을 검색하고, 스레드·메시지·라벨을 다루는 기본 메서드를 확인할 수 있습니다.

GmailApp 검색과 라벨 처리 메서드 확인하기

SpreadsheetApp 공식 문서

Apps Script에서 Google Sheets 파일을 열고, 시트와 범위에 데이터를 쓰는 방식의 기준을 확인할 수 있습니다.

Google Sheets 접근과 저장 방식 확인하기

Apps Script 설치형 트리거 공식 문서

시간 기반 트리거로 함수를 자동 실행하는 방법과 설치형 트리거의 제한 사항을 확인할 수 있습니다.

시간 기반 자동 실행 트리거 기준 확인하기

함께 보면 좋은 글

AI로 반복 업무 줄이는 흐름 넓히기
Gmail 문의 정리는 업무자동화의 한 예시입니다. 메일, 문서, 표 정리처럼 반복되는 일을 ChatGPT와 함께 줄이는 방식까지 넓혀서 볼 수 있습니다.
ChatGPT로 반복 업무를 줄이는 5가지 실전 예시

자동화 흐름을 워크플로로 확장하기
Gmail과 구글시트 연결을 이해했다면 다음에는 여러 단계를 시각적으로 연결하는 워크플로 자동화도 살펴볼 수 있습니다. 설치 없이 시작하는 n8n 기본 흐름을 함께 보면 좋습니다.
n8n으로 설치 없이 시작하는 기본 자동화 흐름

자주 묻는 질문

Q1. Gmail 자동화는 무료로 사용할 수 있나요?

Google Apps Script는 Google 계정에서 바로 사용할 수 있습니다. 다만 Gmail, Google Sheets, Apps Script에는 계정 유형과 사용량에 따른 제한이 있습니다. 개인이나 소규모 업무에서 문의 메일을 하루 몇 차례 정리하는 수준이라면 가볍게 시작할 수 있지만, 대량 메일 처리에는 공식 문서의 할당량과 실행 제한을 함께 확인하는 것이 좋습니다.


Q2. 문의 메일 본문 전체를 구글시트에 저장해도 되나요?

기술적으로는 가능하지만 처음부터 본문 전체를 저장하는 방식은 신중해야 합니다. 문의 메일에는 이름, 연락처, 회사명, 계약 내용처럼 민감한 정보가 들어갈 수 있습니다. 필요한 일부 내용만 요약해 저장하고, 원문 확인은 Gmail에서 하도록 구성하면 시트 공유 범위를 줄이고 개인정보 노출 위험도 낮출 수 있습니다.


Q3. 같은 메일이 계속 저장될 때는 무엇을 확인해야 하나요?

먼저 구글시트에 메일ID 컬럼이 정상적으로 저장되는지 확인합니다. 그다음 Gmail에 처리 완료 라벨이 붙는지, 검색 조건에 -label:자동정리완료 같은 제외 조건이 들어 있는지 봐야 합니다. 라벨명이 코드와 Gmail 화면에서 다르면 이미 처리한 메일도 다시 검색될 수 있습니다.


Q4. 트리거는 몇 분마다 실행하는 것이 좋나요?

문의가 많지 않다면 1시간마다 또는 하루 몇 차례 실행해도 충분합니다. 너무 짧은 간격으로 실행하면 불필요한 호출이 늘고, 실행 시간이나 사용량 제한 문제를 만날 수 있습니다. 처음에는 수동 실행으로 결과를 확인한 뒤, 실제 문의량에 맞춰 시간 기반 트리거 간격을 조정하는 방식이 좋습니다.


Gmail 자동화는 검색 조건을 좁게 잡고, 메일ID와 처리 완료 라벨로 중복을 막는 것부터 시작하면 안정적으로 운영할 수 있습니다.