Remix.js와 Next.js 비교: 서버 동작, 쿠키, 세션 관리 관점

share · 2026-6-22

← 리스트로

Remix.js와 Next.js 비교: 서버 동작, 쿠키, 세션 관리 관점에서 본 Remix의 강점

1. 문서 목적

이 문서는 Remix.js와 Next.js를 비교할 때, 특히 다음과 같은 서버 동작이 필요한 프로젝트에서 Remix.js가 어떤 강점을 가지는지 정리하기 위한 문서이다.

  • httpOnly 쿠키 기반 인증
  • 서버 세션 관리
  • loader 단계에서 인증/권한 확인
  • 서버에서 외부 API를 대신 호출하는 BFF 패턴
  • OAuth callback 처리
  • 결제 callback 처리
  • flash message 처리
  • redirect와 세션 commit 흐름
  • 백엔드 지원이 약한 상황에서 프론트엔드 서버가 일부 서버 역할을 담당해야 하는 경우

결론부터 말하면, Next.js도 대부분의 기능을 구현할 수 있지만, 서버 요청/응답, 쿠키, 세션, redirect, form action이 복잡하게 얽히는 프로젝트에서는 Remix.js가 더 일관적이고 접근하기 쉬운 구조를 제공한다.


2. 핵심 결론

▎ 인증·세션·쿠키·API 우회(BFF)·callback 처리 같은 서버 일을 프론트엔드에 떠맡는 구조라면, 그 일들을 하나의 일관된 모델(loader/action/session/redirect)로 수렴시켜 주는 Remix가 학습·유지보수 비용이 낮다.

특히 이런 환경에서 Remix가 유리한 실무적 이유:

  • 프론트 개발자 진입장벽이 낮다 — 서버 전문가가 아니어도 “읽기는 loader, 쓰기는 action, 세션은 쿠키에서” 라는 단순 규칙만으로 서버 일을 처리할 수 있음.
  • 컨벤션이 강제된다 — 사람마다 제각각 짤 여지가 적어서, 팀에 백엔드 리드가 없어도 코드가 한 방향으로 모임. (Next는 자유도가 높은 만큼 컨벤션 없으면 흩어짐 — 백엔드 지원이 약한 팀일수록 이게 독이 됨.)
  • "다용도(범용 서버 역할)"라는 표현이 딱 맞다 — form 처리, 세션, BFF, callback을 한 프레임워크 안에서 같은 패턴으로 다 커버하니까.

다만 딱 두 가지 단서

  1. "다용도로 항상 더 좋다"는 아니다. 정확히는 “서버 역할을 떠안아야 하는 그 조건에서” 더 적합한 겁니다. 정적 페이지·SEO·이미지 최적화가 주력이면 여전히 Next가 낫고요. 즉 조건부 팩트입니다.
  2. 실무 도입 시 이름은 React Router v7로 보는 게 맞다. 그 loader/action 서버 모델은 지금 React Router로 통합됐으니, 회사에 제안할 때 “Remix(=React Router v7)” 로 표기하면 "Remix 단종된 거 아니냐"는 반론을 미리 막을 수 있습니다.

한 줄 결론: “서버 기능을 프론트엔드가 떠안는 조건에서, 범용 서버 역할을 일관된 모델로 손쉽게 다루기엔 Remix가 더 적합하다” — 이 주장은 회사에 그대로 들고 가도 되는 타당한 명제입니다.

Next.js가 더 적합한 경우

Next.js는 다음과 같은 경우에 강점이 크다.

  • 정적 페이지
  • 마케팅 페이지
  • 콘텐츠 중심 페이지
  • 블로그, 뉴스, 상품 상세 페이지
  • SEO와 렌더링 최적화가 중요한 페이지
  • SSR / SSG / ISR 전략이 중요한 서비스
  • React Server Component 기반 구조를 적극 활용하는 서비스
  • Vercel 생태계와 이미지 최적화, 캐싱 전략을 적극 활용하는 서비스

즉, Next.js는 React 화면 렌더링과 배포/캐싱/최적화 전략에 강한 프레임워크라고 볼 수 있다.


Remix.js가 더 적합한 경우

