엔지니어링 가이드
인증 붙이기
인증 붙이기
템플릿에는 인증이 없다. 무엇을 정하고 어디에 붙일지, 그리고 직접 해 볼 요청 예시
예시 서버는 127.0.0.1 에서만 열리고, 요청이 누구의 것인지 묻지 않는다. 이대로 밖에 열면 주소를 아는 누구나 메모를 읽고 지울 수 있다.
템플릿이 인증을 넣지 않은 이유는 방식이 프로젝트마다 다르기 때문이다. 브라우저 앱만 있으면 쿠키 세션이 맞고, 모바일 · 데스크톱 앱이 있으면 토큰이 필요하다. 사용자를 직접 확인할 수도, 외부 제공자(OIDC)에 맡길 수도 있다. 하나를 골라 넣어 두면 다른 방식을 쓰는 프로젝트는 그것을 걷어내는 일부터 해야 한다. 이 글은 구현 대신 정할 것과 붙일 자리를 정리하고, 에이전트에게 맡길 때 쓸 요청 예시를 남긴다.
먼저 정할 것
- 누가 부르는가. 브라우저 앱만 있는지, 모바일 · 데스크톱 앱도 있는지에 따라 쿠키 세션과 토큰 중 하나를 고른다.
- 누가 사용자를 확인하는가. 비밀번호를 직접 다루는지, OIDC 제공자의 토큰을 검증만 하는지 정한다.
- 어느 서버가 검증하는가. 서버마다 검증하는지, 앱이 들어오는 gateway 한 곳에서 하는지 정한다(gateway 에서 하면 검증한 사용자 id 를 헤더로 넘기고, 서버는 gateway 를 거친 요청만 받게 막는다). 사용자 · 로그인을 맡는 서버(예:
identity)를 따로 두면 다른 서버는 그 서버가 준 토큰을 검증만 한다. 서버 ↔ 서버(gRPC)는 사용자 인증과 별개로 mTLS 나 서비스 토큰으로 막는다. - 데이터의 주인과 오류 코드. 메모에 사용자 id 를 붙이고, 다른 사용자의 메모를 요청하면 404 로 숨길지 403 으로 알릴지 정한다. 인증이 없으면 401 이다.
이 선택은 여러 서버와 앱에 걸치고 되돌리기 어렵다. 구현 전에 decisions/template.md 로 ADR 을 쓴다.
붙일 자리
인증은 api 층의 일이다. domain 은 HTTP 헤더를 모르고, 요청한 사용자의 id 를 인자로 받는다.
| 층 | 할 일 |
|---|---|
| gateway (고르면) | 토큰을 검증하고 사용자 id 를 헤더로 넘긴다. 경로 표 앞에 한 단계를 둔다(servers/gateway). 서버의 api 는 그 헤더만 믿는다 |
| api | 요청에서 사용자를 확인한다. notes(Node)는 src/api/http/server.ts 의 요청 처리 앞, activity(Spring)는 Spring Security 필터, tags(FastAPI)는 dependency 나 server/support/security.py |
| domain | 사용자 id 를 받아 그 사용자의 메모만 다룬다 |
| storage | notes 에 사용자 id 열을 더하는 새 마이그레이션 (database.md) |
| clients | 외부 제공자(토큰 검증 키 조회 등)를 부르는 코드. 테스트에서는 Fake 로 바꾼다 |
- 계약: 서버의 openapi 문서에 인증 방식(securitySchemes)이 나오게 해서 클라이언트도 알 수 있게 한다.
- 테스트: 각
*_specs에 “토큰이 없으면 401”, “다른 사용자의 메모는 404(또는 403)” 같은 경우를 더한다. 외부 제공자는 Fake 다(testing.md). - 브라우저: 쿠키 세션을 쓰면 JSON 본문만 받는 규칙만으로는 부족하다.
SameSite와 CSRF 토큰을 함께 정한다.
요청 예시
아래는 notes 서버와 web 앱에만 토큰 인증을 붙이는 요청이다. 꺾쇠(<...>)를 자기 프로젝트의 값으로 바꿔 쓴다.
첫 단계에서 ADR 을 제안하고 멈추게 한 것은, 인증 방식이 사람이 정할 일이기 때문이다.
목적: 메모를 사용자별로 나눈다. 로그인한 사용자만 자기 메모를 읽고 쓴다.
먼저: docs/decisions/template.md 로 인증 방식 ADR 을 "제안" 상태로 쓰고 멈춘다. 내가 확인한 뒤에 구현한다.
정할 것: 토큰 발급자 <OIDC 제공자>, 전달 방식(Authorization: Bearer), 다른 사용자의 메모를 요청했을 때 404 와 403 중 무엇을 줄지.
변경 범위: notes 서버와 web 앱만. tags · activity 와 다른 앱은 바꾸지 않는다.
- notes api: 액세스 토큰(JWT)을 검증하고 사용자 id 를 domain 에 넘긴다.
- notes clients: 토큰 검증 키(JWKS)를 가져오는 코드를 둔다.
- DB: notes 에 user_id 열을 더하는 새 마이그레이션. 기존 마이그레이션은 고치지 않는다.
- web: 로그인 후 받은 토큰을 API 요청 헤더에 붙인다.
제약: 테스트에서 실제 제공자를 부르지 않는다. 키 조회는 Fake 로 바꾸고 테스트용 키로 토큰을 만든다. mock 은 쓰지 않는다.
완료 기준: /api/notes 의 각 *_specs 에 "토큰이 없으면 401", "다른 사용자의 메모는 <ADR 에서 정한 코드>" 를 더하고,
기존 경우는 자기 토큰으로 지금처럼 통과한다. pnpm gen 결과가 같은 커밋에 있다.
확인: pnpm --filter @app/notes test 와 pnpm typecheck 를 실행한다. 화면은 verify-local 로 띄워 확인할 주소를 알려 준다.
보고: 실행한 확인과 결과, 실행하지 못한 확인과 이유, 범위 밖 변경이 필요했다면 그 이유와 대안을 나눠 적는다.
요청을 나누는 기준은 AI 와 개발하기의 “일을 맡기는 요청”과 같다.