이전 포스트:
https://mini-frontend.tistory.com/11
Next.js 에서 NICE 본인인증 구현하기 (iOS, 카카오톡 인앱 브라우저 환경에서는 왜 안될까)
오랜만에 블로그를 쓴다...회사에 일을 시작하면서 하루하루가 바쁘게 돌아가다 보니 블로그를 쓸 여력이 없었다.. (핑계야 핑계 이 자식아)일하면서 블로그 쓰시는 수많은 개발자 분들 존경합
mini-frontend.tistory.com
이전 글에서 주안점은 request Method가 POST이고, body를 통해 form data을 받을 수 있다는 것이었다.
뭔가 서버와 연관 지어 해결할 수 있지 않을까 싶고, Next.js는 클라이언트 뿐만 아니라 서버와 관련된 처리를 할 수 있지 않는가!
그렇다. 이 문제의 해결 Key로 Next.js의 Route 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, """)}" />
<input type="hidden" name="enc_data" value="${String(
enc_data
).replace(/"/g, """)}" />
<input type="hidden" name="integrity_value" value="${String(
integrity_value
).replace(/"/g, """)}" />
</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가지 과정 거친다.
- NextRequest를 통해 전달된 form data를 읽음
- 읽은 값을 다시 HTML 폼의 input 요소들에 할당
- new NextResponse로 form을 포함한 HTML을 응답으로 반환
여기서 NextResponse는 Response(웹 표준) 객체의 확장 버전이다. new NextResponse()로 사용하듯이 웹 표준의 new Response(body, { status, headers })와 같은 형태로 지원한다.
브라우저가 HTML 응답을 렌더링 하면, 스크립트에서 submit()이 실행되며 action에 지정된 URL로 요청이 전송된다. 이때 method를 GET으로 설정해야, 클라이언트에서 쿼리스트링을 통해 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에서의 서버 처리에 관한 시도를 해보면서 웹 자체에 대한 이해가 조금 늘은 것 같아 뿌듯하다!
참고 자료
- https://skh990427.tistory.com/10
- https://overcome-the-limits.tistory.com/939
- https://minseoky.me/Etc/Pass%EC%97%B0%EB%8F%99%EA%B0%80%EC%9D%B4%EB%93%9C/
- https://velog.io/@simhw/Node.js-%EB%82%98%EC%9D%B4%EC%8A%A4-%EB%B3%B8%EC%9D%B8%EC%9D%B8%EC%A6%9D-API-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0#4-%EB%82%98%EC%9D%B4%EC%8A%A4-%ED%91%9C%EC%A4%80%EC%B0%BD%EC%84%9C%EB%B9%84%EC%8A%A4-%ED%98%B8%EC%B6%9C
- https://velog.io/@kmsk99/NICE-%EB%B3%B8%EC%9D%B8%EC%9D%B8%EC%A6%9D-%ED%8C%9D%EC%97%85%EC%9D%84-Next.js%EC%97%90%EC%84%9C-%EC%95%88%EC%A0%84%ED%95%98%EA%B2%8C-%EB%8B%A4%EB%A3%A8%EA%B8%B0
- https://rick-ford.tistory.com/entry/Nextjs-Nice-API-%EB%B3%B8%EC%9D%B8%EC%9D%B8%EC%A6%9D-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0
- https://binnari.tistory.com/27
- https://velog.io/@jamiep9rk/react-%EC%95%84%EC%9D%B4%ED%95%80-%EC%9D%B8%EC%A6%9D-%EC%95%84%EC%9D%B4%ED%8F%B0-%EC%97%90%EC%84%9C%EB%A7%8C-%EC%95%88%EB%90%A0%EB%95%8C-error-%EB%94%94%EB%B0%94%EC%9D%B4%EC%8A%A4-%ED%86%B5%EC%9D%BC%ED%95%B4%EC%A3%BC%EB%9D%BC
- https://nextjs.org/docs/app/getting-started/route-handlers#special-route-handlers
'문제 해결 (개발)' 카테고리의 다른 글
| Next.js 에서 NICE 본인인증 구현하기 (iOS, 카카오톡 인앱 브라우저 환경에서는 왜 안될까) (0) | 2025.11.18 |
|---|---|
| AWS 서버 비용 줄여 보자! (EC2) (1) | 2024.04.25 |