[HTTP/Server] JSON Server로 HTTP 요청 전송 및 응답 받기

초코침·2023년 3월 29일
0

HTTP/Server

목록 보기
2/6

JSON Server로 가상 REST API 서버를 구축하여 HTTP 요청을 전송하고 응답 받는 연습을 했다.

JSON Server 구축

JSON Server는 json 파일을 이용해 가상 REST API 서버를 구축할 수 있는 툴이다.

npm을 이용해 설치할 수 있다.

npm init -y
npm install json-server --save -dev

npm init의 -y 옵션
package.json 파일을 생성할 때, npm 프로젝트에 대한 기본 양식을 일일이 작성하지 않고 default 값으로 설정된 package.json 파일을 생성하고자 할 때 사용하는 옵션이다.

npm install의 —-save -dev 옵션
—save 옵션은 패키지와 버전을 package.json 파일의 dependencies에 저장하는 옵션이다. 이 옵션을 -dev 옵션과 사용하면 dependencies가 아닌 devDependencies에 저장한다.

이때 dependencies는 배포할 때 포함될 패키지, devDependencies는 개발할 때만 필요한 패키지 정보를 담고 있다. 따라서 npm install을 하면 기본적으로 dependencies에 들어가고, 별도로 옵션(—save -dev)을 줘야 devDependencies에 들어간다.

데이터베이스 JSON 파일 생성

JSON Server에서 데이터베이스 역할을 할 파일을 만든다.

touch db.json

nano 편집기를 열어 내용을 작성했다.

nano db.json
{
  "todos": [
    {
      "id": 1,
      "content": "HTML",
      "completed": true
    },
    {
      "id": 2,
      "content": "CSS",
      "completed": false
    },
    {
      "id": 3,
      "content": "JavaScript",
      "completed": true
    }
  ]
}

JSON Server 실행

다음 명령어를 입력해 서버를 실행할 수 있다. 기본 포트는 3000이며, 포트를 변경하려면 —port {포트 번호} 옵션을 추가하면 된다.

json-server --watch db.json

—-watch 옵션
—watch는 파일의 변화를 감시하는 옵션이다.

서버 실행 에러

그런데 서버를 설치하고 서버 실행 명령어를 입력했으나 서버가 실행되지 않았다.그래서 npm start 명령어로 실행해 보려고 package.json의 scripts를 수정했다.

"scripts": {
	"start": "json-server --watch db.json"
}

수정한 다음 npm start로 서버를 실행시켰더니 되는 듯 했으나…

db.json 파일에 올바르지 않은 형식이 있다고 해서 열어봤더니

무의식적으로 붙인 trailing comma가 있었다.

JSON에서는 trailing comma를 허용하지 않는다.

이걸 삭제했더니

서버가 잘 실행되었다!


나는 npm start로 실행시켰지만, 다른 방법으로는 다음 두 가지가 더 있으니 원하는 방법으로 하면 될 듯.

  1. json-server를 전역적으로 설치하기
npm install -g json-server
  1. npx로 실행하기(전역에 설치할 필요 x)
npx json-server --watch db.json

HTTP 요청 전송

XMLHttpRequest 객체로 HTTP 요청을 보내려 한다.

XMLHttpRequest 객체는 서버와 상호작용할 때 사용하며, 페이지의 새로고침 없이도 URL에서 데이터를 가져올 수 있다. 사용하게 될 메서드와 프로퍼티를 간단히 정리하면,

  • xhr.open(method, url): HTTP 요청을 초기화한다.
  • xhr.setRequestHeader(header, value): HTTP 요청의 헤더 값을 지정한다.
  • xhr.send(body): HTTP 요청을 전송한다. 페이로드가 필요한 요청의 경우 body에 작성하면 된다.
  • xhr.onload: HTTP 요청이 성공적으로 완료된 경우 실행할 이벤트 핸들러다.
  • xhr.status: HTTP 요청에 대한 (숫자로 된) 응답 상태다.
  • xhr.statusText: HTTP 서버로부터 받은 응답 상태 메시지다.
  • xhr.response: HTTP 요청에 대한 응답 값이다.

GET 요청

GET은 엔드포인트의 모든 리소스를 취득할 때 사용한다.

todos에서 모든 todo 취득하기

get_index.html 파일을 작성하고 브라우저에서 http://localhost:포트번호/get_index.html에 접속한다.

