REST API와 Fetch api

fgStudy·2022년 3월 28일
3

자바스크립트

목록 보기
4/26
post-thumbnail

❶ fetch에 대해 알아보자!

✔ 소개

  • 정의
    • HTTP request 전송 기능을 제공하는 클라이언트 사이드 Web API
      • 클라이언트 → 서버 : request
      • 서버 → 클라이언트: response
    • 라이브러리인 axios와 달리 브라우저에 내장된 함수
    • 즉 1) 서버와의 통신을 통해 CRUD를 구현할 수 있게 하는, 2) 프라미스 지원 내장 함수
  • 사용법
    const promise = fetch(url [, options])
    • params

      • 1번째 인자: HTTP 요청을 전달할 url
      • 2번째 인자: 옵션 객체 (HTTP 요청 메서드, HTTP 요청 헤더, payload 등)
    • return

      HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체 반환

      • Response 객체:
        HTTP 응답 상태(status), HTTP 응답 헤더(headers), HTTP 응답 전문(body) 등을 읽어올 수 있다.
      • Ex: Code
        fetch("https://jsonplaceholder.typicode.com/posts/1")
          .then((response) => console.log(response))
        Result
        • Response.ok HTTP 응답 성공 여부를 나타내는 속성
          • true = 200~299 상태코드 (응답 성공)
          • false = not (응답 실패)
        • Response.status HTTP 상태코드 = 서버로부터 리퀘스트 결과를 전달 즉 클라이언트가 서버를 향해 리퀘스트를 보낼 때 서버에서 그 결과가 어떻게 되었는지 알려주는 역할을 한다.
          • 상태코드 클래스
            클래스설명
            1XXInformational리퀘스트를 받아들여 처리중
            2XXSuccess리퀘스트를 정상적으로 처리했음
            3XXRedirection리퀘스트를 완료하기 위해서 추가 동작 필요
            4XXClient Error서버는 리퀘스트 이해 불가능
            5XXServer Err서버는 리퀘스트 처리 실패
        • Response.redirected 3XX 리스폰스와 연결되며, 리퀘스트가 정상적으로 처리를 종료하기 위해 브라우저 측에서 특별한 처리를 수행해야 함을 나타냄
          • EX: 네이버 카페 일반회원이 “특정등급 회원” 게시판에 들어가려고 할 때 경고 페이지로 이동시키기
      • Response.prototype 메소드
        • Response.prototype.json Response 객체에서 HTTP 응답 몸체(response.body)를 취득하여 역직렬화
          • JSON 역직렬화: JSON.parse
            : JSON.parse 메서드는 JSON 포맷의 문자열을 객체로 변환한다.
            서버로부터 클라이언트에게 전송된 JSON 데이터는 문자열이다.
            ⇒ 객체로 사용하기 위해 JSON 포맷 문자열을 객체화! = “역직렬화”


            EX
            const todos = [
              {id: 1, content: 'HTML', completed: false},
              {id: 2, content: 'CSS', completed: true},
              {id: 3, content: 'JS', completed: false}
            ]
            
            // 배열 todos를 JSON 포맷의 문자열로 변환
            const json = JSON.stringify(todos);
            console.log(typeof(json), json);
            // string [{"id":1,"content":"HTML","completed":false},{"id":2,"content":"CSS","completed":true},{"id":3,"content":"JS","completed":false}]
            
            // JSON 포맷의 문자열을 배열로 변환한다.
            // 배열의 요소까지 객체로 변환된다.
            const parsed = JSON.parse(json);
            console.log(typeof parsed, parsed);
            /*
            object [
            	{id: 1, content: 'HTML', completed: false},
              {id: 2, content: 'CSS', completed: true},
              {id: 3, content: 'JS', completed: false}
            ]
            */
    • GET 요청 코드 수정: 역직렬화

      fetch("https://jsonplaceholder.typicode.com/posts/1")
        .then((response) => response.json())
        .then((json) => console.log(json))
      // {userId: 1, id: 1, title: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit', body: 'quia et suscipit\nsuscipit recusandae consequuntur …strum rerum est autem sunt rem eveniet architecto'}