Remix.js는 다음과 같은 경우에 강점이 크다.

  • 서버 request/response 흐름이 중요함
  • loader에서 인증/권한 체크가 필요함
  • action에서 form submit, mutation, redirect 처리가 많음
  • httpOnly 쿠키를 적극적으로 사용함
  • 서버 세션을 자주 읽고 써야 함
  • flash message가 필요함
  • OAuth, 결제, 외부 서비스 callback 처리가 많음
  • 백엔드 지원이 약해서 프론트엔드 서버가 BFF 역할을 해야 함
  • 클라이언트에서 직접 API 호출하지 않고 서버에서 API를 우회 호출해야 함

즉, Remix.js는 웹 표준 request/response 모델을 프론트엔드 개발자가 다루기 쉽게 추상화한 프레임워크라고 볼 수 있다.


3. Remix.js의 가장 큰 장점: 서버 흐름이 단순하고 일관적이다

Remix.js에서는 서버 동작이 주로 loaderaction으로 정리된다.

export async function loader({ request }) {
  // 페이지 진입 전에 서버에서 데이터 로딩
}

export async function action({ request }) {
  // form submit, mutation, 로그인, 로그아웃 등 처리
}

이 구조는 프론트엔드 개발자 입장에서 이해하기 쉽다.

  • 페이지에 들어오기 전에 필요한 데이터는 loader
  • 사용자가 form을 제출하거나 데이터를 변경하면 action
  • 세션은 request.headers.get("Cookie")에서 읽음
  • 응답에는 Set-Cookie를 붙여서 세션을 갱신
  • 필요하면 redirect로 이동

흐름이 다음처럼 단순하다.

브라우저 요청
→ loader/action 실행
→ 쿠키에서 세션 읽기
→ 필요한 서버 API 호출
→ 세션 변경 시 Set-Cookie 생성
→ json 또는 redirect 응답

이 구조는 전통적인 웹 서버의 request/response 흐름과 매우 가깝다.


4. Remix.js의 세션 관리 강점

Remix.js는 세션 관리를 위한 추상화를 프레임워크 차원에서 제공한다.

대표적으로 다음과 같은 패턴을 사용할 수 있다.

const session = await getSession(request.headers.get("Cookie"));

const userId = session.get("userId");

session.set("userId", user.id);
session.flash("message", "저장되었습니다.");

return redirect("/mypage", {
  headers: {
    "Set-Cookie": await commitSession(session),
  },
});

이 구조의 장점은 다음과 같다.

  • 쿠키 읽기
  • 세션 객체 생성
  • 세션 값 읽기
  • 세션 값 저장
  • flash message 저장
  • 세션 commit
  • redirect 응답에 Set-Cookie 붙이기

이 흐름이 하나의 모델 안에서 처리된다.

Next.js에서도 유사한 기능을 만들 수 있지만, Remix.js처럼 loader / action / session / redirect가 하나의 패턴으로 자연스럽게 연결되어 있지는 않다.


5. 쿠키 기반 세션에서 Remix.js가 편한 이유

일반적인 서버 세션은 보통 다음 중 하나를 필요로 한다.

  • 서버 메모리 세션
  • Redis 같은 외부 캐시
  • DB 기반 세션
  • 파일 기반 세션
  • signed/encrypted cookie 기반 세션

Remix.js는 이 중 쿠키 기반 세션을 꽤 간단하게 다룰 수 있다.

쿠키 기반 세션을 사용하면 별도의 Redis나 세션 저장소 없이도 다음과 같은 처리가 가능하다.

세션 데이터
→ 서명/암호화된 쿠키로 저장
→ 브라우저가 매 요청마다 쿠키 전송
→ 서버가 쿠키를 읽어 세션 복원

이 방식은 다음과 같은 상황에서 유용하다.

  • 세션 데이터가 작음
  • 서버를 stateless하게 유지하고 싶음
  • Cloud Run, serverless, container 환경에서 인스턴스 간 세션 공유 문제가 부담스러움
  • 프론트엔드 서버가 간단한 BFF 역할만 하면 됨

다만 쿠키 기반 세션에는 주의점도 있다.

  • 쿠키 크기 제한이 있음
  • 너무 많은 데이터를 넣으면 안 됨
  • 민감한 값을 무분별하게 넣으면 안 됨
  • access token, refresh token 저장 정책은 보안 검토가 필요함
  • 큰 권한 목록이나 사용자 전체 정보는 API나 DB에서 다시 가져오는 편이 안전함

