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
ts
import { 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
ts
const 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
ts
import { 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()을 사용합니다.

ts
return client.callApi(...).pipe(
  auth.withEnsureToken(),
);

인증이 필요 없다면

ts
export const { callApi, callApiStream } = createHttpClient<paths>({
  baseUrl: "/api",
});

공개 API나 간단한 프로젝트에서는 이것으로 충분합니다. HeaderStore와 session auth는 필수 구조가 아닙니다.

© 2026 Byeolnaerim. All rights reserved.소개개인정보처리방침