문제 해결 (개발)

Next.js 에서 NICE 본인인증 구현하기2 (Route Handlers)

마뇨기 2025. 11. 18. 15:41

이전 포스트:

https://mini-frontend.tistory.com/11

 

Next.js 에서 NICE 본인인증 구현하기 (iOS, 카카오톡 인앱 브라우저 환경에서는 왜 안될까)

오랜만에 블로그를 쓴다...회사에 일을 시작하면서 하루하루가 바쁘게 돌아가다 보니 블로그를 쓸 여력이 없었다.. (핑계야 핑계 이 자식아)일하면서 블로그 쓰시는 수많은 개발자 분들 존경합

mini-frontend.tistory.com

 

이전 글에서 주안점은 request MethodPOST이고, body를 통해 form data을 받을 수 있다는 것이었다.

 

뭔가 서버와 연관 지어 해결할 수 있지 않을까 싶고, Next.js는 클라이언트 뿐만 아니라 서버와 관련된 처리를 할 수 있지 않는가!

그렇다. 이 문제의 해결 Key로 Next.jsRoute Handlers에서 해결 방법을 찾을 수 있었다.

 

 

 


 

 

 

Route Handlers ?

 

 

Route Handlers:

Next.js의 App Router에서 특정 경로에 대해 GET·POST 같은 HTTP 요청을 직접 처리하는 서버 전용 핸들러이다.

 

“페이지 컴포넌트”는 page.tsx에서 처리하고, “그 주소로 오는 HTTP 요청을 다루는 서버 코드”는 Route Handlers에서 처리할 수 있다.

 

Route Handlers를 사용하려면 먼저 아래 2가지를 알아둬야 한다. (Next.js 공식문서 참고)

 

  • Route Handlers are defined in a route.js|ts file inside the app directory.
    Route 핸들러는 App 디렉토리 내의 route.js|ts 파일로 정의하면 됩니다.
  • Route Handlers can be nested anywhere inside the app directory, similar to page.js and layout.js.
    But there cannot be a route.js file at the same route segment level as page.js.

    Route 핸들러는 page.tsx 및 layout.tsx와 유사하게 App 디렉토리 내 어디에나 중첩될 수 있습니다.
    그러나 page.tsx와 동일한 Route 세그먼트 레벨에 route.ts 파일이 있을 수 없습니다.

 

첫 번째 말은 페이지 컴포넌트가 page.tsx에서만 동작할 수 있는 것처럼 Route Handlers는 route.ts에서만 동작한다는 의미이다.

 

두 번째로, route.ts는 App 디렉토리 내 어디에나 있을 수 있지만, page.tsx 와 같은 디렉토리에 위치할 수 없다는 의미이다.

// 잘못된 구조
app/
  mypage/
    page.tsx     ← 페이지 컴포넌트
    route.ts     ← 같은 디렉토리(폴더)에 위치할 수 없음

 

 

Route Handlers를 사용하기 위해서는 route.ts 내에서 요청에 따라 함수명을 GET이나 POST를 사용하면 된다.

import { NextRequest } from "next/server";

export async function GET(req: NextRequest) {} // 요청이 GET인 경우

export async function POST(req: NextRequest) {} // 요청이 POST인 경우

 

 

프로젝트에서는 App 디렉토리 내에서 api/nice-auth에 route.ts를 생성하여 사용하였다.

app/
  mypage/
    page.tsx            → /mypage (UI)

  api/
    nice-auth/
      route.ts          → /api/nice-auth (Route Handler)

 

즉, https://domain.com/api/nice-auth에 접속하면 route.ts에 담긴 코드가 동작한다.

 


 

 

Route Handlers에서 form data를 읽어보자

 

 

Next.js의 Route Handlers에서는 request body로 넘어온 form data를 읽을 수 있는 함수를 제공한다.

export async function POST(req: Request) {
  const formData = await req.formData()
  const name = formData.get('name')
  const email = formData.get('email')
  return Response.json({ name, email })
}

 

