Headers & Session Auth
인증이 없는 프로젝트는 createHttpClient만 사용하고, 필요한 경우에만 HeaderStore와 session auth를 붙입니다.
이 페이지의 commonService.ts 코드는 전체 파일의 일부
아래 HeaderStore, headersProvider, sessionAuth 코드는 서로 독립된 파일 예제가 아니라 프로젝트 공용 HTTP adapter(rxjsHttpService.ts/commonService.ts)의 각 부분을 나눠 설명하는 것입니다. 전체 파일 구조를 먼저 보고 싶다면 HTTP Client의 최소 완성형/확장형 전체 코드를 확인한 뒤 이 페이지를 읽으세요.
브라우저에서 공유할 header
로그인 뒤 받은 access token처럼 여러 service가 함께 써야 하는 header는HeaderStore에 보관할 수 있습니다.
commonService.ts
tsimport { createHeaderStore } from "@byeolnaerim/typed-rx-http";
export const headerStore = createHeaderStore({
"Content-Type": "application/json",
});
headerStore.merge({
Authorization: `Bearer ${accessToken}`,
});
headerStore.remove("Authorization");Next.js에서는 브라우저와 서버 header를 나누기
Client Component에서는 HeaderStore를 읽고, Server Component에서는 cookie를 읽도록 headersProvider를 만들 수 있습니다. 이 함수에서 CSR과 SSR의 header 조회 방식을 한 곳에서 분리할 수 있습니다.
commonService.ts
tsconst headersProvider = async () => {
if (typeof window !== "undefined") {
return headerStore.get();
}
const { cookies } = await import("next/headers");
const accessToken = (await cookies()).get("accessToken")?.value;
return accessToken
? { Authorization: `Bearer ${accessToken}` }
: {};
};
export const service = createHttpClient<paths>({
baseUrl: process.env.NEXT_PUBLIC_API_URL || "",
headerStore,
headersProvider,
});401 refresh가 필요하면 callApi에 한 번 감싸기
자동 생성 service를 하나씩 수정하지 말고, 공용callApi에 session operator를 붙입니다. 그러면 모든 생성 service가 같은 토큰 조회와 refresh 규칙을 사용합니다.
commonService.ts
tsimport { createSessionAuth } from "@byeolnaerim/typed-rx-http";
import { defer } from "rxjs";
const sessionAuth = createSessionAuth({
headerStore,
tokenUrl: "/api/auth/token",
refreshUrl: "/api/auth/token/refresh",
logoutUrl: "/api/auth/logout",
onLoginChange: (loggedIn) => setLogin(loggedIn),
});
export const callApi = (serviceArguments) =>
defer(() => service.callApi(serviceArguments)).pipe(
sessionAuth.withSessionAuth(),
);Authorization이 없으면 token endpoint를 먼저 확인하고, 원 요청이 401이면 refresh 뒤 한 번 다시 요청합니다. refresh도 실패하면 logout endpoint를 호출하고 원래 오류를 전달합니다.
refresh/retry 없이 token 동기화만 필요한 경우
401 refresh/retry는 사용하지 않고 요청 전에 token만 동기화하려면 withEnsureToken()을 사용합니다.
return client.callApi(...).pipe(
auth.withEnsureToken(),
);인증이 필요 없다면
export const { callApi, callApiStream } = createHttpClient<paths>({
baseUrl: "/api",
});공개 API나 간단한 프로젝트에서는 이것으로 충분합니다. HeaderStore와 session auth는 필수 구조가 아닙니다.