Middleware
next.js 서버로 요청이 전달되기 전에 코드를 실행할 수 있는 기능을 제공
들어오는 요청을 기반으로 응답을 재작성, 리다이렉트, 요청 또는 응답 헤더 수정, 혹은 직접 응답할 수 있다
생성
src 폴더에 middleware.ts 파일 생성
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
console.log(request);
}
export const config = {
matcher: '/',
};
- middleware(): 실제로 기능을 실행시켜줄 함수
- config: 어떤 페이지에서 해당 기능을 사용할 것인지 matcher를 설정할 수 있음
- 위 예시는 '/' 경로에 접속할 때마다 requst를 출력한다
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/home', request.url));
}
export const config = {
matcher: '/',
};
'/'에 접속시 '/home'으로 redirect 한다 (url까지 '/home'으로 변경)
rewrite 옵션도 있는데, 이 경우 url 자체는 '/'로 유지되지만 실제로는 '/home'의 컴포넌트가 출력된다
matcher의 옵션들
1) *
'/about/:path*' 와 같이 사용하는 경우 '/about/:path' 아래 모든 경로들에 적용된다
2) [ ]
다수의 matcher를 지정하고 싶은 경우 배열을 사용할 수 있다
matcher: ['/', 'dashboard/:path*']
3) 정규식 사용
matcher: "/((?!api|_next/static|_next/image|favicon.ico).*)"
와 같이 경로에 대해 원하는 조건을 정규식으로 표현할 수도 있다
middleware()에서 검증하기
export async function middleware(request: NextRequest) {
const isLogin = false;
if(!isLogin && request.nextUrl.pathname.includes('/cart') {
// 원하는 처리
}
}
위와 같이 middleware 함수에서도 matcher에 맞아 들어온 요청을 조건문 등으로 검증할 수도 있다
Authentication
json-sever-auth 설치
json-server와 유사한데, auth 기능이 있는 라이브러리다
yarn add -D json-server-auth
// package.json
"scripts": {
"auth": "json-server-auth --watch auth-db.json --port 8000"
}
auth-db.json 생성
루트 디렉토리에 파일을 생성한다
{
"users": [
{
"email": "user@example.com",
"password": "$2a$10$eHUzzsY1tbOmyGVqPwVEsuYRQb4LP2Hw/dMXgxp5p8eYE4UgcZMA.",
"id": 1
}
]
}
api 검증
// app/api/sign-in/route.ts
import { NextResponse } from 'next/server';
export async funtcion POST(request: Request){
const payload = await response.json(); // request body에 넣어둔 payload를 받을 수 있다
return NextResponse.json({
data: true,
});
}
로그인 api 요청을 하는 페이지에서 바로 api url이 아니라 위에 만들어둔 내부 서버에 요청하도록 수정한다
// src/.../SignInForm.tsx
const onSubmit = async(value: FieldValues) => {
const res = await fetch('/api/sign-in', {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
...value,
}),
}
}
원래 localhost:8000 (json-server-auth 서버 주소)로 보내려던 걸 '/api/sign-in' 으로 보내줬으니,
이제 '/api/sign-in'에서 json-server-auth 서버로 보내도록 설정해줘야한다!
// app/api/sign-in/route.ts
import { NextResponse } from 'next/server';
export async funtcion POST(request: Request){
const payload = await response.json(); // request body에 넣어둔 payload를 받을 수 있다
const res = await fetch("http://localhost:8000/sign-in", {
method: "POST",
headers: {
"content-Type": "application/json",
},
cache: "no-store",
body: JSON.stringify({
...payload,
})
});
const data = await res.json();
const cookieStore = cookies();
cookieStore.set("accessToken", data.accessToken, {
httpOnly: true, // 브라우저 쿠키에서는 accessToken에 접근할 수 없고, 서버 환경에서만 접근 가능해짐
});
return NextResponse.json({
data: true,
});
}
그럼 인증된 사용자인지 확인할 때 이 cookie에 저장된 값을 사용할 수 있을 것이다! (middleware)
export async function middleware(request: NextRequest) {
const isLogin = !!request.cookies.get("accessToken")?.value;
if(!isLogin && request.nextUrl.pathname.includes('/cart')) {
return NextResponse.redirect(new URL('/sign-in', request.url));
}
}
'Next.js' 카테고리의 다른 글
[Next.js] 개인과제 트러블슈팅 (동적 라우팅 경로, 클라이언트 컴포넌트 환경변수, Module not found) (0) | 2024.10.07 |
---|---|
[Next.js/Tanstack-Query] Next에서 prefetch하기 (1) | 2024.10.01 |
[Next.js] Parallel Routes & Intercepting Routes (1) | 2024.09.29 |
[Next.js] Caching (1) | 2024.09.28 |
[Next.js] Router Handler & Server Action (0) | 2024.09.27 |