POST 함수의 파라미터인 req에서 formData() 함수를 사용하면 form data를 읽을 수 있다.

 

그렇다면 NICE에서 보낸 form data를 읽고 그 이후의 처리까지 해보자

 

import { NextRequest, NextResponse } from "next/server";

export async function POST(req: NextRequest) {
  const form = await req.formData();
  const token = form.get("token_version_id");
  const enc_data = form.get("enc_data");
  const integrity_value = form.get("integrity_value");

  if (token && enc_data && integrity_value) {
    const html = `
      <html>
        <body>
          <form id="nice-redirect-form" method="GET" action="리다이렉트 할 url">
            <input type="hidden" name="token_version_id" value="${String(
              token
            ).replace(/"/g, "&quot;")}" />
            <input type="hidden" name="enc_data" value="${String(
              enc_data
            ).replace(/"/g, "&quot;")}" />
            <input type="hidden" name="integrity_value" value="${String(
              integrity_value
            ).replace(/"/g, "&quot;")}" />
          </form>
          <script>
            document.getElementById("nice-redirect-form").submit();
          </script>
        </body>
      </html>
    `;
    return new NextResponse(html, {
      status: 200,
      headers: {
        "Content-Type": "text/html; charset=utf-8",
      },
    });
  }
}

 

위 코드는 아래 3가지 과정 거친다.

  1. NextRequest를 통해 전달된 form data를 읽음
  2. 읽은 값을 다시 HTML 폼의 input 요소들에 할당
  3. new NextResponseform을 포함한 HTML을 응답으로 반환

여기서 NextResponseResponse(웹 표준) 객체의 확장 버전이다. new NextResponse()로 사용하듯이 웹 표준의 new Response(body, { status, headers })와 같은 형태로 지원한다.


브라우저가 HTML 응답을 렌더링 하면, 스크립트에서 submit()이 실행되며 action에 지정된 URL로 요청이 전송된다. 이때 methodGET으로 설정해야, 클라이언트에서 쿼리스트링을 통해 form data 값을 정상적으로 전달받을 수 있다.

 

 

NICE 인증 후, GET method로 접속하는 경우는 어떻게 처리할까?

 

백엔드에서 NICE 인증 후 리다이렉트 되는 URL은 하나만 지정할 수 있다. POST나 GET에 따라 URL을 다르게 지정할 수 없기 때문에 하나의 route.ts에서 POST와 GET을 모두 처리해야 했다.

GET method로 요청이 올 경우에는 POST와 달리, 쿼리스트링이 보존되기 때문에 백엔드에서 route.ts로 이동되는 URL을 지정할 때 쿼리스트링에 3가지 값을 추가해 두었다.

(POST method에서는 쿼리스트링이 추가하여도 없애진 채로 요청된다.)

 

export async function GET(req: NextRequest) {
  const { searchParams } = new URL(req.url);
  const token = searchParams.get("token_version_id");
  const enc_data = searchParams.get("enc_data");
  const integrity_value = searchParams.get("integrity_value");

  cosnt html = ~~ POST 함수에 있던 코드와 동일 ~~
  
  return new NextResponse(html, {
      status: 200,
      headers: {
        "Content-Type": "text/html; charset=utf-8",
      },
    });
}

 

위 코드처럼 쿼리스트링에서 값을 읽은 후, POST와 동일한 방식으로 처리해 두었다.

 

이렇게 NICE에서 보내는 요청이 POST와 GET으로 나누어 요청되어도 모두 처리할 수 있도록 해두었다!

 


 

뭔가 더 좋은 방법이 있지 않을까 싶은데, 뚜렷한 방법이 떠오르지 않긴 한다.

그래도 Next.js에서의 서버 처리에 관한 시도를 해보면서 웹 자체에 대한 이해가 조금 늘은 것 같아 뿌듯하다!

 

 

 

참고 자료