❷ 통신 규칙 “REST API” !

✔ 등장배경

개발자들이 너~무 제멋대로 통신해서 다른 개발자들이 이해하기 어려워!
GET이 있길래 당연히 특정 데이터를 받아오는 건줄 알았는데, 데이터를 삭제하네?
우리 서로 알아먹을 수 있게끔 통신 규칙을 세워보자!

✔ 정의

  • HTTP의 통일성을 위해 만들어진 아키텍쳐
  • HTTP 프로토콜을 의도에 맞게 디자인하도록 유도하는 권고사항
  • REST API만으로도 HTTP 요청의 내용을 이해할 수 있다

✔ 구성

  • REST API의 3가지 요소
    • 자원(Resource)

    • 행위(Verb)

    • 표현(representations)

      구성요소내용표현 방법
      자원자원URI
      행위자원에 대한 행위HTTP 요청 메서드
      표현자원에 대한 행위의 구체적 내용payload

✔ 설계원칙

➀ URI는 리소스를 표현해야 한다.
  • 리소스를 표현하기 위해 명사 사용! 이름에 행위에 대한 표현(동사) 금지!
  • EX:
    // bad
    GET /getTodos/1
    GET /todos/show/1
    
    // good
    GET /todos/1

➁ 리소스에 대한 행위는 HTTP 요청 메소드로 표현한다.

  • HTTP 요청메소드
    • 정의: 클라이언트가 서버에게 request 종류와 목적(리소스에 대한 행위)를 알리는 방법

    • GET, POST, PUT, PATCH, DELETE

      HTTP 요청 메서드종류목적페이로드
      GETindex/retrieve모든/특정 리소스 취득X
      POSTcreate리소스 생성O
      PUTreplace리소스의 전체 교체O
      PATCHmodify리소스의 일부 수정O
      DELETEdelete모든/특정 리소스 삭제X
    • 모든 / 특정 리소스 ?

      • 모든: todos
      • 특정: todos/1
    • 리소스에 대한 행위는 HTTP 요청 메서드를 통해 표현하며 URI에 표현하지 않는다.

      • EX:

        // bad
        GET /todos/delete/1
        
        // good
        DELETE /todos/1

❸ Fetch api 실습

그럼 이제 fetch 함수를 통해 HTTP 요청을 전송해보자!
우리는 가상 REST API를 제공해주는 JSONPlaceholder 웹 사이트를 이용해서 실습을 할 것이다.

JSONPlaceholder

[1] GET 방식

GET 방식에서는 보낼 데이터가 없기 때문에, headers와 body 옵션이 필요가 없다.

// GET 요청
fetch("https://jsonplaceholder.typicode.com/posts/1")
  .then((response) => response.json())
  .then((data) => console.log(data));
// HTTP response.body 역직렬화
{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit↵suscipit recusandae consequuntur …strum rerum est autem sunt rem eveniet architecto"
}

[2] POST 방식

  • fetch(url, {method, headers, body})

    • method = HTTP 요청 메서드
    • headers = HTTP 헤더
      • “Content-Type”
        • 정의: HTTP 메시지에 담겨 보내는 데이터의 형식을 알려주는 헤더
        • EX:
          "Content-Type": "application/json" = JSON 형식으로 데이터를 보내줘
    • body = body안에 payload 작성
      • payload
        • 페이로드(payload)는 전송되는 데이터를 의미한다.
        • 데이터를 전송할 때, 헤더와 메타 데이터, 에러 체크 비트 등과 같은 다양한 요소들을 함께 보내어, 데이터 전송의 효율과 안정성을 높이게 된다.
        • 이 때, 보내고자 하는 데이터 자체를 의미하는 것이 바로 페이로드 그 이외의 데이터들은 전부 통신을 용이하게 해주는 부차적인 정보인 프로토콜 오버헤드
  • EX:

    response 데이터

    {
      "status" : "OK"
      "from": "localhost",
      "to": "https://hanamon.kr/users/1",
      "method": "GET",
      "data":{ "username" : "하나몬" }
    }

    이중 data가 payload로,
    클라이언트도 마찬가지로 서버에게 request할 때 body 안에 넣는 데이터 객체를 뜻한다.

  • status code: 201 created
    • POST가 성공적으로 이루어져 생성이 되었다는 의미이다.
    • 생성된 리소스는 response 메시지의 본문(body)에 동봉된다.

