본문 바로가기

JavaScript/Next.js

[Next.js] API 통신 흐름 - API Routes, route.js, page.jsx (Promise, fetch, await)

✏️ 흐름

[Client]   ---->   [/api/test]   ---->   [Backend API]
 (page.jsx)         (route.js)           (실제 데이터 처리)
  • 클라이언트가 백엔드 API와 직접 통신하지 않도록 중간 서버(Next.js의 API Routes)를 두어 인증 및 데이터 요청을 처리하는 Next.js 애플리케이션 설계

 

📒 핵심 개념 요약

Next.js API Routes: 클라이언트와 백엔드 간의 중계 역할 수행
route.js: 클라이언트가 직접 백엔드와 통신하지 않고, Next.js 서버를 통해 데이터를 요청하도록 만듦
→ 이 방식을 통해 보안(인증 토큰 관리), API 통합 관리를 간소화할 수 있음
page.jsx: Next.js의 클라이언트 컴포넌트, UI 렌더링과 API 호출 로직을 포함

 


✏️ 전체 통신 구조

✅ 클라이언트에서 /api/test 로 요청

  • 브라우저(클라이언트)가 /api/test로 요청을 보냅니다.
  • 이 요청은 Next.js의 route.js로 전달됩니다.
  • 주요 흐름
    • useEffect로 데이터 요청
      • 페이지가 처음 렌더링될 때 실행됩니다.
      • 브라우저에서 /api/test로 fetch 요청을 보냅니다.
      • 이 요청은 Next.js의 API 라우트(route.js)로 전달됩니다.
    • fetch의 응답 처리
      • 서버에서 응답받은 데이터를 JSON으로 변환합니다.
      • 응답의 상태 코드에 따라 다음과 같이 처리합니다.
        • 400 이상: 서버에서 보낸 리다이렉트 URL을 통해 다른 페이지로 이동합니다.
        • 200: 데이터를 setRes를 통해 상태로 저장합니다.
    • 상태 관리와 렌더링
      • res 상태에 저장된 데이터가 변경될 때마다 로그를 출력합니다.
      • UI에서 두 버튼을 클릭하면 각각 AlertModal과 BottomDrawer 컴포넌트를 제어합니다.

 

✅ Next.js 서버에서 백엔드로 요청

  • route.js: 클라이언트 요청을 처리하며, 필요 시 백엔드 서버(process.env.SERVER_URL)로 데이터를 요청합니다.
  • 백엔드에서 인증된 데이터를 받아옵니다.
  • 주요 흐름
    • 사용자 인증 (auth 호출)
      • auth() 함수로 현재 세션 정보를 가져옵니다.
      • 인증 토큰 (accessToken)을 포함한 세션 정보를 획득합니다.
    • 백엔드 서버로 데이터 요청
      • 환경 변수 SERVER_URL을 기반으로 백엔드의 API 엔드포인트 (/v1/api/member/info)로 요청을 보냅니다.
      • 요청의 헤더에 인증 토큰을 추가하여 인증된 요청을 보냅니다.
    • 응답 처리 및 전달
      • 백엔드로부터 받은 응답 데이터를 JSON으로 변환합니다.
      • 응답 상태 코드에 따라 클라이언트로 전달할 내용을 결정합니다.
        • 400 이상: 클라이언트가 리다이렉트할 URL을 JSON 형태로 반환합니다.
        • 200: 백엔드에서 받은 데이터를 클라이언트로 그대로 전달합니다.

 

✅ 클라이언트로 응답 반환

  • 백엔드 응답에 따라 클라이언트가 필요한 데이터를 반환하거나, 리다이렉트 URL을 제공합니다.

✏️ 비동기 처리와 HTTP 요청

📒 Promise

미래에 완료될 작업을 나타냅니다.
비동기 함수는 Promise를 반환하고, 이 Promise가 나중에 완료되면 결과를 받을 수 있습니다.
상태 변화
- Pending (대기): Promise가 실행되는 동안.
- Fulfilled (이행): 비동기 작업이 성공적으로 끝난 경우.
- Rejected (거부): 비동기 작업이 실패한 경우.

 

