worksOS와 연동하기

서버의 세팅이 끝났으니 다음은 workOS를 연동해서 인증 기능을 구현하는 것이었습니다. 가장 먼저 진행해야 할 일들은 우선 quickstart 에서 제시하는 login, callback API를 구현하는 것이었습니다. 직접 인증을 세션 혹은 jwt 발급하는 것과 workOS를 사용하는 인증 과정은 달라 꽤나 재밌었습니다.

workOS에서 authKit이라는 것을 제공해 유저가 로그인을 요청할 수 있는 페이지를 제공합니다. 서버는 workOS에 로그인 작업이 진행된 이후에 인증 과정을 처리할 콜백의 url을 제공합니다. 그러면 유저는 authKit 페이지에서 로그인 과정을 workOS를 통해 진행하고, workOS 서버는 해당 유저의 세션 관리 등을 진행하면서 인증 요청을 보낸 서버에는 이후의 과정을 진행하는 데 필요한 데이터를 제공합니다. 이 때의 정보들에는 workOS에 해당 유저의 정보를 요청하는 데 필요한 임시 코드 값이 제공되며, 서버는 해당 코드를 기반으로 workOS가 관리하고 있는 유저의 인증 관련한 정보인 유저 정보 및 세션 정보들을 획득할 수 있습니다.

이 때 유저가 인증을 요청한 서버의 기준으로 최초로 접근을 요청하는 유저일 경우 validation을 거친 뒤에 데이터베이스에 등록을 진행하거나 거절하고, 조직을 추가해주는 등의 작업을 진행할 수 있습니다. 원래는 구현해야하는 회원가입 기능과 로그인에 필요한 보안에 예민한 이슈 및 세션 관리 등을 workOS에서 대신 진행해준다고 생각하면 될 것 같네요.

해당 기능을 구현하고 나서 동작을 확인하고 나니 이제 남은 것은 인증이 필요한 엔드포인트들에 인증이 자동으로 이루어지도록 하기 위한 기능을 추가로 구현하는 것이었고, 저는 별 생각 없이 미들웨어의 형태로 구현을 하기로 결정했습니다. 해당 미들웨어는 우선 인증을 진행하고 유저 정보를 엔드포인트의 로직에 제공하며, 인증이 실패한 경우 workOS의 로그인 authkit으로 리다이렉션하도록 구현했습니다. 그리고 그것이 재앙의 시작이란 것을 그 때는 미처 알지 못했습니다.

미들웨어와 fastAPI

제가 생각한 방식은 이랬습니다. 모든 HTTP 요청에 대해 공통적으로 인증 로직을 수행하는 미들웨어를 구현하고, 각 엔드포인트의 특정 요구사항에 따라 해당 미들웨어의 동작을 “튜닝”하는 형태였습니다. 예를 들어, 로그인이 필요한 서비스에서는 인증 미들웨어가 동작하고 아닌 경우에는 해당 미들웨어를 붙이지 않는 형태였지요.

그리고 해당 기능을 적용하고 나서 스테이징 서버에 배포하고 난 뒤 클라이언트 개발하는 분의 요구사항에서 제 구현 방식의 문제가 발견됐습니다. 요구사항들은 다음과 같습니다.

1. 인증이 필요하지 않은 api들에 대해서 인증요구가 발생하는 부분들을 제거해주세요.
2. 에러 발생 페이지(404 not found 등)에 대해서도 일괄적으로 인증 요구가 발생하고 있습니다.
3. swagger에 authorization이 동작하도록 해주세요.
4. 인증이 실패한 경우 307 redirection이 아닌 401 unauthorized 응답을 제공해주세요.

하나하나 클라이언트 개발하는 분의 입장이라면 당연히 필요하겠단 것을 요구사항을 듣고 나서 인지할 수 있었습니다만, 다음과 같은 문제들이 있었습니다.