쿠키 기반 세션에는 보통 다음 정도만 넣는 것이 적절하다.

userId
role
짧은 accessToken 또는 sessionId
returnUrl
flash message
일회성 state

6. Next.js에서도 가능하지만 레이어가 분산된다

Next.js도 현재는 쿠키 관련 기능이 많이 좋아졌다.

App Router에서는 다음과 같은 API를 사용할 수 있다.

import { cookies } from "next/headers";

const cookieStore = await cookies();

cookieStore.set("session", value, {
  httpOnly: true,
  secure: true,
  sameSite: "lax",
  path: "/",
});

또는 Route Handler에서 다음처럼 사용할 수 있다.

import { NextResponse } from "next/server";

export async function POST() {
  const response = NextResponse.json({ ok: true });

  response.cookies.set("session", "value", {
    httpOnly: true,
    secure: true,
    sameSite: "lax",
    path: "/",
  });

  return response;
}

즉, Next.js에서도 httpOnly 쿠키를 굽고 읽는 것은 충분히 가능하다.

문제는 쿠키 자체가 아니라 세션 흐름 전체다.

Next.js에서는 상황에 따라 다음 개념들을 조합해야 한다.

Server Component
Route Handler
Server Action
Middleware
cookies()
headers()
NextResponse
NextAuth/Auth.js
iron-session
jose
fetch cache
dynamic rendering

따라서 단순한 쿠키 조작은 쉬워졌지만, Remix.js처럼 loader / action / session / redirect가 하나의 일관된 흐름으로 연결되는 느낌은 상대적으로 약하다.


7. NextAuth/Auth.js와 iron-session 조합의 복잡성

Next.js에서 인증과 세션을 처리하려면 보통 다음 선택지가 있다.

1. NextAuth/Auth.js
2. iron-session
3. jose 직접 구현
4. 백엔드 인증 서버에 전적으로 위임
5. Redis/DB 기반 자체 세션 구현

각각의 성격은 다르다.

NextAuth/Auth.js

NextAuth/Auth.js는 인증 프레임워크에 가깝다.

잘 맞는 경우:

  • OAuth 로그인
  • 소셜 로그인
  • Credentials 로그인
  • JWT session
  • Database session
  • provider callback
  • CSRF 처리
  • 로그인/로그아웃 라우트 관리

즉, NextAuth/Auth.js는 인증 시스템 전체를 관리하는 도구다.


iron-session

iron-session은 쿠키 기반 세션 유틸에 가깝다.

잘 맞는 경우:

  • signed/encrypted cookie 기반 세션
  • 간단한 stateless session
  • session.userId = ...
  • session.save()
  • session.destroy()
  • flash message
  • 결제 callback state
  • returnUrl 임시 저장

즉, iron-session은 Remix.js의 cookie session에 가까운 사용감을 Next.js에서 구현하기 위한 도구에 가깝다.


둘을 같이 쓰는 경우

NextAuth와 iron-session을 같이 쓸 수도 있다.

예를 들면 역할을 이렇게 나눌 수 있다.

NextAuth/Auth.js
→ 로그인, OAuth, 인증 세션 담당
→ "이 사용자가 누구인가?"

iron-session
→ 인증 외 임시 상태 담당
→ 결제 state, returnUrl, flash message, nonce

하지만 이 조합은 조심해야 한다.

두 개의 세션 레이어가 생기면 다음과 같은 혼란이 생길 수 있다.

userId는 NextAuth에 넣어야 하나?
iron-session에 넣어야 하나?

accessToken은 NextAuth JWT에 넣어야 하나?
iron-session에 넣어야 하나?

로그아웃할 때 두 세션을 모두 지워야 하나?

callback 처리 중 어느 세션을 봐야 하나?

만료 시간은 어디 기준으로 봐야 하나?

따라서 같이 쓰려면 팀 규칙이 매우 명확해야 한다.

권장 규칙은 다음과 같다.

NextAuth/Auth.js
→ 인증 상태만 담당
→ userId, account, provider, OAuth token 등

