[js] js 개인 정리

20210321

20210321_002317

홈페이지에 요청보내고 출력을 하는 코드 실행하면 자바스크립트 실행되고 출력결과가 서버로 부터 받은 응답의 내용을 출력해줌.


fetch

-> 서버에 리퀘스트 보내고 리스폰 받는거 오늘은 fetch 쓰는게 보편적. 이외의 방법은 후술. fetch함수는 파라미터로 넘어온 url로 리퀘스트를 보냄.

20210321_003036

서버로부터 response 받으면 처리할 부분이 그 아래의 response.text가 실행되고 그걸 response라는 객체에 저장한다.

이 함수가 fetch 함수 실행될 때 바로 실행되는게 아니라 response 가 실행되고 실행하고 이렇게 어느 조건 만족시켜야 실행하는 함수가 콜백함수라 한다.

.then메서드는 callback을 등록해주는 메서드. fetch함수가 리턴하는 어떤 객체의 메서. 이 객체는 promise 객체라 한다. promise의 then메서드는 콜백을 등록한 메서드가 서버에 리스폰이 왔을 때 그 콜백이 실행된다.

그 아래 then은 위의 then메서드가 실행 된 후 실행.

20210321_003416

여기서 중요한 건 이전 함수의 리턴값을 다음함수가 이어받을 수 있다.

