크롬 익스텐션, API 하나 붙이는데 왜 이렇게 어렵죠?

LinkDropper·2025년 5월 8일
11
post-thumbnail

🧱 배경

링크 드라퍼 익스텐션은 단순한 북마크 저장기가 아닙니다.
로그인한 사용자 정보를 기반으로 서버에 요청을 보내고, 그 결과에 따라 링크를 저장하죠.

그래서 필연적으로 외부 API 연동이 필요했고,
여기서부터 진짜 실전 개발이 시작됐습니다.


🧩 문제 1. 세션 쿠키가 안 붙는다?

익스텐션은 일반 웹앱과 달리, 브라우저 탭과 분리된 환경에서 돌아갑니다.
특히 popup이나 background에서 API 요청을 보내면,
자동으로 쿠키가 붙지 않는 경우가 많았습니다.

🔍 예시: 쿠키 없이 fetch 호출 시 에러

// background script 내부에서 fetch 호출
fetch("https://link-dropper.com/api/me", {
  credentials: "include"
});

// 서버 응답: 401 Unauthorized

🔐 해결: chrome.cookies.get() 활용

chrome.cookies.get({ url: "https://link-dropper.com", name: "session_token" }, (cookie) => {
  if (cookie) {
    chrome.storage.local.set({ session_token: cookie.value });
  }
});
// 이후 fetch 시 Authorization 헤더에 붙여 사용
chrome.storage.local.get("session_token", async ({ session_token }) => {
  await fetch("https://link-dropper.com/api/me", {
    headers: {
      Authorization: `Bearer ${session_token}`
    }
  });
});

주의: 이 API는 content script에서는 사용할 수 없고, 반드시 popup or background에서 실행해야 합니다.


🚧 문제 2. CORS 에러가 터진다

“Access to fetch at 'https\://...' from origin 'chrome-extension://...' has been blocked by CORS policy”

익스텐션 환경에서는 기본 fetch 요청도 다르게 동작합니다.
특히 background script는 CORS 제약을 덜 받지만,
popup이나 content script는 엄격한 동일 출처 정책을 따릅니다.

⚙️ 해결: 권한 설정 + 서버 CORS 설정 함께 필요

manifest.json 예시

{
  "host_permissions": ["https://link-dropper.com/*"],
  "permissions": ["cookies"],
  ...
}

서버 설정 예시 (Express 기준)

app.use(cors({
  origin: ["chrome-extension://<YOUR_EXTENSION_ID>", "http://localhost:3000"],
  credentials: true,
}));

🌍 문제 3. 환경변수는 어디다 두죠?

Vite + MV3 조합에서는 .env 파일의 내용이 그대로 클라이언트에 노출될 수 있습니다.

예시:

console.log(import.meta.env.VITE_SECRET_API_KEY); // 🚨 노출됨

🔐 보안 + 편리성 측면에서 환경변수 관리 팁

✅ 1. .env 파일 분리 관리

  • VITE_ prefix를 붙여야 클라이언트 코드에서 사용 가능
  • .env.development / .env.production 으로 자동 분리 가능
# .env.development
VITE_API_URL=http://localhost:4000
fetch(`${import.meta.env.VITE_API_URL}/api/links`);

✅ 2. vite.config.ts에서 define으로 주입

  • process.env를 통해 민감 정보 직접 주입 가능
  • 빌드 시점에 치환되어 하드코딩됨 (노출 여부 주의)
// vite.config.ts
export default defineConfig({
  define: {
    __API_URL__: JSON.stringify(process.env.API_URL),
  },
});
// 코드 내부에서 안전하게 사용
fetch(`${__API_URL__}/api/secure-endpoint`);

✅ 3. manifest.json에 민감 정보 절대 금지

  • manifest.json은 사용자가 직접 확인 가능한 파일
  • 절대로 API 키나 시크릿을 직접 넣지 말 것

✅ 4. background에서만 민감 변수 참조

  • background.ts는 브라우저 탭에 노출되지 않음
  • 상대적으로 안전하나, 번들 파일에는 여전히 포함되므로 주의 필요
// background.ts
const API_KEY = import.meta.env.VITE_INTERNAL_API_KEY;

✅ 5. 프록시 서버 우회 방식으로 민감 요청 처리

  • 민감한 키가 필요한 외부 요청은 서버를 통해 처리
  • 익스텐션은 프록시 API만 호출하고, 백엔드가 키를 붙여 외부 요청 처리
// client → proxy API → external API
fetch('/api/proxy?target=og-data&url=https://example.com');
// server-side
const result = await fetch(`https://api.external.com?url=${url}`, {
  headers: { 'Authorization': `Bearer ${API_SECRET}` }
});

이처럼, 환경변수는 기능과 보안 수준에 따라 분리해서 관리하는 것이 중요합니다.

Vite + MV3 조합에서는 .env 파일의 내용이 그대로 클라이언트에 노출될 수 있습니다.

예시:

console.log(import.meta.env.VITE_SECRET_API_KEY); // 🚨 노출됨

🔐 팁: 민감한 값은 백그라운드 코드 내에서만 참조하도록 분리

// vite.config.ts
export default defineConfig({
  define: {
    __API_URL__: JSON.stringify(process.env.VITE_API_URL),
  },
});
// 실제 코드에서는 전역 상수로 참조
fetch(`${__API_URL__}/api/secure`) // 안전하게 분리 가능

🗂️ 팝업에서 새 탭 열기, 탭 닫기 UX 개선

링크 저장 후 사용자를 폴더 관리 페이지로 유도하거나,
팝업이 끝나면 자동으로 닫히도록 UX 개선을 진행했습니다.

✅ 탭 제어 예시

// 새 탭 열기
chrome.tabs.create({ url: "https://link-dropper.com/folders" });

// 현재 탭 닫기
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
  if (tabs[0]?.id) {
    chrome.tabs.remove(tabs[0].id);
  }
});

✍️ 마치며

이번 글에서는 크롬 익스텐션에서 외부 API를 연동하며 마주친 다양한 문제들과 그 해결 방법을 정리해봤습니다.

다음 글에서는 MV3 기반 크롬 익스텐션을 실제로 배포하는 과정과
스토어 등록 시 주의할 점, 권한 검토 통과 팁 등을 정리해보려 합니다.

놓치지 말고 확인해 주세요!

익스텐션에서 외부 API 연동은 단순해 보이지만,보안 + 브라우저 정책 + 쿠키 + CORS + UI 피드백까지 신경 써야 할 요소가 많습니다.

이번 글에서는 우리가 직접 겪은 시행착오와 함께,
실제 사용자를 위한 기능 완성까지 어떻게 해결했는지를 공유해봤습니다.


🧪 링크 드라퍼, 지금 베타 테스트 중입니다

링크 드라퍼는 단순한 저장 툴이 아닙니다.
정리하고, 수정하고, 다시 꺼내보게 만드는 링크 관리 도구를 지향하고 있습니다.

• 🔗 빠르고 간편한 링크 저장
• 🧠 저장한 링크를 폴더별로 정리
• 🌐 폴더를 친구에게 공유 가능
• ⚡ OG 미리보기 자동 불러오기

👉 🔗 링크 드라퍼 베타 체험하러 가기

직접 써보시고, 익스텐션에서의 기능이 어떠셨는지도 알려주세요!

profile
“기록하는 습관을 도구로 만들다 — 두 개발자의 링크 드라퍼 구축기”

0개의 댓글