✅ 정리

  • fetch: HTTP 요청을 보내고 응답을 받는 기본 함수. Promise를 반환합니다.
  • await: 비동기 작업의 완료를 기다려, 동기적인 코드처럼 작성할 수 있게 해줍니다.
  • 결합: await fetch를 사용하면 네트워크 요청과 응답 처리를 효율적으로 작성할 수 있습니다.

💻 fetch

: JavaScript의 내장 함수로, 브라우저에서 HTTP 요청을 보내고 응답을 처리하는 데 사용됩니다.

 

기본 구조

fetch(url, options)
  .then(response => {
    // 응답 처리
  })
  .catch(error => {
    // 에러 처리
  });

 

주요 특징

  1. HTTP 요청: REST API와 같은 엔드포인트로 요청을 보낼 때 사용됩니다. (GET, POST, PUT, DELETE 등)
  2. Promise 반환: fetch는 요청에 대한 Promise 객체를 반환합니다. 이를 통해 비동기적으로 응답을 처리할 수 있습니다.
  3. 옵션 지정 가능: 헤더, 본문 데이터, 요청 메서드 등 다양한 요청 설정이 가능합니다.

 

예제

fetch("<https://api.example.com/data>", {
  method: "GET", // HTTP 메서드 (기본값: GET)
  headers: {
    "Content-Type": "application/json", // JSON 데이터 요청
  },
})
  .then(response => response.json()) // 응답을 JSON으로 변환
  .then(data => console.log(data))  // 변환된 데이터 출력
  .catch(error => console.error("Error:", error)); // 에러 처리

 

💻 await

: JavaScript에서 비동기 작업의 결과를 기다릴 때 사용하는 키워드입니다. 이는 주로 async 함수 내부에서 사용됩니다.

 

주요 특징

  1. Promise의 결과를 기다림: await는 비동기 작업이 완료될 때까지 코드 실행을 일시적으로 멈춥니다.
  2. 코드 가독성 향상: 기존 Promise의 .then() 체인을 대체하여 동기적인 코드처럼 읽히게 만듭니다.

 

예제

async function fetchData() {
  try {
    const response = await fetch("<https://api.example.com/data>"); // fetch 호출
    const data = await response.json(); // 응답 데이터 처리
    console.log(data); // 데이터 출력
  } catch (error) {
    console.error("Error:", error); // 에러 처리
  }
}

fetchData();

 

💻 fetch와 await 결합

: fetch와 await를 함께 사용하면, 비동기 작업을 더 직관적이고 간결하게 처리할 수 있습니다.

 

fetch + await의 흐름

  1. HTTP 요청: fetch로 서버에 요청을 보냅니다.
  2. 응답 대기: await를 사용해 요청이 완료될 때까지 기다립니다.
  3. 응답 처리: 응답 데이터를 JSON으로 변환하거나, 상태 코드를 확인합니다.

 

예제: GET 요청

async function getData() {
  try {
    const response = await fetch("<https://api.example.com/data>");
    if (!response.ok) { // 응답 상태 확인 (200~299 범위가 아니면 에러)
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json(); // JSON 데이터 변환
    console.log(data); // 데이터 출력
  } catch (error) {
    console.error("Error:", error); // 에러 처리
  }
}

getData();

 

✅ 주의사항

  • fetch - 기본적으로 실패 처리 없음
    : 네트워크 에러가 아니라면 fetch는 상태 코드(예: 404, 500)를 자동으로 에러로 간주하지 않습니다. 상태 코드를 수동으로 확인해야 합니다.
if (!response.ok) {
  throw new Error(`HTTP error! status: ${response.status}`);
}
  • 기본 HTTP 메서드는 GET
    : POST, PUT 등을 사용하려면 명시적으로 method를 지정해야 합니다.
  • 옵션 추가로 헤더 설정 가능
    : headers를 사용해 요청의 헤더를 커스터마이징할 수 있습니다.
반응형