1. 현재 구현한 blacklist 방식으로는 어느 페이지들이 제외돼야하는지 파악하는 것이 어렵다.
2. whitelist 방식으로 전환할 경우 endpoint의 스트링 값을 효율적으로 관리하기 위한 const
관리 체계를 구축하거나, 하드코딩을 해야한다.
3. 해당 기능을 위해서는 fastAPI의 security를 사용해야하며, 이를 위해서는 middleware가 아닌
dependency 형태로 인증 기능 구현이 전환돼야한다.
4. api를 웹 브라우저에서 호출한다는 잘못된 가정을 기반으로 구현해 set-cookie를 하고 있었으나,
네이티브 앱 기반에서 동작하기 위해서는 다른 구현 방식을 취할 필요가 있다.

많은 다른 구현 사례들을 통해 1,2,3의 문제를 해결하기 위해서는 지금 구현한 middleware를 들어내고 dependency의 형태로 구현해야한다는 것을 알 수 있었고, api들 자체에서 해당 기능을 동작시키는 것은 어렵지 않았으나 middleware에 대한 mocking들을 사용하고 있는 테스트 코드들의 경우에는 해당 미들웨어에 대한 모킹을 전부 제거하고 새로 만든 dependency 기반의 모킹으로 변경해야한다는 이야기였습니다.

서버 재 구조화 진행

다행히도 해당 작업의 경우에는 이미 동작하는 예시가 있고, 어떻게 변경해야하는 것이 굉장히 명확히 정의된 문제였기 때문에 ai의 도움을 받을 수 있을 것이라 생각했고 최근 무료로 풀린 Gemini CLI를 적극적으로 사용해보기로 했습니다.

이를 위해서 우선 middleware to dependency migration plan 문서를 작성하고, 해당 dependency에 대한 구현을 확인한 뒤, 이 구현 기반으로 서버 내의 엔드포인트들에 대한 수정 지시 및 테스트 코드의 변경을 요청했습니다. 이 때 엔드포인트에 대한 변경은 꽤나 잘 이루어졌습니다만, 테스트 코드에 대한 인증 모킹 방식의 변경 같은 경우에는 저도 어떻게 해야할 지 잘 모르는 상태에서 해달라고 요청을 해서였는지 전혀 쓸모있게 작동하지 않더군요.

저는 이를 위해서 다음과 같은 작업 과정을 거쳤습니다.

1. 인증 dependency의 구현 및 유닛 테스트 진행
2. 미들웨어 제거
3. 깨지는 테스트들을 기반으로 인증 기능이 필요한 엔드포인트 판별
4. 인증 기능 필요 엔드포인트에 대한 dependency 설정
5. 깨지는 테스트의 모킹을 middleware to dependency로 전환

이 때 인증 실패시 307을 반환하던 것에서 401을 반환하다보니 기존에 실패 케이스들에 대한 테스트도 다시 다 변경될 필요가 있었습니다. 사족이지만, 제가 클라이언트를 개발하는 사람의 입장이었어도 대체 모든 api에서 307 인증 redirection request가 튀어나온다는 건 대체 뭐하는 놈인가 싶긴 했을 것 같군요.

마무리

아주 다행히도 해당 변경이 모두 이루어진 이후에 클라이언트 개발자께서 요청해주신 기능들이 정상적으로 동작한다는 사실도 알 수 있었고, 저는 새로운 버그를 찾았기 때문에 이에 대한 수정 작업을 진행했 습니다. 아주 해피엔딩(?)이군요.

이번 기회를 통해 웹 프레임워크 자체에 대한 이해나 api 설계 자체에 대해서 좀 더 신경써서 공부해 볼 필요를 느껴 최근 OpenAPI와 스웨거를 활용한 실전 API 설계라는 책을 읽기 시작했습니다. 조만간에 해당 책에 대한 후기도 올릴 수 있으면 좋겠군요.

부디 저처럼 fastAPI의 인증 기능을 미들웨어를 통하는 불상사가 다른분에게서는 일어나질 않길 바라는 마음에 부끄러운 경험 한 번 공유해봅니다.

읽어주셔서 감사합니다.


2025-07-18
카테고리로 돌아가기 ↩