2026년 08월 18일

크롬 확장 프로그램에서 인증을 구현하는 방법

크롬 확장 프로그램을 개발하다 보면 사용자 계정과 연동하거나 외부 서비스의 API를 호출해야 하는 상황이 생깁니다. 이 경우 인증(Authentication) 구현이 반드시 필요한데, 일반적인 웹 애플리케이션과는 환경이 달라 주의해야 할 점이 많습니다. 이 글에서는 크롬 확장 프로그램에서 인증을 구현하는 주요 방식과 실제 적용 방법을 체계적으로 정리합니다.

크롬 확장 프로그램 인증의 특수한 환경

크롬 확장 프로그램은 일반 웹 페이지와 달리 백그라운드 서비스 워커, 팝업(popup), 콘텐츠 스크립트 등 여러 컨텍스트로 나뉘어 실행됩니다. 각 컨텍스트는 서로 독립적인 실행 환경을 가지며, 직접 DOM을 공유하거나 전역 변수를 참조할 수 없습니다.

이런 구조 때문에 인증 토큰을 어디에 저장하고, 어떻게 각 컨텍스트에서 접근하게 할 것인지가 중요한 설계 포인트가 됩니다. 또한 크롬 확장 프로그램은 manifest.json에 명시적으로 퍼미션(permissions)을 선언해야만 특정 기능을 사용할 수 있기 때문에, 인증 관련 API를 사용할 때도 사전에 권한을 등록해야 합니다.

인증 구현 방식 개요

크롬 확장 프로그램에서 인증을 구현하는 주요 방식은 크게 세 가지로 나눌 수 있습니다.

  • chrome.identity API 사용: 구글 계정 기반의 OAuth 2.0 인증을 가장 간단하게 처리할 수 있는 공식 방법입니다.
  • 외부 OAuth 2.0 흐름 직접 구현: GitHub, Kakao, Naver 등 구글 외 서비스와 연동할 때 사용합니다.
  • 자체 서버 기반 인증: 직접 운영하는 백엔드 서버에 이메일/비밀번호 방식으로 로그인하는 방식입니다.

각 방식은 사용 목적과 연동 서비스에 따라 선택하면 됩니다.

chrome.identity API로 구글 계정 인증하기

구글 계정 기반 인증이 필요하다면 chrome.identity API가 가장 권장되는 방법입니다. 이 API는 OAuth 2.0 흐름을 크롬이 직접 처리해주기 때문에 복잡한 인증 코드 교환 과정을 생략할 수 있습니다.

manifest.json 설정

먼저 manifest.json에 필요한 권한과 OAuth 클라이언트 ID를 등록해야 합니다.

{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0",
  "permissions": ["identity"],
  "oauth2": {
    "client_id": "YOUR_CLIENT_ID.apps.googleusercontent.com",
    "scopes": [
      "https://www.googleapis.com/auth/userinfo.email",
      "https://www.googleapis.com/auth/userinfo.profile"
    ]
  }
}

client_id는 Google Cloud Console에서 크롬 확장 프로그램용 OAuth 클라이언트를 생성할 때 발급받는 값입니다. 애플리케이션 유형을 “Chrome App”으로 선택하고, 확장 프로그램 ID를 입력해야 합니다.

액세스 토큰 요청

권한 설정이 완료되면 아래와 같이 액세스 토큰을 요청할 수 있습니다.

chrome.identity.getAuthToken({ interactive: true }, function (token) {
  if (chrome.runtime.lastError) {
    console.error(chrome.runtime.lastError);
    return;
  }
  // token을 이용해 Google API 호출
  fetch('https://www.googleapis.com/oauth2/v1/userinfo', {
    headers: { Authorization: `Bearer ${token}` }
  })
    .then(res => res.json())
    .then(userInfo => console.log(userInfo));
});

interactive: true로 설정하면 사용자가 로그인되어 있지 않을 때 구글 로그인 팝업이 자동으로 열립니다. false로 설정하면 이미 로그인된 경우에만 토큰을 반환하며, 로그인이 필요한 상황에서는 오류를 반환합니다.

토큰 캐시 무효화

로그아웃이나 토큰 갱신이 필요할 때는 캐시된 토큰을 명시적으로 제거해야 합니다.

chrome.identity.removeCachedAuthToken({ token: currentToken }, function () {
  console.log('토큰이 제거되었습니다.');
});

외부 OAuth 2.0 서비스 연동하기

구글 외 서비스(GitHub, Kakao 등)와 연동할 때는 chrome.identity.launchWebAuthFlow를 사용합니다. 이 메서드는 외부 OAuth 인증 페이지를 새 창에서 열고, 인증 완료 후 리디렉션 URL을 통해 인증 코드를 전달받습니다.

리디렉션 URL 확인

외부 OAuth 제공자에 애플리케이션을 등록할 때 리디렉션 URI를 아래 형식으로 설정해야 합니다.

https://<extension-id>.chromiumapp.org/

확장 프로그램 ID는 Chrome 개발자 도구 또는 chrome://extensions 페이지에서 확인할 수 있습니다.

launchWebAuthFlow 사용 예시