iron-session
→ 인증 외 임시 상태만 담당
→ payment state, returnUrl, flash message, nonce 등

중복 저장 금지
→ userId/accessToken을 양쪽에 동시에 저장하지 않기

이 원칙이 없으면 유지보수 난이도가 급격히 올라간다.


8. OAuth와 결제 callback에서는 서버 세션이 특히 중요하다

OAuth나 결제 연동에서는 단순히 로그인 여부만 확인하는 것이 아니라, 외부 서비스로 이동하기 전의 상태를 잠깐 기억해야 하는 경우가 많다.

예를 들면 OAuth에서는 다음 값들이 필요할 수 있다.

state
nonce
PKCE code_verifier
redirectUrl
provider
returnUrl

결제에서는 다음 값들이 필요할 수 있다.

orderId
paymentAttemptId
amount
returnUrl
cancelUrl
userId
csrfToken

흐름은 보통 다음과 같다.

1. 사용자가 OAuth 로그인 또는 결제 시작
2. 서버가 임시 상태값 생성
3. 임시 상태값을 세션 또는 저장소에 저장
4. 외부 서비스로 redirect
5. 외부 서비스가 callback URL로 돌아옴
6. 서버가 callback 값과 기존 임시 상태를 비교
7. 성공/실패 처리
8. 임시 상태 삭제
9. flash message 저장
10. 최종 페이지로 redirect

이런 흐름을 직접 구현하려면 다음을 모두 신경 써야 한다.

상태값 생성
위변조 방지
재사용 방지
만료 처리
callback 검증
CSRF 방어
redirect URL 검증
flash message 처리
세션 정리
에러 처리

Next.js에서도 구현은 가능하지만, NextAuth, Route Handler, cookies(), iron-session, middleware 등을 조합해야 할 수 있다.

반면 Remix.js는 loader / action / session / redirect 모델 안에서 이런 흐름을 비교적 자연스럽게 다룰 수 있다.


9. BFF 패턴에서 Remix.js가 유리한 이유

BFF는 Backend For Frontend의 약자로, 프론트엔드 서버가 클라이언트와 백엔드 API 사이에서 중간 계층 역할을 하는 구조다.

예를 들면 다음과 같다.

브라우저
→ Remix.js 서버
→ 세션 쿠키 확인
→ 외부 API에 Authorization 헤더 붙여서 요청
→ 결과를 페이지에 내려줌

Remix.js에서는 이 흐름을 loader에서 자연스럽게 처리할 수 있다.

