Cian 2024. 5. 29. 20:57

▶ 패치(Fetch)란 무엇일까

브라우저와 Node.js 환경에서 HTTP 요청을 보내기 위해 사용되는 현대적인 API이다. 이 함수는 비동기적으로 동작하며, Promise를 반환하여 비동기 처리를 쉽게 할 수 있게 해준다. fetch를 사용하여 데이터를 가져오거나 서버에 데이터를 보낼 수 있다. (※Promise란? JavaScript에서 비동기 작업을 처리하기 위한 객체다. Promise는 비동기 작업이 완료되면 결과 값을 제공하거나, 실패하면 오류를 제공할 것을 약속한다.)

 

예를들어, 본인이 어떤 웹사이트의 데이터를 요청하려면, fetch를 사용하여 그 웹사이트에 요청을 보낼 수 있다. 그럼 그 웹사이트는 요청을 받고, 당신에게 그에 대한 응답을 보내게 될텐데, 이 응답은 주로 데이터가 포함된 형태일 것이다. 이러한 데이터를 사용하여 웹사이트를 업데이트하거나 특정한 작업을 수행할 수 있다. 이 모든 과정이 비동기적으로 이루어지므로, 다른 작업을 하거나 대기하면서 결과를 기다릴 수 있다. 아래는 간단한 코드 예제이다.

fetch(url, options)
  .then(response => response.json())  // 받아온 데이터를 JSON 형식으로 변환
  .then(data => console.log(data))    // 변환된 데이터를 콘솔에 출력
  .catch(error => console.error('Error:', error));  // 에러가 발생한 경우 에러 처리

주요 매개변수는 url(요청을 보낼 URL), options(요청의 설정을 담은 객체. 여기에는 메서드, 헤더, 바디 등 다양한 설정이 포함된다.)

 

 

▶ 기본 예제

GET 요청: 아무런 추가 옵션 없이 기본 GET 요청을 보낼 수 있다.

fetch('https://api.example.com/data')
  .then(response => response.json()) // 응답을 JSON으로 파싱
  .then(data => console.log(data))   // 파싱된 데이터를 콘솔에 출력
  .catch(error => console.error('Error:', error));

 

POST 요청: 데이터를 서버에 보내려면 options 객체에 메서드와 바디를 설정한다.

fetch('https://api.example.com/data', {
  method: 'POST', // HTTP 메서드 설정
  headers: {
    'Content-Type': 'application/json' // 헤더 설정
  },
  body: JSON.stringify({              // 요청 바디 설정
    key1: 'value1',
    key2: 'value2'
  })
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

 

 

▶ 적용

GitHub OAuth 인증 과정에서 fetch 함수를 사용하여 GitHub API로 요청을 보내고 응답을 처리하는 방법을 사용하였다. 이 코드는 GitHub에서 액세스 토큰을 얻고, 그 토큰을 사용하여 사용자 정보를 가져오는 과정을 수행한다.

 

export const finishGithubLogin = async (req, res) => {
  const baseUrl = "https://github.com/login/oauth/access_token";

GitHub OAuth 액세스 토큰을 요청하는 URL을 생성

 

 const baseUrl = "https://github.com/login/oauth/access_token";
  const config = {
    client_id: process.env.GH_CLIENT,
    client_secret: process.env.GH_SECRET,
    code: req.query.code,
  };
  const params = new URLSearchParams(config).toString();
  const finalUrl = `${baseUrl}?${params}`;

요청에 필요한 데이터를 구성하고, baseUrl과 params를 결합하여 finalUrl을 생성

 

const tokenRequest = await (
    await fetch(finalUrl, {
      method: "POST",
      headers: {
        Accept: "application/json",
      },
    })
  ).json();

finalURL로 POST 요청을 보내고, 응답을 JSON으로 파싱하여 엑세스 토큰을 요청

 

 

  if ("access_token" in tokenRequest) {
    const { access_token } = tokenRequest;

토큰 요청의 응답에 "access_token"이 있는지 확인하고, 있다면 해당 토큰을 추출하여 access_token 변수에 할당

 

    const apiUrl = "https://api.github.com";
    const userData = await (
      await fetch(`${apiUrl}/user`, {
        headers: {
          Authorization: `token ${access_token}`,
        },
      })
    ).json();

사용자 정보를 가져오기 위해 GitHub API로 GET 요청을 보낸다.

 

   const emailData = await (
      await fetch(`${apiUrl}/user/emails`, {
        headers: {
          Authorization: `token ${access_token}`,
        },
      })
    ).json();

엑세스 토큰을 사용하여 GitHub API의 사용자 이메일 정보를 요청한다. primary와 verified가 모두 true가 아닌 경우는 보통 다음과 같다.

-보조 이메일: 사용자가 메인 이메일 주소 이외에 여러 이메일 주소를 등록할 수 있다. 이러한 보조 이메일 주소는 primary로 설정되어 있지 않을 수 있다.

-이메일 확인 필요: 사용자가 이메일을 추가했지만 아직 이메일 확인 단계를 거치지 않은 경우, verified가 false로 표시될 수 있다.

 

if (!email) {
      return res.redirect("/login");
} else {
    return res.redirect("/login");
  }

유효한 이메일이 없을 경우 "/login" 페이지로 리다이렉션하고, 토큰 요청의 응답에 "access_token"이 없는 경우 "/login" 페이지로 리다이렉션한다.