const clientId = 'YOUR_GITHUB_CLIENT_ID';
const redirectUri = chrome.identity.getRedirectURL();
const authUrl =
  `https://github.com/login/oauth/authorize` +
  `?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=user`;

chrome.identity.launchWebAuthFlow(
  { url: authUrl, interactive: true },
  function (redirectUrl) {
    if (chrome.runtime.lastError || !redirectUrl) {
      console.error('인증 실패');
      return;
    }
    const url = new URL(redirectUrl);
    const code = url.searchParams.get('code');
    // code를 백엔드 서버로 전달하여 액세스 토큰 교환
  }
);

인증 코드를 받은 후에는 보안 상 이유로 액세스 토큰 교환은 반드시 서버 측에서 처리하는 것을 권장합니다. 클라이언트 시크릿을 확장 프로그램 코드에 직접 포함하면 누구나 소스 코드를 통해 확인할 수 있기 때문입니다.

자체 서버 기반 인증 구현

이메일/비밀번호 방식의 자체 로그인 시스템과 연동할 때는 백엔드 API 서버를 통해 인증 토큰을 발급받고, 이를 확장 프로그램 내에 안전하게 저장하는 방식을 사용합니다.

로그인 API 호출

팝업 또는 사이드 패널에서 폼 데이터를 수집한 후 서버로 전송합니다.

async function login(email, password) {
  const response = await fetch('https://your-api.com/auth/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password })
  });
  const data = await response.json();
  if (data.token) {
    await chrome.storage.local.set({ authToken: data.token });
  }
}

저장된 토큰 사용

이후 API 요청 시 저장된 토큰을 꺼내 헤더에 포함합니다.

async function fetchUserData() {
  const { authToken } = await chrome.storage.local.get('authToken');
  if (!authToken) return;

  const response = await fetch('https://your-api.com/user/profile', {
    headers: { Authorization: `Bearer ${authToken}` }
  });
  return response.json();
}

인증 토큰 저장 방법 비교

크롬 확장 프로그램에서 토큰을 저장하는 방법은 여러 가지가 있으며, 각각 특성이 다릅니다.

저장 방식범위특징
chrome.storage.local로컬 디바이스브라우저 재시작 후에도 유지, 용량 제한 있음
chrome.storage.session현재 세션브라우저 닫으면 삭제, MV3에서 사용 가능
chrome.storage.sync구글 계정 동기화다기기 동기화 가능, 용량 제한 엄격
메모리(변수)런타임 중서비스 워커 종료 시 소멸

민감한 인증 정보를 저장할 때는 chrome.storage.local이 가장 일반적으로 사용됩니다. 단, chrome.storage는 암호화를 자체적으로 제공하지 않으므로 매우 민감한 정보는 추가적인 암호화를 고려해야 합니다.

보안 고려사항

인증을 구현할 때 반드시 챙겨야 할 보안 사항들이 있습니다.

  • 클라이언트 시크릿 노출 금지: OAuth 클라이언트 시크릿은 절대 확장 프로그램 코드에 포함하지 않습니다. 토큰 교환은 반드시 서버에서 처리해야 합니다.
  • Content Security Policy(CSP) 설정: manifest.json에 적절한 CSP를 설정하여 외부 스크립트 삽입 공격을 방지합니다.
  • 최소 권한 원칙: scopes나 permissions는 실제로 필요한 것만 최소한으로 요청합니다.
  • 토큰 만료 처리: 액세스 토큰의 만료 시간을 확인하고, 필요 시 리프레시 토큰을 이용한 갱신 로직을 구현합니다.
  • HTTPS 통신: 모든 인증 관련 API 통신은 반드시 HTTPS를 사용합니다.

Manifest V3에서의 변경 사항

Manifest V3(MV3)로 넘어오면서 백그라운드 페이지(background page)가 서비스 워커(service worker)로 대체되었습니다. 서비스 워커는 일정 시간이 지나면 자동으로 종료되기 때문에, 메모리에만 저장된 인증 토큰은 사라질 수 있습니다.

이를 해결하기 위해 MV3 환경에서는 인증 상태를 반드시 chrome.storage.local 또는 chrome.storage.session에 영속적으로 저장해야 합니다. 또한 서비스 워커가 재시작될 때 저장소에서 토큰을 불러오는 초기화 로직을 별도로 구성하는 것이 좋습니다.

정리

크롬 확장 프로그램에서의 인증 구현은 사용 목적에 따라 적합한 방식을 선택하는 것이 중요합니다. 구글 계정 연동에는 chrome.identity.getAuthToken이 가장 간편하고, 외부 OAuth 서비스 연동에는 launchWebAuthFlow를 활용합니다. 자체 서버 인증의 경우 chrome.storage.local에 토큰을 저장하고 API 요청 시 활용하는 패턴이 일반적입니다.

어떤 방식을 선택하든 클라이언트 시크릿 보호, 최소 권한 요청, HTTPS 사용 등 기본적인 보안 원칙을 반드시 지켜야 합니다. 특히 MV3 환경에서는 서비스 워커의 생명주기를 고려한 토큰 저장 전략을 함께 설계해야 안정적인 인증 흐름을 유지할 수 있습니다.