[JS] API, 유틸화

오리·2024년 3월 14일
post-thumbnail

API, 백엔드와 연관이 많은 개념이다. 오늘 건 콜백 지옥때문에 어려운 부분이 있었다. 그리고 자바에도 있긴 했지만, 자바와는 조금 다른 개념이였어서 생소해서 그런지 쉽지 않았다. 코드와 개념을 차근차근 정리해보자!

1. API

Application Programming Interface

  • 애플리케이션이나 디바이스가 서로 간에 연결하여 통신할 수 있는 방법을 정의하는 규칙 세트
  • 프론트엔드에서 백엔드로 데이터를 요청(request), 백엔드에서 프론트엔드로 응답(response)

1) REST API

  • HTTP 프로토콜을 통해 api를 설계하기 위한 아키텍처 스타일
  • 서버에서 직접 웹 애플리케이션이나 사이트의 사용자에게 데이터를 제공해야하는 모든 곳에서 사용

REST

  • GET (Read - 검색,읽기)
    - 뉴스 기사 제목/내용 등을 가져오기

JSONPlaceholder API

  • json 형태의 mock data(더미 데이터)를 주는 오픈 api
// JSONPlaceholder API 사용해 가짜 데이터로 CRUD 작업 하기
주는 open API
// get 요청
// 특정 게시물을 가져오는 함수
const getPost = () => {
  fetch("https://jsonplaceholder.typicode.com/posts/1")
    .then((res) => res.json())
    .then((data) => {
      console.log(data);
    });
};

  • POST (Create - 생성)
    - 댓글,게시글 등록
// post 요청
// 새로운 게시물 생성하는 함수
// fetch가 Jsonapi와 통신해서 json형태로 데이터를 가져오기 때문에, js->json 필요
const postPost = () => {
  fetch("https://jsonplaceholder.typicode.com/posts", {
    method: "POST",
    // js -> Json
    body: JSON.stringify({
      Title: "제목제목제목",
      body: "게시물 내용 내용 내용",
      userId: 1,
    }),
    headers: {
      "Content-type": "application/json; charset=UTF-8",
    },
  })
    .then((response) => response.json())
    .then((data) =>
      // 브라우저에 렌더링 등 응답으로 받은 데이터를 사용
      console.log(data)
    )
    .catch((err) => {
      // 에러 발생 시 원하는 에러 처리
      console.log("err : ", err);
    });
};

  • PUT (Update - 모두수정)
    - 원래 있는 글 {title:"", content:""} 모두 수정
  • PATCH (Update - 부분수정)
    - 원래 있는 글 {title:""} 하나만 PATCH 날려도 전체 수정됨
  • DELETE (Delete - 삭제)
// delete 요청
const deletePost = () => {
  fetch("https://jsonplaceholder.typicode.com/posts/1", {
    method: "DELETE",
  })
    .then((response) => response.json())
    .then((data) => console.log("Delete!"))
    .catch((err) => console.log("err : ", err));
};

2. 동기 vs 비동기

1) 동기와 비동기

  • 동기(synchronous) : 어떤 코드가 있을 때 순서대로 진행
  • 비동기(asynchronous) : 순서대로 X! 먼저 읽힌 코드가 실행
  • 비동기 코드 예시
    - setTimeout( ( )=>{}, 밀리초 )
    - 자바스크립트에서 비동기처리를 할 수 있는 메소드
    - 설정한 시간초 이후에 첫번째 인자 내부의 동작이 실행됨
    - 해당 시간동안 코드가 실행을 멈추는 것이 아니라,setTimeout자체는 실행되고 있다. 다만 특정 시간을 기다렸다 실행되는 것일 뿐이다.

2) 비동기코드를 동기적으로 처리하기

콜백함수

  • 인자로 들어가는 함수

promise resolve

  • ES6에서 추가된 JS문법
  • new Promise 만들어서 사용
    - new Promise가 만들어질 때, excutor(실행함수)가 자동으로 실행
    - Promise가 생성되면 작업을 실행하고, 작업의 완료여부를 excutor의 매개변수를 통해 전달
// promise를 사용해 비동기 처리를 구현하는 예시
const id2 = "layla";
let userId2;

// todo new promise 만들기 
const promise = new Promise((resolve, reject) => {
  console.log("Promise 시작");

setTimeout(() => {
userId2 = "layla01"; // 서버에서 아이디 받아옴

if (userId2 === id2) {
	resolve(userId2); // 성공하면 userId2값 전달
} else {
	reject(new Error("서버에서 사용자의 아이디를 받아오는 것을 실패함"));
		}
	}, 2000);
});