<!DOCTYPE html>
<html lang="en">
  <body>
    <pre></pre>
    <script>
      // XMLHttpRequest 객체 생성
      const xhr = new XMLHttpRequest();

      // HTTP 요청 초기화 - todos 리소스에서 모든 todos를 취득
      xhr.open('GET', '/todos');

      // HTTP 요청 전송
      xhr.send();

      // HTTP 요청이 성공적으로 완료됐다면 실행할 이벤트
      xhr.onload = () => {
        // status 프로퍼티 값이 200이면 정상적으로 응답된 것임
        if (xhr.status === 200) {
          document.querySelector('pre').textContent = xhr.response;
        } else {
          console.error('Error', xhr.status, xhr.statusText);
        }
      };
    </script>
  </body>
</html>

브라우저에서 확인하면 db.json 파일의 내용이 전부 가져와졌음을 알 수 있다.

성공적으로 가져왔기 때문에 응답 status는 200(OK)이 되며, 새로고침을 하면 응답이 수정되지 않았기 때문에 status는 응답의 캐시된 버전을 사용한다는 304(Not Modified)이다.

todos에서 특정 todo 취득하기

get_retrieve.html 파일을 작성하고 브라우저에서 http://localhost:포트번호/get_retrieve.html에 접속한다.

<!DOCTYPE html>
<html lang="en">
  <body>
    <pre></pre>
    <script>
      // XMLHttpRequest 객체 생성
      const xhr = new XMLHttpRequest();

      // HTTP 요청 초기화 - todos 리소스에서 1번 todo 취득
      xhr.open('GET', '/todos/1');

      // HTTP 요청 전송
      xhr.send();

      // HTTP 요청이 성공적으로 완료됐다면 실행할 이벤트
      xhr.onload = () => {
        if (xhr.status === 200) {
          document.querySelector('pre').textContent = xhr.response;
        } else {
          console.error('Error', xhr.status, xhr.statusText);
        }
      };
    </script>
  </body>
</html>

브라우저에서 확인하면 id가 1인 todo만을 가져왔음을 알 수 있다.

성공적으로 가져왔기 때문에 status는 200(OK)이다.


만약 다음과 같이 없는 id를 가져오려 한다면

xhr.open('GET', '/todos/0');

status는 404(Not Found)이다.

POST 요청

POST는 엔드포인트 리소스에 새로운 리소스를 생성할 때 사용한다.

새로 생성할 리소스를 서버에 보내야 하므로 setRequestHeader 메서드를 사용해 서버로 전송할 페이로드의 MIME 타입을 지정해야 한다. 보낼 내용(페이로드)은 send 메서드에 담는다.

MIME 타입: 미디어 타입 즉, 데이터의 형식을 말한다.

post.html 파일을 작성하고 브라우저에서 http://localhost:포트번호/post.html에 접속한다.

<!DOCTYPE html>
<html lang="en">
  <body>
    <pre></pre>
    <script>
      // XMLHttpRequest 객체 생성
      const xhr = new XMLHttpRequest();

      // HTTP 요청 초기화 - todos 리소스에 새로운 todo 생성
      xhr.open('POST', '/todos');

      // 요청 body에 담아 서버로 전송할 페이로드의 MIME 타입 지정
      xhr.setRequestHeader('content-type', 'application/json');

      // HTTP 요청 전송 - 새로운 todo 생성 위해 페이로드 전송 필요
      xhr.send(JSON.stringify({ id: 4, content: 'Angular', completed: false }));

      // HTTP 요청이 성공적으로 완료됐다면 실행할 이벤트
      xhr.onload = () => {
        if (xhr.status === 200 || xhr.status === 201) {
          document.querySelector('pre').textContent = xhr.response;
        } else {
          console.error('Error', xhr.status, xhr.statusText);
        }
      };
    </script>
  </body>
</html>

브라우저에는 생성한 todo의 내용이 나타났다.

이전과 다른 응답 status가 왔는데, 201(Created)은 요청이 성공적이었으며 그 결과로 새로운 리소스가 생성되었음을 알리는 status다. 즉, 새로운 리소스가 생길만한 요청인 POST 또는 (일부)PUT에 따라올 수 있는 상태값이다.


여기서 페이지 새로고침을 한면 응답 status가 500(Internal Server Error)이 된다. 이는 서버가 처리 방법을 모르는 상황임을 나타내는 값인데, 서버 에러를 총칭하는 응답(적합한 에러 status가 없을 때 보내는 응답)이기도 하다.

에러 메시지를 좀 더 살펴보면, 이미 존재하는 id로 새로운 리소스를 추가하려고 해서 에러가 발생한 상황임을 알 수 있다.

PUT 요청

PUT은 특정 리소스 전체를 교체할 때 사용한다.

