자바스크립트 웹 개발 기본기 (1) (fetch, JSON, Request, Response)

LeeKyungwon·2024년 3월 27일
0

프론트엔드 

목록 보기
15/56
post-custom-banner

웹 기초

fetch 함수

request : 웹브라우저가 서버로 보내는 요청
response : 서버가 보내주는 응답

fetch : 서버로 리퀘스트를 보내고 리스폰스를 받는 함수

fetch('https://google.com')
  .then((response) => response.text()) //서버에서 리스폰스가 온 후 실행 (콜백)
  .then((result) => {console.log(result);});

파라미터로 넘어온 url로 리퀘스트 보내고 서버로부터 리스폰스 받음
서버로부터 리스폰스 오면 두번째 줄 실행
리스폰스는 하나의 객체가 되어 response 파라미터로 넘어옴 (이름은 달라도 됨)
then이라는 메소드는 콜백을 등록해줌 (promise 객체)
세번째 줄 콜백을 등록하는 메소드
이전 콜백의 리턴 값을 다음 콜백이 넘겨 받을 수 있음

콜백(callback) : 추후에 특정 조건이 만족되었을 때 실행되는 함수

fetch 함수의 실행 원리 정리

  1. fetch 함수는 어떤 객체를 리턴하는데(Promise 객체)
  2. 이 객체의 then 메소드로, '리스폰스가 왔을 때 실행할 콜백'을 등록할 수 있다.
  3. 이렇게 등록된 콜백들은 then 메소드로 등록한 순서대로 실행되고, 이때 이전 콜백의 리턴값을 이후 콜백이 넘겨받아서 사용할 수 있다.

response 파라미터로 실제 내용 자체가 넘어오는 것이 아니라 부가 정보들, 실제 내용을 가지고 있는 객체가 넘어오기 때문에

  .then((response) => response.text())

이렇게 text 메소드를 호출해야 한다.

개발자 도구

구글에서 제공하는 크롬의 개발자 도구 설명

단축키
Mac : Command 키 + Option 키 + 알파벳 i 키
Windows : Ctrl 키 + Shift 키 + 알파벳 i 키

console창에서 아무 값도 리턴하지 않는 경우에는 undefined를 리턴한 것으로 간주한다.
(함수 선언이나 단순한 문자열을 출력할 때는 undefined도 리턴된다는 점 주의)

웹이란?

전세계적인 연결망
HyperText : 참조하는 글자

URL이란?

웹에 존재하는 특정 데이터를 나타내는 문자열
호스트 (Host) : 전세계 서버 중 하나의 서버를 특정
경로 (Path) : 서버에 있는 데이터 중 원하는 데이터를 특정(해당 서비스를 설계하는 개발자들의 역할)
쿼리 (Query) : 데이터에 관한 세부적인 요구사항 (존재할 때도, 존재하지 않을 때도 있음)

리퀘스트를 보내면 일어나는 일

도메인 네임 : 특정 서버를 외우기 어려운 IP주소가 아니라 외우기 쉬운 문자열로 나타낸 것

  1. 웹 브라우저는 URL에서 호스트 부분을 보고 어느 서버와 통신하는지 찾는다.
  2. 어느 서버와 통신해야 하는지 식별하고 나면 해당 서버로 리퀘스트를 보낸다.
  3. 리퀘스트를 받은 서버는 리퀘스트에 담긴 path 이후의 부분들을 보고, 그것이 의미하는 데이터를 찾고, 찾은 결과를 리스폰스에 담아서 보낸다.
  4. 웹 브라우저는 받은 리스폰스의 내용을 갖고 사용자에게 보여준다.

HTTP

프로토콜 : 통신을 하는 두 주체가 지켜야 하는 통신 규약
https : 프로토콜의 이름

Web API

JSON

JavaScript Object Notation
자바스크립트의 문법을 빌려서 나타내는 데이터포맷 (어떤 정보를 교환하기 위해 만들어짐)
객체로 정보를 나타냄