// 성공하면 then부분 코드실행 (resolve)
   .then((data) => {
    console.log(`userId는 ${data}입니다.`);
   })
//   실패하면 catch 실행 (reject)
   .catch((error) => {
    console.log(error);
  })
//   마지막 무조건적으로 실행
   .finally(() => {
    console.log("Promise 종료");
   });
  • resolve가 실행되면 .then으로 받아서 처리하고, .catch가 reject의 결과를 받아서 처리한다.
  • .finally는 resolve,reject와 관계없이 무조건 실행된다.

async await

  • Promise도 체이닝 하다보면 가독성이 떨어지므로 async, await이 나오게 됨.
  • 기능이 추가된 것이 아닌, 직관적인 코드를 위해 만들어졌다.
  • async : await 사용할 것을 알린다.
  • await : 해당 함수가 실행될 때 까지 기다리게 한다.
  • try/catch : try 스코프를 실행했을때, 에러 발생하면 catch절로 이동하고 finally는 무조건 실행한다.
const id = "layla01"; // 성공
//  const id = "layla"; // 실패
let userId;

//  Promise를 함수에 담아 해당 함수 호출 시 Promise가 실행되도록 작성
const promiseFunc = () => {
	return new Promise((res, rej) => {
	    console.log("promise 시작");

//     서버에서 데이터 받아오는 시간 대체
		setTimeout(() => {
       userId = "layla01";

       if (userId === id) {
         res(userId); // 성공하면 아이디 자체 반환
       } else {
         rej(new Error("서버에서 사용자의 아이디를 받아오는 것을 실패함"));
       }
     }, 2000);
   }); // Promise 자체를 반환
 };

const checkUserId = async () => {
   try {
     const result = await promiseFunc(); // promiseFunc()이 실행될때까지 기다림
     console.log(result);
//      try하다가 문제발생하면 바로 catch절로 넘어감
   } catch (error) {
     console.log(error);
   } finally {
     console.log("Promise 종료");
   }
 };

 checkUserId();

3) 데이터 요청 메소드

Fetch()

  • Js기본 요청 메소드
  • 서버요청을 위한 메소드
  • promise 기반으로 구성. 리턴값은 promise객체

Ajax()

  • JQuery 메소드, CDN필요, 무겁다
    -> 이러한 이유들로 Ajax()는 잘 사용하지 않는다.

Axios()

  • CDN, 설치 필요

3. OPEN API

  • 누군가가 만들어놓은 백엔드를 사용하는 것이다.
  • 사용법이 명세되어 있고, 보통 open api는 사용자 key를 발급받아야 한다.

1) json

  • 데이터 공유를 위한 파일 형식
  • 자바스크립트 객체와 유사하지만 키도 큰따옴표로 감싸는 형식
  • 여러 언어에서 쉽게 사용할 수 있어서 서버와의 통신에서는 json으로 통신한다.

json 파싱하기

  • 파싱이란, .json()형태로 하는데, JSON 형식의 문자열을 자바스크립트에서 사용할 수 있는 객체 또는 배열로 변환하는 것을말한다.
const jsonString =
  '{"name":"장화","age":13,"isEmployed":true,"position": "이사", "address":{"gu":"마포구","city":"서울시"}}';
// console.log(jsonString.name); // undefined -> js객체처럼 바로 사용할 수 없음!

// json을 js로 파싱
const obj = JSON.parse(jsonString);
console.log(obj);
console.log(obj.name);

// js객체 -> json으로 파싱
const jsonStr = JSON.stringify(obj);
cosole.log(jsonStr);

2) open api 사용하기

  • api 사용시, api key가 github에 올릴때 올라가지 않도록 유의
// * open API 사용
console.log("------------------open api 사용---------------------");
// 고양이 사진 가져오기
// fetch로 json과 통신
fetch("https://api.thecatapi.com/v1/images/search")
  .then((response) => { // response 응답객체 (텍스트)
    // response를 파싱하여 json 형식의 (js에서 사용할 수 있는) 객체/배열로 반환
    return response.json(); // 파싱
  })
  // 파싱된 값(json)이 data로 들어감
  .then((data) => {
    console.log(data); 
    // img 태그 생성
    const img = document.createElement("img");
    img.src = data[0].url; 
    img.setAttribute("width", 500);
    // 생성한 img를 div cat에 추가 -> 고양이 사진 화면출력
    document.querySelector("#cat").append(img);
  });


