본문 바로가기
JavaScript

[TIL] REST API와 데이터 가져오기

by 어느새벽 2024. 9. 9.

REST API는 클라이언트(웹 애플리케이션)와 서버 간의 통신을 가능하게 하는 규칙과 구조를 제공하는 방법이다.

REST는 Representational State Transfer의 약자로,

웹 애플리케이션이 서버에서 데이터를 가져오거나 서버에 데이터를 전송할 때 사용하는 일련의 원칙이다.

쉽게 말해, REST API는 웹 애플리케이션이 서버와 데이터를 주고받기 위해 사용하는 일종의 "규칙서"라고 할 수 있다.

이 규칙에 따라 웹 애플리케이션은 서버와 소통하면서 필요한 데이터를 가져오거나 업데이트할 수 있다.


REST API의 핵심 개념

  1. HTTP 메서드: REST API는 주로 HTTP 메서드를 사용한다.
    GET : 서버에서 데이터를 가져올 때 
    POST : 서버에 새로운 데이터를 보낼 때
    PUT : 서버의 기존 데이터를 업데이트 할 때
    DELETE : 서버에서 데이터를 삭제할 때
  2. 엔드포인트(Endpoint): 서버에서 제공하는 특정 URL이다. 예를 들어, /users 엔드포인트는 사용자와 관련된 데이터에 접근할 수 있는 경로를 의미한다.
  3. 리소스(Resource): API에서 다루는 대상입니다. REST API는 각 리소스에 고유한 URL을 부여하여 데이터를 주고받을 수 있게 한다. 예를 들어, 특정 사용자의 정보는 /users/123와 같이 접근할 수 있다.
  4. 상태와 요청/응답: REST는 요청(request)과 응답(response)을 통해 통신한다. 클라이언트는 서버에 요청을 보내고, 서버는 이에 대한 응답을 반환한다. 응답에는 상태 코드(예: 200 OK, 404 Not Found)와 함께 필요한 데이터가 포함된다.

구현 예시

API 주소 작성

// 학생 리스트
https://www.주소.com/students

// 학생 중 12번 학생
https://www.주소.com/students/12

// 2반의 학생들 리스트
https://www.주소.com/classes/2/students

// 2반에서 12번 학생
https://www.주소.com/classes/2/students/12

// 스포츠 뉴스 중 축구 
https://www.주소.com/news/sports/soccer

// 영화에서 인기 있는 영화
https://www.주소.com/movies/popular

// 띄어쓰기가 필요하면 하이픈(-) 사용
http://www.cgv.co.kr/movies/detail-view/?midx=87045

 

* 밑줄(_)은 사용하지 않는다.

* 대문자를 사용하지 않는다.

* 동사는 사용하지 않지만 회사마다 다를 수 있음.

메서드 작성 방식

1) GET : 데이터 조회
필터링, 정렬 시 주로 물음표(?) 다음에 작성함

METHOD: GET
https://블로그주소.com/posts // (블로그) 게시물 리스트 정보 좀 줘

METHOD: GET
https://www.주소.com/movies?genre=action // 영화 리스트 정보 좀 줘 & 장르는 액션만!

METHOD: GET
https://www.주소.com/students/12 // id가 12번 블로그 정보 좀 줘

 

2) POST : 데이터 추가

로그인할 때 POST 사용

METHOD: POST
https://블로그주소.com/posts // 블로그 게시물 추가하자.

body: {
	id: 123,
	title: "오늘의 맛집"
	contents: "~~~~~",
	...
}

 

3) PUT : 데이터 수정 (특정 데이터 전체를 수정할 때)

METHOD: PUT
https://블로그주소.com/posts/123 // id가 123인 블로그 게시물을 수정하자.

body: {
	id: 123,
	title: "오늘의 최고 맛집"
	contents: "~~~~~!!",
	...
}

 

4) PATCH : 데이터를 수정 (특정 데이터의 일부만 수정할 때)

METHOD: PATCH
https://블로그주소.com/posts/123 // id가 123인 블로그 게시물의 일부 데이터를 수정하자.

body: {
	title: "오늘의 최고 맛집" // 제목만 바꿈
}

 