교체할 리소스를 서버에 보내야 하므로 setRequestHeader 메서드를 사용해 서버로 전송할 페이로드의 MIME 타입을 지정해야 한다. 보낼 내용(페이로드)은 send 메서드에 담는다.

put.html 파일을 작성하고 브라우저에서 http://localhost:포트번호/put.html에 접속한다.

<!DOCTYPE html>
<html lang="en">
  <body>
    <pre></pre>
    <script>
      // XMLHttpRequest 객체 생성
      const xhr = new XMLHttpRequest();

      // HTTP 요청 초기화 - id가 4인 todo의 리소스 교체(교체 대상에서 id는 제외함)
      xhr.open('PUT', '/todos/4');

      // 요청 body에 담아 서버로 전송할 페이로드의 MIME 타입 지정
      xhr.setRequestHeader('content-type', 'application/json');

      // HTTP 요청 전송 - 기존 todo의 내용을 교체하기 위해 페이로드 전송 필요
      xhr.send(JSON.stringify({ id: 4, content: 'React', completed: true }));

      // HTTP 요청이 성공적으로 완료됐다면 실행할 이벤트
      xhr.onload = () => {
        if (xhr.status === 200) {
          document.querySelector('pre').textContent = xhr.response;
        } else {
          console.error('Error', xhr.status, xhr.statusText);
        }
      };
    </script>
  </body>
</html>

기존에 Angular, false였던 값이 React, true로 변경되었다.

응답 status는 200(OK)이다.

PATCH 요청

PATCH는 특정 리소스의 일부를 수정할 때 사용한다.

수정할 리소스를 서버에 보내야 하므로 setRequestHeader 메서드를 사용해 서버로 전송할 페이로드의 MIME 타입을 지정해야 한다. 보낼 내용(페이로드)은 send 메서드에 담는다.

patch.html 파일을 작성하고 브라우저에서 http://localhost:포트번호/patch.html에 접속한다.

<!DOCTYPE html>
<html lang="en">
  <body>
    <pre></pre>
    <script>
      // XMLHttpRequest 객체 생성
      const xhr = new XMLHttpRequest();

      // HTTP 요청 초기화 - id가 4인 todo의 리소스 수정
      xhr.open('PATCH', '/todos/4');

      // 요청 body에 담아 서버로 전송할 페이로드의 MIME 타입 지정
      xhr.setRequestHeader('content-type', 'application/json');

      // HTTP 요청 전송 - 기존 todo의 내용을 수정하기 위해 페이로드 전송 필요
      xhr.send(JSON.stringify({ completed: false }));

      // HTTP 요청이 성공적으로 완료됐다면 실행할 이벤트
      xhr.onload = () => {
        if (xhr.status === 200) {
          document.querySelector('pre').textContent = xhr.response;
        } else {
          console.error('Error', xhr.status, xhr.statusText);
        }
      };
    </script>
  </body>
</html>

true였던 값이 false로 변경되었다.

응답 status는 200(OK)이다.

DELETE 요청

DELETE는 엔드포인트 리소스에서 특정 리소스를 삭제할 때 사용한다.

delete.html 파일을 작성하고 브라우저에서 http://localhost:포트번호/delete.html에 접속한다.

<!DOCTYPE html>
<html lang="en">
  <body>
    <pre></pre>
    <script>
      // XMLHttpRequest 객체 생성
      const xhr = new XMLHttpRequest();

      // HTTP 요청 초기화 - id가 4인 todo 삭제
      xhr.open('DELETE', '/todos/4');

      // HTTP 요청 전송
      xhr.send();

      // HTTP 요청이 성공적으로 완료됐다면 실행할 이벤트
      xhr.onload = () => {
        if (xhr.status === 200) {
          document.querySelector('pre').textContent = xhr.response;
        } else {
          console.error('Error', xhr.status, xhr.statusText);
        }
      };
    </script>
  </body>
</html>

id가 4인 todo가 삭제되었다.

응답 status는 200(OK)이다.


여기서 페이지 새로고침을 하면 응답 status가 404(Not Found)가 된다. id가 4인 리소스는 이미 삭제되었기 때문에 /todos/4라는 엔드포인트를 참조할 수 없게 되어 나타나는 에러다.


REST API 서버를 이용해 CRUD를 위한 HTTP 요청을 보내는 연습 끝!

다음엔 postman을 써 볼까 한다.

전체 코드(Github) 보러가기


[Reference] 모던 자바스크립트 Deep Dive

profile
블로그 이사중 🚚 (https://sungjihyun.vercel.app)

0개의 댓글