❓ 여기서, json으로 파싱하는 이유가 이해가지 않았다. fetch하여 api가져온 값은 json값이라고 생각했다.

-> 그러나, fetch를 통해 가져온 값은 http형식의 객체, 즉 텍스트 형식이고 텍스트형식은 자바스크립트에서 사용이 어렵기에 자바스크립트에서 사용가능한 객체인 json으로 변환했다는 것이다.

💡그렇다면, json은 자바스크립트에서 사용가능한 객체인데, 왜 굳이 js코드를 json으로 변환 (stringify)하는걸까 의문이 들었다.
->데이터를 교환하거나 저장하는 과정에서는 자바스크립트 객체를 직접 전송할 수 없기 때문이다.

// * OMDB api 사용해 영화 데이터 받아와 브라우저에 보여주기

async function getMovieData() {
  // '영화받아오기' 클릭하면 다음 키워드 뜬다.
  let word = "love";
  const h3 = document.querySelector("h3");
  h3.innerText = `검색된 키워드 : ${word}`;

  // 1. fetch로 데이터 불러오기 (api 데이터 불러오기)
  // response 변수에는 서버에서 받아온 데이터가 저장됨 (json)
  // ! 받은 키는 github에 올리면 안된다.
  // 받은키에 &s붙인다.
  const response = await fetch(`받은키&s=${word}`); // 객체형태
  const movieData = await response.json(); // 객체를 json으로 변환

  console.log(movieData.Search);

  // ul태그 (포스터) 
  const ul = document.querySelector("ul");
  ul.innerText = ""; // 새로 버튼 눌렀을때, 밑에 포스터 추가 안되게 하는 코드

  // 2. 불러온 데이터 각 변수에 담고 태그에 추가하기
  // 불러온 데이터는 movieData.Search 배열 안에 각각의 객체로 있음
  // movieData.Search 배열을 반복문을 통해 돌아서 각 요소를 만들고 DOM에 추가
  for (let movie of movieData.Search) {
    // 태그 생성
    const img = document.createElement("img"); // 영화 카드 컨테이너
    const div = document.createElement("div"); // 영화 포스터
    const p = document.createElement("p"); // 영화 제목

    // 태그변수에 api 배열 데이터값 넣기
    img.src = movie.Poster;
    img.alt = movie.Title;
    p.innerText = movie.Title;

    // div 태그를 ul에 추가
    div.append(img, p);
    ul.append(div);
  }
}

4. 유틸화

  • 함수를 분리하여 필요할 때마다 사용하기 위해 유틸화 한다.
  • 불필요한 코드를 줄이고, 효율적인 개발 가능하다. 또한 유지보수도 쉬워진다.
  • 함수 내보내는 방법은 다음과 같다.
    1. 함수 앞에 export 키워드 작성
export function consoleName(name) {
  console.log(`당신의 이름은 ${name}`);
}

export function consoleName2(name) {
   console.log(`당신의 이름은 ${name} 222`);
}
// ? default 키워드 작성 시 해당 함수가 이 파일의 대표 함수가 된다.
 export default function consoleName2(name) {
   console.log(`당신의 이름은 ${name} main 함수`);
}

// ? 한번에 모아서 export 작성 가능
export { consoleName, consoleName2 };
  1. 마지막에 모아서 export문 함수문들을 작성
function consoleName(name) {
  console.log(`당신의 이름은 ${name}`);
}

function consoleName2(name) {
  console.log(`당신의 이름은 ${name} 222`);
}
  • 함수를 불러오는 방법은 다음과 같다.
    1. import {} from 불러올 파일 경로 작성
// export만 작성시 (default 작성x) 중괄호에 감싸서 작성
import { consoleName, consoleName2 } from "./02_util.js";

// export default 키워드 작성시 중괄호 감싸지 않고 불러옴
// import consoleNameMain from "./02_util.js";

/ 한 줄로 default 함수와 다른 함수들도 불러올 수 있음
// import consoleNameMain, { consoleName, consoleName2 } from "./02_util.js";

consoleName("layla"); // '당신의 이름은 layla'
consoleName2("layla"); // '당신의 이름은 layla 222'
// util.js에서 작성된 consoleName이 불러와져서 사용됨.
  • html에서 다른 파일의 함수나 변수를 import한 경우에는 type="module" 지정 필수다.
    <script type="module" src="./02_import.js"></script>
profile
암튼 해보는 개발자호소인

0개의 댓글