Nodemailer와 GCP로 Gmail OAuth2 설정

발행: (2026년 6월 6일 PM 08:00 GMT+9)
10 분 소요
원문: Dev.to

출처: Dev.to

애플리케이션에서 이메일을 보내는 방식은 수년간 크게 변했습니다. 예전에는 Gmail SMTP에 사용자명·비밀번호 인증을 사용했지만, 보안 문제와 Google이 “덜 안전한” 앱으로 간주하는 애플리케이션에 대한 제한 때문에 이제는 더 이상 권장되지 않습니다.

현재 가장 안전한 방법은 Gmail OAuth2 인증을 사용하고, Nodemailer와 같은 외부 메일 전송 라이브러리를 함께 활용하는 것입니다. 저는 이 과정을 제 포트폴리오에 적용해 보았고, 다른 사람들에게도 도움이 될 것이라 생각해 글을 남깁니다.

이 가이드를 통해 다음을 배울 수 있습니다:

  • Google Cloud Platform(GCP) 프로젝트 설정
  • Gmail API 활성화
  • OAuth 동의 화면 구성
  • OAuth 자격 증명 생성
  • 리프레시 토큰 생성
  • Nodemailer에 Gmail OAuth2 적용
  • 흔히 발생하는 오류 처리
  • 애플리케이션 보안 강화

이 튜토리얼은 다음 환경에서 동작합니다:

  • Node.js
  • Express
  • Nuxt 서버 라우트
  • Vue 백엔드 API
  • Next.js API 라우트
  • TypeScript 프로젝트

목차

  • 왜 Gmail OAuth2를 사용해야 할까?
  • 사전 준비 사항
  • Google Cloud 프로젝트 만들기
  • Gmail API 활성화
  • OAuth 동의 화면 구성
  • OAuth 자격 증명 만들기
  • 의존성 설치
  • 리프레시 토큰 생성
  • Nodemailer 설정
  • 이메일 전송
  • HTML 이스케이프 및 인젝션 방지
  • 흔한 오류와 해결 방법
  • 운영 환경 권장 사항
  • 마무리 생각

왜 Gmail OAuth2를 사용해야 할까?

Google은 많은 애플리케이션에서 비밀번호 기반 SMTP 인증을 더 이상 지원하지 않게 되었습니다.

OAuth2는 다음과 같은 장점을 제공합니다:

  • 향상된 보안
  • 토큰 기반 인증
  • Gmail 비밀번호 노출 방지
  • 접근 범위(스코프) 제어
  • 언제든지 접근 권한 회수 가능

예전처럼 아래와 같이 작성하지 마세요:

auth: {
  user: "example@gmail.com",
  pass: "gmail-password"
}

전체 화면 모드 진입
전체 화면 모드 종료

다음과 같이 작성하면 됩니다:

auth: {
  type: "OAuth2",
  user,
  clientId,
  clientSecret,
  refreshToken
}

전체 화면 모드 진입
전체 화면 모드 종료

사전 준비 사항

작업을 시작하기 전에 아래 항목들을 준비하세요:

  • Google 계정
  • Node.js 설치
  • npm 또는 yarn
  • 백엔드/서버 환경
  • JavaScript 또는 TypeScript 기본 지식

Google Cloud 프로젝트 만들기

Google Cloud Console에 접속합니다:

Google Cloud Console

1단계: 새 프로젝트 만들기

  • 상단 바의 프로젝트 드롭다운을 클릭
  • New Project 클릭
  • 원하는 프로젝트 이름 입력
  • Create 클릭

프로젝트가 초기화될 때까지 기다립니다.

Gmail API 활성화

프로젝트가 생성되면:

  • API 라이브러리를 엽니다:

Google APIs Library

검색창에 다음을 입력:

Gmail API

전체 화면 모드 진입
전체 화면 모드 종료

  • Gmail API를 클릭
  • Enable 클릭

Gmail API를 활성화하지 않으면 OAuth를 이용한 메일 전송이 작동하지 않습니다.

OAuth 동의 화면 구성

OAuth 자격 증명을 만들기 전에 반드시 이 과정을 거쳐야 합니다.

다음 주소로 이동합니다:

OAuth Consent Screen

1단계: 사용자 유형 선택

External

전체 화면 모드 진입
전체 화면 모드 종료

Create 클릭.

2단계: 앱 정보 입력

다음 항목을 입력:

  • 앱 이름
  • 지원 이메일
  • 개발자 연락 이메일

예시:

App Name: Portfolio Mailer

전체 화면 모드 진입
전체 화면 모드 종료

3단계: 테스트 사용자 추가

앱이 아직 테스트 단계라면:

  • Test Users 섹션을 엽니다
  • 메일 전송에 사용할 Gmail 계정을 추가합니다

