Next.js API 라우트에서 다양한 HTTP 메서드를 처리하는 방법을 알아보겠습니다.
각 메서드별 처리 로직, 요청 검증, 그리고 적절한 응답 구조화에 중점을 두고 설명하겠습니다.
HTTP 메서드별 처리 로직
Next.js에서는 각 HTTP 메서드에 대해 별도의 함수를 export하여 처리할 수 있습니다.
// app/api/users/route.js
export async function GET ( request ) {
// GET 요청 처리 로직
}
export async function POST ( request ) {
// POST 요청 처리 로직
}
export async function PUT ( request ) {
// PUT 요청 처리 로직
}
export async function DELETE ( request ) {
// DELETE 요청 처리 로직
}
Copy
요청 본문 및 쿼리 파라미터 처리
POST 및 PUT 요청의 본문 처리
export async function POST ( request ) {
const body = await request . json ()
// body를 사용한 로직
}
Copy
쿼리 파라미터 처리
export async function GET ( request ) {
const { searchParams } = new URL ( request . url )
const query = searchParams . get ( 'query' )
// query를 사용한 로직
}
Copy
상태 코드와 응답 반환
적절한 HTTP 상태 코드와 함께 응답을 반환하는 것이 중요합니다.
export async function POST ( request ) {
try {
const body = await request . json ()
// 데이터 처리 로직
return new Response ( JSON . stringify ({ message: 'Created successfully' }), {
status: 201 ,
headers: { 'Content-Type' : 'application/json' }
})
} catch ( error ) {
return new Response ( JSON . stringify ({ error: 'Invalid request' }), {
status: 400 ,
headers: { 'Content-Type' : 'application/json' }
})
}
}
Copy
요청 검증
요청을 처리하기 전에 유효성을 검사하는 것이 중요합니다.
export async function PUT ( request ) {
const body = await request . json ()
if (! body . id || ! body . name ) {
return new Response ( JSON . stringify ({ error: 'Missing required fields' }), {
status: 400 ,
headers: { 'Content-Type' : 'application/json' }
})
}
// 유효한 요청 처리 로직
}
Copy
8장 폼 제출 및 데이터 처리와의 연관성
11장의 HTTP 메서드 처리는 8장에서 다룬 폼 제출 및 데이터 처리와 밀접하게 연관됩니다. 클라이언트에서 폼을 제출할 때, 해당 데이터는 일반적으로 POST 또는 PUT 요청으로 API 라우트에 전송됩니다. API 라우트에서는 이 데이터를 받아 처리하고, 적절한 응답을 반환합니다.
예를 들어, 8장에서 구현한 폼 제출 로직이 다음과 같다면
const handleSubmit = async ( event ) => {
event . preventDefault ()
const formData = new FormData ( event . target )
const response = await fetch ( '/api/users' , {
method: 'POST' ,
body: JSON . stringify ( Object . fromEntries ( formData )),
headers: {
'Content-Type' : 'application/json' ,
},
})
const data = await response . json ()
// 응답 처리
}
Copy
API 라우트에서는 이 요청을 다음과 같이 처리할 수 있습니다.
export async function POST ( request ) {
const body = await request . json ()
// 데이터베이스에 사용자 추가 로직
return new Response ( JSON . stringify ({ message: 'User created successfully' }), {
status: 201 ,
headers: { 'Content-Type' : 'application/json' }
})
}
Copy
실습 : 사용자 정보를 관리하는 완전한 CRUD API 구현
사용자 정보를 관리하는 완전한 CRUD(Create, Read, Update, Delete) API를 구현해보겠습니다.
// app/api/users/route.js
let users = [
{ id: 1 , name: 'John Doe' , email: '[email protected] ' },
{ id: 2 , name: 'Jane Doe' , email: '[email protected] ' },
]
export async function GET ( request ) {
const { searchParams } = new URL ( request . url )
const id = searchParams . get ( 'id' )
if ( id ) {
const user = users . find ( u => u . id === parseInt ( id ))
if ( user ) {
return new Response ( JSON . stringify ( user ), {
status: 200 ,
headers: { 'Content-Type' : 'application/json' }
})
} else {
return new Response ( JSON . stringify ({ error: 'User not found' }), {
status: 404 ,
headers: { 'Content-Type' : 'application/json' }
})
}
}
return new Response ( JSON . stringify ( users ), {
status: 200 ,
headers: { 'Content-Type' : 'application/json' }
})
}
export async function POST ( request ) {
const body = await request . json ()
if (! body . name || ! body . email ) {
return new Response ( JSON . stringify ({ error: 'Name and email are required' }), {
status: 400 ,
headers: { 'Content-Type' : 'application/json' }
})
}
const newUser = {
id: users . length + 1 ,
name: body . name ,
email: body . email
}
users . push ( newUser )
return new Response ( JSON . stringify ( newUser ), {
status: 201 ,
headers: { 'Content-Type' : 'application/json' }
})
}
export async function PUT ( request ) {
const body = await request . json ()
if (! body . id || ! body . name || ! body . email ) {
return new Response ( JSON . stringify ({ error: 'Id, name, and email are required' }), {
status: 400 ,
headers: { 'Content-Type' : 'application/json' }
})
}
const index = users . findIndex ( u => u . id === body . id )
if ( index === - 1 ) {
return new Response ( JSON . stringify ({ error: 'User not found' }), {
status: 404 ,
headers: { 'Content-Type' : 'application/json' }
})
}
users [ index ] = { ... users [ index ], ... body }
return new Response ( JSON . stringify ( users [ index ]), {
status: 200 ,
headers: { 'Content-Type' : 'application/json' }
})
}
export async function DELETE ( request ) {
const { searchParams } = new URL ( request . url )
const id = searchParams . get ( 'id' )
if (! id ) {
return new Response ( JSON . stringify ({ error: 'Id is required' }), {
status: 400 ,
headers: { 'Content-Type' : 'application/json' }
})
}
const index = users . findIndex ( u => u . id === parseInt ( id ))
if ( index === - 1 ) {
return new Response ( JSON . stringify ({ error: 'User not found' }), {
status: 404 ,
headers: { 'Content-Type' : 'application/json' }
})
}
const deletedUser = users . splice ( index , 1 )[ 0 ]
return new Response ( JSON . stringify ( deletedUser ), {
status: 200 ,
headers: { 'Content-Type' : 'application/json' }
})
}
Copy
이 실습에서는 메모리 내 배열을 사용하여 사용자 데이터를 관리합니다. 실제 애플리케이션에서는 데이터베이스를 사용해야 합니다. 각 HTTP 메서드에 대해 적절한 처리 로직을 구현하고, 요청 검증과 에러 처리를 포함하고 있습니다.
이러한 API 라우트 구현을 통해 클라이언트 측 애플리케이션에서 사용자 데이터를 효과적으로 관리할 수 있습니다. Next.js의 API 라우트 기능을 활용하면 서버리스 함수로 동작하는 강력한 백엔드 API를 쉽게 구축할 수 있습니다.