export async function loader({ request }) {
  const session = await getSession(request.headers.get("Cookie"));
  const token = session.get("accessToken");

  if (!token) {
    return redirect("/login");
  }

  const response = await fetch(`${API_URL}/me`, {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  const user = await response.json();

  return json({ user });
}

이 구조의 장점은 다음과 같다.

  • 클라이언트 JS가 accessToken을 직접 알 필요가 없음
  • httpOnly 쿠키 기반 인증과 잘 맞음
  • 페이지 진입 전에 권한 확인 가능
  • 권한 없으면 바로 redirect 가능
  • 서버에서 API 응답을 가공해서 내려줄 수 있음
  • 프론트엔드 개발자가 백엔드 API를 안전하게 우회 호출할 수 있음

Next.js에서도 Server Component나 Route Handler에서 비슷한 구현이 가능하지만, 어디에서 처리해야 하는지 선택지가 많아 구조가 분산될 수 있다.


10. 프론트엔드 개발자 접근성 관점

백엔드 지원이 충분하지 않은 팀에서는 프론트엔드 개발자가 다음 업무를 처리해야 할 수 있다.

로그인 처리
로그아웃 처리
세션 쿠키 관리
권한 체크
API proxy
외부 callback 처리
form action 처리
flash message 처리
redirect 처리

이 경우 Remix.js의 장점이 커진다.

Remix.js는 프론트엔드 개발자가 서버 동작을 배울 때 다음과 같이 단순하게 접근할 수 있다.

데이터 읽기
→ loader

데이터 변경
→ action

세션 읽기
→ getSession(request.headers.get("Cookie"))

세션 저장
→ commitSession(session)

페이지 이동
→ redirect(...)

반면 Next.js는 다음 개념들을 함께 이해해야 할 수 있다.

Server Component
Client Component
Route Handler
Server Action
Middleware
cookies()
headers()
NextResponse
fetch cache
dynamic/static rendering
NextAuth callback
iron-session

이 차이 때문에 서버 동작이 복잡한 서비스에서는 Remix.js가 더 직관적으로 느껴질 수 있다.


11. 단, Remix.js가 항상 더 좋은 것은 아니다

Remix.js가 서버 세션과 request/response 흐름에서 강점이 있다고 해서 항상 Next.js보다 좋은 것은 아니다.

Next.js가 더 나은 선택일 수 있는 경우도 많다.

예를 들면 다음과 같다.

정적 페이지가 많음
콘텐츠 SEO가 중요함
이미지 최적화가 중요함
Vercel 배포와 캐싱 전략을 적극 활용함
React Server Component를 활용하고 싶음
App Router 기반 생태계를 활용하고 싶음
팀이 이미 Next.js 경험이 많음
NextAuth/Auth.js를 표준 인증 방식으로 사용하고 있음

반대로 Remix.js가 더 나은 선택일 수 있는 경우는 다음과 같다.

form submit과 mutation이 많음
서버 세션을 자주 다룸
쿠키 기반 인증을 적극 활용함
flash message가 필요함
OAuth/결제 callback이 복잡함
BFF 역할이 중요함
백엔드 지원이 약함
프론트엔드 서버에서 API 우회 호출이 많음

12. 의사결정 기준

프로젝트 선택 기준은 다음처럼 잡을 수 있다.

질문 Next.js 쪽에 가까움 Remix.js 쪽에 가까움
정적 페이지가 많은가? 아니오
콘텐츠 SEO와 캐싱이 중요한가? 경우에 따라 다름
서버 세션을 많이 다루는가? 경우에 따라 복잡
form action이 많은가? 가능하지만 분산됨
OAuth/결제 callback 상태 관리가 복잡한가? 라이브러리 조합 필요 더 자연스러움
백엔드 지원이 충분한가? 아니오일수록 유리
FE 서버가 BFF 역할을 해야 하는가? 가능 매우 적합
팀이 Next.js 경험이 많은가? 학습 필요
request/response 모델을 단순하게 유지하고 싶은가? 상대적으로 복잡

13. 실무적 결론

정리하면 다음과 같다.

화면 중심, 정적 페이지, 렌더링 최적화 중심
→ Next.js가 유리

서버 요청/응답, 세션, 쿠키, form, callback 흐름 중심
→ Remix.js가 유리

Next.js는 강력하고 생태계가 크지만, 서버 세션과 쿠키 흐름이 복잡해지면 여러 도구를 조합해야 할 수 있다.

NextAuth/Auth.js
iron-session
Route Handler
Server Action
Middleware
cookies()
headers()

이 조합은 강력하지만, 팀 내 규칙이 없으면 레이어가 많아지고 혼란스러워질 수 있다.

반면 Remix.js는 다음 흐름이 하나의 모델로 정리된다.

loader
action
session
commitSession
destroySession
redirect
json

따라서 백엔드 지원이 약하고, 프론트엔드 서버가 세션/쿠키/API 우회/callback 처리까지 담당해야 하는 상황이라면 Remix.js는 매우 합리적인 선택지가 될 수 있다.


14. 최종 요약

Remix.js의 강점은 단순히 “SSR이 된다”가 아니다.

진짜 강점은 다음에 있다.

웹 표준 request/response 모델을 프론트엔드 개발자가 다루기 쉽게 만든 것

특히 다음 기능들이 중요한 서비스에서는 Remix.js의 장점이 크다.

httpOnly 쿠키
쿠키 기반 세션
loader 기반 권한 체크
action 기반 mutation
flash message
redirect
OAuth callback
결제 callback
BFF API 우회 호출

따라서 다음과 같이 정리할 수 있다.

단순 페이지와 렌더링 최적화 중심 서비스라면 Next.js가 강하다. 하지만 서버 세션, 쿠키, form action, callback, BFF 흐름이 복잡한 서비스라면 Remix.js가 더 일관적이고 프론트엔드 개발자에게 접근하기 쉬운 선택이 될 수 있다.