이 단계를 건너뛰면 다음 오류가 발생할 수 있습니다:

unauthorized_client

전체 화면 모드 진입
전체 화면 모드 종료

OAuth 자격 증명 만들기

이제 OAuth 자격 증명을 생성합니다.

다음 주소로 이동합니다:

Google Cloud Credentials

1단계: OAuth 클라이언트 ID 만들기

  • Create Credentials 클릭
  • OAuth Client ID 선택

2단계: 애플리케이션 유형 선택

Web Application

전체 화면 모드 진입
전체 화면 모드 종료

다음 옵션은 선택하지 마세요:

  • Desktop App
  • Android
  • iOS

3단계: 리디렉션 URI 추가

아래 섹션에 입력:

Authorized redirect URIs

전체 화면 모드 진입
전체 화면 모드 종료

예시:

http://localhost:3000

전체 화면 모드 진입
전체 화면 모드 종료

또는 사용 중인 포트를 입력합니다. 리프레시 토큰을 생성하려면 반드시 필요합니다.

4단계: 자격 증명 저장

설정을 마치면 Google이 다음 정보를 제공합니다:

Client ID
Client Secret

전체 화면 모드 진입
전체 화면 모드 종료

이 정보를 안전하게 보관하고, 복사하거나 다운로드해 두세요.

의존성 설치

필요한 패키지를 설치합니다:

npm install nodemailer googleapis dotenv

전체 화면 모드 진입
전체 화면 모드 종료

TypeScript를 사용하는 경우 추가로 실행합니다:

npm install -D tsx typescript

전체 화면 모드 진입
전체 화면 모드 종료

환경 변수

프로젝트 루트에 .env 파일을 생성하고 다음을 입력합니다:

SMTP_USER=your-email@gmail.com

GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_OAUTH_REFRESH_TOKEN=your-refresh-token

전체 화면 모드 진입
전체 화면 모드 종료

.env 파일을 절대 GitHub 등에 커밋하지 마세요. 보안에 유의하시기 바랍니다.

리프레시 토큰 생성

이 단계는 설정 과정에서 가장 중요한 부분 중 하나입니다.

1단계: 스크립트 파일 만들기

프로젝트 루트에 다음 경로와 파일을 생성합니다:

scripts/generate-refresh-token.ts

전체 화면 모드 진입
전체 화면 모드 종료

다음 코드를 추가합니다:

import { google } from "googleapis";
import dotenv from "dotenv";

dotenv.config();

const oauth2Client = new google.auth.OAuth2(
    process.env.GOOGLE_CLIENT_ID,
    process.env.GOOGLE_CLIENT_SECRET,
    "http://localhost:3000"
);

const scopes = [
    "https://mail.google.com/",
];

const url = oauth2Client.generateAuthUrl({
    access_type: "offline",
    scope: scopes,
    prompt: "consent",
});

console.log("Authorization url: ", url);

전체 화면 모드 진입
전체 화면 모드 종료

2단계: 스크립트 실행

TypeScript를 사용할 경우:

npx tsx scripts/generate-refresh-token.ts

전체 화면 모드 진입
전체 화면 모드 종료

JavaScript 파일로 실행하려면:

node scripts/generate-refresh-token.js

전체 화면 모드 진입
전체 화면 모드 종료

3단계: 인증 URL 열기

터미널에 출력된 Google 인증 URL을 복사해 브라우저에 붙여넣습니다.

SMTP_USER와 동일한 Gmail 계정으로 로그인합니다.

전체 화면 모드 진입
전체 화면 모드 종료

권한 요청 화면이 나타나면 승인합니다.

4단계: 인증 코드 복사

승인 후 Google이 설정해 둔 리디렉션 URL(예: http://localhost:3000/?code=...)로 이동합니다.

URL에 포함된 code 값을 복사합니다.

예시:

4/0AX4XfWh...

전체 화면 모드 진입
전체 화면 모드 종료

5단계: 코드와 토큰 교환

스크립트를 다음과 같이 수정합니다:

import { google } from "googleapis";
import dotenv from "dotenv";

dotenv.config();

const oauth2Client = new google.auth.OAuth2(
    process.env.GOOGLE_CLIENT_ID,
    process.env.GOOGLE_CLIENT_SECRET,
    "http://localhost:3000"
);

async function getRefreshToken() {
    const code = "PASTE_AUTHORIZATION_CODE";
    const { tokens } = await oauth2Client.getToken(code);
    console.log("Refresh Token:", tokens.refresh_token);
}

getRefreshToken().catch(console.error);

전체 화면 모드 진입
전체 화면 모드 종료

0 조회
Back to Blog

관련 글

더 보기 »

모바일 한여름 열풍

!Cover image for Mobile Midsommer Madnesshttps://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploa...