2026.03.14·3

Pickle을 만들며 고른 기술들 (04) - 익스텐션 로그인과 웹 세션을 왜 따로 다루지 않았을까

Pickle에서 익스텐션 OAuth, PKCE, 세션 갱신, 웹과의 동기화 흐름을 어떤 기준으로 설계했는지 정리합니다.

Pickle을 만들며 고른 기술들 (04) - 익스텐션 로그인과 웹 세션을 왜 따로 다루지 않았을까 대표 이미지

사용자는 익스텐션에서 로그인했는데 웹에서는 다시 로그인해야 하는 흐름을 거의 용납하지 않습니다. 그래서 인증은 기능이 아니라 경험의 연결 문제에 가까웠습니다.

들어가며

Pickle에서는 익스텐션이 저장의 시작점이었지만, 저장한 내용을 다시 보고 정리하는 곳은 결국 웹 클라이언트였습니다. 그래서 익스텐션에서 로그인했는데 웹에서는 다시 로그인해야 하거나, 반대로 웹에서는 로그인됐는데 익스텐션에서는 다시 연결해야 하는 흐름은 가능한 한 피하고 싶었습니다.

초기에는 웹 클라이언트에서 로그인한 세션을 익스텐션으로 동기화하는 쪽도 함께 두고 있었습니다. 웹에서 로그인한 뒤 동기화 페이지를 거쳐 익스텐션으로 세션을 넘기는 방식입니다. 이 방식은 구현 자체는 가능했지만, 익스텐션 사용 흐름에서 보기에 조금 어색했습니다. 사용자가 자주 여는 익스텐션에서 버튼을 눌렀는데, 별도의 웹 창이 먼저 뜨고 그 흐름을 거쳐 다시 돌아와야 했기 때문입니다.

그래서 나중에는 방향을 반대로 바꿨습니다. 익스텐션 안에서 바로 구글 로그인을 시작하고, 그 로그인 세션을 웹 클라이언트로 넘기는 쪽이 더 낫다고 판단했습니다. 이 글은 왜 그렇게 판단했는지, 그리고 그 흐름을 구현할 때 어떤 기준을 두었는지를 정리한 기록입니다.

익스텐션 인증은 왜 독립적으로 완결되어야 했는가

익스텐션은 Pickle을 사용하는 첫 화면에 가까웠습니다. 사용자가 저장을 시작하려고 눌렀을 때 가장 먼저 만나는 곳이기 때문입니다. 그렇다면 로그인도 그 안에서 바로 끝나는 편이 더 자연스럽다고 봤습니다.

웹 로그인 페이지를 새로 열어 인증하고, 그 결과를 다시 익스텐션으로 가져오는 방식은 한 단계가 더 필요합니다. 기능적으로는 가능하지만, 사용자는 자신이 익스텐션을 쓰고 있다고 느끼는 순간에 갑자기 웹 흐름으로 끌려가는 셈입니다. 이 어색함은 생각보다 크게 느껴졌습니다.

그래서 Pickle에서는 익스텐션이 스스로 로그인 흐름을 시작하고 끝낼 수 있는 쪽이 더 맞다고 판단했습니다. 현재 구조가 chrome.identity.launchWebAuthFlow를 쓰는 것도 그 이유입니다. 익스텐션 안에서 구글 로그인 팝업을 띄우고, 콜백을 다시 익스텐션 쪽에서 받는 흐름이 사용자 경험상 더 짧고 일관됐기 때문입니다.

이 방식으로 바꾸고 나니 "지금 로그인은 어디서 하고 있는가"가 훨씬 덜 헷갈렸습니다. 사용자는 저장을 시작한 곳에서 바로 로그인하고, 그 결과를 웹이 나중에 이어받는 형태가 되었기 때문입니다.

왜 세션은 익스텐션에서 웹으로 넘기는 편이 더 나았는가

흐름을 반대로 바꾸고 나서도 고민은 남았습니다. 익스텐션에서 로그인한 세션을 웹 클라이언트와 어떻게 연결할 것인가 하는 문제입니다.

