icon안동민 개발노트

HTTP 메서드 처리


 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 요청 처리 로직
}

요청 본문 및 쿼리 파라미터 처리

 POST 및 PUT 요청의 본문 처리

export async function POST(request) {
  const body = await request.json()
  // body를 사용한 로직
}

 쿼리 파라미터 처리

export async function GET(request) {
  const { searchParams } = new URL(request.url)
  const query = searchParams.get('query')
  // query를 사용한 로직
}

상태 코드와 응답 반환

 적절한 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' }
    })
  }
}

요청 검증

 요청을 처리하기 전에 유효성을 검사하는 것이 중요합니다.

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' }
    })
  }
 
  // 유효한 요청 처리 로직
}

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()
  // 응답 처리
}

 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' }
  })
}

실습 : 완전한 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' }
  })
}

 이 실습에서는 메모리 내 배열을 사용하여 사용자 데이터를 관리합니다.

 실제 애플리케이션에서는 데이터베이스를 사용해야 합니다.

 각 HTTP 메서드에 대해 적절한 처리 로직을 구현하고, 요청 검증과 에러 처리를 포함하고 있습니다.

 이러한 API 라우트 구현을 통해 클라이언트 측 애플리케이션에서 사용자 데이터를 효과적으로 관리할 수 있습니다.

 Next.js의 API 라우트 기능을 활용하면 서버리스 함수로 동작하는 강력한 백엔드 API를 쉽게 구축할 수 있습니다.