5) DELETE : 데이터 삭제

METHOD: DELETE
https://블로그주소.com/posts/123 // id가 123인 블로그 게시물을 삭제하자

 

실제처럼 데이터 가져오기

* 연습용으로 많이 쓰이는 API: https://jsonplaceholder.typicode.com/ 

 

JSONPlaceholder - Free Fake REST API

{JSON} Placeholder Free fake and reliable API for testing and prototyping. Powered by JSON Server + LowDB. Serving ~3 billion requests each month.

jsonplaceholder.typicode.com

 

1) 학생 리스트 정보 조회

// Promise 코드

fetch("<주소>/students")
	.then((res) => res.json())
	.then((result) => console.log(result))
	.catch((error) => console.error('Error:', error));
    
-------------------------------------------------------
// async await 코드

async function fetchAllStudents() {
  const response = await fetch("<주소>/students");
  const result = await response.json();
  console.log(result);
}

fetchAllStudents()

-------------------------------------------------------
//try catch 추가

async function fetchAllStudents() {
  try {
    const response = await fetch("<주소>/students");
    const result = await response.json();
    console.log(result);
  } catch (error) {
    console.error('Error:', error);
  }
}

fetchAllStudents()

 

  • 특정 학생의 정보를 조회하려면 "<주소>/students/{id}"처럼 추가하면 됨.
  • json()을 넣어야 자바스크립트에서 사용할 수 있게끔 형식이 변환된다.
  • result가 바로 우리가 사용할 수 있는 data 값이므로 console.log 대신 데이터 사용할 로직을 작성하면 된다.

 

2) 학생 정보 추가

// Promise 코드

fetch('<주소>/students', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json; charset=UTF-8'
  },
  body: JSON.stringify({
    id: "2",
    name: "soo",
    major: "Trade"
  })
})
.then(response => response.json())
.then(data => console.log(data))
.catch((error) => console.error('Error:', error));

------------------------------------------------------
// async await 코드

async function addStudent() {
  const response = await fetch('<주소>/students', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json; charset=UTF-8'
    },
    body: JSON.stringify({
      id: "2",
      name: "soo",
      major: "Trade"
    })
  });
  const data = await response.json();
  console.log(data);
}

addStudent()

------------------------------------------------------
// try catch 추가

async function addStudent() {
  try {
    const response = await fetch('<주소>/students', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json; charset=UTF-8'
      },
      body: JSON.stringify({
        id: "2",
        name: "soo",
        major: "Trade"
      })
    });
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  }
}

addStudent()

 

3) 학생 정보 수정

// Promise 코드

// PUT 메소드를 사용하여 학생 정보 업데이트
fetch('<주소>/students/2', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json; charset=UTF-8'
  },
  body: JSON.stringify({
    name: 'soooooo'
  })
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch((error) => console.error('Error:', error));

--------------------------------------------------------
// async await 

async function updateStudent() {
  const response = await fetch('http://localhost:3000/students/2', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json; charset=UTF-8'
    },
    body: JSON.stringify({
      name: 'soooooo'
    })
  });
  const data = await response.json();
  console.log('Success:', data);
}

updateStudent()

---------------------------------------------------------
// try catch

async function updateStudent() {
  try {
    const response = await fetch('<주소>/students/2', {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json; charset=UTF-8'
      },
      body: JSON.stringify({
        name: 'soooooo'
      })
    });
    const data = await response.json();
    console.log('Success:', data);
  } catch (error) {
    console.error('Error:', error);
  }
}

updateStudent()

 

4) 학생 정보 삭제

// Promise 코드

// DELETE 메소드를 사용하여 학생 정보 삭제
fetch('<주소>/students/2', {
  method: 'DELETE'
})
.then(response => response.json())
.then(data => console.log('Deleted Successfully:', data))
.catch((error) => console.error('Error:', error));

------------------------------------------------------------
// async await 코드

async function deleteStudent() {
  const response = await fetch('<주소>/students/2', {
    method: 'DELETE'
  });
  const data = await response.json();
  console.log('Deleted Successfully:', data);
}