여기서도 기준은 단순했습니다. 사용자가 한 번 로그인했다면, Pickle 안에서는 가능한 한 같은 상태를 공유하는 편이 더 낫다는 것입니다. 익스텐션과 웹이 완전히 별개의 제품처럼 보이면 안 된다고 생각했습니다.

그래서 현재 흐름은 대체로 이렇게 갑니다.

  1. 익스텐션에서 구글 로그인 시작
  2. 익스텐션이 세션을 확보하고 로컬에 저장
  3. 그 세션을 웹 클라이언트의 동기화 경로로 전파
  4. 웹 클라이언트가 그 세션을 받아 그대로 로그인 상태를 이어받음

이 방식이 좋았던 이유는 사용자 입장에서 "어디서 로그인했는지"보다 "지금 Pickle 안에 로그인돼 있는가"가 더 중요했기 때문입니다. 그리고 서비스 입장에서도 익스텐션이 시작점일 때는, 세션을 익스텐션에서 웹으로 넘기는 편이 흐름상 더 자연스러웠습니다.

왜 hash fragment로 세션을 넘겼는가

세션을 다른 쪽으로 전달해야 한다면, 그 경로도 신경 써야 합니다. Pickle에서는 웹 클라이언트의 /auth/extension-sync 페이지를 열고, 토큰은 URL의 hash fragment로 붙여 넘기는 방식을 택했습니다.

이 방식을 택한 이유는 비교적 분명했습니다.

  • 클라이언트는 진입 직후 바로 세션을 설정할 수 있습니다.
  • 처리 후 URL을 즉시 정리할 수 있습니다.
  • 토큰이 일반 쿼리스트링보다 덜 노출되는 흐름을 만들 수 있습니다.

이 부분은 사용자에게는 거의 보이지 않는 구현 디테일에 가깝습니다. 하지만 인증에서는 이런 보이지 않는 경로가 더 중요하다고 생각했습니다. "된다"보다 "어디로 지나가고 어디에서 지워지는가"를 설명할 수 있어야 했기 때문입니다.

세션은 왜 백그라운드 중심으로 다루는 편이 맞았는가

익스텐션에서 인증은 한 번으로 끝나지 않습니다. 로그인 후에도 세션을 읽고, 필요하면 갱신하고, 저장 요청을 보낼 때 유효성을 확인해야 합니다.

Pickle에서는 이런 흐름을 백그라운드 쪽에 더 가깝게 두었습니다. 세션을 읽고 유지하는 책임을 한 군데에 모아두는 편이, 각 화면과 컨텐트 스크립트가 제각각 세션을 들고 있는 것보다 더 안정적이라고 봤기 때문입니다.

이 판단 덕분에 로그인 흐름도 조금 더 정리됐습니다.

  • 로그인은 익스텐션에서 시작
  • 세션 관리는 백그라운드 중심
  • 웹 클라이언트는 동기화 경로를 통해 로그인 상태를 이어받음

이렇게 나누고 나니 역할이 조금 더 분명해졌습니다. 그리고 인증처럼 민감한 문제일수록, 책임이 어디에 있는지가 먼저 보이는 편이 훨씬 다루기 쉬웠습니다.

마치며

Pickle에서 인증은 단순히 구글 로그인 버튼을 어디에 둘 것인가의 문제가 아니었습니다. 익스텐션과 웹이 함께 있는 서비스에서, 사용자가 로그인 상태를 어떻게 받아들이는가에 더 가까운 문제였습니다.

초기에는 웹에서 로그인하고 익스텐션으로 동기화하는 방식도 함께 두고 있었습니다. 하지만 익스텐션이 시작점인 서비스라면, 로그인 역시 그 안에서 바로 시작되는 편이 더 자연스럽다고 느꼈습니다. 그래서 현재는 익스텐션에서 로그인하고, 그 세션을 웹으로 넘기는 흐름이 중심이 되었습니다.

인증 흐름이 복잡해 보일수록, 사용자에게는 더 단순하게 느껴져야 한다는 점을 이 과정에서 다시 배웠습니다.

다음 글에서는 인증 흐름에서 잠시 벗어나, 왜 Pickle에서 익스텐션 UI를 iframe으로 격리하게 되었는지를 정리해 보려고 합니다.