REST API란 무엇인가?

이강용·2024년 7월 17일
0

CS

목록 보기
75/109

REST API란?

  • REST API(Representational State Transfer Application Programming Interface)는 웹 서비스 개발을 위한 일련의 규칙을 정의하는 아키텍처 스타일
    • 웹의 기존 HTTP 프로토콜을 활용하여 클라이언트와 서버 간의 통신을 간단하고 확장 가능하게 만듦

REST API의 특징

  1. Uniform - Interface
  • 자원들은 각각의 독립적인 인터페이스를 가지며 각각의 자원들이 URI 자원 식별, 표현을 통한 자원조작, Self-descriptive messages, HATEOAS 구조를 가지는 것을 말함

    • URI 자원 식별

      • Identification of resources를 말하며 자원은 URL로 식별되어햐 함
    • 표현을 통한 자원 조작

      • Manipulation of resources through representations은 URL과 GET, DELETE 등 HTTP 표준 메서드 등을 통해 자원을 조회, 삭제 등 작업을 설명할 수 있는 정보가 담겨야 하는 것을 말함
    • Self-descriptive messages

      • HTTP Header에 타입을 명시하고 각 메시지(자원)들은 MIME types에 맞춰 표현되어야 함, 예를 들어 .json을 반환한다면 application/json으로 명시해주어야 함
      • MIME types는 문서, 파일 등의 특성과 형식을 나타내는 표준(font/ttf, text/plain, text/csv)
const express = require("express");
const app = express();
app.get("/good", (req, res) => {
  res.status(200).json({ a: 1 });
});
app.get("/bad", (req, res) => {
  res.setHeader("content-type", "application/json");
  res.send("leesfact");
});
const server = app.listen(12010, () => {
  console.log("오늘도 재밌는 CS공부서버 ~ : http://127.0.0.1:12010/good");
});

잘못된 부분

res.send("leesfact")

수정된 부분

app.get("/bad", (req, res) => {
  res.status(200).json({ message: "leesfact" });
});
  • Content-Type을 application/json으로 설정했지만, 실제로 보내는 데이터는 유효한 JSON 형식이 아님, "leesfact"는 단순한 문자열이므로 JSON 파싱 오류가 발생

HATEOAS 구조

  • HATEOAS(Hypermedia as the Engine of Application State)는 하이퍼링크에 따라 다른 페이지를 보여줘야 하며 데이터마다 어떤 URL에서 원했는지 명시해주어야 하는 것을 말함
  • 보통은 href, links, link, url 속성 중 하나에 해당 데이터의 URL을 담아서 표기해야 함(_links 속성에 담기도 함, 링크를 유추할 수 있는 변수명을 쓰면 됨)
const express = require("express");
const app = express();
const books = [
  { id: 1, title: "자바스크립트 풀스택 MEVN", author: "아무개1" },
  { id: 2, title: "CS지식노트", author: "아무개2" },
  { id: 3, title: "자바스크립트 어나더레벨", author: "아무개3" },
];
app.get("/books", (req, res) => {
  const bookCollection = books.map((book) => ({
    ...book,
    links: [{ rel: "self", href: `/books/${book.id}` }],
  }));
  res.status(200).json(bookCollection);
});
app.get("/books/:id", (req, res) => {
  const bookId = parseInt(req.params.id);
  const book = books.find((book) => book.id === bookId);
  if (book) {
    book.links = [{ rel: "self", href: `/books/${book.id}` }];
    res.status(200).json(book);
  } else {
    res.status(404).json({ error: "Book not found" });
  }
});
app.listen(12010, () => {
  console.log("책서버 시작 : http://127.0.0.1:12010/books");
});

참고

rel : relation으로 링크와 요청한 자원과의 관계를 나타냄
self : 해당 자원에 대한 링크를 나타냄

  1. Stateless
  • 이 규칙은 HTTP 자체가 Stateless이기 때문에 HTTP를 사용하는 것만으로도 만족됨
  • REST API를 제공해주는 서버는 세션(session)을 해당 서버 쪽에 유지하지 않는다는 의미