deleteStudent() 

------------------------------------------------------------
// try catch

async function deleteStudent() {
  try {
    const response = await fetch('<주소>/students/2', {
      method: 'DELETE'
    });
    const data = await response.json();
    console.log('Deleted Successfully:', data);
  } catch (error) {
    console.error('Error:', error);
  }
}

deleteStudent()

REST API 호출 시 발생할 수 있는 오류를 처리하는 방법

1. 오류 처리 기본 원칙

  • 에러 핸들링 함수 사용: 모든 API 호출은 try-catch 블록이나 then().catch()를 사용하여 오류를 처리해야 한다.
  • 상태 코드 확인: API 호출의 응답에서 상태 코드를 확인하여 성공(200대 코드) 또는 실패(400대, 500대 코드)를 구분하고 적절하게 대응한다.

2. 일반적인 오류와 처리 방법

  1. 클라이언트 오류 (400번대)
    • 400 Bad Request: 요청이 잘못된 경우이다. 예를 들어, 필수 파라미터가 누락되었을 때 발생할 수 있다.
      • 처리 방법: 사용자에게 입력이 잘못되었음을 알리고, 올바른 형식으로 다시 시도하도록 안내한다.
    • 401 Unauthorized: 인증이 필요한 요청이 인증되지 않은 상태에서 시도된 경우이다.
      • 처리 방법: 로그인 페이지로 리디렉션하거나, 인증 정보를 다시 입력하도록 유도한다.
    • 403 Forbidden: 사용자가 요청할 권한이 없는 리소스를 요청한 경우이다.
      • 처리 방법: 권한이 없음을 사용자에게 알리고, 필요한 권한을 얻을 수 있는 방법을 안내한다.
    • 404 Not Found: 요청한 리소스를 찾을 수 없는 경우이다.
      • 처리 방법: 사용자에게 해당 리소스가 없음을 알리고, 대체 경로를 안내하거나 재시도할 수 있도록 한다.
  2. 서버 오류 (500번대)
    • 500 Internal Server Error: 서버에서 알 수 없는 오류가 발생한 경우이다.
      • 처리 방법: 사용자에게 문제가 발생했음을 알리고, 나중에 다시 시도하도록 안내한다. 백엔드 팀에 문제를 보고할 수도 있다.
    • 502 Bad Gateway / 503 Service Unavailable / 504 Gateway Timeout: 서버가 현재 요청을 처리할 수 없거나 다른 서버의 응답이 지연되는 경우이다.
      • 처리 방법: 사용자에게 서버가 불안정함을 알리고, 잠시 후 다시 시도하도록 안내한다.
  3. 네트워크 오류
    • Timeout: 요청 시간이 초과된 경우이다.
      • 처리 방법: 네트워크 상태를 확인하거나, 나중에 다시 시도하도록 사용자에게 알린다.
    • Network Error: 인터넷 연결이 끊어졌거나 서버에 접근할 수 없는 경우이다.
      • 처리 방법: 인터넷 연결 상태를 확인하고, 연결이 복구되면 다시 시도할 수 있도록 안내한다.

3. 구현 예시

async function fetchData(url) {
    try {
        const response = await fetch(url);
        if (!response.ok) {
            // HTTP 상태 코드에 따른 오류 처리
            switch (response.status) {
                case 400:
                    alert('잘못된 요청입니다. 입력값을 확인해주세요.');
                    break;
                case 401:
                    alert('인증이 필요합니다. 로그인 해주세요.');
                    // 로그인 페이지로 리디렉션
                    break;
                case 403:
                    alert('권한이 없습니다.');
                    break;
                case 404:
                    alert('요청한 리소스를 찾을 수 없습니다.');
                    break;
                case 500:
                    alert('서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요.');
                    break;
                default:
                    alert('알 수 없는 오류가 발생했습니다.');
            }
        } else {
            const data = await response.json();
            // 데이터 처리
        }
    } catch (error) {
        // 네트워크 오류 처리
        console.error('Network error:', error);
        alert('네트워크 오류가 발생했습니다. 인터넷 연결을 확인해주세요.');
    }
}