자바스크립트 문법과 JSON 문법이 완벽하게 동일한 것은 아니다.
차이점

1. JSON에는 프로퍼티의 이름과 값을 표현하는 방식에 제한이 있다.

(1) JSON에서는 각 프로퍼티의 이름을 반드시 큰따옴표(")로 감싸줘야 한다.
자바스크립트에서는 큰 따옴표를 붙이지 않아도 되고, 큰 따옴표를 붙여도 되지만 JSON에서는 항상 큰 따옴표로 감싸서 적어줘야 한다.

{
   "name":"Michael Kim",
   "height":180,
   "weight":70,
   "hobbies":["Basketball", "Listening to music"]
}

큰따옴표로 감싸주지 않으면 JSON을 처리하려고 할 때 에러가 난다.

(2) JSON에서는 값이 문자열인 경우 큰따옴표(")를 사용해야 한다.
자바스크립트에서는 작은 따옴표를 써도 되고, 큰 따옴표를 써도 되지만 JSON에서는 항상 큰 따옴표로 감싸서 적어줘야 한다.

{
   "name":"Michael Kim",
   "height":180,
   "weight":70,
   "hobbies":["Basketball", "Listening to music"]
}

2. JSON에서는 표현할 수 없는 값들이 있다.

자바스크립트에서는 프로퍼티의 값으로 사용할 수 있는 undefined, NaN, Infinity 등을 JSON에서는 사용할 수 없다.

3. JSON에는 주석을 추가할 수 없다.

JSON은 코드가 아니라 데이터 포맷이기 때문에 그 안에 주석을 포함시킬 수 없다.

JSON 데이터를 객체로 변환하기

fetch('https://jsonplaceholder.typicode.com/users')
  .then((response) => response.text())
  .then((result) => {const users = JSON.parse(result)});

JSON.parse을 사용하면 string 타입의 JSON 데이터를 자바스크립트 객체로 변환할 수 있다.

메소드

메소드의 정보를 보고 어떤 리퀘스트인지 알 수 있다.

Request 종류,메소드
1. 데이터 조회 : GET
2. 데이터 추가 : POST
3. 데이터 수정 : PUT
4. 데이터 삭제 : DELETE

하나의 Request는 Head, Body로 이루어져 있다.
Head : Request에 대한 부가 정보 (메소드)
Body : 실제 데이터를 담는 부분
GET, DELETE 리퀘스트는 보통 바디가 필요하지 않음

개발자 도구의 네트워크 탭에서는 웹 브라우저가 보낸 리퀘스트와 받은 리스폰스를 확인할 수 있다.
Header : Head 안에 존재하는 하나 하나의 키와 값의 쌍

POST request 보내기

추가할 정보를 리퀘스트의 바디에 넣어줘야 한다.

const newMember = {
    name: 'Jerry',
    email: 'jerry@codeitmail.kr',
    department: 'engineering',
};
fetch('https://learn.codeit.kr/api/members',{
  method:'POST', 
  body: JSON.stringify(newMember),
})
  .then((response) => response.text())
  .then((result) => {console.log(result);});
{
  method:'POST', 
  body: JSON.stringify(newMember),
}

-> 리퀘스트에 관한 각종 설정이 들어있는 객체(옵션객체)가 새로운 아규먼트로 추가
fetch 함수의 기본 값은 GET 리퀘스트! GET이 아닌 다른 메소드 값을 가진 리퀘스트를 보내려면 이런 옵션 객체가 필요함

stringify : parse 메소드와 정반대 기능 자바스크립트의 객체를 string 타입의 JSON 데이터로 변환
어떤 자바스크립트가 담고 있는 정보를 외부에 전송하려면 반드시 stringify 메소드로 전송해줘야 한다.

PUT 리퀘스트 보내기

2번 직원의 정보 수정

const member = {
    name: 'Alice',
    email: 'alice@codeitmail.kr',
    department: 'marketing',
};
fetch('https://learn.codeit.kr/api/members/2',{
  method:'PUT', 
  body: JSON.stringify(member),
})
  .then((response) => response.text())
  .then((result) => {console.log(result);});

DELETE 리퀘스트 보내기

body 필요 없음

fetch('https://learn.codeit.kr/api/members/2',{
  method:'DELETE', 
})
  .then((response) => response.text())
  .then((result) => {console.log(result);});

Web API, REST API

API (Application Programming Interface) 개발할 때 사용할 수 있도록 특정 라이브러리나 플랫폼 등이 제공하는 데이터나 함수 등 을 의미한다.
웹 개발에서는 어느 URL로 어떤 리퀘스트를 보냈을 때, 무슨 처리가 수행되고 어떤 리스폰스가 오는지에 관해 미리 정해진 규격을 Web API라고 한다.

Web API가 잘 설계되었는지에 관한 기준으로 REST API라는 기준이 사용되고 있다.
REST architecture가 되기 위한 조건

1. Client-Server

Client, Server 양측의 관심사를 분리하고 독립적으로 운영될 수 있도록 한다.

2. Stateless

Client가 보낸 각 리퀘스트에 관해서 Server는 그 어떤 맥락(context)도 저장하지 않는다. (매 리퀘스트는 각각 독립적인 것으로 취급) 이 때문에 리퀘스트에는 항상 필요한 모든 정보가 담겨야합니다.

3. Cache

Cache를 활용해서 네트워크 비용을 절감해야 한다. erver는 리스폰스에, Client가 리스폰스를 재활용해도 되는지 여부(Cacheable)를 담아서 보내야 함

4. Uniform Interface

Client가 Server와 통신하는 인터페이스는 다음과 같은 하위 조건 4가지를 준수해야 한다. (REST API와 연관이 깊은 조건임)

(4-1) identification of resources
리소스: 웹상에 존재하는 데이터
리소스(resource)를 URI(Uniform Resource Identifier)로 식별할 수 있어야 한다 (URI는 URL의 상위 개념)
(URL에 메소드를 나타내면 안된다? URL에 add 적지 말라)

(4-2) manipulation of resources through representations
Client와 Server는 둘 다 리소스를 직접적으로 다루는 게 아니라 리소스의 '표현(representations)'(HTML 파일과 PNG 파일 같은 것들)을 다뤄야 한다. 리소스는 웹에 존재하는 특정 데이터를 나타내는 추상적인 개념이다. 실제로 우리가 다루게 되는 것은 리소스의 표현들뿐이다. 이렇게 '리소스'와 '리소스의 표현'이라는 개념 2개를 서로 엄격하게 구분하는 것이 REST architecture의 특징이다.

(4-3) self-descriptive messages
(자기 설명적인) Stateless 조건 때문에 Client는 매 리퀘스트마다 필요한 모든 정보를 담아서 전송해야 한다. 그리고 이때 Client의 리퀘스트와 Server의 리스폰스 모두 그 자체에 있는 정보만으로 모든 것을 해석할 수 있어야 한다.

(4-4) hypermedia as the engine of application state
웹은 분산 하이퍼미디어 시스템(Distributed Hypermedia System)이다.
하이퍼미디어(Hypermedia) :'문서'에 국한된 것이 아니라 이미지, 소리, 영상 등까지도 모두 포괄하는 더 넓은 개념의 단어
웹을 하나의 프로그램으로 간주했을 때, Server의 리스폰스에는 현재 상태에서 다른 상태로 이전할 수 있는 링크를 포함하고 있어야 한다는 조건이다. 즉, 리스폰스에는 리소스의 표현, 각종 메타 정보들뿐만 아니라 계속 새로운 상태로 넘어갈 수 있도록 해주는 링크들도 포함되어 있어야 한다는 것

5. Layered System

Client와 Server 사이에는 프록시(proxy), 게이트웨이(gateway)와 같은 중간 매개 요소를 두고, 보안, 로드 밸런싱 등을 수행할 수 있어야 한다.
이를 통해 Client와 Server 사이에는 계층형 층(hierarchical layers)들이 형성된다.

6. Code on Demand

Client는 받아서 바로 실행할 수 있는 applet이나 script 파일을 Server로부터 받을 수 있어야 한다. 이 조건은 Optional한 조건으로 REST architecture가 되기 위해 이 조건이 반드시 만족될 필요는 없다.

(4-1) identificaton of resources 에 관해서 특히 개발자들이 강조하는 규칙

(1) URL은 리소스를 나타내기 위해서만 사용하고, 리소스에 대한 처리는 메소드로 표현해야 한다.
-> URL에서 리소스에 대한 처리를 드러내면 안 된다
리소스에 대한 처리는 메소드로 표현해야 한다

(2) 도큐먼트는 단수 명사로, 컬렉션은 복수 명사로 표시한다.
도큐먼트 : 하나의 객체로 표현할 수 있는 리소스 (ex. 파일)
컬렉션 : 여러 개의 '도큐먼트'를 담을 수 있는 리소스(ex. 디렉토리)

text 메소드 말고 json 메소드도 있다.

자바스크립트 객체를 string 타입의 JSON 데이터로 변환하는 것은 영어로 Serialization, 우리말로는 직렬화라고 한다. (stringify)
그리고 이와 반대로 string 타입의 JSON 데이터를 자바스크립트 객체로 변환하는 것을 영어로는 Deserialization, 우리말로는 역직렬화라고 한다. parse

fetch('https://jsonplaceholder.typicode.com/users')
  .then((response) => response.text())
  .then((result) => { const users = JSON.parse(result); });

이 코드를 아래와 같이 바꿔줄 수도 있다.

fetch('https://jsonplaceholder.typicode.com/users')
  .then((response) => response.json())
  .then((result) => { const users = result; });

response 객체의 text 메소드 대신 json이라는 메소드를 호출하면, 리스폰스의 내용이 JSON 데이터에 해당하는 경우, 바로 Deserialization까지 수행해준다.

Status Code (상태 코드)

Response

Head : Response에 대한 부가 정보 (상태 코드)
Body : 실제 데이터 (JSON)

각각의 상태 코드에는 대응되는 상태 메시지가 있다.

(1) 100번대

서버가 클라이언트에게 정보성 응답을 줄 때 사용되는 상태 코드

100 Continue : 클라이언트가 서버에게 계속 리퀘스트를 보내도 괜찮은지 물어봤을 때, 계속 리퀘스트를 보내도 괜찮다고 알려주는 상태 코드
예를 들어, 클라이언트가 용량이 좀 큰 파일을 리퀘스트의 바디에 담아 업로드하려고 할 때 서버에게 미리 괜찮은지를 물어보는 경우가 있다고 할 때, 서버가 이 100번 상태 코드의 리스폰스를 주면 그제서야 본격적인 파일 업로드를 시작한다.

101 Switching Protocols : 클라이언트가 프로토콜을 바꾸자는 리퀘스트를 보냈을 때, 서버가 '그래요, 그 프로토콜로 전환하겠습니다'라는 뜻을 나타낼 때 쓰이는 상태 코드

(2) 200번대

클라이언트의 리퀘스트가 성공 처리되었음을 의미하는 상태 코드들입니다.

200 OK : 리퀘스트가 성공적으로 처리되었음을 포괄적으로 의미하는 상태 코드

201 Created : 리퀘스트의 내용대로 리소스가 잘 생성되었다는 뜻.
POST 리퀘스트가 성공한 경우에 200번 대신 201번이 올 수도 있다.

202 Accepted : 리퀘스트의 내용이 일단은 잘 접수되었다는 뜻.
당장 리퀘스트의 내용이 처리된 것은 아니지만 언젠가 처리할 것이라는 의미. 리퀘스트를 어느 정도 모아서 한번에 실행하는 서버인 경우 등에 이런 응답을 줄 수도 있다.

(3) 300번대

클라이언트의 리퀘스트가 아직 처리되지 않았고, 리퀘스트 처리를 원하면 클라이언트 측의 추가적인 작업이 필요함을 의미하는 상태 코드들입니다.

301 Moved Permanently : 리소스의 위치가 바뀌었음을 나타낸다.
보통 이런 상태 코드가 있는 리스폰스의 헤드에는 Location이라는 헤더도 일반적으로 함께 포함되어 있다. 그리고 그 헤더의 값으로 리소스에 접근할 수 있는 새 URL이 담겨있는데, 대부분의 브라우저는 만약 GET 리퀘스트를 보냈는데 이런 상태 코드가 담긴 리스폰스를 받게 되면, 헤드에 포함된 Location 헤더의 값을 읽고, 자동으로 그 새 URL에 다시 리퀘스트를 보내는 동작(리다이렉션, redirection)을 수행한다.

302 Found : 리소스의 위치가 일시적으로 바뀌었음을 나타낸다.
나중에 현재 요청한 URL이 정상적으로 인식될 것이라는 뜻이다. 이 상태 코드의 경우에도 보통 그 리스폰스의 헤드에 Location 헤더가 있고, 여기에 해당 리소스의 임시 URL 값이 있다. 이 경우에도 대부분의 브라우저들은 임시 URL로 리다이렉션한다.

304 Not Modified : 요청한 자원에 대해 변경된 사항이 없으므로 캐시되어있는 자원으로 리디렉션 하겠다는 의미
마지막 요청 이후 요청한 페이지는 수정되지 않았다. 서버가 이 응답을 표시하면 페이지의 콘텐츠를 표시하지 않는다. 요청자가 마지막으로 페이지를 요청한 후 페이지가 변경되지 않으면 이 응답(If-Modified-Since HTTP 헤더라고 함)을 표시하도록 서버를 구성해야 한다.

(4) 400번대

리퀘스트를 보내는 클라이언트 쪽에 문제가 있음을 의미하는 상태 코드

400 Bad Request : 리퀘스트에 문제가 있는 경우, 리퀘스트 내부 내용의 문법에 오류가 존재하는 등의 이유로 인해 발생한다.

401 Unauthorized : 아직 신원이 확인되지 않은(unauthenticated) 사용자로부터 온 리퀘스트를 처리할 수 없다는 뜻이다.

403 Forbidden : 사용자의 신원은 확인되었지만 해당 리소스에 대한 접근 권한이 없는 사용자라서 리퀘스트를 처리할 수 없다는 뜻이다.

404 Not Found : 해당 URL이 나타내는 리소스를 찾을 수 없다는 뜻이다.

405 Method Not Allowed : 해당 리소스에 대해서 요구한 처리는 허용되지 않는다는 뜻이다.
만약 어떤 서버의 이미지 파일을 누구나 조회할 수는 있지만 아무나 삭제할 수는 없다고 할 때 그 이미지에 대한 DELETE 리퀘스트를 보낸다면 이런 상태 코드를 보게될 수도 있다.

413 Payload Too Large : 현재 리퀘스트의 바디에 들어있는 데이터의 용량이 지나치게 커서 서버가 거부한다는 뜻이다.

429 Too Many Requests : 일정 시간 동안 클라이언트가 지나치게 많은 리퀘스트를 보냈다는 뜻이다.

(5) 500번대

서버 쪽의 문제로 인해 리퀘스트를 정상적으로 처리할 수 없음을 의미하는 상태 코드

500 Internal Server Error : 현재 알 수 없는 서버 내의 에러로 인해 리퀘스트를 처리할 수 없다는 뜻이다.
503 Service Unavailable : 현재 서버 점검 중이거나, 트래픽 폭주 등으로 인해 서비스를 제공할 수 없다는 뜻이다.

Content-Type

Content-Type 헤더는 현재 리퀘스트 또는 리스폰스의 바디에 들어 있는 데이터가 어떤 타입인지를 나타낸다.
Content-Type 헤더의 값은 '주 타입(main type)/서브 타입(sub type)'의 형식으로 나타낸다.

  • 주 타입이 text인 경우(텍스트)
    일반 텍스트 : text/plain
    CSS 코드 : text/css
    HTML 코드 : text/html
    JavaScript 코드 : text/javascript ...

  • 주 타입이 image인 경우(이미지)
    image/bmp : bmp 이미지
    image/gif : gif 이미지
    image/png : png 이미지 ...

  • 주 타입이 audio인 경우(오디오)
    audio/mp4 : mp4 오디오
    audio/ogg : ogg 오디오 ...
    주 타입이 video인 경우(비디오)
    video/mp4 : mp4 비디오
    video/H264 : H264 비디오 ...

  • 주 타입이 application인 경우
    application/json : JSON 데이터
    application/octet-stream : 확인되지 않은 바이너리 파일 ...

const newMember = {
  name: 'Jerry',
  email: 'jerry@codeit.kr',
  department: 'engineering',
};

fetch('https://learn.codeit.kr/api/members', {
  method: 'POST',
  headers: { // 추가된 부분
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(newMember),
})
  .then((response) => response.text())
  .then((result) => { console.log(result); });

알아두면 좋은 Content-type들

  1. XML
    태그를 사용하여 데이터를 나타내는 방법
<?xml version="1.0" encoding="UTF-8" ?>
<person>
    <name>Michael Kim</name>
    <height>180</height>
    <weight>70</weight>
    <hobbies>
        <value>Basketball</value>
        <value>Listening to music</value>
    </hobbies>
</person>

JSON이 활성화 되기 전에 주로 사용되던 데이터 타입이다.
요즘에는 많이 사용되지 않지만 오픈 api를 살펴볼 때 xml을 발견할 수 있다.

  1. form 태그에서 사용되는 타입들
    (1) application/x-www-form-urlencoded
    form 태그를 사용하면 자바스크립트 코드 없이 HTML만으로도 리퀘스트를 보내는 것이 가능하다.
    (2) multipart/form-data
    여러 종류의 데이터를 하나로 합친 데이터

Ajax

현재 페이지를 그대로 유지한 채로 서버에 리퀘스트를 보내고 리스폰스를 받아서, 새로운 페이지를 로드하지 않고도 변화를 줄 수 있게 해주는 기술

자바스크립트에서는 XMLHttpRequest라고 하는 객체를 통해 Ajax 통신을 할 수 있다.

const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://learn.codeit.kr/api/members');
xhr.onload = function () {
  console.log(xhr.response);
};
xhr.onerror = function () {
  alert('Error!');
};
xhr.send();

예전엔 XMLHttpRequest를 이렇게 직접 사용할 일이 많았지만 요즘에는 굳이 그렇게 하지 않아도 된다.
그 이유는
1. fetch 함수를 사용해서 Ajax 통신을 할 수 있기 때문이다.
2. XMLHttpRequest을 기반으로 더 쓰기 편하게 만들어진 axios라는 패키지가 존재하기 때문이다.

GET, POST, PUT, DELETE 이외의 메소드들

1. PATCH

PATCH 메소드는 기존의 데이터를 수정할 때 사용하는 메소드이다.

PUT은 기존 데이터를 아예 새로운 데이터로 덮어씀으로써 수정하려고 할 때 쓰는 메소드이고, PATCH는 새 데이터로 기존 데이터의 일부를 수정하려고 할 때 쓰는 메소드이다.
ex) 서버에 id, name, age라는 데이터가 있을 때, age만 데이터에 담아서 보내면 PATCH는 age 속성만 갱신되지만, PUT은 age 속성만 남는다.
PUT은 덮어쓰기, PATCH는 일부 수정

(2) HEAD

GET 메소드와 동일, 하지만 딱 헤드 부분만 받는다.
ex) 영화를 보기 전 컨텐츠 용량을 나타내는 헤더를 통해 파일의 용량 정보를 알게 되고 이 용량을 사용자에게 보여주고 그래도 영화 파일을 시청할 건지 물어보는 코드 작성 가능

post-custom-banner

0개의 댓글