3 Cacheable

  • HTTP는 아무런 로직을 구현하지 않더라도 자동적으로 캐싱이 됨

    • 새로고침을 하면 304가 뜨면서 원래 있던 js와 css 이미지 등을 불러오는 것을 볼 수 있음
  • 이는 HTTP 메서드 중 GET에 한정되며 Cache-Control:max-age=100 (100초) 이런 식으로 한정된 시간을 정할 수 있으며 캐싱된 데이터가 유효한지를 판단하기 위해 Last-modifiedEtag라는 헤더값을 씀

    • Etag는 전달되는 값에 태그를 붙여서 캐싱되는 자원인지를 확인해주는 것

참고
HTTP 헤더의 Cache-control = no-store로 하게 되면 캐싱이 안됨, 기본적으로 cache-control = public으로 되어있기 때문에 캐싱이 되며 HTTP header를 기반으로 캐싱 컨트롤을 하는게 중요함

  1. Client-Server 구조
  • 클라이언트와 서버가 서로 독립적인 구조를 가져야 함
    • 서버에서 HTTP 표준만 지킨다면 웹에서는 그에 따른 화면이 잘 나타나게 됨
    • 서버는 API를 제공하고 그 API에 맞는 비즈니스 로직을 처리하면 됨
    • 마찬가지로 클라이언트에서는 HTTP로 받는 로직만 잘 처리하면 됨
  1. Layered System
  • 계층구조로 나눠져 있는 아키텍처를 뜻함

REST API의 URI 규칙

  1. 동작은 HTTP 메서드로만 해야 하고 url에 해당 내용이 들어가면 안됨
    • 수정 = put, 삭제 = delete, 추가 = post, 조회 = get을 이용해야 함
      • 예를 들어 /books/delete/1 이렇게 표기하면 안됨
  2. .jpg, .png 등 확장자는 표시 하지 말아야 함
  3. 동사가 아닌 명사로만 표기해야 함
유저가 책을 소유한다 라는 것을 표현한다면
→ 유저/유저아이디/inclusion/책/책아이디
유저가 소유한 아파트를 조회한다 를 표현한다면
→ /users/{userid}/aparts
또한 /getAllUsers 식의 동사를 집어넣으면 안됨
  1. 계층적인 내용을 담고 있어야 함

    • 예) /집/아파트/전세
  2. 대문자가 아닌 소문자로만 쓰며 너무 길 경우에 바를 써야 할 경우 언더바_가 아닌 일반적인 바-를 씀

  3. HTTP 응답 상태코드를 적재적소에 활용해야 함

    • 성공 시 200, 리다이렉트는 301

도서관 시스템

app.get('/books')
// 모든 책을 조회합니다.
app.post('/books/:booksid')
// 책을 생성합니다. 
app.put('/books/:booksid')
// 책을 수정합니다. 
app.get('/books/:booksid')
// 특정 책을 조회합니다. 
app.put('/users/:userid/books/:booksid') 
// 어떤 유저가 특정 책을 빌립니다. 
app.patch('/users/:userid/books/:booksid') 
// 어떤 유저가 특정 책을 빌립니다.

쿼리스트링과 혼합한 url

  • REST API는 /를 기반으로만 구축되는 것도 있지만 적절히 쿼리스트링을 혼재해서 쓰기도 함
  • 검색, 페이지네이션, 정렬 등 매개변수가 많거나 복잡할 때 쿼리스트링을 쓰는게 좋음
실제 워드프레스에서 제공하는 REST API
posts의 2번째 결과물을 나타냄
/wp/v2/posts?page=2

[참고] api를 설정할 때 /v2, /v1으로 버전을 명시해 놓는게 좋음, 이를 통해 현재 버전을
사용하다가 새로운 버전이 안정화되면 자체적으로 마이그레이션할 수 있음

실제 KAKAO API 
/oauth/token?grant_type=refresh_token&client_id=${REST_API_KEY}

바벨이 필요한 운동정보를 가져온다. 
/api/v1/workouts?equipment=barbell

모든 운동정보를 생성날짜 기준으로 내림차순으로 가져온다면 
/api/v1/workouts?sort=-createdAt
profile
HW + SW = 1

0개의 댓글