코드

fetch("https://jsonplaceholder.typicode.com/posts", {
	// method 옵션 POST 지정
  method: "POST",
	// JSON 포맷 (JSON으로 보낼거야~)
  headers: {
    "Content-Type": "application/json",
  },
	// body안에 payload 넣기
  body: JSON.stringify({
    title: "Test",
    body: "I am testing!",
    userId: 1,
  }),
})
  .then((response) => response.json())
  .then((data) => console.log(data));
{title: "Test", body: "I am testing!", userId: 1, id: 101}

async / await

async function run() {
    const res = await fetch(`https://jsonplaceholder.typicode.com/posts`, {
        method: 'POST',
        body: JSON.stringify({
          title: "HI",
          body: "NICE TO MEET YOU",
          userId: 1,
        }),
        headers: {
          'Content-type': 'application/json; charset=UTF-8',
        },
      }
    )
    const payload = await res.json();
    console.log(payload);
  }

[3] PATCH 방식

fetch("https://jsonplaceholder.typicode.com/posts/1", {
  method: "PATCH",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "프론트공부",
    body: "프론트를 사랑하는 프론트공부"
  }),
})
  .then((response) => response.json())
  .then((data) => console.log(data));
{userId: 1, id: 1, title: '프론트공부', body: '프론트를 사랑하는 프론트공부'}

[4] PUT 방식

fetch("https://jsonplaceholder.typicode.com/posts/1", {
  method: "PUT",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "Test",
    userId: 1,
  }),
})
  .then((response) => response.json())
  .then((data) => console.log(data));
{title: 'Test', userId: 1, id: 1}

[5] DELETE 방식

DELETE 방식에서는 보낼 데이터가 없기 때문에, headers와 body 옵션이 필요가 없다.

fetch("https://jsonplaceholder.typicode.com/posts/1", {
  method: "DELETE",
})
  .then((response) => response.json())
  .then((data) => console.log(data));

// {}

[+] request 객체를 만들어서 fetch하자!

매번 fetch 메소드를 작성하면 번거로우니, 객체로 저장해서 간편하게 써보자!

request 객체

const request = {
	get(url) {
  	return fetch(url);
  },
  post(url, payload) {
  	return fetch(url, {
    	method: 'POST',
      headers: { 'content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
  },
  patch(url, payload) {
  	return fetch(url, {
    	method: 'PATCH',
      headers: { 'content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
  },
  put(url, payload) {
  	return fetch(url, {
    	method: 'PUT',
      headers: { 'content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });
  },
  delete(url) {
  	return fetch(url, {method: 'DELETE'});
  }
};

POST 예시

request.post('https://jsonplaceholder.typicode.com/posts', {
    id: 1,
    userId:1,
    title: "프공",
    body: "프론트공부"
})
.then(res => res.json())
.then(data => console.log(data));

DELETE 예시

request.delete("https://jsonplaceholder.typicode.com/posts/1")
  .then((response) => response.json())
  .then((data) => console.log(data));

(ref)

profile
지식은 누가 origin인지 중요하지 않다.

1개의 댓글

comment-user-thumbnail
2023년 6월 27일

와 중간쯤 읽다가 이 글은 일단 잘 읽겠다고 선플박고 읽어야겠다는 마음에 선플박고 다시 읽으러갑니다. 진짜 fetch는 물론 fetch를 이해하는데 필요한 배경지식까지 너무 잘 작성해두셨네요. 진짜 goat
//
다읽고 댓글 다시 쓰는데 와 마지막부분에 request 객체 만들어서 fetch하는 부분 너무 잘 얻어갑니다 진짜진짜 감사합니다 최고최고

답글 달기