본문 바로가기
Automation Tool

n8n, Google OAuth2 인증 오류

by 그때 그때 끄적 2025. 8. 12.

<Docker 재실행시 인증 오류>

https://cord-ai.tistory.com/213

 

n8n, Google Calendar OAuth2 인증 오류

n8n을 Docker에 설치해서 잘 사용하다가, 서버를 재시작하거나 Docker 컨테이너를 다시 실행했더니 Google Calendar 인증이 풀리는 경험, 해보셨나요?문제 상황: 도커 재시작 후 인증 오류 발생n8n에서 Goog

cord-ai.tistory.com

 

매주 반복되던 Google Sheets 노드의 인증 오류 문제를 해결하기 위한 과정과 해결책을 공유한다.

매주 화요일 아침만 되면 어김없이 n8n 워크플로우가 실패했다는 알림이 와 있었다. 이상한 점은 다른 요일에는 멀쩡하게 잘 돌아간다는 것이었다. 로그를 확인해보니 항상 Google Sheets 노드에서 "refresh token is invalid, expired, revoked..." 라는 메시지와 함께 인증 오류가 발생하고 있었다.

 

처음에는 내 워크플로우 로직 문제인가 싶었지만, n8n과 연동된 Google Cloud Platform의 OAuth 앱이 '테스트' 상태일 경우, 보안상의 이유로 Refresh Token이 7일 동안 사용되지 않으면 자동으로 만료되는 정책 때문이었다. 주말 동안 워크플로우가 멈춰 있으니, 이 7일 유효 기간에 걸리기 쉬웠던 것이다.

 

근본적인 문제 해결을 위해 Google Cloud Platform의 설정을 직접 변경하는 방식을 택했다. 매주 재인증을 반복하는 것은 너무나 비효율적이었기 때문이다.

 

STEP 1. 첫번째 시도, 실패

  1. Google Cloud Platform Console 접속
  2. API 및 서비스 > OAuth 동의 화면(Consent Screen)으로 이동
  3. 게시 상태(Publishing status)'테스트'에서 '프로덕션'으로 변경 (앱 게시 버튼 클릭)
    1. 처음에는 게시 상태가 Testing이라고 적혀있을텐데, 눌러주면 변경됨

  • 참고: 앱을 프로덕션으로 전환하기 위해 비즈니스 인증 등 추가 정보를 요구할 수 있으나, 대부분의 개인용/내부용 앱은 간단한 정보 입력만으로 전환이 가능

이렇게 '프로덕션' 상태로 전환하면, Refresh Token이 장기간 사용되지 않아도 만료되지 않아 문제가 영구적으로 해결된다.

 

STEP 2. 두번째 시도, 해결

Service Account, 서비스 계정 생성

Google Cloud Platform에 들어가서 API &Service 탭에 들어가 Service Account를 생성한다.

서비스 계정이란?

사용자(사람)의 계정이 아닌, 애플리케이션(n8n) 자체에 부여하는 로봇 계정. 사람처럼 로그인/로그아웃하거나 Refresh Token을 주기적으로 갱신할 필요가 없어, 한 번 설정해두면 만료 걱정 없이 영구적으로 사용 가능.

 

<생성 절차>

 

    • Google Cloud Platform 에서 'API 및 서비스' > '사용자 인증 정보'로 이동.
    • 상단의 '+ 사용자 인증 정보 만들기'를 클릭하고, 드롭다운 메뉴에서 '서비스 계정'을 선택
    • 서비스 계정의 이름(예: n8n-sheets-bot)을 입력하고 '만들고 계속하기' 선택
    • (선택사항) 역할 부여 단계에서는 '편집자' 또는 더 세분화된 역할을 부여할 수 있다. (일단 '소유자'나 '편집자'로 설정하고 나중에 변경 가능)
    • 마지막 단계에서 '키 만들기'를 클릭하고, 키 유형은 'JSON'을 선택하여 파일을 다운로드합니다. 이 JSON 파일은 절대로 외부에 노출되면 안 됩니다.
    • n8n의 Credentials 메뉴에서 새 인증 정보를 추가하고, Google Sheets를 선택
    • 인증 유형(Authentication)을 OAuth2/OAuth1이 아닌 Service Account로 선택
      • Workflow내에서 Credential을 인증하지말고, Workflow 선택란에서 Credential 생성을 하게되면 Service Account 탭이 보인다. => 이거 왜이렇게 만들었는지 모르겠다.
    • 다운로드한 JSON 파일의 내용을 그대로 복사하여 n8n의 JSON Key File 필드에 붙여넣고 저장
    • 마지막으로, 데이터를 읽고 쓸 Google Sheet를 열고, 우측 상단의 '공유' 버튼을 눌러 서비스 계정의 이메일 주소(GCP에서 확인 가능, ...@...gserviceaccount.com 형식)를 추가하고 '편집자' 권한을 부여
      • Google Sheet 파일 공유 설정 정리
        • n8n에서 조회하려는 Google Sheet 파일을 연다.
        • 오른쪽 위 초록색 '공유(Share)' 버튼을 클릭.
        • '사용자 및 그룹 추가' 입력란에 방금 복사한 서비스 계정의 이메일 주소를 붙여넣기.
        • 권한을 '편집자(Editor)'로 설정. (읽기뿐만 아니라 나중에 쓰기 작업을 위해서도 편집자 권한이 필요.)
        • '보내기'를 클릭하여 공유

 

왜 서비스 계정을 사용하니 문제가 해결되었는지,
그리고 n8n이 왜 OAuth2를 권장하는지

 