fetch(‘https://www.google.com’) .then((response) => response.text()) .then((result) => { console.log(result); });

이전 영상에서는 fetch 함수로 리퀘스트를 보내고, 리스폰스를 받아서 그 내용을 출력해봤습니다. fetch 함수의 실행 원리를 다시 정리하자면,

fetch 함수는 어떤 객체를 리턴하는데(Promise 객체, 챕터 3에서 배웁니다) 이 객체의 then 메소드로, ‘리스폰스가 왔을 때 실행할 콜백’을 등록할 수 있습니다. 이렇게 등록된 콜백들은 then 메소드로 등록한 순서대로 실행되고, 이때 이전 콜백의 리턴값을 이후 콜백이 넘겨받아서 사용할 수 있는데요. 그런데 예리한 분들은 이 코드를 보고 이런 궁금증이 생겼을 수도 있습니다.

위 코드처럼 적지 않고 그냥

fetch(‘https://www.google.com’) .then((response) => { console.log(response); });

‘이렇게 코드를 적어도 리스폰스의 내용을 출력할 수 있지 않나요?’ 라는 의문을 가지셨을 수도 있는데요.

사실 이 response 파라미터로는 리스폰스의 실제 내용 자체가 넘어오는 게 아닙니다. response 파라미터에는, 리스폰스에 관한 각종 부가 정보들과, 실제 내용을 함께 갖고 있는 하나의 객체(object)가 넘어오는데요. 그래서 우리가 원하는 리스폰스의 실제 내용을 보려면,

fetch(‘https://www.google.com’) .then((response) => response.text()) .then((result) => { console.log(result); });

이렇게 reponse 객체의 text라는 메소드를 호출해야 합니다. 그리고 이 text 메소드의 리턴값이 바로 리스폰스의 실제 내용입니다.(사실은 실제 내용을 갖고 있는 Promise 객체이지만, 더 자세한 내용은 챕터 3에서 알아봅시다)

왜 바로 response를 출력하지 않았는지 아시겠죠? 사실 이 코드를 완벽하게 해석하려면 좀 더 많은 내용을 알아야 합니다. 그런 내용은 곧 챕터 3에서 배울 거니까 일단은 이런 식으로 리스폰스를 받아서 처리할 수 있다는 정도만 기억하고 갑시다.


이전 영상에서는 크롬 웹 브라우저의 ‘개발자 도구’에서 자바스크립트 코드를 실행했습니다. 오늘날 많은 웹 브라우저들이 이렇게 개발자 도구를 포함하고 있는데요. 이번 노트에서는 개발자 도구에 관해 알아야 할 사실들을 배워보겠습니다.

  1. 개발자 도구란? 웹 브라우저에 내장된 개발자 도구는, 웹 브라우저가 내부적으로 어떤 동작을 하고 있는지 살펴보게 해주는 도구입니다. 사실 일반 사용자들에게는 필요 없는 도구이지만, 웹 페이지를 만드는 개발자 즉, ‘웹 프론트엔드 개발자’에게 이 개발자 도구는 정말 중요한 도구입니다. 왜냐하면 이 개발자 도구를 사용해서 자신이 작성한 코드를 브라우저가 어떻게 해석하고 실행하는지 자세하게 살펴볼 수 있기 때문인데요.

그래서 웹 프론트엔드 개발자가 되고 싶은 분이라면, 이 개발자 도구의 기초적인 사용법을 익혀두는 게 좋습니다. 하지만 이번 토픽은 개발자 도구 사용법에 관한 토픽은 아니기 때문에 사용법을 별도로 배우지는 않습니다. 혹시 크롬의 개발자 도구를 별도로 공부해보고 싶은 분은 구글에서 제공하는 공식 설명을 참조하세요. 해당 링크를 방문했을 때 모든 내용이 영어라서 보기가 힘들다면,

페이지 우측 상단의 버튼을 클릭해서 언어를 바꿔볼 수 있습니다. 참고로 개발자 도구 사용법을 몰라도 이번 토픽을 듣는 데는 아무 지장이 없습니다. 안심하세요.

  1. 개발자 도구를 여는 단축키 자바스크립트를 실행하는 방법에는 여러 가지가 있습니다. 보통은 HTML 태그에서 자바스크립트 파일을 로드해서 실행하지만, 이번 토픽에서는 보다 빠르고 직관적인 결과 확인을 위해서, 개발자 도구에서 자바스크립트를 실행할 겁니다. 따라서 웹 브라우저에서 매번 마우스로 개발자 도구를 여는 것보다는 그 단축키를 알아두는 것이 효율적인데요. 크롬에서 개발자 도구를 여는 단축키는 다음과 같습니다.

Mac : Command 키 + Option 키 + 알파벳 i 키 Windows : Ctrl 키 + Shift 키 + 알파벳 i 키 각자 자신의 환경에 맞는 단축키를 외우고, 활용해보세요.

  1. 개발자 도구 위치 설정 개발자 도구를 처음 여는 분들은 개발자 도구 창이 전체 화면의 오른쪽에 떠 있을 수도 있습니다.

만약 이전 영상에서 본 것처럼, 개발자 도구의 위치를 화면 하단으로 옮기고 싶다면, 위 이미지에서 보이는 빨간색 박스 안의 점 세 개 아이콘을 클릭하세요. 그럼 다음과 같이

개발자 도구의 위치를 설정하는 탭을 볼 수 있습니다. 여기서 여러분이 원하는 위치를 자유롭게 선택하시면 됩니다.

  1. Console 탭의 출력 원리 앞으로 여러분은 개발자 도구의 Console 탭에서 자바스크립트 코드를 실행하게 될 겁니다.

그런데 Console 탭의 출력 결과에 관해 여러분이 알아둬야 할 내용이 있습니다. 잠깐 Console 탭 화면에서, 어떤 숫자를 합한 값을 리턴해주는 add라는 함수를 정의해보겠습니다. 함수를 정의하고 엔터를 치면

20210321_005011

이런 식으로 그 뒤에 undefined가 출력되는 것을 알 수 있습니다. 이 undefined는 왜 출력된 걸까요? 이번엔 잠깐 이 add 함수를 실행해봅시다.

이번에는 add 함수가 리턴한 값인 3이 잘 출력되었습니다. 자, 이번엔 Hello라는 단어를 출력해보겠습니다.

이번에는 Hello라는 단어가 출력되고, 그 밑에 또 undefined가 출력되었습니다. 이번에도 undefined가 등장했네요. 자, 그럼 이제 add 함수를 여러 번 호출해볼까요?

이렇게 코드를 여러 줄 연달아 작성하려면 Enter 말고 Shift + Enter를 사용하시면 됩니다. 실행 결과를 보니 가장 마지막 add 함수의 리턴값인 201만 출력되네요.

이때까지 본 것처럼 개발자 도구의 Console 탭은 해당 코드에서 최종적으로 리턴하는 값을 출력합니다. 만약 아무런 값도 리턴하지 않는 경우에는 undefined를 리턴한 것으로 간주하는데요. 그래서 위에서 봤던 것처럼 단순히

(1) add 함수를 선언하거나, (2) Hello라는 문자열을 출력하는 코드는

어떤 값을 리턴하는 코드는 아니기 때문에 undefined를 리턴한 것으로 간주해서 undefined가 출력된 것입니다. 하지만

add(1, 2) 처럼 실제로 어떤 값을 리턴하는 코드인 경우에는 undefined가 아닌 실제 리턴값 3이 출력됩니다. 그리고 위에서 add 함수를 여러 번 실행한 경우처럼, 여러 개의 리턴 값이 존재하는 경우에는, 가장 마지막 코드의 리턴값을 출력합니다.

앞으로 Console 탭의 자바스크립트 코드를 실행하다보면,

(1) 개발자 도구가 출력하는 undefined 때문에 당황하거나, (2) 나의 코드에서 출력한 undefined와, 개발자 도구가 출력한 undefined가 섞여서 혼란스러울 수도 있는데요.

그럴 때마다 방금 배운 내용에 유의하면서, Console 탭에서의 출력 결과를 해석하시면 됩니다.


웹이란?

20210321_005608

World WIde web (거미줄, 연결망을 의미하다) -> 전 세계적으로 연결 된 통신망

웹 브라우저를 통해 돌아다니는 가상의 연결망을 의미한다.

HyperText = 다른 텍스트에 참조

20210321_005807

HTML이 이 의미


URL이란?

20210321_010038

-> 웹에 존재하는 특정 데이터를 나타내는 문자열

20210321_010153

호스트는 특정 서버 지칭 전세계의 수많은 서버 중 하나의 도메인에 해당하는 걸 특정.

20210321_010438

경로(path)는 서버에 있는 데이터 중 원하는 데이터 특정. 서버마다 다르게 설정 남성용 상품 중 셔츠 나타냄. 다른 서버에서는 다르게 나타낼 수 있음. 이건 개발자들이 정함. 이걸 잘 설계하는 게 개발자의 역할. path는 서버안의 데이터를 나타냄.

20210321_010603

?뒤의 부분은 쿼리 데이터에 대한 세부적인 요구사항

20210321_010624


이전 영상에서는 웹에 존재하는 수많은 데이터 중에서 원하는 데이터를 특정하기 위해 URL을 사용한다는 사실을 배웠습니다. 그리고 URL은 크게

호스트(host), 패스(path), 쿼리(query) 로 이루어져있다는 걸 배웠는데요.(다른 구성 요소들도 있지만 일단은 일반적으로 보게 되는 것들만 배워봅시다.) 이번 노트에서는 URL에 관한 또 다른 궁금증들을 해결해봅시다.

  1. 전 URL을 직접 입력한 적이 거의 없는데요? 이전 영상에서 URL의 의미와 구조에 대해 배울 때, 여러분은 이런 의문을 가졌을 수도 있습니다.

‘내가 URL을 직접 입력한 적은 거의 없는데?’

하는 의문 말이죠.

굉장히 의미 있는 생각입니다. 여러분이 웹 서핑을 할 때를 생각해봅시다. 여러분은 보통 웹 브라우저의 주소창에 www.naver.com나 www.google.com 처럼, URL에서의 호스트(host) 부분까지만 입력하고, 어떤 서비스의 메인 페이지로 진입할 겁니다. 그리고 그 뒤로는 마우스로 화면에 있는 이미지나 버튼 등을 클릭할 뿐, 더이상 URL을 직접 입력할 일이 많지는 않은데요. 그 이유는 바로, 이미 여러분이 화면에서 클릭하는 버튼 등에 어느 URL로 새로운 리퀘스트를 보낼지, HTML 코드 또는 Javascript 코드로 다 작성이 되어있기 때문입니다. 예를 들어, 여러분이 화면에서 클릭하는 버튼은 이런 식의 HTML 코드로 작성되어 있습니다.

<a href=”https://www.nazer.com/blogs/codeitOfficial/120”…>…</a> <a href=”/codeitCommunity/threads/731” …>…</a> (지금 두 번째 URL은 상대 URL입니다. 같은 서버 안에 존재하는 데이터의 경우 이렇게 path 이후의 부분만 표시해서 나타낼 수도 있습니다.)

우리가 웹 페이지에서 버튼을 클릭하면 지금 보이는 것 같은 a 태그의 href 속성에 적힌 URL 주소로 웹 브라우저가 알아서 리퀘스트를 보내서 리스폰스를 받아 새로운 웹 페이지를 로드합니다. 이런 식으로 웹 페이지에 미리 모든 것이 세팅되어 있기 때문에 여러분은 해당 서비스의 서버에서 요구하는 path의 형식, query의 형식을 알 필요가 없습니다. 다만 의식하지 않는 상태에서 우리는 계속 URL을 사용하고 있는 겁니다.

하지만 일반 사용자가 아닌 개발자라면, 이런 path에 관한 설계, query에 관한 설계를 직접 해야 하기 때문에 URL의 구조에 대해서 정확하게 알고 있어야 합니다.

  1. 리퀘스트를 보내면 일어나는 일 우리가 웹 브라우저의 주소창에 URL을 입력하고 엔터를 치면, 실제로 어떤 일이 이루어지는 걸까요? 잠깐 아래 그림을 봅시다.

위 이미지에서 왼쪽 아이콘은 웹 브라우저를 나타내고, 오른쪽은 codeitshopping이라고 하는 서비스의 서버를 나타낸다고 가정해봅시다. 만약 우리가 위와 같은 URL을 입력하고 엔터를 치면 다음과 같은 일들이 순차적으로 발생합니다.

(1) 웹 브라우저는 URL에서 호스트(host, 위 그림에서 www.codeitshopping.com에 해당하는 부분) 부분을 보고, 전 세계의 수많은 서버들 중에서 정확히 어느 서버와 통신을 해야 하는지를 찾습니다. 이때 호스트 부분에 적힌 www.codeitshopping.com 같은 것을 도메인 네임(Domain Name)이라고 하는데요. 특정 서버를, 외우기 어려운 IP 주소가 아니라 외우기 쉬운 문자열로 나타낸 것이 바로 도메인 네임입니다. 그럼 어떻게 웹 브라우저는 도메인 네임만으로 특정 서버를 식별할 수 있는 걸까요? 이를 위해서는 Domain Name Resolution이라고 하는 작업을 수행해야 합니다. 이 작업을 수행하면 해당 도메인 네임이 나타내는 특정 서버를 식별할 수 있는데요. 혹시 Domain Name Resolution이 뭔지 궁금한 분들은 코드잇의 또 다른 토픽에 있는 ‘도메인 네임과 IP 주소’ 노트를 참조하세요.

(2) (1)에서 어떤 서버와 통신해야 하는지를 식별하고 나면, 웹 브라우저는 해당 서버로 리퀘스트를 보냅니다. 이때 URL에서 path 이후의 부분들(보라색 표시한 부분, path와 query)을 리퀘스트에 담아서 보냅니다.

(3) 리퀘스트를 받은 서버는 리퀘스트에 담긴 path 이후의 부분들을 보고, 그것이 의미하는 데이터를 찾고, 찾은 결과를 리스폰스에 담아서 보내줍니다.

(4) 그럼 웹 브라우저는 받은 리스폰스의 내용을 갖고 사용자에게 보여줍니다. 이때 리스폰스의 내용이 HTML 코드, Javascript 코드 등에 해당하면 그에 맞는 예쁜 화면을 사용자에게 그려서 보여주는 것이구요. 리스폰스의 내용에는 다른 종류도 많은데요. 이건 챕터 2에서 배워봅시다.

이때까지 우리가 브라우저에서 URL을 입력하고 엔터를 치면 발생하는 일에 대해 배워봤는데요. URL을 기반으로 해서 실제 리퀘스트가 어떻게 이루어지는지 어느 정도 감이 오시죠?


Https란?

스킴 -> 프로토콜의 이름

프로토콜 -> 통신 하는 두 주체가 지켜야 하는 통신 규약(웹 브라우저와 서버가 지켜야 하는규약 )

20210321_011743

20210321_012037

웹 브라우저 서버 각 리퀘스트와 리스폰 둘다 제대로 이뤄져야한다.

20210321_012237

http는(HyperText Transfer Protocol Secure) 하이퍼 텍스트 전송하는거

요즘은 텍스트 뿐 아니라 이미지, 소리, 영상도 보낸다.

여기에 보안성이 더해진 s를 붙여서 더 사용한다. Secure

20210321_012259


우리가 어떤 웹 페이지를 보기 위해 URL을 입력하고 엔터를 치면 보통 한 번 이상의 리퀘스트와 리스폰스가 오고 갑니다. 딱 한 번의 리퀘스트와 리스폰스만 오고 가면 될 것 같은데, 이게 무슨 말일까요? 확인해보겠습니다.

저는 지금 크롬의 개발자 도구를 열어두었습니다. 20210321_013446

그리고 개발자 도구에서 Network 탭이라고 하는 걸 클릭했는데요. 이 Network 탭에서는 브라우저가 구체적으로 어떻게 생긴 리퀘스트를 보내고, 어떻게 생긴 리스폰스를 받는지를 보여줍니다. 이 상태에서 웹 브라우를 새로고침해보겠습니다.

20210321_013505

그럼 구글 메인 페이지로 재접속하게 되고, 이제 Network 탭에 여러 개의 줄(row)들이 뜨는데요. 이때 각각의 한 줄이, 하나의 ‘리퀘스트-리스폰스’ 쌍이라고 보시면 됩니다. 전 딱 한 번 엔터를 쳤을 뿐인데 정말 많은 수의 리퀘스트와 리스폰스가 오고 갔죠? 화면 하단을 보면 총 19번의 리퀘스트가 전송된 것을 알 수 있는데요. 왜 이런 일이 발생하는 걸까요?

사실 웹 브라우저가 처음으로 리퀘스트를 보내고, 서버로부터 받는 첫 리스폰스의 내용만으로 온전한 화면을 그릴 수 있는 경우는 많지 않습니다. 보통은 받은 첫 리스폰스의 내용에 적힌 ‘추가적으로 필요한 데이터’들을 재차 요청해야 하는 것이 더 일반적입니다. 예를 들어, 이런 식의 HTML 코드가 첫 리스폰스의 내용으로 왔다고 해봅시다.

<html>
<head></head>
<body>
    ...
    <div>
        <img src="https://www.server_A.com/a/b/exmaple.png".../>
    </div>
  ...
<script src="http://www.server_B.com/c/d/main.js"></script>
</body>
</html>

웹 브라우저는 당장 이 코드만으로는 완벽한 화면을 그릴 수 없습니다. 왜냐하면 새롭게 리퀘스트를 보내서 가져와야할 것들이 존재하기 때문이죠.

예를 들어, 지금 여기서 이 img 태그의 src 속성에 있는 이미지를 그리려면

<img src="https://www.server_A.com/a/b/exmaple.png".../>

img 태그의 src 속성에 적힌 URL로 다시 리퀘스트를 보내서 example.png에 해당하는 이미지를 받아와야 합니다.

그리고

<script src="http://www.server_B.com/c/d/main.js"></script>

이 script 태그의 src 속성에 적힌 URL로도 리퀘스트를 보내서 main.js라는 자바스크립트 파일을 받아와야 하구요.

벌써 이렇게 2번의 추가적인 리퀘스트가 필요한 겁니다.

이런 식으로 보통 브라우저가 하나의 페이지를 그릴 때는 첫 리스폰스의 내용 안에서 또다시 요구되는, 여러 가지 다른 것들을 구하기 위해 다시 여러 개의 리퀘스트를 보내는 것이 일반적입니다. 게다가 그렇게 또 받은 리스폰스의 내용에 따라 또 새로운 리퀘스트를 보내야 할 수도 있습니다. 바로 이런 원리 때문에 여러분이 어떤 웹 페이지를 딱 한번 접속했다고 해도 그 사이에는 수많은 리퀘스트와 리스폰스가 발생하는 겁니다.

예를 들어, 지금 Network 탭에 보이는 하나의 줄(하나의 ‘리퀘스트-리스폰스 쌍’)을 클릭해보면

20210321_013613

https://bakey-api.codeit.kr/api/files/resource?root=static&seqId=4340&directory=Untitled%202.png&name=Untitled+2.png

이렇게 Google 로고 이미지를 받기 위해 추가적인 리퀘스트를 보내고, 이 이미지를 받아온 것을 확인할 수 있습니다.

이렇게 우리가 웹 브라우저로 특정 페이지에 접속할 때, 보통 한 번 이상의 리퀘스트-리스폰스가 오고간다는 사실, 잘 기억하세요.

실습) fetch 함수를 사용하면, 원하는 URL로 리퀘스트를 보내고 리스폰스를 받을 수 있다는 것을 배웠습니다. 이번 챕터의 영상에서는 fetch 함수로 구글 홈페이지 URL에 리퀘스트를 보내고 리스폰스를 받아서 출력하는 것만 봤는데요. 이번 실습에서 아래의 URL에 리퀘스트를 보내고 그 리스폰스의 내용을 출력하는 코드를 작성해봅시다.

URL : https://workey.codeit.kr/ratings

fetch('https://workey.codeit.kr/ratings')
  .then((response) => response.text())
  .then((result) => { console.log(result); });


개발자가 꼭 알아야할 웹 개발

Web API

20210321_015112

구글 홈페이지로 리퀘스트 보내면 서버가 html과 자바스크립트로 이뤄진 내용을 리스폰으로 보내줌. 그럼 웹브라우저 이 화면을 해석해서 보여준다.

html과 자바스크립트가 담긴 리스폰 말고 어떤 정보가 담긴 response도 있다.

20210321_015248

저 버튼 누르고 위 화살표 눌러서 입력한 코드 다시 가져와서 입력해보자.

기존코드에서 url 부분 바꿔서 저 url로 리스폰 보내면 다른 종류의 response 보내보자

20210321_015344

20210321_015354

보면 일반 html과 js가 아닌 데이터 형식(객체형식) 의 무언가가 콘솔에 출력된다.

이걸 json이라 하는 포맷으로 나타냈다.

방금 구글 url로 보낸 리퀘스트 보내서 받은 리스폰스 내용 웹 브라우저가 화면을 그리기 위해 필요한 정보였는데 이번 순수하게 어떤 정보만을 담은걸 response로 받았다. 개발자면 이런 종류의 데이터를 받을 경우가 더 많다.

지금 이 결과는 웹에서도 바로 확인가능.

JSON(JavaScript Object Notation)

json은 어떤 정보를 교환하기 위해 만들어진 포맷으로 스크립트 언어의 문법을 빌려서 만들어진 데이터 포맷.

그래서 제이슨의 문법은 자바스크립의 문법과 비슷하다.

20210321_020508

이 사진은 사용자 한명을 제이슨 객체로 나타냈다. 중괄호 쓰고 그 안에서 각 프로퍼티 이름과 값을 쓰는게 자바스크립트의 객체 나타낼떄의 방식과 같다. 그리고 이걸 {} 대괄호로 둘러싸서 배열로 나타내는 것도 자바스크립트와 동일하다.

개발자로 일하면 이런 제이슨을 사용하는 경우가 많다. 하지만 자바스크립트와 제이슨의 문법이 100프로 동일하진 않다.


이전 영상에서는 자바스크립트에서 객체와 배열을 나타내는 문법이 그대로 JSON에서 쓰이고 있다고 했습니다. 그런데 이 두 가지가 비슷하기는 하지만 완벽하게 동일한 것은 아닙니다. 아래에서 둘 사이의 차이점에 대해 알아봅시다.

  1. JSON에는 프로퍼티의 이름과 값을 표현하는 방식에 제한이 있습니다. (1) JSON에서는 각 프로퍼티의 이름을 반드시 큰따옴표(“)로 감싸줘야 합니다. 잠깐 자바스크립트 코드로 member라는 객체를 생성해볼까요?
    const member = {
      name: 'Michael Kim',
      height: 180,
      weight: 70,
      hobbies: ['Basketball', 'Listening to music']
    };
    

    자바스크립트에는 객체를 생성할 수 있는 여러 가지 방법이 있는데요. 그중 한 가지는 이런 식으로 중괄호(‘{ }’) 안에 객체의 프로퍼티의 이름(키)과 값(밸류)쌍을 순서대로 나열해서 생성하는 방법입니다. 지금 보이는 표기를 Object Literal이라고 하는데요. Object Literal을 쓸 때는 문법에 약간의 유연함이 있습니다. 저는 지금 member 객체의 각 프로퍼티의 이름인 name, height, weight, hobbies에 큰따옴표를 붙이지 않았는데요. Object Literal에서는 이렇게 프로퍼티의 이름에 큰따옴표를 붙이지 않아도 되고,

    const member = {
      "name": 'Michael Kim',
      "height": 180,
      "weight": 70,
      "hobbies": ['Basketball', 'Listening to music']
    };
    

    이렇게 큰따옴표를 붙여도 됩니다.

하지만 JSON의 경우에는 프로퍼티의 이름에 반드시 큰따옴표를 붙여줘야만 합니다.

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

지금 각 프로퍼티의 이름이 모두 큰따옴표로 둘러싸여 있죠? 이렇게 JSON에서는 각 프로퍼티의 이름을 반드시 큰따옴표로 감싸주어야 합니다. 큰따옴표로 감싸주지 않으면 JSON을 처리하려고 할 때 에러가 납니다.

(2) JSON에서는 값이 문자열인 경우 큰따옴표(“)를 사용해야 합니다.

const member = {
  "name": 'Michael Kim',
  "height": 180,
  "weight": 70,
  "hobbies": ['Basketball', 'Listening to music']
};

잠깐 member 객체를 다시 볼게요. 지금 name 프로퍼티의 값으로 ‘Michael Kim’이라는 문자열이 들어가 있죠? 자바스크립트에서는 문자열을 나타낼 때, 이렇게 작은따옴표(‘)를 써도 되고, 큰따옴표(“)를 써서 “Michael Kim”이라고 써도 됩니다.

하지만 JSON에서는 문자열 값을

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

지금 보이는 “Michael Kim”, “Basketball”, “Listening to music”처럼 항상 큰따옴표로 감싸서 적어줘야만 합니다.

  1. JSON에서는 표현할 수 없는 값들이 있습니다. 자바스크립트에서는 프로퍼티의 값으로 사용할 수 있는 undefined, NaN, Infinity 등을 JSON에서는 사용할 수 없습니다. 참고로, JSON은 비록 자바스크립트로부터 비롯된 데이터 포맷이지만, 그 탄생 목적은 언어나 환경에 종속되지 않고, 언제 어디서든 사용할 수 있는 데이터 포맷이 되는 것이었습니다. 따라서 자바스크립트의 문법에서만 유효한 개념을 JSON에서는 나타낼 수 없다는 것은 어찌 보면 당연한 결과입니다.

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

자, 이때까지 자바스크립트의 문법과 JSON 문법 간의 미세한 차이를 배워봤는데요. 이 둘은 일반적으로 호환되는 것이 맞지만, 위에서 살펴본 세부적인 차이가 있다는 점을 알아두는 게 좋습니다. 이런 차이가 있다는 것을 모르면, 나중에 실무에서 JSON 데이터를 처리하다가 에러가 생겨도, 그 이유를 이해할 수 없기 때문입니다.

자바스크립트 문법과 JSON 문법 간의 차이가 더 궁금한 분들은 이 링크를 참조하세요.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON


Json 데이터를 객체로 변경하기

20210321_021339

이 부분은 String 타입이다.

typeof 연산자로 확인해보면 string타입이 나오고 저 response 부분에서 string 타입으로 넘겨주는 거.

20210321_021440

얘를 들어 위의 json에서 이름만 추출하고 싶으 현재 string타입에 문자열 넣고 할 수는 있겠지만 그럴 필요가 없다. String 타입의 json은 바로 자바스크립트의 객체로 변경이 가능하기 때문이다.

20210321_021637

저 JSON 부분은 제이슨 데이터를 다루기 위해 사용되는 기본 객체이다.

제이슨이라는 객체에 parse라는 걸 사용하면 string타입의 객체를 자바스크립트로 변환이 가능하다.

다르게 표현하면 스트링 타입의 json데이터 타입에 표현 가능 그게 뒤에 있는 parse가 하는 기능이다.

20210321_022408

스트링 타입의 제이슨 데이터에 표현된 사용자 정보들의 배열을 실제로 자바스크립트의 배열로 변환한다는 뜻.

그 변환한 거로 users 객체에 넣어줬다.

20210321_023755

배열의 각 요소 순회하면서 각 파라미터로 받은걸 실행하는 거.

20210321_023848

방금 말한 것 처 스트링 타입의 json 타입은 자바스크립트 객체로 변환해줘야 한다.

자바스크립트의 내장 객체인 Json객체의 parse 메서드를 사용했다는 걸 잊지 말자.


실습)

이번에 코드잇에 신입 개발자로 입사한 태우는 간단한 업무 하나를 맡게 되었습니다. 그건 바로 코드잇에 있는 모든 토픽들 중에서, 그 난이도가 ‘초급’에 해당하는 토픽들만을 추려서 그 평균 별점을 계산하는 업무인데요. 아래의 URL로 리퀘스트를 보내면 코드잇의 모든 토픽 정보를 받을 수 있다는 점은 전달받았습니다.

fetch('https://learn.codeit.kr/api/topics')
   .then((response) => response.text())
   .then((result) => { console.log(result) })


URL : https://learn.codeit.kr/api/topics

fetch 함수를 사용해서 이 URL로 리퀘스트를 보내면, 코드잇 토픽들의 정보를 담고 있는 JSON 데이터를 받을 수 있는데요. 일단 코드잇의 ‘초급’ 토픽들만 추려서 그 정보를 출력해보겠습니다. 지금 코드잇 실행기에, 토픽 정보가 담긴 배열에서 ‘초급’에 해당하는 토픽들만 추려내는 코드는 이미 작성되어 있습니다. 현재 코드에서 빠진 코드가 뭔지 잘 생각해보고, 채워넣어 보세요.

힌트0/2 해설 보기 과제 해설close solution tab 모범 답안

fetch('https://learn.codeit.kr/api/topics')
  .then((response) => response.text())
  .then((result) => {
    const topics = JSON.parse(result);
    const beginnerLevelTopics = topics.filter((topic) => topic.difficulty === '초급');
    console.log(beginnerLevelTopics);
  });

문제의 URL로 리퀘스트를 보내면

[
   {
      "id":1,
      "title":"업무 자동화 for Windows",
      "keyword":"Python",
      "difficulty":"초급"
   },
   {
      "id":2,
      "title":"업무 자동화 for Mac",
      "keyword":"Python",
      "difficulty":"초급"
   },
   {
      "id":3,
      "title":"프로그래밍 기초 in JavaScript",
      "keyword":"JavaScript",
      "difficulty":"초급"
   },
...
]

이렇게 리스폰스의 내용으로 토픽 정보가 담긴 JSON 데이터가 옵니다. 그런데 이 JSON 데이터가

이 코드에서 result 파라미터로 넘어올 때는 그 데이터 타입이 string이기 때문에 자바스크립트 객체로 변환을 해줘야 합니다. 이를 위해서 자바스크립트의 기본 내장 객체인 JSON이라는 객체의 parse 메소드의 파라미터로 해당 JSON 데이터를 넣고 실행하면 되는데요.

그럼 JSON 데이터에서 현재 배열로 표현돼있는 부분이, 실제로 자바스크립트 배열(객체)로 변환되어서 코드 상에서 자유롭게 사용할 수 있게 됩니다. 이렇게 string 타입의 JSON 데이터를 실제 자바스크립트 객체로 변환하는 것을 Deserialization, 우리말로는 역직렬화라고 합니다. 아주 중요한 개념이니까 잘 기억해두세요.

Deserialization 이후의 나머지 코드를 보면, topics 배열의 filter 메소드를 사용해서 각 요소의 difficulty 프로퍼티(토픽의 난이도) 값이 ‘초급’에 해당하는 것들만 추출해서 만든 새로운 배열을 리턴하고 있습니다. 그리고 마지막에 초급 토픽들로 이루어진 배열을 출력하고 있네요.

개발자가 되면 이번 과제에서 한 것처럼 리스폰스의 내용으로 오는 JSON 데이터를 다뤄야할 경우가 많습니다. 그리고 이때는 보통 string 타입의 JSON 데이터를 자바스크립트 객체로 만드는 Deserialization을 먼저 수행한다는 사실, 꼭 기억하세요.


어떤 데이터를 보내기 위해 request를 했는데 다른 성격의 request도 존재한다.

서버에 어떤 데이터를 추가해 달라는 데이터를 보내건다 할 수있다 리퀘스트는 종류에 따라 4개로 나눌 수 있다.

  1. 서버의 데이터 조회
  2. 서버의 데이터 추가
  3. 서버의 데이터 수정
  4. 서버의 데이터 삭제 이게 (CRUD)이다.

이걸 아는 법은 리퀘스트의 메서드를 통해 알 수 있다.

20210321_025851

20210321_030134


Request의 Head와 Body

리퀘스트 메서드 값이 어떻게 설정되어있나 Request는 head와 body로 이뤄져 있다.

20210321_032535

Head는 부가정보가 들어가 있고 메서드가 헤드에 들어간다 Body는 실제 데이터를 담는 부분. 리퀘스트 보낼때 실 데이터는 바디에 들어간다.

20210321_033531

데이터 추가하려는 post나 수정하려는 pust은 body에 넣어서 보내줘야 하는데 데이터 가져오는 get이나 삭제하는 delete메서드에서는 body가 필요하지 않다.

20210321_033612

콘솔에 이전 꺼 넣어서 실행해보자 이전처럼 response내용 잘 출력

개발자도구에서 NetWork탭

여기서 네트워크가 준 리퀘스트와 리스폰을 저기를 누르면 볼 수 있고 Headers 부분을 클릭하면 리퀘스트 정보를 볼 수 있다.

20210321_033740

헤더란 헤드 안에 존재하는 하나하나의 쌍이다. 각각의 헤더들은 리퀘스트에 대한 부가정보를 갖고 있고 리퀘스트를 갖는 서버가 알았으면 하는 정보를 담고 있다.

20210321_033907

우리가 배운 메서드가 있다(method:get)

현재 리퀘스트가 데이터를 조회하려는 get리퀘스트임을 알 수 있다.

메서드 값은 리퀘스트에 헤더에 존재한다(아주 중요)

path라는 헤더는 url구조 할떄 봤었다. 패스 정보가 리퀘스트 헤더에 있으므로 웹 브라우저가 무슨 정보를 원하는 지 알 수있다.

아래엔 user-agent정보도 있는데 request를 보낸 브라우저와 os를 알 수 있다.

만약 서버에서 웹브라우저 정보를 수집하면 이 헤더의 값을 수

이 헤더들에는 다양한 정보가 존재한다.

헤더는 종류가 많아서 외우기도 힘들고 그럴 필요도 없다. 필요시마다 검색을 통해 해결하자 request body도 봐야하는데 이건 데이터가 존재하는지 확인하는 get메서드이기 떄문에 body가 없어서 post나 put메서드 할때 봐야한다.


이제 우리는 웹 브라우저가 서버로 보내는 리퀘스트의 종류에 크게 다음과 같은 4가지 종류가 있다는 걸 배웠습니다.

기존 데이터를 조회하는 리퀘스트 - GET 새 데이터를 추가하는 리퀘스트 - POST 기존 데이터를 수정하는 리퀘스트 - PUT 기존 데이터를 삭제하는 리퀘스트 - DELETE 그리고 각 리퀘스트의 종류에 따라 리퀘스트의 헤드에, 오른쪽에 써있는 각각의 method(메소드)를 설정해야 한다는 것도 배웠는데요.

다음 영상부터는 이때까지 우리가 해온 GET 리퀘스트 뿐만 아니라 POST 리퀘스트, PUT 리퀘스트, DELETE 리퀘스트도 차례대로 직접 수행해볼 겁니다. 그리고 이를 위해서 코드잇에서 제공하는 다음과 같은 학습용 URL을 사용할 건데요.

학습용 URL : https://learn.codeit.kr/api/members 이 URL을 사용해서 다음과 같은 작업들을 순차적으로 진행해볼 겁니다.

(1) 전체 직원 정보 조회 - GET (2) 특정 직원 정보 조회 - GET (3) 새 직원 정보 추가 - POST (4) 기존 직원 정보 수정 - PUT (5) 기존 직원 정보 삭제 - DELETE

각 작업을 위해 리퀘스트의 헤드에 무슨 메소드를 설정해야하는지 기억해두세요.

그리고 마지막으로 한 가지 더 기억해야할 중요한 내용이 있습니다. 그건 위의 5가지 작업을 수행할 때 사용하는 URL의 유형에 크게 2가지가 있다는 점입니다.

위의 5가지 작업 중

(2) 특정 직원 정보 조회 - GET (4) 기존 직원 정보 수정 - PUT (5) 기존 직원 정보 삭제 - DELETE

이 작업들을 수행할 때는 작업의 대상이 되는 직원 정보를 특정할 수 있도록 URL 끝에 아래와 같은 고유 식별자를 붙여줘야 합니다. (직원의 id 값입니다.)

https://learn.codeit.kr/api/members/3 지금 이 URL은 3번 직원 정보에 대한 작업을 수행하겠다는 뜻입니다. 이렇게 작업의 종류에 따라 메소드뿐만 아니라 URL도 적절하게 변경해가며 써줘야 합니다.

그리고 나머지 작업인

(1) 전체 직원 정보 조회 - GET (3) 새 직원 정보 추가 - POST

들은 특정 직원 정보를 대상으로 수행하는 작업이 아니라 아니라 전체 직원 정보에 대해서 수행하는 작업이기 때문에

https://learn.codeit.kr/api/members /members로 끝나는 원래의 URL을 그대로 사용하면 됩니다.

이 내용을 잘 기억해두고 다음 영상으로 갑시다.


20210321_034528

이건 어떤 회사의 직원의 정보를 나타내는 데이 이 url의 순서대로 put,get,post,delete를 보내보자

get은 그대로 보내보자.

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

20210321_035605

특정 직업의 사워 조회하고 싶으면 members뒤에 조건을 더 넣어주면 된다.

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

아이디 3인 사원 브라이언만 출력 될거.

post request는 추가해야할 사원 정보를 body에 넣어줘야한다.

새로운 직원 객체를 나타내는 newMember객체 정의함

20210321_040204

저 부분이 객체인데 옵션객체라 한다.

url 뒤에 새로운 객체가 새로운 argument가 설정되어있는(추가) 새 아규먼트 리퀘스트에 관한 새로운 설정을 해주는데, 앞으로 이 객체를 옵션객체라 부른다.

const newMember = {
  name:'Jerry',
  email:'jerry@codeitmall.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); });


get 리퀘스트 보낼때는 이런게 없었는데 fetch함수는 디폴트가 get이기 때문.

그래서 get이 아닌 다른 메서드 값을 보내려 이런 옵션 객체가 필요하다.

리퀘스트의 메서드를 post로 설정. body부분이 리퀘스트에 담을 바디부분을 설정하는 것.

새로운 직원객체를 가진 뉴멤버를 바로 넣은게 아니라 이전에 배운 제이슨 객체가 보인다. 제이슨 객체에 stringify해서 그 결과를 설정했다. 왜?

예전에 스트링타입의 제이슨 타입 자바스크립트 객체로 변환하기 위해 parse메서드를 썼는데 stringify는 정 반대의 기능

Stringfy는 자바스크립트 객체를 스트링 타입으로 변환. 어떤 자바스크립트객체에 담긴 내용을 외부에 전송하고 싶으면 Stringfy로 타입을 변환해야한다.

자바스크립트 자체로는 외부에 바로 전송이 안되기 떄문이다.

20210321_041628

근데 id는 새로운 정보 추가할 때 서버의 데이터 베이스에서 새로 설정해주는 값을 설정해 주는데 post 리퀘스트 하면 추가 되는게 다를 수 있다. 어떤 리스폰스 줄지는 개발자 설계에 따라 달라지므로 당연.

20210321_041741

post리퀘스트 보낼때는 get리퀘스트 보낼때와 달리 fetch함수의 두번쨰 파라미터에 옵션 객체를 넣어줘야 했는데 옵션객체에 메서드값과 바디의 내용을 설정했다는 걸 잘 기억해두자.


이전 영상에서는 처음으로 GET 리퀘스트가 아닌, POST 리퀘스트를 보내봤습니다. 우리는 리퀘스트의 헤드와 바디에 대해서 배울 때 GET 리퀘스트를 가지고 배웠는데요. POST 리퀘스트의 경우에는 리퀘스트의 헤드와 바디가 어떻게 생겼는지 살펴봅시다. 개발자 도구의 Network 탭을 사용해서 확인해볼게요.

20210321_042706

이렇게 이전 영상에서처럼 새 직원 정보를 POST 리퀘스트로 추가하고 Network 탭을 클릭할게요.

20210321_042735

그리고나면 뜨게 되는 화면에서 제가 보낸 POST 리퀘스트와 받은 리스폰스 쌍을 의미하는 한 줄(members)을 클릭할게요. 그다음 오른쪽 화면을 보면 지금 Request Method 부분에 POST라고 써있는게 보입니다.

자, 그리고 이번에는 GET 리퀘스트 때는 보지 못했던 바디도 확인해보겠습니다. 스크롤을 좀 더 내려보면

20210321_042755

이렇게 Request Payload라고 쓰인 부분이 바로 리퀘스트의 바디 부분입니다. 새 직원 정보를 나타내는 JSON 데이터가 잘 들어가 있죠? GET 리퀘스트 때는 없었던 바디의 내용을 POST 리퀘스트에서는 볼 수 있네요.

그리고 Response 탭을 눌러보면,

20210321_042830

이렇게 실제로 추가된 직원 정보가 JSON 데이터로 잘 온 것을 알 수 있습니다.

앞으로 여러분도 자바스크립트로 웹 통신을 할 때, 이렇게 개발자 도구로 리퀘스트와 리스폰스의 모습을 종종 살펴보세요. 그럼 현재 무슨 일이 이루어지고 있는지 훨씬 실감나게 느낄 수 있을 겁니다.


put, delete request

PUT 메서드로 수정을 해보자.

id2를 가진 사원 Alice의 부서를 수정하는 코드

20210321_043425 에서

20210321_043446 이와같이 넣고 실행하면

const member = {
  name:'Alice',
  email:'alice@codeitmall.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); });


20210321_043415

값 변경을 확인할 수 있다

DELETE 메서드도 확인해보자

20210321_043608


fetch('https://learn.codeit.kr/api/members/2',
{
  method:'DELETE',

  .then((response) => response.text())
  .then((result) => { console.log(result); });


delete메서드는 삭제요청이라 바디가 필요없다.

20210321_043639

삭제되어서 보이지 않는다.

이러한 작업들을 하기 위해 fetch함수를 어떻게 사용했는지 잘 알아두자.


덤(WEB API)

우리는 이제 웹 브라우저가 리퀘스트를 보낼 때

(1) 어느 URL로 리퀘스트를 보내는지 (2) 무슨 메소드(GET, POST, PUT, DELETE 등)가 그 헤드에 설정되어있는지가

중요하다는 것을 배웠습니다.

그런데 우리가 어떤 리퀘스트를 보냈을 때, 무슨 리스폰스를 받는지는 어떻게 설계되는 걸까요? 개발자들이 실제로 개발을 할 때 이 부분을 어떻게 만들고 있는지 이번 노트에서 배워보겠습니다.

  1. Web API 우리가 어떤 리퀘스트를 보냈을 때, 무슨 리스폰스를 받는지는 모두 그 서비스를 만드는 개발자들이 정하는 부분입니다. 잠깐 실제 개발 현장에서 일어나는 이야기를 해볼게요. 개발자에는 크게 두 가지 종류가 있습니다. 첫 번째는 사용자가 직접 서비스 화면을 보는 웹 페이지나 앱 등을 만드는 프론트엔드(Front-end) 개발자, 두 번째는 웹 브라우저나 앱이 보내는 리퀘스트를 받아서 적절한 처리를 한 후 리스폰스를 주는 서버의 프로그램을 만드는 백엔드(Back-end) 개발자, 이 두 가지인데요.

하나의 서비스를 만들 때는 프론트엔드 개발자들과 백엔드 개발자들이 모여 ‘프론트엔드에서 이 URL로 이렇게 생긴 리퀘스트를 보내면, 백엔드에서 이런 처리를 하고 이런 리스폰스를 보내주는 것으로 정합시다’와 같은 논의를 하고, 이런 내용들을 정리한 후에 개발을 시작합니다.

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

Web API를 설계한다는 것은 서비스에서 사용될 모든 URL들을 나열하고, 각각의 URL에 관한 예상 리퀘스트와 리스폰스의 내용을 정리한다는 뜻입니다. 예를 들어, 이전 영상에서 사용한 학습용 URL(https://learn.codeit.kr/api/members)에서 직원 정보 추가 기능을 설계한다면 다음과 같이 할 수 있는 겁니다.

  1. 직원 정보 추가

https://learn.codeit.kr/api/members

(1) Request

  • Head Method : POST …

  • Body { “name”: “Jerry”, “email: “jerry@codeitshopping.kr”, “department”: “engineering”, } …

(2) Response Success인 경우 :

  • Head …
  • Body { “id”: “[부여된 고유 식별자 값]”, “name”: “Jerry”, “email”: “jerry@codeshopping.kr” “department”: “engineering”, } Fail인 경우 : … 이렇게 해당 서비스에서 제공되는 각 URL에, 어떤 리퀘스트를 보내면, 서버는 어떤 리스폰스를 보내야 하는지를 일일이 설계하는 것이 Web API 설계인 겁니다. 물론 실무에서는 지금 보이는 예시보다 훨씬 체계적이고 단정한 방식으로, 상용 툴 등을 사용해서 정리하지만 일단은 이해 차원에서 보여드렸습니다. 이런 식으로 Web API가 설계되고 나면, 그때 프론트엔드/백엔드 개발자들이 해당 설계에 맞게 각자 코드를 작성하기 시작하는 겁니다. 물론 설계와 개발이 동시에 진행되기도 하고, 설계 내용이 중간에 수정되기도 합니다.

오늘날 많은 회사 내의 개발팀은 이런 식으로 Web API를 설계하고 웹 서비스를 만듭니다. 그런데 문제가 하나 있습니다. 그건 바로 Web API는 어떻게 설계해도 동작하는 데는 아무런 지장이 없다는 문제입니다.

이전 영상들에서 저는 직원 정보를 추가하기 위해

(1) ‘https://learn.codeit.kr/api/members’ URL로
(2) 리퀘스트의 헤드에 POST 메소드를 설정하고, (3) 리퀘스트의 바디에 새 직원 정보를 넣어서 보내면 된다

는 내용의 설계를 했습니다.

그런데 어떤 회사는 같은 기능을 이런 식으로 설계할 수도 있습니다.

(1) ‘https://learn.codeit.kr/api/members’ URL로 (2) 리퀘스트의 헤더에 GET 메소드를 설정하고, (3) 리퀘스트의 바디에 새 직원 정보를 넣어서 보내면 된다

어느 방식으로 설계해도 서비스가 동작하는 데는 아무런 문제가 없습니다. 하지만 기능적으로 아무런 문제가 없다고 해도 Web API를 아무렇게나 설계해도 되는 것은 아닙니다. 사실 Web API가 잘 설계되었는지에 관한 기준으로는 보통 REST API라는 기준이 사용되고 있는데요. 많은 개발자들이 Web API를 개발할 때 이 REST API를 준수하기 위해 노력하고 있습니다. 이게 뭔지 한번 살펴봅시다.

  1. REST API 이야기 REST API는 오늘날 많은 웹 개발자들이 Web API 설계를 할 때, 준수하기 위해 노력하는 일종의 가이드라인입니다. REST API를 이해하기 위해서는 일단 REST architecture가 무엇인지부터 알아야 하는데요. 일단 REST architecture에 대해 설명하겠습니다.

REST architecture란 미국의 컴퓨터 과학자인 Roy Fielding이 본인의 박사 논문 ‘Architectural Styles and the Design of Network-based Software Architectures’에서 제시한 개념인데요. 그는 웹이 갖추어야 할 이상적인 아키텍처(구조)로 REST architecture라는 개념을 제시했습니다. 여기서 REST는 Representational State Transfer(표현적인 상태 이전)의 줄임말로, 해석하면 ‘표현적인, 상태 이전’이라는 뜻입니다. 이게 무슨 말일까요? 이 용어는 Roy Fielding이 고안한 용어인데요. 지금 여러분이 웹 서핑을 할 때를 생각해보세요. 만약 웹을 하나의 거대한 컴퓨터 프로그램이라고 생각한다면, 각각의 웹 페이지는 그 프로그램의 내부 상태를 나타낸다고 할 수 있습니다. 그렇다면 우리가 웹 페이지들을 계속 옮겨 다니면서 보게 되는 내용은, 웹이라는 프로그램의 매번 새로운 상태를 나타내는 표현이라고 할 수 있는데요. 그래서 이것을 ‘표현적인, 상태 이전’이라고 하는 겁니다. 조금 추상적인 느낌이지만 이해는 되시죠?

그럼 REST architecture가 되기 위한 조건에는 어떤 것들이 있을까요? 다음과 같은 6가지 기준을 충족하면 REST architecture로 인정됩니다.

Client-Server Stateless Cache Uniform Interface Layered System Code on Demand 각 기준에 대해 간략하게 설명해보자면 REST architecture는,

(Client-Server) Client-Server 구조를 통해 양측의 관심사를 분리해야 합니다. 현재 토픽에서는 웹 브라우저가 실행되고 있는 컴퓨터가 Client, 서비스를 제공하는 컴퓨터가 Server에 해당하는데요. 이렇게 분리를 해놓으면 Client 측은 사용자에게 어떻게 하면 더 좋은 화면을 보여줄지, 다양한 기기에 어떻게 적절하게 대처해야할지 등의 문제에 집중할 수 있고, Server 측은 서비스에 적합한 구조, 확장 가능한 구조를 어떻게 구축할 것인지 등의 문제에 집중할 수 있습니다. 이렇게 각자가 서로를 신경쓰지 않고 독립적으로 운영될 수 있는 겁니다.

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

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

(Uniform Interface) Client가 Server와 통신하는 인터페이스는 다음과 같은 하위 조건 4가지를 준수해야 합니다. 이 조건이 REST API와 연관이 깊은 조건입니다. 어떤 4가지 하위 조건들이 있는지 살펴봅시다.

(4-1) identification of resources : 리소스(resource)는 웹상에 존재하는 데이터를 나타내는 용어인데요. 저도 이번 노트에서는 리소스라는 용어를 사용하겠습니다. 이것은 리소스(resource)를 URI(Uniform Resource Identifier)로 식별할 수 있어야 한다는 조건입니다. URI는 URL의 상위 개념으로 일단 지금은 URL이라고 생각하셔도 큰 무리는 없습니다.

(4-2) manipulation of resources through representations : Client와 Server는 둘 다 리소스를 직접적으로 다루는 게 아니라 리소스의 ‘표현(representations)’을 다뤄야 합니다. 예를 들어, Server에 ‘오늘 날씨’(/today/weather)라는 리소스를 요청했을 때, 어떤 Client는 HTML 파일을 받을 수도 있고, 어떤 Client는 이미지 파일인 PNG 파일을 받도록 구현할 수도 있는데요. 이때 HTML 파일과 PNG 파일 같은 것들이 바로 리소스의 ‘표현’입니다. 즉, 동일한 리소스라도 여러 개의 표현이 있을 수 있다는 뜻입니다. 사실, 리소스는 웹에 존재하는 특정 데이터를 나타내는 추상적인 개념입니다. 실제로 우리가 다루게 되는 것은 리소스의 표현들뿐인데요. 이렇게 ‘리소스’와 ‘리소스의 표현’이라는 개념 2개를 서로 엄격하게 구분하는 것이 REST architecture의 특징입니다.

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

(4-4) hypermedia as the engine of application state : REST architecture는 웹이 갖추어야 할 이상적인 아키텍처라고 했죠? 이때 ‘웹’을 좀더 어려운 말로 풀어써 보자면 ‘분산 하이퍼미디어 시스템’(Distributed Hypermedia System)이라고도 할 수 있는데요. 여기서 하이퍼미디어(Hypermedia)는 하이퍼텍스트(Hypertext)처럼 서로 연결된 ‘문서’에 국한된 것이 아니라 이미지, 소리, 영상 등까지도 모두 포괄하는 더 넓은 개념의 단어입니다. 즉, 웹은 수많은 컴퓨터에 하이퍼미디어들이 분산되어 있는 형태이기 때문에, ‘분산 하이퍼미디어 시스템’에 해당합니다. 이 조건은 웹을 하나의 프로그램으로 간주했을 때, Server의 리스폰스에는 현재 상태에서 다른 상태로 이전할 수 있는 링크를 포함하고 있어야 한다는 조건입니다. 즉, 리스폰스에는 리소스의 표현, 각종 메타 정보들뿐만 아니라 계속 새로운 상태로 넘어갈 수 있도록 해주는 링크들도 포함되어 있어야 한다는 거죠.

자, 여기까지가 Uniform Interface의 4가지 하위 조건입니다. 사실, 오늘날 우리가 Web API를 설계할 때 위의 하위 조건들을 모두 제대로 이해하고 준수하는 것은 쉽지 않은 일인데요. 일단 아직 남은 5, 6번 조건들을 마저 살펴보고, 4번에 관해 그나마 우리가 실천할 수 있는 규칙들을 아래에서 살펴봅시다.

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

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

자, 이때까지 REST architecture가 되기 위해 충족해야 하는 조건들을 배웠는데요. 이해가 잘 되는 것도 있고 조금 어려운 것도 있죠? 사실 이 내용은 다소 이론적이기도 하고, 웹에 대해 좀 더 많이 공부해야 이해할 수 있는 것들도 있기 때문에 일단은 그냥 넘어가셔도 괜찮습니다.

하지만 기억해야 할 사실은, REST API는 바로 이런 REST architecture에 부합하는 API를 의미한다는 사실입니다. 참고로 이런 REST API를 사용하는 웹 서비스를 RESTful 서비스라고 합니다. 그렇다면 구체적으로 어떤 식으로 Web API를 설계해야 REST API가 될 수 있는 걸까요? 사실 Roy Fielding의 논문에는 이것에 관한 구체적이고 실천적인 내용들은 제시되어 있지 않습니다. 하지만 많은 개발자들의 경험과 논의를 통해 형성된 사실상의(de facto) 규칙들이 존재하는데요.

우리는 그중에서도 조건 4. Uniform Interface의 하위 조건인 (4-1) identificaton of resources 에 관해서 특히 개발자들이 강조하는 규칙, 2가지만 배워보겠습니다.

(1) URL은 리소스를 나타내기 위해서만 사용하고, 리소스에 대한 처리는 메소드로 표현해야 합니다. 이 규칙은 조금 다르게 설명하자면, URL에서 리소스에 대한 처리를 드러내면 안 된다는 규칙인데요. 이게 무슨 말인지 1. Web API 부분에서 마지막에 언급했던 예시를 통해 이해해보겠습니다.

예를 들어, 새 직원 정보를 추가하기 위해서

(1) ‘https://learn.codeit.kr/api/members’ URL로
(2) 리퀘스트의 헤드에 POST 메소드를 설정하고, (3) 리퀘스트의 바디에 새 직원 정보를 넣어서 보내면 된다

고 하는 경우는, URL은 리소스만 나타내고, 리소스에 대한 처리(리소스 추가)는 메소드 값인 POST로 나타냈기 때문에 이 규칙을 준수한 것입니다.

하지만

(1) ‘https://learn.codeit.kr/api/members/add’ URL로 (2) 리퀘스트의 헤더에 GET 메소드를 설정하고, (3) 리퀘스트의 바디에 새 직원 정보를 넣어서 보내면 된다

고 하는 이 경우는 URL에서 리소스뿐만 아니라, 해당 리소스에 대한 처리(add, 추가하다)까지도 나타내고 있습니다. 그리고 정작 메소드 값으로는 리소스 추가가 아닌 리소스 조회를 의미하는 GET을 설정했기 때문에 이 규칙을 어긴 것입니다.

URL은 리소스를 나타내는 용도로만 사용하고, 리소스에 대한 처리는 메소드로 표현해야 한다는 사실, 꼭 기억하세요!

(2) 도큐먼트는 단수 명사로, 컬렉션은 복수 명사로 표시합니다. 또 다른 규칙 하나를 살펴볼까요? 이 규칙은 URL로 리소스를 나타내는 방식에 관한 규칙인데요. URL에서는

https://www.soccer.com/europe/teams/manchester-united/players/pogba 이런 식으로 path 부분에서 특정 리소스(pogba, 축구 선수 포그바의 정보)를 나타낼 때 슬래시(/)를 사용해서 계층적인 형태로 나타냅니다. 지금 위 URL의 path 부분을 보면 ‘유럽의’, ‘축구팀들 중에서’, ‘맨체스터 유나이티드 팀의’, ‘선수들 중에서’, ‘포그바’라는 선수의 정보를 의미하는 리소스라는 걸 한눈에 알 수 있는데요. 이렇게 계층적 관계를 잘 나타내면, URL만으로 무슨 리소스를 의미하는지를 누구나 쉽게 이해할 수 있습니다. Web API를 설계할 때는 이렇게 가독성 좋고, 이해하기 쉬운 URL을 설계해야 하는데요. 그런데 이때 지켜야 할 규칙이 있습니다.

사실 리소스는 그 특징에 따라 여러 종류로 나눠볼 수 있습니다. 이 중에서 우리는 ‘컬렉션(collection)’과 ‘도큐먼트(document)’를 배울 건데요. 보통 우리가 하나의 객체로 표현할 수 있는 리소스를 ‘도큐먼트’라고 합니다. 그리고 여러 개의 ‘도큐먼트’를 담을 수 있는 리소스를 ‘컬렉션’이라고 하는데요. 쉽게 비유하자면, 도큐먼트는 하나의 ‘파일’, 컬렉션은 여러 ‘파일’들을 담을 수 있는 하나의 ‘디렉토리’에 해당하는 개념입니다.

그리고 이에 관한 규칙은 바로, URL에서 ‘도큐먼트’를 나타낼 때는 단수형 명사를, ‘컬렉션’을 나타낼 때는 복수형 명사를 사용해야 한다는 규칙입니다.

지금 위 URL에서 europe, manchester-united, pogba가 ‘도큐먼트’에 해당하고, teams, players가 ‘컬렉션’에 해당합니다. 도큐먼트는 단수 명사로, 컬렉션은 복수 명사로 표현한 것이 잘 보이죠?

이 규칙을 잠깐 이전 영상의 내용과 연관 지어 생각해볼까요? 예를 들어, 제가

전체 직원 정보 조회 - GET 새 직원 정보 추가 - POST 이 작업들을 수행하기 위해 사용했던 ‘https://learn.codeit.kr/api/members’ URL에서도 직원 전체를 의미하는 members는 이렇게 복수 명사를 사용했다는 것을 알 수 있습니다. members는 member들을 담을 수 있는 컬렉션에 해당하는 개념이기 때문입니다.

그리고 제가

특정 직원 정보 조회 - GET 기존 직원 정보 수정 - PUT 기존 직원 정보 삭제 - DELETE 이 작업들을 수행하기 위해 사용했던 https://learn.codeit.kr/api/members/3 URL에서는 도큐먼트를 나타내기 위해 단수 명사 대신 직원 고유 식별자인 id 값을 썼는데요. 이렇게 숫자를 쓰는 경우에는 단복수 문제가 없겠죠?

‘도큐먼트’, ‘컬렉션’ 개념을 우리가 배운 메소드 종류와 연결해서 모든 경우의 수를 생각해보면 다음과 같습니다.

제목 /members /members/3 GET 전체 직원 정보 조회 3번 직원 정보 조회 POST 새 직원 정보 추가 X PUT 전체 직원 정보 수정(잘 쓰이지 않음) 3번 직원 정보 갱신 DELETE 전체 직원 정보 삭제(잘 쓰이지 않음) 3번 직원 정보 삭제 지금 표에서 보이는 것처럼, 전체 직원 정보를 대상으로 PUT 리퀘스트 또는 DELETE 리퀘스트를 보내는 것은 전체 직원 정보를 모두 수정 또는 모두 삭제한다는 뜻이기 때문에 사실상 잘 쓰이지 않습니다. 위험한 동작이기 때문에 애초에 Web API 설계에 반영하지도 않고, 서버에서 허용하지 않을 때가 일반적이죠.

그리고 또 여기서 주목할 점은 POST 리퀘스트를 보낼 때, 컬렉션(members) 타입의 리소스를 대상으로 작업을 수행한다는 점입니다. 이 부분이 조금 헷갈릴 수도 있는데요. POST 리퀘스트를 보낼 때는 우리가 전체 직원 정보를 의미하는 컬렉션에 하나의 직원 정보(하나의 도큐먼트)를 추가하는 것이기 때문에 URL로는 컬렉션까지만 /members 이렇게 표현해줘야 합니다. 따라서 /members/3 이렇게 특정 도큐먼트를 나타내는 URL에 POST 리퀘스트를 보내는 것은 문맥상 맞지 않는 표현입니다. 그리고 지금 같은 경우는 추가될 직원 정보가 어떤 id 값을 할당받을지 알 수도 없기 때문에 애초에 /members/[id]에 id 값을 지정한다는 것도 불가능하죠.

이 도큐먼트와 컬렉션 개념을 잘 기억하고 있으면 나중에 URL에서 단수 명사를 써야 할지, 복수 명사를 써야 할지 고민이 될 때 답을 얻을 수 있을 겁니다.

자, 이때까지 REST API의 조건 중 하나인 4. Uniform Interface을 좀 더 잘 지키기 위해 개발자들이 강조하는 규칙 2가지를 배웠습니다. 하지만 이것만으로 Web API를 REST API로 설계할 수 있는 것은 아닙니다. 여전히 만족시켜야 하는 다른 조건들도 있기 때문이죠. 나머지 조건들을 어떻게 지킬 수 있는지에 관한 내용은 난이도 및 분량 관계상 생략하겠습니다. 나머지 조건들을 어떻게 준수하는지는 여러분이 웹에 좀더 익숙해지고 나서 나중에 더 찾아보시는 걸 추천합니다.

REST API는 개발자들이 Web API를 설계할 때 굉장히 중요하게 고려하는 가이드라인이기는 하지만, 앞서 제시한 6가지 조건을 모두 만족시켜가면서까지 100% 준수해야 할 필요성이 있는지에 관해서는 의견이 많습니다. 그래도 REST API는 웹 개발자의 주요 단골 면접 주제니까 관심이 있는 분은 이번 노트의 내용을 다시 자세히 읽고 필요한 내용을 더 찾아보세요.


20210321_044443

const newMember = {
  name: 'Michael',
  email: 'michael@codeitmall.kr',
  department: 'engineering',
};
fetch('https://learn.codeit.kr/api/members', {
  method: 'POST',
  body: JSON.stringify(newMember),
})
  .then(() => {
    fetch('https://learn.codeit.kr/api/members')
      .then((response) => response.text())
      .then((result) => {
        const members = JSON.parse(result);
        console.log(members[members.length - 1]);
      });
  });


자바스크립트 객체를 string 타입의 JSON 데이터로 변환하는 것은 영어로 Serialization, 우리말로는 직렬화라고 합니다. 그리고 이와 반대로 string 타입의 JSON 데이터를 자바스크립트 객체로 변환하는 것을 영어로는 Deserialization, 우리말로는 역직렬화라고 하는데요. 그리고 이것들을 동사로 표현하면 Serialize한다, Deserialize한다고 표현할 수 있겠죠?

이 Serialization과 Deserialization은 자바스크립트뿐만 아니라 모든 프로그래밍 언어에서 중요하게 다뤄지는 개념입니다. 왜냐하면 어떤 언어든지 리퀘스트를 보내거나, 리스폰스를 받을 때 이런 작업을 수행해줘야하기 때문입니다. 이번 노트에서는 Serialization과 Deserialization에 대해 좀 더 자세하게 살펴보겠습니다.

  1. string 타입의 JSON 데이터 vs 자바스크립트 객체 우리는 Serialization을 수행하기 위해 JSON이라는 자바스크립트 기본 내장 객체의 stringify 메소드를 사용했고, Deserialization을 수행하기 위해 JSON 객체의 parse 메소드를 사용했는데요.

혼동을 막기 위해서, 앞으로 데이터 포맷으로서의 json은 이렇게 소문자로, stringify 메소드, parse 메소드를 갖고 있는 JSON 객체는 이렇게 대문자로 쓸게요.

이제 string 타입의 json 데이터와 자바스크립트 객체 사이에 구체적으로 어떤 차이가 있는 건지, 각 작업이 왜 필요한지 그 이유를 생각해봅시다.

잠깐 아래 코드를 볼까요?

const obj = { x: 1, y: 2 };
const jsonString = JSON.stringify(obj);

지금 x 프로퍼티와 y 프로퍼티를 가진 obj라는 객체를 Serialize했는데요. 이 코드를 실행하고 obj와 jsonString을 순서대로 조회해보면

20210321_045033

이렇게 obj는 자바스크립트 객체이고, 이것을 Serialize한 결과인 jsonString은 string 타입이라는 걸 알 수 있습니다. obj 객체 왼쪽의 화살표를 클릭해보면

20210321_045058

이렇게 obj 객체는 자바스크립트 객체로서, 우리가 직접 정의하지는 않았지만, 기본으로 내장하는 프로퍼티들이 존재한다는 것을 알 수 있습니다. 이런 것들은 자바스크립트 실행 환경에서, 객체라면 가지는 프로퍼티들일 뿐 서버에는 전혀 보낼 필요가 없는 것들입니다. 그리고 특히 이 객체의 메소드 같은 경우 서버에서 이를 인식 가능하도록 보낼 수 있는 방법도 없구요. 바로 이러한 이유 때문에 우리는 객체(object)가 가진 데이터만을 string 타입으로 변환하는 Serialization 작업을 해야하는 겁니다.(Serialization이 왜 필요한지에 대해서 제대로 이해하려면 컴퓨터 공학에 관한 깊은 지식이 필요합니다. 지금은 자바스크립트 실행 환경에서만 인식되는 객체라는 존재를 어느 환경에서든 해석될 수 있는 포맷으로 변환하기 위해 Serialize를 한다는 정도로만 이해하시면 됩니다.)

그럼 이번엔 반대로 Deserialize를 해봅시다.

const jsonString = '{"x": 1, "y": 2}';
const obj = JSON.parse(jsonString);

이번엔 코드 순서가 반대이고, JSON 객체의 stringify 메소드 대신 parse 메소드를 썼는데요.

지금 jsonString은 string 타입입니다. 이때 y키의 값인 2를 가져와야 한다고 해봅시다. 어떻게 가져와야할까요? 지금 같은 문자열 상태로는 y 값을 가져올 수 없습니다. 문자열 자체를 파싱(parsing)해서 어떻게든 2라는 값을 가져올 수 있겠지만 그건 우리가 원하는 게 아니죠. 따라서 이 string 타입의 값을 Deserialize해서 그대로 자바스크립트 객체로 변환해줘야 코드에서 자유롭게 사용할 수 있게 됩니다. 그 후에는 이렇게

obj.y처럼 자바스크립트에서 객체의 프로퍼티의 값을 읽을 때 쓰는 문법을 사용해서, obj 객체의 y프로퍼티에 바로 접근할 수 있죠. 왜 리스폰스의 내용이 JSON 데이터일 때 그것을 Deserialize해야 하는지 아시겠죠? 굳이 string 타입의 값에서 문자열을 파싱하느라 낑낑대며 어렵게 필요한 데이터를 추출하기보다는 이렇게 자바스크립트 객체로 변환해서 편하게 데이터를 다루면 되는 겁니다.

Serialization과 Deserialization은 자바스크립트로 웹 개발을 할 때 반드시 숙지하고 있어야 하는 개념입니다. 리퀘스트를 보내거나 리스폰스를 받았을 때 이 작업을 빼먹지 않도록 주의하셔야 합니다.

  1. text 메소드 말고 json 메소드도 있어요. 우리가 배웠던 코드를 잠깐 살펴봅시다.
fetch('https://jsonplaceholder.typicode.com/users')
  .then((response) => response.text())
  .then((result) => { const users = JSON.parse(result); });

이 코드에서는 리스폰스의 내용을 추출하기 위해 response.text()를 호출했고, 그 다음에 그 리턴값인 JSON 데이터 (result, 실제로는 JSON 데이터를 품은 Promise 객체라는 것이 리턴됩니다. Promise 객체는 챕터 3에서 배웁니까 조금만 기다려주세요.) 를 Deserialize(JSON.parse(result))해서 생성한 객체를 users에 할당했는데요.

그런데 여기서 코드의 양을 조금이나마 줄일 수 있는 방법이 있습니다. 바로 보여드릴게요.

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

지금 저는 response 객체의 text 메소드 대신 json이라는 메소드를 사용했고, 콜백 안에 있던 JSON.parse 코드를 삭제했습니다. 왜 그런 걸까요?

response 객체의 text 메소드 대신 json이라는 메소드를 호출하면, 리스폰스의 내용이 JSON 데이터에 해당하는 경우, 바로 Deserialization까지 수행해줍니다. 이렇게 json 메소드를 사용하면, 두 번째 콜백의 result 파라미터로는 Deserialization 결과로 생성된 자바스크립트 객체가 넘어가게 되는데요. 그래서 두 번째 콜백 안에서 JSON.parse를 해주지 않아도 result를 바로 자바스크립트 객체로서 사용할 수 있는 겁니다. 참고로, 리스폰스의 내용이 JSON 데이터에 해당하지 않을 경우에는 에러가 발생하게 됩니다.

리스폰스의 내용이 JSON 데이터로 미리 약속된 경우에는 response 객체의 text 메소드 대신 json 메소드를 사용해서 Deserialization까지 한 번에 수행하기도 합니다. 앞으로 코드에서 text 메소드 대신 json 메소드가 등장하기도 하니까 잘 기억해두세요.


Response에 대해 공부해보자.

Response도 head와 body로 이뤄짐.

20210321_051616

근데 response에서 더 알아야 할건 상태코드

20210321_051911

20210321_052009


상태코드 정리

이번 노트에서는 알아두면 개발할 때 도움이 되는 상태 코드(Status Code)들을 알아보겠습니다. 자, 시작해볼까요?

  1. 각각의 상태 코드에는 대응되는 상태 메시지가 있습니다. 모든 상태 코드(Status Code)는 각각 그에 대응되는 상태 메시지(Status Message)를 갖고 있습니다.

예를 들어, 우리가 배운 200번은 OK, 404번은 Not Found라는 상태 메시지를 갖고 있습니다. 각 상태 코드의 의미를 모두 외우기는 힘들기 때문에 이러한 상태 메시지는 상태 코드의 의미를 빠르게 파악하는데 도움을 줍니다.

  1. 상태 코드는 100번대~500번대까지 있어요. 이전 영상에서는 상태 코드 200번과 404번만 봤는데요. 사실 상태 코드는 100번대부터 500번대까지 존재합니다. 그리고 각 번호대는 그것만의 의미를 가지고 있는데요. 각 번호대 별 주요 상태 코드들을 살펴봅시다. 각 상태 코드는 상태 코드 옆에 바로 상태 메시지를 쓰는 형식(예: 200 OK)으로 나타내겠습니다.

(1) 100번대 서버가 클라이언트에게 정보성 응답(Informational response)을 줄 때 사용되는 상태 코드들입니다.

100 Continue : 클라이언트가 서버에게 계속 리퀘스트를 보내도 괜찮은지 물어봤을 때, 계속 리퀘스트를 보내도 괜찮다고 알려주는 상태 코드입니다. 예를 들어, 클라이언트가 용량이 좀 큰 파일을 리퀘스트의 바디에 담아 업로드하려고 할 때 서버에게 미리 괜찮은지를 물어보는 경우가 있다고 할 때, 서버가 이 100번 상태 코드의 리스폰스를 주면 그제서야 본격적인 파일 업로드를 시작합니다. 101 Switching Protocols : 클라이언트가 프로토콜을 바꾸자는 리퀘스트를 보냈을 때, 서버가 ‘그래요, 그 프로토콜로 전환하겠습니다’라는 뜻을 나타낼 때 쓰이는 상태 코드입니다. (2) 200번대 클라이언트의 리퀘스트가 성공 처리되었음을 의미하는 상태 코드들입니다.

200 OK : 리퀘스트가 성공적으로 처리되었음을 포괄적으로 의미하는 상태 코드입니다. 이때 성공의 의미는 리퀘스트에 있던 메소드의 종류에 따라 다르겠죠? GET 리퀘스트의 경우 리소스가 잘 조회되었다는 뜻이고, POST 리퀘스트의 경우 새 리소스가 잘 생성되었다, PUT 리퀘스트의 경우 기존 리소스가 잘 수정되었다, DELETE 리퀘스트의 경우 기존 리소스가 잘 삭제되었다는 뜻입니다. 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 : 브라우저들은 보통 한번 리스폰스로 받았던 이미지 같은 리소스들을 그대로 내부에 저장하고 있습니다. 그리고 서버는 해당 리소스가 바뀌지 않았다면, 리스폰스에 그 리소스를 보내지 않고 304번 상태 코드만 헤드에 담아서 보냄으로써 ‘네트워크 비용’을 절약하고 브라우저가 저장된 리소스를 재활용하도록 하는데요. 사실 이 상태 코드는 웹에서 ‘캐시(cache)’라는 주제에 대해서 공부해야 정확하게 이해할 수 있습니다. 당장 배울 내용은 아니니까 넘어갈게요. 혹시 관심이 있는 분들은 이 링크를 참조하세요. (4) 400번대 리퀘스트를 보내는 클라이언트 쪽에 문제가 있음을 의미하는 상태 코드들입니다.

400 Bad Request : 말그대로 리퀘스트에 문제가 있음을 나타냅니다. 리퀘스트 내부 내용의 문법에 오류가 존재하는 등의 이유로 인해 발생합니다. 401 Unauthorized : 아직 신원이 확인되지 않은(unauthenticated) 사용자로부터 온 리퀘스트를 처리할 수 없다는 뜻입니다. 403 Forbidden : 사용자의 신원은 확인되었지만 해당 리소스에 대한 접근 권한이 없는 사용자라서 리퀘스트를 처리할 수 없다는 뜻입니다. 404 Not Found : 해당 URL이 나타내는 리소스를 찾을 수 없다는 뜻입니다. 보통 이런 상태 코드가 담긴 리스폰스는 그 바디에 관련 웹 페이지를 이루는 코드를 포함하고 있는 경우가 많습니다. 예를 들어, 다음과 같이

20210321_052158

https://www.google.com/abc와 같이 존재하지 않는 URL에 접속하려고 하면 이런 페이지가 보이는 것을 알 수 있습니다.

405 Method Not Allowed : 해당 리소스에 대해서 요구한 처리는 허용되지 않는다는 뜻입니다. 만약 어떤 서버의 이미지 파일을 누구나 조회할 수는 있지만 아무나 삭제할 수는 없다고 해봅시다. GET 리퀘스트는 허용되지만, DELETE 메소드는 허용되지 않는 상황인 건데요. 그런데 만약 그 이미지에 대한 DELETE 리퀘스트를 보낸다면 이런 상태 코드를 보게될 수도 있습니다. 413 Payload Too Large : 현재 리퀘스트의 바디에 들어있는 데이터의 용량이 지나치게 커서 서버가 거부한다는 뜻입니다. 429 Too Many Requests : 일정 시간 동안 클라이언트가 지나치게 많은 리퀘스트를 보냈다는 뜻입니다. 서버는 수많은 클라이언트들의 리퀘스트를 정상적으로 처리해야 하기 때문에 특정 클라이언트에게만 특혜를 줄 수는 없습니다. 따라서 지나치게 리퀘스트를 많이 보내는 클라이언트에게는 이런 상태 코드를 담은 리스폰스를 보낼 수도 있습니다. (5) 500번대 서버 쪽의 문제로 인해 리퀘스트를 정상적으로 처리할 수 없음을 의미하는 상태 코드들입니다.

500 Internal Server Error : 현재 알 수 없는 서버 내의 에러로 인해 리퀘스트를 처리할 수 없다는 뜻입니다. 503 Service Unavailable : 현재 서버 점검 중이거나, 트래픽 폭주 등으로 인해 서비스를 제공할 수 없다는 뜻입니다. 자, 각 번호대의 주요 상태 코드들을 알아봤는데요. 정말 다양한 상태 코드들이 있죠? 이 상태 코드들만 깊게 공부해도 웹 개발에 필요한 많은 지식들을 쌓을 수 있습니다. 혹시 또다른 상태 코드들도 궁금한 분들은 여기 이 페이지를 참조하세요.

이 상태 코드들도 ‘모범적인 Web API, REST API’ 노트에서 배웠던 ‘Web API 설계’ 시에 결정되어야 하는 요소들입니다. 리퀘스트에 관한 URL과 메소드 종류 뿐만 아니라 리스폰스의 상태 코드 또한 각각의 상황에 알맞은 것들이 설정되도록 설계해야 하는데요. 사실 모든 상황을 세분화해서 매번 거기에 맞는 상태 코드를 넣는 것은 불필요한 작업이 될 수도 있긴 합니다. 그래서 보통은 꼭 사용할 상태 코드들만 추린 다음에 특정 유형의 상황들은 모두 하나의 상태 코드로 나타내는 전략이 주로 활용되는데요.

하지만 그렇다고 해서 서버가 리퀘스트를 잘 처리했든, 실패했든 상태 코드로 항상 200번을 보내버린다거나 하는 것은 매우 좋지 않습니다. 가장 이상적인 것은 존재하는 상태 코드를 최대한 많이 활용하는 것입니다.


이제 우리는 리퀘스트와 리스폰스의 바디에 정말 다양한 타입의 데이터들이 들어갈 수 있다는 것을 배웠습니다. 이때까지는 실제로 개발자가 되면 주로 사용하게 될 JSON 타입을 많이 다뤄봤는데요. 하지만 정말 개발자가 된다면 JSON 뿐만 아니라 이전 노트에서 봤던 일반 텍스트, 이미지, 음성, 영상 등 수많은 타입들을 다루게 될 겁니다. 이번 노트에서는 여러분이 추가적으로 알아두면 좋을 데이터 타입들을 공부해보겠습니다.

  1. JSON 말고 XML도 있어요. 개발자들이 어떤 정보를 나타내기 위해 흔히 쓰는 데이터 포맷으로는 JSON 뿐만 아니라 XML(Extensible Markup Language)이라고 하는 데이터 포맷도 있습니다. XML을 한마디로 쉽게 이야기하자면, 태그를 사용해서 데이터를 나타내는 것입니다. 예를 들어
{
   "name":"Michael Kim",
   "height":180,
   "weight":70,
   "hobbies":[
      "Basketball",
      "Listening to music"
   ]
}

이런 JSON 데이터를 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>

뭔가 HTML에서나 볼 법한 태그들로 이루어져있죠? 자세히 보면 원래 JSON에서

"name": "Michael Kim"

이라고 나타낸 부분을 XML에서는

<name>Michael Kim</name>

이런 식으로 시작 태그()와 끝 태그(), 그리고 그 사이의 값으로 나타낸 것을 알 수 있습니다.

사실 XML이라는 데이터 타입은 JSON이 2013년에 표준화되고 그 뒤로 활성화되기 전까지만 해도 정말 많이 사용되던 데이터 타입이었습니다. 여러분이 개발 관련 문서들을 구글링하다보면 여전히 이 XML로 표현된 데이터들을 자주 볼 수 있게 될 텐데요.

XML을 쓸 때는 보통 스키마(Schema)라는 별도의 문서를 함께 사용합니다. 이 스키마에는 각 조직, 기관 등에서 XML로 데이터를 나타낼 때, 어떤 태그들을 사용할 수 있고, 각 태그의 의미는 무엇이며, 특정 태그는 어떤 타입의 값을 가질 수 있는지 등의 정보가 담겨있는데요. 따라서 XML은 데이터에 대한 엄격한 유효성(validity) 검증에 특화된 데이터 포맷이라고 할 수 있습니다.

하지만 XML은 같은 양의 데이터를 표현하더라도 JSON에 비해 더 많은 용량을 차지하고, JSON에 비해 가독성이 떨어지며, 배우기가 어렵다는 문제 등으로 인해, 오늘날 XML의 입지는 다소 좁아진 것이 사실입니다. 특히나 자바스크립트가 중심이 되는 웹 개발 세계에서는 우리가 배운 것처럼 자바스크립트의 문법과 JSON 문법이 대체로 호환되기 때문에 더더욱 JSON을 사용하는 것이 편리합니다.

하지만 만약 여러분이 외부로 공개된 여러 Open API 같은 것들을 살펴보면 여전히 XML 타입의 데이터를 리스폰스로 주는 경우가 많다는 것을 알 수 있습니다. 그렇기 때문에 XML 타입이라는 것이 존재한다는 것을 인지하고, 이런 타입의 데이터는 어떻게 처리해야 할지 미리 고민해보는 것도 좋습니다. 참고로 XML을 나타내는 Content-Type 헤더의 값은 ‘application/xml’입니다. 그리고 ‘application/xml’뿐만 아니라 XML의 문법을 따르되 거기에 특수한 규칙을 더해 만든 데이터 타입들도 존재합니다. 보통 이런 타입들은 그 이름 끝에 +xml을 붙여서 사용하는데요. Content-Type 헤더의 값에 관한 이 공식 문서에 접속해서 +xml 이라는 키워드로 페이지 내 검색을 해보세요. XML 문법을 활용한 다양한 데이터 타입들을 볼 수 있을 겁니다.

  1. form 태그에서 사용되는 타입들 이때까지 배운 JSON, XML 이런 것들 말고도 개발자라면 알아둬야 할 데이터 타입이 또 있습니다. 그것은 바로

(1) application/x-www-form-urlencoded 타입 (2) multipart/form-data 타입


이때까지 웹 개발을 하기 위해서 알아야 할 기초 지식들을 배웠습니다. 이번 노트에서는 아직 미처 다루지 못했지만 꼭 알고가야 할 내용들을 다뤄보겠습니다. 총 3가지 주제에 대해 배워보겠습니다. 먼저 Ajax라는 것부터 배워볼게요.

  1. Ajax 초창기의 웹은 특정 웹 페이지에서 다른 웹 페이지로 갈 수 있는 링크(공식 명칭은 hyperlink입니다)를 클릭하면 새로운 웹 페이지가 로드되는 방식이었습니다. 오늘날에도 당연히 쓰이고 있는 방식인데요.

하지만 화면의 일부분만 바뀌면 되는 경우에도 매번 새 페이지가 로드되는 방식은 효율적이지도 않고 사용자에게도 그다지 좋지 않은 경험을 안겨주었습니다. 그래서 2000년대 초부터는 웹의 이런 단점을 극복하기 위해서 Ajax라는 기술이 도입되었습니다. Ajax는 웹 브라우저가 현재 페이지를 그대로 유지한 채로 서버에 리퀘스트를 보내고 리스폰스를 받아서, 새로운 페이지를 로드하지 않고도 변화를 줄 수 있게 해주는 기술입니다.

Ajax는 Asynchronous JavaScript And XML의 줄임말인데요. 이는 자바스크립트를 사용해서 비동기적으로(=사용자가 보고 있는 현재 화면에 영향을 미치지 않고 별도로 백그라운드에서 작업을 처리한다는 뜻) 리퀘스트를 보내고 리스폰스를 받는데 기반이 되는 기술들의 집합을 의미합니다. 여기서 마지막에 XML이 쓰인 것은 Ajax라는 용어가 생겨난 당시에 XML이 가장 많은 인기를 누리던 데이터 타입이었기 때문입니다. 오늘날에는 XML 말고 JSON도 꽤 많이 쓰이고 있긴 하지만요.

자, 어쨌든 지금 중요한 것은 Ajax의 원리를 이해하는 것입니다. Ajax의 원리는 여러분이 흔히 쓰는 구글 맵(Google Map) 같은 웹 서비스를 생각해보면 이해하기 쉽습니다. 구글 맵 웹 페이지를 예로 들어볼게요.

20210321_060609

제가 지금 구글 맵에서 서울특별시 중구 을지로 쪽을 보다가 ‘명동 성당’의 정보가 보고 싶어졌다고 해봅시다. 그럼 명동 성당 아이콘을 클릭하면 되겠죠? 이렇게 명동 성당을 클릭했을 때, 초창기의 웹이었다면 아예 새로운 페이지를 로드해야 했을 겁니다. 하지만 오늘날 우리가 쓰는 구글 맵이 그렇지는 않죠? 실제로 명동 성당 아이콘을 클릭해보면

20210321_060615

현재 웹 페이지는 그대로 유지되고, 단지 그 밑에 명동 성당에 관한 간단한 정보창이 떠오를 뿐입니다. 이것이 가능한 이유는 웹 브라우저가, 사용자가 보고 있는 현재 페이지를 방해하지 않고 별도로 서버로 리퀘스트를 보내고, 리스폰스를 받아왔기 때문입니다.

만약 이런 Ajax 기술이 없었다고 생각해보세요. 우리는 웹 서비스를 사용할 때마다 별로 크게 바뀌지도 않는 화면을 매번 로드하는 불편함을 느꼈을 겁니다. 하지만 Ajax 기술 덕분에 구글 맵처럼 부드러운 UX(User Experience, 사용자 경험)를 제공하는 수많은 웹 서비스들을 사용할 수 있게 된 겁니다.

그럼 자바스크립트로는 어떻게 이 Ajax 기술을 사용해서 리퀘스트를 보내고 리스폰스를 받을 수 있을까요? 앞으로는 Ajax 기술을 기반으로 한 통신을 그냥 짧게 줄여서 ‘Ajax 통신’이라고 할게요.

자바스크립트에서는 XMLHttpRequest라고 하는 객체를 통해 Ajax 통신을 할 수 있습니다. XMLHttpRequest를 사용하는 예시 코드는 다음과 같은데요.

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라고 하는 생성자 함수로 객체를 생성한 것 보이시죠? 이런 식의 코드를 작성하면 Ajax 통신을 할 수 있습니다. 궁금한 분들은 이 코드를 개발자 도구에 붙여넣고 직접 실행해보세요.

그런데 예전엔 XMLHttpRequest를 이렇게 직접 사용할 일이 많았지만 요즘에는 굳이 그렇게 하지 않아도 됩니다.(2020년 1월 기준) 그 이유에는 크게 두 가지가 있는데요.

첫 번째 이유는 XMLHttpRequest 객체 이후에 등장한 함수, 바로 이때까지 우리가 배운 fetch 함수를 사용해서 Ajax 통신을 할 수 있기 때문입니다. 이때까지 배운 fetch 함수가 Ajax 통신을 하는 함수였다니 놀랍죠? fetch 함수는 XMLHttpRequest 객체를 사용할 때에 비해 좀 더 짧고 간단한 코드로 Ajax 통신을 할 수 있게 해주는 함수입니다. 그래서 많은 개발자들의 환영을 받았죠.

두 번째 이유는 XMLHttpRequest을 기반으로 더 쓰기 편하게 만들어진 axios라는 패키지가 존재하기 때문입니다. (자바스크립트에서는 라이브러리보다는 ‘패키지’라는 단어를 더 일상적으로 사용하기 때문에 ‘패키지’라고 표현하겠습니다.)

이런 이유들 때문에 굳이 XMLHttpRequest 객체를 직접 가져다 쓸 필요성이 줄어든 것입니다.

개발 실무에서는 fetch 함수 또는 axios 패키지를 사용하는데요. 보통 axios 패키지에 좀더 다양한 기능들이 있어서 주로 axios를 쓰는 편이지만, 외부의 패키지를 설치하고 싶지 않은 경우에는 fetch 함수를 사용하기도 합니다. 그리고 일단 fetch 함수의 원리에 대해서 알아야 axios도 잘 사용할 수 있기 때문에 이번 토픽에서는 fetch 함수를 중심으로 내용을 진행하고 있는 겁니다. fetch 함수의 어떤 원리를 알아야하는지에 대해서는 챕터 3부터 알아봅시다.

자, 다시 원래의 이야기로 내용을 마무리하겠습니다. 앞으로 웹 개발을 할 때는 Ajax 통신인 것과 Ajax 통신이 아닌 것을 구분할 수 있어야 합니다. 일단 Ajax 통신이 아닌 것은 이런 태그를 사용자가 클릭하도록 해서

<a href="https://learn.codeit.kr/api/main">메인 화면으로 가기</a>

웹에서의 전통적인 방식처럼 새 페이지를 로드하게 하는 방식이고, Ajax 통신인 것은

// (위 예시를 단순화한 코드입니다)
function getLocationInfo(latitude, longitude) {
  fetch('https://map.google.com/location/info?lat=latitude&lng=longitude')
    .then((response) => response.text())
    .then((result) => { /* 사용자 화면에 해당 위치 관련 정보 띄워주기 */ });
}

이런 식으로 사용자가 느낄 수 없게, 리퀘스트를 보내고 리스폰스를 받아 현재 페이지에 원하는 변화를 주는 방식이죠.

사용자 경험을 고려해서

(1) 언제 아예 새로운 페이지를 로드하고 (2) 언제 Ajax 통신을 해서 현재 페이지 내에서 부드러운 변화를 줄 건지를

잘 결정하는 것은 중요합니다.

양쪽 모두 공부해둬야 필요한 순간에 코드로 잘 구현해낼 수 있겠죠? 일단 이때까지 배운 fetch 함수가 사실은 Ajax 통신을 하는 함수였다는 사실만큼은 꼭 기억합시다!

  1. GET, POST, PUT, DELETE 이외의 메소드들 이때까지 우리는 리퀘스트에 설정할 수 있는 GET, POST, PUT, DELETE 메소드에 대해 배웠습니다. 그런데 사실 메소드에는 이것 말고 다른 것들도 있습니다. 그중에서도 알아두면 좋은 2가지 메소드를 소개합니다.

(1) PATCH PATCH 메소드는 기존의 데이터를 수정할 때 사용하는 메소드입니다. 그럼 우리가 배운 PUT 메소드와는 어떤 차이가 있을까요? PUT은 기존 데이터를 아예 새로운 데이터로 덮어씀으로써 수정하려고 할 때 쓰는 메소드이고, PATCH는 새 데이터로 기존 데이터의 일부를 수정하려고 할 때 쓰는 메소드입니다.

그러니까 예를 들어 서버에

{
  "id": 3,
  "name": "Michael",
  "age": 25
}

이런 식으로 표현되는 데이터가 있을 때, 리퀘스트에 PATCH 메소드를 설정하고

{
  "age": 30
}

이라는 데이터를 바디에 담아서 보내면,

{
  "id": 3,
  "name": "Michael",
  "age": 30
}

서버의 기존 데이터는 이렇게 age 속성만 갱신되지만, 같은 리퀘스트더라도 PUT 메소드를 설정해서 보내면

{
  "age": 30
}

이렇게 서버의 데이터에는 age 속성만 남게 됩니다. 어떤 차이가 있는지 이해되시나요? 이전에 배운 PUT 메소드는 서버에 존재하는 기존 데이터를 새로운 데이터로 아예 덮어쓰기하는 방식으로 수정합니다. 따라서 PUT 메소드의 경우에는 원하는 새 데이터의 온전한 모습 전체를 바디에 담아서 보내줘야 합니다. 아래의 데이터처럼 말이죠.

{
  "id": 3,
  "name": "Michael",
  "age": 30
}

하지만 PATCH의 경우에는 보통, 리퀘스트의 바디에 있는 내용을 기존 데이터의 각 속성과 대조 및 병합(merge-patch)하면서 데이터를 수정하기 때문에 때문에, 바디에 수정할 프로퍼티의 데이터만 넣어줘도 되는 겁니다.

데이터를 수정하는 메소드 중에서 PUT은 덮어쓰기, PATCH는 일부 수정를 의미한다는 사실을 기억해두세요.

(2) HEAD 메소드에는 HEAD 메소드라는 것도 있습니다. HEAD 메소드는 GET 메소드와 동일합니다. 대신 GET 리퀘스트를 보냈을 때 받았을 리스폰스에서 바디 부분은 제외하고, 딱 헤드 부분만 받는다는 점이 다른데요. 왜 이런 메소드가 필요할까요? 예를 들어, 웹 브라우저가 서버로부터 용량이 엄청나게 큰 영상 파일을 받고자 하는 상황이라고 해봅시다. 만약 파일의 용량이 너무 큰 경우에는 파일을 받지 않으려고 하는데요. 이때 파일의 용량만 조사하기 위해서 HEAD 메소드가 담긴 리퀘스트를 보내볼 수 있습니다. 만약 https://movie.net/matrix (영화 ‘매트릭스’) 라는 URL이 있다고 할 때 해당 URL로 HEAD 메소드가 설정된 리퀘스트를 보내면 그 리스폰스는 바디는 없고 헤드만 있을 겁니다. 대신 이때 Content-length와 같이 컨텐츠 용량을 나타내는 헤더가 있어서 파일의 용량 정보는 알게 될 수도 있는데요. 그럼 이 용량을 사용자에게 보여주고 그래도 영화 파일을 시청할 건지 물어보는 코드를 작성할 수 있겠죠? 바로 이렇게 실제 데이터가 아니라 데이터에 관한 정보만 얻으려고 하는 상황 등에 HEAD 메소드가 활용됩니다.

방금 본 것처럼 우리가 배운 GET, POST, PUT, DELETE 외에도 리퀘스트에 설정할 수 있는 메소드 종류에는 여러 가지가 있습니다. 각 메소드의 의미를 잘 이해하고 기억해두면 Web API를 설계하는데 큰 도움이 됩니다. 혹시 또 다른 메소드들에 대해서도 알고 싶다면 이 링크를 참조하세요.

  1. 웹 통신 말고 다른 통신도 있어요. 우리는 이때까지 웹에서 이루어지는 통신에 대해서 배웠습니다. 그런데 이 시점에서 한 가지 짚고 넘어가야 하는 사실이 있습니다. 사실 하나의 컴퓨터와 다른 컴퓨터가 통신하는 공간에는 웹만 있는 것은 아니라는 사실입니다. 이게 무슨 말일까요? 이전에 살펴본 웹의 특징에는 ‘HTTP, HTTPS 같은 프로토콜을 사용하여 통신한다’는 것도 있었죠?

하지만 컴퓨터끼리 통신하는 프로토콜에는 이것만 있는 것이 아닙니다. HTTP, HTTPS 이외에도, FTP, SSH, TCP, UDP, IP, Ethernet 등 정말 다양한 종류의 프로토콜들이 있는데요. 그리고 여기서 중요한 것은 이런 프로토콜들은 각각 네트워크 통신의 특정 계층에 속한다는 점입니다.

사실 우리가 배운 HTTP(HyperText Transmission Protocol)는

20210321_060719

이 이미지에서 보이는 것처럼 보통, 그 밑에 TCP(Transmission Control Protocol), 그리고 그 밑에 IP(Internet Protocol), 그리고 그 밑에 Ethernet이라는 프로토콜을 기반으로 동작하고 있습니다. 그러니까 사실 HTTP나 HTTPS 프로토콜을 기반으로 한 통신은 그 하위 프로토콜을 기반으로 이루어지는 겁니다. 이때 위로 갈수록 고수준 프로토콜, 아래로 갈수록 저수준 프로토콜이라고 하는데요. HTTP는 매우 고수준에 해당하는 프로토콜임을 알 수 있습니다. ‘웹 개발자’라고 하면 당장은 HTTP 프로토콜 상에서 이루어지는 일만 공부한다고 해도 큰 어려움이 없을 수도 있습니다. 하지만 특히 서버 쪽을 담당하는 ‘백엔드 개발자’의 경우에는 서비스의 사용자 수가 늘어나서 리퀘스트의 수가 늘어날수록 HTTP 아래에 있는 프로토콜에 대해서도 어느 정도 알고 있어야 각종 성능 문제 등을 해결할 수 있습니다. 그래서 혹시 ‘백엔드 개발자’를 꿈꾸는 분들이라면 당장은 공부하지 않더라도 다른 프로토콜들에 대해서도 일단은 미리 관심을 가져두는 게 좋습니다.

그리고 ‘웹 개발자’ 뿐만 아니라

20210321_060545

예를 들어, 이렇게 HTTP 없이 TCP라는 프로토콜만으로 통신하는 코드를 짜는 개발자들도 많이 존재합니다. 이제 여기부터는 웹 개발 세계 밑에 감춰진 또 다른 개발 세계가 존재하는데요. MMORPG 게임 서버 개발이나, IOT 기기 개발 등과 같이 성능 최적화 등이 필요한 경우에는 이런 저수준 프로토콜로 통신하는 프로그램을 개발하기도 합니다. 일반 사용자에게는 웹이 컴퓨터 네트워크의 전부인 것 같지만 실제로는 웹 밑에 가려진 또 다른 거대한 세계가 있다는 사실은 기억하고 가주세요.





© 2021.03. by yacho

Powered by github