Skip to content

[Refactor] Next js 마이그레이션 - 인증 플로우 개선#679

Merged
rtttr1 merged 27 commits intodevelopfrom
refactor/#678/auth
Feb 9, 2026
Merged

[Refactor] Next js 마이그레이션 - 인증 플로우 개선#679
rtttr1 merged 27 commits intodevelopfrom
refactor/#678/auth

Conversation

@rtttr1
Copy link
Copy Markdown
Collaborator

@rtttr1 rtttr1 commented Feb 6, 2026

📌 Related Issues

✅ 체크 리스트

  • PR 제목의 형식을 잘 작성했나요? e.g. [Feat] PR 템플릿 작성
  • 빌드가 성공했나요? (pnpm build)
  • 리뷰어와 라벨을 지정했나요?

📄 Tasks

  • BFF 패턴 도입: catch-all API 라우트 및 백엔드 프록시 구현
  • 인증 API Route Handler 구현 (로그인, 로그아웃, reissue, 탈퇴)
  • 토큰 관리 localStorage 제거 후 httpOnly 쿠키(ACCESS / TEMP / REFRESH) 기반으로 전환
  • 온보딩·재가입 시 온보딩 과정중에 TEMP_ACCESS_TOKEN 사용, 완료 시 promote-onboarding-token으로 ACCESS_TOKEN 승격
  • 미들웨어 라우트 가드 구현 (AuthGuard, GuestGuard, 예약·탈퇴 가드) -> 추후 다른 pr에서 코드 정리할 예정

⭐ PR Point

인증 플로우를 개선했어요.
코드 볼곳
/src/app/api -> api route 설정
/src/app/api/[...path] -> BFF 설정, 모든 api가 거치는곳
/src/app/api/auth -> 인증 관련 api들
/src/middleware.ts -> 라우트 가드 설정 미들웨어

현재 상황

  1. 서버측에서 http 헤더의 Authrization에 들어간 토큰으로 인증을 처리한다.
  2. 현재 클라이언트에서 토큰을 localStorage로 관리한다.

문제점

  1. 서버 컴포넌트에서는 localStorage에 접근을 못한다.
  2. 이제 릴리즈를 할텐데 localStorage 관리 방식은 토큰 갈취 위험이 크다.

가능한 개선 방향

  1. http-only 쿠키 방식으로 인증 구조 변경
  2. Next Auth 같은 인증 관리 라이브러리로 Next 서버에 세션 만들어서 관리

둘중에서 http-only 쿠키 방식으로 인증 구조를 변경하기를 선택했어요.

Next Auth는 Next 서버에서 session 기반으로 인증 정보 + 유저 정보를 관리하는 기능 / 0Auth 간편하게 구현 같은 다양한 편의 사항 제공해줘요.
하지만 우리는 유저정보를 별도로 관리할 필요가 없고 (이미 api 활용하는 중) / 0Auth 인증을 이미 서버에서 다 구현해뒀어요.
따라서 정말 인증만 관리하는데 굳이 라이브러리까지? 라는 생각에 http-only 쿠키 방식으로 가야겠다 결정했어요.

그런데 이제 현실적인 상황이 저를 마주했어요.

  1. 쿠키 기반으로 서버의 인증 구조를 다갈아 엎어야함 -> 서버측 리소스 부족 (바쁨)
  2. 서버를 개발 / prod를 나눠서 띄워두지 않고 단일로 사용중 -> 서버의 인증 구조를 바꾸는 동시에 클라쪽 마이그레이션이 반영되기 전까지 Prod 제품 안돌아감 -> UT 및 릴리즈 막바지 준비에 지장 생김

위의 두가지 이유로 현실적으로 서버에서 지금 당장 인증 구조를 바꾸기 어렵다 생각했어요.

그렇다면 이제 상황을 정리하면 아래와 같아요.

  1. login시 응답으로 body에 토큰이 담겨온다.
  2. 클라에서 http 요청시 헤더의 Authrization에 토큰을 끼워서 보내야 한다.
  3. 1, 2번 조건상에서 http-only 쿠키 방식을 적용해야한다.
  4. 클라측에서 api쪽 코드 수정 없이 서버컴포넌트 + 클라이언트 컴포넌트에서 모두 api 요청이 가능해야 한다.

많은 삽질 끝에 위의 요구사항을 만족할 수 있는 방법인 BFF 패턴을 도입하기로 했어요.

BFF 패턴

BFF는 프론트엔드 전용 백엔드 레이어에요. 쉽게 이해하면 브라우저와 백엔드 서버 사이에 프록시 서버가 하나 낀다고 생각하면돼요.

기존 api 요청
브라우저 < ---- > 백엔드