🔑 OAuth2, '나(사용자)'를 대신하는 불안정한 대리인

OAuth2는 한마디로 '권한 위임' 방식이다. 비유하자면, 내가(사용자) 내 집 열쇠를 n8n(앱)이라는 친구에게 잠시 빌려주면서 "이 열쇠로 거실 청소만 해줘"라고 허락해 주는 것과 같다.

  • 정체성의 주체
    바로 '사용자'다. n8n은 내 허락을 받고 내 권한을 빌려서 내 구글 시트에 접근한다.
  • 인증 방식
    내가 직접 "Google 계정으로 로그인" 팝업창에서 아이디/비번을 입력하고 "n8n이 내 시트 정보를 보는 것을 허용합니다"라고 동의해야 한다.
  • Refresh Token
    이 과정에서 구글은 n8n에게 아주 짧은 시간만 유효한 '임시 키(Access Token)'와, 이 키가 만료되면 새 임시 키를 발급받을 수 있는 더 긴 유효기간의 '만능 키(Refresh Token)'를 준다.

하지만 바로 이 '만능 키(Refresh Token)'가 매주 화요일의 범인이었다! Google의 정책상, 보안을 위해 이 만능 키는 '테스트' 상태의 앱에서는 7일간 사용하지 않으면 만료되거나, 사용될 때마다 새로운 만능 키로 교체되면서 기존 키는 버려진다(회전 정책).

내 경우, 월요일에 실행된 워크플로우가 키를 새로 발급받고 기존 키를 버렸는데, 화요일의 워크플로우가 어떤 이유로 이 버려진 예전 키를 사용하려고 시도했기 때문에 인증 실패가 발생했던 것이다.

 

🤖 서비스 계정, '로봇' 자체가 주인이 되는 방식

서비스 계정(Service Account)은 n8n이라는 '로봇' 자체에게 고유한 신분증과 열쇠를 발급해주는 방식이다. 이 로봇은 더 이상 내 허락을 받거나 열쇠를 빌릴 필요 없이, 자기 자신의 신분으로 직접 구글 시트에 접근한다.

  • 정체성의 주체
    '애플리케이션(n8n)'
    이다. 서비스 계정은 ...@...gserviceaccount.com이라는 독립적인 이메일 주소를 가진 '로봇 사용자'다.
  • 인증 방식
    사용자의 로그인이나 동의가 필요 없다. 대신, 절대 만료되지 않는 영구적인 '마스터 키(JSON 파일)'를 발급받아 n8n에 등록해 놓으면 끝이다.
  • Refresh Token 갱신 과정 없음
    서비스 계정에는 이 골치 아픈 토큰 갱신 과정 자체가 없으니, 토큰이 꼬일 걱정이 원천적으로 사라지는 것이다.

서비스 계정으로 바꾸니 문제가 해결된 이유는 바로 이것이었다. 매번 키를 바꿔야 하는 불안정한 대리인(OAuth2) 대신, 영구적인 마스터 키를 가진 독립적인 로봇(서비스 계정)이 일을 처리하게 되었기 때문이다.

대신 이 로봇은 내 파일에 접근할 권한이 기본적으로 없기 때문에, "이 로봇은 이 시트 파일을 편집해도 좋아"라고 시트의 '공유' 기능을 통해 직접 초대(이메일 주소 추가)를 해주어야 했던 것이다.

OAuth2 VS 서비스 계정

구분 🔑 OAuth2 🤖 서비스 계정 (Service Account)
정체성 사용자의 권한을 위임받은 대리인 앱 자체가 독립적인 로봇 사용자
인증 방식 사용자 로그인 및 동의 필요 (Refresh Token 사용) 영구적인 키 파일(JSON) 등록
핵심 문제 Refresh Token이 만료되거나 회전되어 인증 실패 가능성 있음 토큰 만료/회전 문제가 원천적으로 없음
주요 용도 사용자가 직접 로그인하는 웹/앱 서비스 n8n과 같은 서버 간의 백그라운드 자동화
구분 장점 단점
🔑 OAuth2 설정이 간편함- 실제 사용자 기반이라 추적이 용이함 Refresh Token 만료/회전 문제로 자동화가 멈출 수 있음
🤖 서비스 계정 (Service Account) 토큰 만료가 없어 매우 안정적임 - 파일 단위의 세밀한 권한 제어 가능 키(JSON) 유출 시 보안에 치명적임 - 초기 설정 및 파일 공유 관리가 번거로움

감사 및 추적의 어려움 

여러 사람이 함께 사용하는 환경이라면 누가 작업을 실행했는지 추적하기가 어렵습니다.

  • OAuth2
    구글 시트의 수정 기록에 홍길동 (gildong@gmail.com)이 오후 3:10에 수정함 과 같이 실제 사용자 계정이 남습니다.
  • 서비스 계정
    수정 기록에 n8n-robot@your-project.iam.gserviceaccount.com이 오후 3:10에 수정함 과 같이 로봇 계정의 이름이 남습니다.

🧠 진행 중 고민한 점

  • 왜 n8n은 OAuth2를 권장했을까?
    가장 일반적이고 표준적인 '사용자' 인증 방식이기 때문이다. 하지만 내 작업은 사용자의 개입 없이 서버 혼자서 백그라운드로 계속 돌아야 하는 '자동화' 작업이다. 이런 경우에는 '로봇'에게 직접 권한을 주는 서비스 계정이 훨씬 안정적이고 적합한 방식이었던 것이다. 작업의 성격을 제대로 파악하는 것이 중요했다.

댓글