BFF 패턴 api 요청
브라우저 < ---- > BFF (Next 서버) < ---- > 백엔드

선택 이유 (장점)

  1. http-only 쿠키 설정은 서버측에서만 할 수 있다. 우리 백엔드는 못하니, Next서버에서 쿠키를 설정해준다.
  2. 서버 컴포넌트, 클라이언트 컴포넌트 모두 Next서버를 거친다. (단일 진입점 -> 인증 관리 로직 응집)
  3. 기존 api 호출 코드를 수정하지 않아도 된다.
  4. 보안에 좋음 (백엔드 BASE_URL, 토큰을 Next 서버만 안다)
  5. 백엔드 응답을 BFF에서 가공할 수 있다. (서버의 변화에 유연하게 대처 가능)

우려 사항 (단점)

  1. 네트워크상 1홉이 늘어난거라 성능 우려 (일단 local에서 prod 띄워서 테스트 해본결과 큰 차이는 없지만 배포하면 어떨지 모름)
    -> 웹 배포 리전과 서버 리전을 가까운데 두면 어느정도 커버 가능

이런 단점이 존재하지만 현실적으로 최선의 선택이라 선택하게 되었어요.

구현

Next js에서는 Route handlercatch-all segement로 BFF를 구현할 수 있어요.

  • 인증 API Route Handler
    로그인(/api/auth/login), 로그아웃(/api/auth/logout), reissue(/api/auth/reissue)를 Next Route Handler로 구현했어요. Next 서버에서 백엔드 인증 API를 호출하고, 응답에 따라 쿠키를 설정·삭제한 뒤 클라이언트에는 필요한 정보만 반환해요.
    이에 따라 클라이언트 localStorage 토큰 로직을 제거하고, access/refresh 토큰은 Next 서버에서만 httpOnly 쿠키로 설정·삭제해요.
    XSS로부터 토큰 노출을 줄이고, BFF·미들웨어에서 일관되게 쿠키만 읽어 사용하는 구조입니다.

  • 기존 api 요청 프록시
    app/api/[...path]/route.ts catch-all로 백엔드 프록시를 두고, axios의 Base Url을 /api로 설정해 기존 요청을 모두 해당 경로로 보내게 했어요.
    route.ts 에서는 http 요청 헤더에 'Authorization'을 설정해서 백엔드로 전송해요.

async function proxyToBackend(request: NextRequest, params: RouteParams) {
  try {
    const path = `/${(params.path ?? []).join('/')}`;
    const targetUrl = new URL(path + request.nextUrl.search, process.env.BACKEND_BASE_URL);

    const proxyRequest = new Request(targetUrl, request);

    const cookieAccessToken = request.cookies.get(ACCESS_TOKEN_KEY)?.value;
    const cookieTempAccessToken = request.cookies.get(TEMP_ACCESS_TOKEN_KEY)?.value;
    const accessToken = cookieAccessToken ?? cookieTempAccessToken;

    if (accessToken) {
      proxyRequest.headers.set('Authorization', `Bearer ${accessToken}`);
    }

    return await fetch(proxyRequest);
  } catch {
    return NextResponse.json({ message: 'Proxy failed' }, { status: 500 });
  }
}

미들웨어 라우트 가드

기존 라우트 가드들은 middleware.ts 에서 처리했어요. 지금은 ai한테 돌아가게만 하도록 구현해둔 상태라 추후 pr에서 코드를 리펙토링 해야해요.

📷 Screenshot

이해에 도움이 될까 하여 간단하게 도식화 해보았어요.

스크린샷 2026-02-07 오전 1 24 09 스크린샷 2026-02-07 오전 1 24 28

🔔 ETC

@rtttr1 rtttr1 self-assigned this Feb 6, 2026
@rtttr1 rtttr1 added the 🪄 Refactor 코드 리팩토링 label Feb 6, 2026
@github-actions github-actions Bot added the 규홍 슈퍼주니-어에요 label Feb 6, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 6, 2026

✅ Storybook 배포 완료! 🔗 https://67e4fd1fd2c7078dceec04a4-nekcamtezp.chromatic.com/

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Feb 6, 2026

Deploying dash-client-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: 505dda6
Status:🚫  Build failed.

View logs

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Feb 6, 2026

Deploying dash-client with  Cloudflare Pages  Cloudflare Pages

Latest commit: 505dda6
Status:🚫  Build failed.

View logs

@rtttr1 rtttr1 merged commit be56a8b into develop Feb 9, 2026
5 of 7 checks passed
@rtttr1 rtttr1 deleted the refactor/#678/auth branch February 9, 2026 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

규홍 슈퍼주니-어에요 🪄 Refactor 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor] Next js 마이그레이션 - 인증 플로우 변경

1 participant