1. What is ORM?

 

  ORM은 Object Relational Mapping 즉, 객체 - 관계 매핑의 줄임말이다.

  객체-관계 매핑이란 객체 지향 프로그래밍에서 구현한 클래스와 RDB(Relational DataBase)에서 테이블을 매핑(연결)하는 것을 의미한다.

 

  이 연결을 위해 필요한 기능을 제공하는 것이 ORM이다.

  따라서 ORM을 이용하면 따로 SQL문을 짤 필요 없이 객체를 통해 간접적으로 데이터베이스를 조작할 수 있게 된다.

 

 

2. Sequelize ORM

 

  Sequelize는 Postgres, MySQL, MariaDB, SQLite 등을 지원하는 Promise에 기반한 비동기로 동작하는 Node.js ORM이다.

 

  2 - 1) model

 

    모델은 Sequelize의 본질이다.

    모델은 데이터베이스에서 하나의 테이블을 나타낸다.

    Sequelize에서 내가 만든 모델은 Model이라는 것을 상속하는 클래스다.

    이 모델을 이용하여 실제 데이터베이스에 존재하는 테이블에 CRUD 할 수 있다.

 

  2 - 2) migration

 

    Git을 사용하여 코드의 변경 사항을 관리하는 것처럼 마이그레이션을 사용하여 데이터베이스의 변경 사항을 추적할 수 있다.

    마이그레이션을 통해 기존 데이터베이스를 다른 상태로 또는 그 반대로 전송할 수 있다.

 

    상태 전환은 마이그레이션 파일에 직접 작성할 수 있다.

    그리고 새 상태로 전환하는 방법과 이전 상태로 돌아 가기 위해 변경 사항을 되돌리는 방법을 설명할 수 있다.

 

    또한 마이그레이션을 다루기위해선 Sequelize CLI가 필요하다.

    CLI는 마이그레이션 및 프로젝트 부트 스트랩에 대한 지원을 제공한다.

 

    마이그레이션은 마이그레이션을 실행하고 취소하는 기능을 의미하는 두 가지 기능인 (up/down)을 내보내는 자바스크립트 파일이다.

    이러한 함수를 직접 정의해야하지만 수동으로 호출하지는 않고 CLI에 의해 자동으로 호출할 수 있다.

    이러한 함수에서는 sequelize.query 및 Sequelize가 제공하는 다른 메서드를 사용하여 필요한 쿼리를 간단히 수행해야 한다.

 

 

 

*참고 : sequelize.org/master/

 

Manual | Sequelize

Constraints & Circularities Adding constraints between tables means that tables must be created in the database in a certain order, when using sequelize.sync. If Task has a reference to User, the User table must be created before the Task table can be crea

sequelize.org

  

    

'CodeStates' 카테고리의 다른 글

MVC Design Pattern  (0) 2021.03.03
IM 35일차 (nodemon & Debugging for node.js)  (0) 2021.02.15
IM 32일차 (Postman 사용법)  (0) 2021.02.12
IM 31일차 (MIME type 과 HTTP headers 의 Content-Type)  (0) 2021.02.11
IM 26일차 (CORS)  (0) 2021.02.06

1. MVC 패턴

 

 

 

  모델-뷰-컨트롤러(Model–View–Controller, MVC)는 소프트웨어 공학에서 사용되는 소프트웨어 디자인 패턴이다.

  이 패턴을 성공적으로 사용하면, 사용자 UI로부터 내부 로직을 분리하여 서로 영향 없이 쉽게 개발할 수 있는 애플리케이션을 만들 수 있다.

 

  MVC에서 모델은 애플리케이션의 데이터를 나타내며, 뷰는 브라우저를 통해 그려지는 화면을 나타내고, 컨트롤러는 데이터와 비즈니스 로직 사이의 상호동작을 관리한다.

 

 

 

2. Model

 

  실제 데이터베이스의 데이터와 상호작용이 일어나는 곳.

  뷰와 컨트롤러에서 모델의 상태를 조작하거나 가져오기 위한 인터페이스를 제공하고 모델에서 자신의 상태 변화에 대해서 옵저버들에게 알려주긴 하지만 기본적으로 모델은 뷰와 컨트롤러에 대해 별 관심이 없다.

 

 

 

3. View

 

  사용자와 상호작용하는 클라이언트단이라고 할 수 있다.

  화면에 데이터를 표시하기위해 컨트롤러와 상호작용하여 모델에서 데이터를 받아온다.

 

 

 

4. Controller

 

  뷰와 모델 사이에 위치하며 사용자의 뷰로부터 요청을 받아 그것을 모델에게 전달한다.

  단순히 모델한테 전달하는 역할만 하는 것이 아니라 사용자가 입력한 것을 분석하여 그것을 바탕으로 모델을 조작하는 임무를 맡고 있다.

 

 

 

*참고 : thefif19wlsvy.tistory.com/49, ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC

 

'CodeStates' 카테고리의 다른 글

Sequelize ORM  (0) 2021.03.07
IM 35일차 (nodemon & Debugging for node.js)  (0) 2021.02.15
IM 32일차 (Postman 사용법)  (0) 2021.02.12
IM 31일차 (MIME type 과 HTTP headers 의 Content-Type)  (0) 2021.02.11
IM 26일차 (CORS)  (0) 2021.02.06

1. nodemon

 

  nodemon이 무엇일까?

  npm에서 nodemon에 대한 정의는 다음과 같다.

 

  nodemon is a tool that helps develop node.js based applications by automatically restarting the node application when file changes in the directory are detected.

 

  간단하게 말하면 우리가 node.js로 만든 애플리케이션의 변화(코드 수정)가 있을 때 자동으로 애플리케이션을 재실행시켜주는 도구이다.

 

  1 - 1) 설치

 

npm install -g nodemon //전역적 설치

npm install --save-dev nodemon //특정 디렉토리 내에서만 사용

 

  1 - 2) 사용법

 

    node.js 애플리케이션을 서버로 동작시킬 때 node app.js 와 같이 사용하는데 이때 node 부분을 nodemon으로만 바꿔주면

    nodemon을 사용할 수 있다.

 

  1 - 3) cli options

 

Configuration
--config <file> .......... alternate nodemon.json config file to use
--exitcrash .............. exit on crash, allows nodemon to work with other watchers
-i, --ignore ............. ignore specific files or directories
--no-colors .............. disable color output
--signal <signal> ........ use specified kill signal instead of default (ex. SIGTERM)
-w, --watch path ......... watch directory "dir" or files. use once for each
directory or file to watch
--no-update-notifier ..... opt-out of update version check
 
Execution
-C, --on-change-only ..... execute script on change only, not startup
--cwd <dir> .............. change into <dir> before running the script
-e, --ext ................ extensions to look for, ie. "js,pug,hbs"
-I, --no-stdin ........... nodemon passes stdin directly to child process
--spawn .................. force nodemon to use spawn (over fork) [node only]
-x, --exec app ........... execute script with "app", ie. -x "python -v"
-- <your args> ........... to tell nodemon stop slurping arguments
 
Watching
-d, --delay n ............ debounce restart for "n" seconds
-L, --legacy-watch ....... use polling to watch for changes (typically needed
when watching over a network/Docker)
-P, --polling-interval ... combined with -L, milliseconds to poll for (default 100)
 
Information
--dump ................... print full debug configuration
-h, --help ............... default help
--help <topic> ........... help on a specific feature. Try "--help topics"
-q, --quiet .............. minimise nodemon messages to start/stop only
-v, --version ............ current nodemon version
-V, --verbose ............ show detail on what is causing restarts

 

 

 

2. Debugging for node.js

 

  nodejs.org/ko/docs/guides/debugging-getting-started/

 

디버깅 - 시작하기 | Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

  자세한 내용은 위 공식 문서에서 찾아볼 수 있다.

  node.js 에서 간단한 경우에는 console.log 를 통해 디버깅을 할 수 있지만 좀 더 원본 객체를 뜯어보거나 해야 할 경우

  단순히 콘솔만 찍어서는 디버깅이 어렵다.

 

  이 때 --inspect 옵션을 주면 크롬 개발자 도구에서 node.js를 디버깅할 수 있다!

  또한 해당 --inspect 옵션은 위에서 설명한 nodemon에도 줄 수 있다!

'CodeStates' 카테고리의 다른 글

Sequelize ORM  (0) 2021.03.07
MVC Design Pattern  (0) 2021.03.03
IM 32일차 (Postman 사용법)  (0) 2021.02.12
IM 31일차 (MIME type 과 HTTP headers 의 Content-Type)  (0) 2021.02.11
IM 26일차 (CORS)  (0) 2021.02.06

1. Postman?

 

  브라우저는 서버에게 HTTP 요청을 보낼 수 있는 훌륭한 도구이지만, GET 요청을 보낼 때만 유용하다.

  주소창을 통해서 URL을 입력하는 입력하는 행위가 바로 GET 요청이다.

  GET이 아닌 기타 다른 요청을 보내려면, 개발자 도구를 이용해 fetch를 이용한 JavaScript 코드를 작성해야만 한다.

 

  이러한 한계로, 브라우저가 아닌 다른 종류의 HTTP 요청을 테스트할 수 있는 다양한 도구들이 존재한다.

  이러한 도구를 API 테스팅 도구라고 부른다.

  이러한 API 테스팅 도구는, 클라이언트 입장에서 서버 API를 테스트하거나, 애초에 처음부터 API를 만들 때에도 매우 유용하다.

 

  그 중 하나가 Postman이다.

 

 

 

2. 사용법

 

출처 : 코드스테이츠

 

 

  1. 새로운 탭 오픈
    • 요청/응답을 여러 개 확인할 수 있다.
  2. HTTP 메소드 선택
    • GET, POST, DELETE 등과 같은 메소드 중 하나를 선택할 수 있다.
  3. URL 입력 창
    • endpoint 및 URL을 입력할 수 있다.
  4. HTTP 요청 버튼
    • 요청을 보낸다.
  5. HTTP 요청시 설정할 수 있는 각종 옵션
    • 추가적인 파라미터나, 요청 본문(body)을 추가할 수 있다.
  6. HTTP 응답 화면
    • 여러분이 실제로 요청을 보낸 후에 응답을 확인할 수 있다!

'CodeStates' 카테고리의 다른 글

MVC Design Pattern  (0) 2021.03.03
IM 35일차 (nodemon & Debugging for node.js)  (0) 2021.02.15
IM 31일차 (MIME type 과 HTTP headers 의 Content-Type)  (0) 2021.02.11
IM 26일차 (CORS)  (0) 2021.02.06
IM 25일차 (http)  (0) 2021.02.06

1. MIME type

 

  Multipurpose Internet Mail Extensions의 약자로 간단히 말하면 파일 변환을 의미한다.

  현재는 웹을 통해 여러 형태의 파일을 전달하는데 사용하고 있다.

  이 용어가 처음 생겼을 땐 이메일과 함께 동봉할 파일을 텍스트 문자로 전환해서 이메일 시스템을 통해 전달하기 위해 개발되어 Internet Mail Extensions라고 불리기 시작했다고 한다.

 

 

 

2. MIME 사용 이유

 

  예전에는 텍스트 파일을 주고 받는데에 ASCII로 공통된 표준에 따르기만 하면 문제가 없었으나 네트워크를 통해 ASCII가 아닌 바이너리 파일을 보내는 경우가 생기게 되었다.

  음악파일, 무비파일, 워드파일 등등 ASCII만으로는 전송이 안되기 때문에 기존 시스템에서 문제 없이 전달하기 위해서는 텍스트로의 변환이 필요했다.

 

  텍스트 파일로 변환하는 것을 인코딩(Encoding), 텍스트 파일을 바이너리 파일로 변환하는 것을 디코딩(Decoding)이라고 한다.

  그리고 MIME으로 인코딩한 파일은 네트워크 통신을 할 때 Content-type정보를 앞부분에 담게되며 Content-type은 여러가지 타입이 있다. 브라우저는 Content-Type에 담긴 값을 토대로 디코딩을 해서 사용자의 화면에 보여줄 것이다

 

  예를 들어 웹 브라우저에서 서버에 접속하여 html 문서를 요청하면서 html문서에 있는 이미지 파일의 경로를 불러올 수 있다.

  이러한 과정에서 이미지의 경로에 있는 파일이 웹브라우저에서 지원되는 MIME-Type이라면 웹브라우저를 이용하여 열어볼 수 있다.

 

  바이너리파일(음악 파일, 무비 파일, 워드 파일 등) 또한 마찬가지 이다. 주로 쓰고 있는 대부분의 포맷인 .gif .jpg .mov 등등의 파일들은 웹 브라우저에서 무리없이 열리게 되는데 브라우저에서 지원하지 못하는 유형은 따로 지정해줘야 한다.

 

 

 

3. 다양한 Content-Type

 

  3 - 1) Multipart Related MIME 타입

    - Content-Type: Multipart/related <-- 기본형태

    - Content-Type: Application/X-FixedRecord

 

  3 - 2) XML Media의 타입

   - Content-Type: text/xml

   - Content-Type: Application/xml

   - Content-Type: Application/xml-external-parsed-entity

   - Content-Type: Application/xml-dtd

   - Content-Type: Application/mathtml+xml

   - Content-Type: Application/xslt+xml

 

  3 - 3) Application의 타입

    - Content-Type: Application/EDI-X12 <--  Defined in RFC 1767 

    - Content-Type: Application/EDIFACT <--  Defined in RFC 1767 

 

   - Content-Type: Application/javascript <-- Defined in RFC 4329 

   - Content-Type: Application/octet-stream  : <-- 디폴트 미디어 타입은 운영체제 종종 실행파일, 다운로드를 의미

   - Content-Type: Application/ogg <-- Defined in RFC 3534

   - Content-Type: Application/x-shockwave-flash <-- Adobe Flash files

   - Content-Type: Application/json <-- JavaScript Object Notation JSON; Defined in RFC 4627 

   - Content-Type: Application/x-www-form-urlencode <-- HTML Form 형태

 

  * x-www-form-urlencode와 multipart/form-data은 둘다 폼 형태이지만 x-www-form-urlencode은 대용량 바이너리 테이터를 전송하기에 비효율적이기 때문에 대부분 첨부파일은 multipart/form-data를 사용하게 된다.

 

  3 - 4) 오디오 타입

    - Content-Type: audio/mpeg <-- MP3 or other MPEG audio

    - Content-Type: audio/x-ms-wma <-- Windows Media Audio;

    - Content-Type: audio/vnd.rn-realaudio <--  RealAudio;  등등 

 

  3 - 5) Multipart 타입

    - Content-Type: multipart/mixed: MIME E-mail; 

    - Content-Type: multipart/alternative: MIME E-mail;

    - Content-Type: multipart/related: MIME E-mail <-- Defined in RFC 2387 and used by MHTML(HTML mail) 

    - Content-Type: multipart/formed-data  <-- 파일 첨부

 

  3 - 6) TEXT 타입

    - Content-Type: text/css

    - Content-Type: text/html

    - Content-Type: text/javascript

    - Content-Type: text/plain

    - Content-Type: text/xml

 

  3 - 7) file 타입

    - Content-Type: application/msword <-- doc

    - Content-Type: application/pdf <-- pdf

    - Content-Type: application/vnd.ms-excel <-- xls

    - Content-Type: application/x-javascript <-- js

    - Content-Type: application/zip <-- zip

    - Content-Type: image/jpeg <-- jpeg, jpg, jpe

    - Content-Type: text/css <-- css

    - Content-Type: text/html <-- html, htm

    - Content-Type: text/plain <-- txt

    - Content-Type: text/xml <-- xml

    - Content-Type: text/xsl <-- xsl

 

 

*참고 : velog.io/@aerirang647/MIME-type%EC%9D%B4%EB%9E%80,

yunzema.tistory.com/186

'CodeStates' 카테고리의 다른 글

IM 35일차 (nodemon & Debugging for node.js)  (0) 2021.02.15
IM 32일차 (Postman 사용법)  (0) 2021.02.12
IM 26일차 (CORS)  (0) 2021.02.06
IM 25일차 (http)  (0) 2021.02.06
IM 24일차 (Basic Web Architecture, Ajax)  (0) 2021.02.05

1. CORS

 

  CORS는 Cross Origin Resource Sharing의 줄임말이다.

  mdn 에서 우리말로 번역했을 땐 '교차 출처 리소스 공유'라는 뜻이 되는데 뭔가 이해하기 어렵다,,

  그래서 교차 출처 보다는 다른 출처, 즉 '다른 출처 간 리소스를 공유하는 것'이라고 이해하면 좋을 것 같다.

 

  그리고 출처라는 말이 나오는데 출처란 Protocol Host, 포트 번호까지 모두 합친 것을 의미한다.

  https://www.naver.com 까지가 출처가 되겠다.

 

  이 출처를 이루는 세 가지 중 하나라도 다르면 다른 출처라고 생각하면 된다.

  브라우저의 개발자 도구에서 Location의 origin 프로퍼티에 접근함으로써 손 쉽게 애플리케이션이 실행되고 있는 출처를 알아낼 수 있다.

 

 

 

2. 같은 출처와 다른 출처의 구분

 

  위에서 같은 출처란 프로토콜, 호스트, 포트 번호까지 모두 같으면 같은 출처이고 그중 하나라도 다르면 다른 출처로 인식한다고 했다.

  그럼 그러한 출처를 비교하는 로직이 어디에서 이루어지냐 하면 브라우저에 구현되어 있는 스펙이다.

 

  만약 우리가 CORS 정책을 위반하는 리소스 요청을 하더라도 해당 서버가 같은 출처에서 보낸 요청만 받겠다는 로직을 가지고 있는 경우가 아니라면 서버는 정상적으로 응답을 하고, 이후 브라우저가 이 응답을 분석해서 CORS 정책 위반이라고 판단되면 그 응답을 사용하지 않고 그냥 버리는 순서인 것이다.

 

 

 

 

3. CORS 동작 원리

 

  그럼 본격적으로 어떤 방법을 통해 서로 다른 출처를 가진 리소스를 안전하게 사용할 수 있는지 알아보도록 하자.

기본적으로 웹 클라이언트가 다른 출처의 리소스를 요청할 때는 HTTP 프로토콜을 사용하여 요청을 보내게 되는데, 이때 브라우저는 요청 헤더에 Origin이라는 필드에 현재 요청을 보내는 출처를 함께 담아 보낸다.

 

이후 서버가 이 요청에 대한 응답을 할 때 응답 헤더의 Access-Control-Allow-Origin이라는 값에 “허용된 출처”를 내려주고, 이후 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin의 값을 비교해본 후 이 응답이 유효한 응답인지 아닌지를 결정한다.

 

기본적인 흐름은 이렇게 간단하지만, 사실 CORS가 동작하는 방식은 한 가지가 아니라 세 가지의 시나리오에 따라 변경되기 때문에 여러분의 요청이 어떤 시나리오에 해당되는지 잘 파악해야 CORS 정책 위반으로 인한 에러를 디버깅하는 것이 한결 쉬울 것이다.

 

  3 - 1) Preflight Request

 

    프리플라이트(Preflight) 방식은 일반적으로 우리가 개발할 때 가장 많이 마주치는 시나리오이다.

    이 시나리오에 해당하는 상황일 때 브라우저는 요청을 한 번에 보내지 않고 예비 요청과 본 요청으로 나누어서 서버로 전송한다.

 

    이때 브라우저가 본 요청을 보내기 전에 보내는 예비 요청을 Preflight라고 부르는 것이며, 이 예비 요청의 HTTP 메서드는

    OPTIONS 메소드가 사용된다.

    예비 요청의 역할은 본 요청을 보내기 전에 브라우저 스스로 이 요청을 보내는 것이 안전한지 확인하는 것이다.

 

 

  우리가 fetch API를 사용하여 브라우저에게 리소스를 받아오라는 명령을 내리면 브라우저는 서버에게 예비 요청을 먼저 보내고, 서버는 이 예비 요청에 대한 응답으로 현재 어떤 것들을 허용하고, 어떤 것들을 금지하고 있는지에 대한 정보를 응답 헤더에 담아서 브라우저에게 다시 보내주게 된다.

이후 브라우저는 자신이 보낸 예비 요청과 서버가 응답에 담아준 허용 정책을 비교한 후, 이 요청을 보내는 것이 안전하다고 판단되면 같은 엔드포인트로 다시 본 요청을 보내게 된다. 이후 서버가 이 본 요청에 대한 응답을 하면 브라우저는 최종적으로 이 응답 데이터를 자바스크립트에게 넘겨준다.

 

  3 - 2) Simple Request

 

    단순 요청은 예비 요청을 보내지 않고 바로 서버에게 본 요청을 한 후, 서버가 이에 대한 응답의 헤더에 Access-Control-Allow-Origin과 같은 값을 보내주면 그때 브라우저가 CORS 정책 위반 여부를 검사하는 방식이다. 즉, 프리플라이트와 전반적인 로직 자체는 같되, 예비 요청의 존재 유무만 다르다. 

 

 

  하지만 아무 때나 단순 요청을 사용할 수 있는 것은 아니고, 특정 조건을 만족하는 경우에만 예비 요청을 생략할 수 있다. 게다가 이 조건이 조금 까다롭기 때문에 일반적인 방법으로 웹 애플리케이션 아키텍처를 설계하게 되면 거의 충족시키기 어려운 조건들이라 이런 경우는 드물다. 조건은 아래와 같다.

 

  1. 요청의 메서드는GET, HEAD, POST 중 하나여야 한다.
  2. Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width를 제외한 헤더를 사용하면 안 된다.
  3. 만약 Content-Type를 사용하는 경우에는 application/x-www-form-urlencoded, multipart/form-data, text/plain만 허용된다.

    사실 1번 조건의 경우는 그냥 PUT이나 DELETE 같은 메서드를 사용하지 않으면 되는 것뿐이니 그렇게 보기 드문 상황은 아니다.

    하지만 2번이나 3번 조건 같은 경우는 조금 까다롭다.

 

    애초에 저 조건에 명시된 헤더들은 진짜 기본적인 헤더들이기 때문에, 이 헤더들 외에 추가적인 헤더를 사용하지 않는 경우는 드물다.

    당장 사용자 인증에 사용되는 Authorization 헤더 조차 저 조건에는 포함되지 않는다.

    게다가 대부분의 API는 application/json 컨텐츠 타입을 가지도록 설계되기 때문에 사실 상 이 조건들을 모두 만족시키는 상황을 만들기는 그렇게 쉽지 않은 것이 현실이다.

 

  3 - 3) Credentialed Request

 

    3번째 시나리오는 인증된 요청을 사용하는 방법이다.

기본적으로 브라우저가 제공하는 비동기 리소스 요청 API인 XMLHttpRequest 객체나 fetch API는 별도의 옵션 없이 브라우저의 쿠키 정보나 인증과 관련된 헤더를 함부로 요청에 담지 않는다.

 

    이때 요청에 인증과 관련된 정보를 담을 수 있게 해주는 옵션이 바로 credentials 옵션이다.

    이 옵션에는 총 3가지의 값을 사용할 수 있으며, 각 값들이 가지는 의미는 다음과 같다.

 

same-origin (기본값) 같은 출처 간 요청에만 인증 정보를 담을 수 있다
include 모든 요청에 인증 정보를 담을 수 있다
omit 모든 요청에 인증 정보를 담지 않는다

 

    만약 same-origin이나 include와 같은 옵션을 사용하여 리소스 요청에 인증 정보가 포함된다면, 이제 브라우저는 다른 출처의 리소스를 요청할 때 단순히 Access-Control-Allow-Origin만 확인하는 것이 아니라 검사 조건을 추가하게 된다.

 

만약 인증 모드가 include일 경우,  브라우저는 모든 요청을 허용한다는 의미의 *를 Access-Control-Allow-Origin 헤더에 사용하면 안 된다고 이야기한다.

이처럼 요청에 인증 정보가 담겨있는 상태에서 다른 출처의 리소스를 요청하게 되면 브라우저는 CORS 정책 위반 여부를 검사하는 룰에 다음 두 가지를 추가하게 된다.

 

  1. Access-Control-Allow-Origin에는 *를 사용할 수 없으며, 명시적인 URL 이어야 한다.
  2. 응답 헤더에는 반드시 Access-Control-Allow-Credentials: true가 존재해야 한다.

 

 

4. 끝으로

 

  CORS 정책 위반으로 인해 생기는 문제를 해결할 때 가장 번거로운 점은 문제를 겪는 사람과 문제를 해결해야 하는 사람이 다르다는 것이다.

  CORS 정책은 브라우저의 구현 스펙이기 때문에 정책 위반으로 인해 문제를 겪는 사람은 대부분 프런트엔드 개발자이지만, 정작 문제를 해결하기 위해서는 백엔드 개발자가 서버 애플리케이션의 응답 헤더에 올바른 Acccess-Control-Allow-Origin이 줄 수 있도록 세팅해줘야 하기 때문이다.

1. http란?

 

  클라이언트와 서버가 데이터를 주고받을 때 통신하는 방식, 통신 규약, 하나의 약속이다.

  메시지 타입은 두 가지다. 요청(request) 메시지가 있고 응답(respnse) 메시지가 있다.

  요청 메세지는 클라이언트의 요구사항이고, 응답 메시지는 서버의 응답이다.

  

  웹 개발자가 직접 HTTP 메시지를 텍스트로 작성하는 경우는 거의 없다.

  대신에 소프트웨어, 브라우저, 프록시, 또는 웹 서버가 그 일을 대신 수행한다.

  HTTP 메시지는 설정 파일(프록시 혹은 서버의 경우), API(브라우저의 경우), 혹은 다른 인터페이스를 통해 제공된다.

 

 

 

 

2. http 메세지의 구조

 

  HTTP 요청과 응답의 구조는 거의 비슷하며, 그 구조는 다음과 같다.

  기본적으로 시작 줄(start-line), header, body로 이루어져 있다.

  그리고 http header 와 body 사이에는 구분을 위해 빈 줄(blank line)이 주어진다.  

 

  HTTP 메시지의 start line 과 header를 묶어서 요청 헤드(head)라고 부르며, 본문(body) 을 HTTP 메시지의 payload 라고 합니다.

 

 

 

 

3. http request, response message

 

  3 - 1) request start line

 

    http 요청 메시지의 시작 줄에는 http 메서드, URL, http 버전으로 이루어져 있다.

   

    http 메서드는 요청이 어떤 동작을 수행할 것인지를 나타낸다.

    조회를 데이터를 달라고 할 때는 GET

    해당 데이터가 서버에 저장되어야 할 때는 POST

    특정 데이터의 전체 수정이 필요하다면 PUT

    특정 데이터의 부분만 수정이 필요하다면 PATCH

    특정 데이터의 삭제가 필요하다면 DELETE

    위 동작이 수행가능한 것인지 미리 확인하고자 할 때는 OPTIONS

   

    일단 이 정도는 꼭 기억하자

 

    그 다음은 URL인데 이것은 내가 위 메서드들에 해당하는 동작을 하길 원하는 경로라고 할 수 있다.

    그리고 마지막으로 버전은 말 그대로 http 버전이다.

 

  3 - 2) response start line

 

    http 응답 메시지의 시작 줄에는 http 버전, 응답 상태 코드와 상태 텍스트로 이루어져 있다.

    버전은 말 그대로 버전이다.

 

    응답 상태 코드는 1~500 번대의 코드가 있는데 앞자리에 따라 의미가 다르다.

    의미는 다음과 같다.

    상태 코드를 하나하나 다 외울순 없다. 필요할 때마다 찾아보자! developer.mozilla.org/ko/docs/Web/HTTP/Status

    

  3 - 3) common headers

 

    요청과 응답에 모두 사용되는 헤더를 공통 헤더라 한다. 이 중에서 Content 시리즈는 엔티티 헤더라고 불린다.

Date

HTTP 메시지가 만들어진 시각이다. 자동으로 만들어진다.

Date: Thu, 12 Jul 2018 03:12:27 GMT

Connection

Connection: keep-alive

HTTP/2를 사용하지 않는다면 보통 HTTP/1.1을 사용하게 되는데 Connection은 기본적으로 keep-alive로 되어있는데 사실상 아무런 의미도 없다. HTTP/2에서는 아예 사라져 버렸다.

Cache-Control

매우 중요하고 알아두어야 하는 헤더이기 때문에 따로 추후에 블로깅을 하자.

Content-Length

요청과 응답 메시지의 본문 크기를 바이트 단위로 표시해준다. 마찬가지로 자동으로 만들어진다.

Content-Length: 52

Content-Type

Content-Type: text/html; charset=utf-8

콘텐츠의 타입(MIME)과 문자열 인코딩(utf-8 등등)을 명시할 수 있다. 조금 뒤에 나오는 Accept 헤더, Accept-Charset 헤더와 대응된다. 위에 예시로 든 헤더는 현재 메시지 내용이 text/html 타입이고 문자열은 utf-8 문자열임을 알려주고 있다.

Content-Language

사용자의 언어를 뜻한다.

Content-Encoding

Content-Encoding: gzip, deflate

Content-Encoding은 콘텐츠가 압축된 방식입니다. 응답 컨텐츠를 br, gzip, deflate 등의 알고리즘으로 압축해서 보내면, 브라우저가 알아서 해제해서 사용한다. 이 외에도 다양한 압축 알고리즘이 존재하고 컨텐츠 용량이 줄어들기 때문에 압축을 권장한다.

 

  3 - 4) request headers

Host

서버의 도메인 네임이 나타나는 부분이다(포트 포함). 

Host: www.naver.com

Host 헤더는 반드시 하나가 존재해야 한다.

User-Agent

Host보다 더 유명한 헤더는 User-Agent다.

현재 사용자가 어떤 클라이언트(운영체제와 브라우저 같은 것)를 이용해 요청을 보냈는지 나온다.

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36

Accept

Accept 헤더는 요청을 보낼 때 서버에게 이런 타입(MIME)의 데이터를 보내줬으면 좋겠다고 명시할 때 사용한다.

예를 들어 요청의 헤더로

Accept: text/html

를 보내면 HTML 형식인 응답을 기대한다는 뜻이다.

Accept: image/png, image/gif
Accept: text/*

콤마로 여러 타입을 동시에 적어줄 수도 있고, *로 "텍스트이기만 하면 돼"라고 적어줄 수도 있다.

Accept로 원하는 형식을 보내면, 서버가 그에 맞춰 보내주면서 응답 헤더의 Content를 알맞게 설정할 것이다.

Accept-Charset: utf-8
Accept-Language: ko, en-US
Accept-Encoding: br, gzip, deflate

Charset은 문자 인코딩(UTF-8 등)을 명시하는 부분이고, Language는 원하는 언어, Encoding은 원하는 컨텐츠 압축 방식이다.

뭘 적어야 할지 모르겠다면 *(와일드카드)를 적거나, 그냥 브라우저가 알아서 설정해서 보내는 Accept를 사용하면 된다.

Authorization

Authorization 헤더는 인증 토큰(JWT든, Bearer 토큰이든)을 서버로 보낼 때 사용하는 헤더다.

API 요청 같은 것을 할 때 토큰이 없으면 거절당하기 때문에 이때, Authorization을 사용하면 된다.

Authorization: Bearer XXXXXXXXXXXXX

보통 Basic이나 Bearer 같은 토큰의 종류를 먼저 알리고 그다음에 실제 토큰 문자를 적어 보낸다.

Origin

POST 같은 요청을 보낼 때, 요청이 어느 주소에서 시작되었는지를 나타낸다. 여기서 요청을 보낸 주소와 받는 주소가 다르면 CORS 문제가 발생하기도 한다.

Referer

Referer: https://www.xxx.com/category/JavaScript

현재 페이지 이전의 페이지 주소가 담겨 있다.

이 헤더를 사용하면 어떤 페이지에서 지금 페이지로 들어왔는지 알 수 있기 때문에 애널리틱스 같은 데 많이 사용된다.

 

3 - 5) response headers

Access-Control-Allow-Origin

프런트엔드 개발자들에게 악명 높은 헤더다. 요청을 보내는 프론트 주소와 받는 백엔드 주소가 다르면 CORS 에러가 발생한다.

이때 서버에서 응답 메시지 Access-Control-Allow-Origin 헤더에  요청을 보내는 프런트 주소를 적어주어야 에러가 나지 않는다.

Access-Control-Allow-Origin: www.naver.com
Access-Control-Allow-Origin: *

프로토콜, 서브도메인, 도메인, 포트 중 하나만 달라도 CORS 에러가 나게 된다.

만약 주소를 일일이 지정하기 싫다면 *으로 모든 주소에 CORS 요청을 허용하면 된다. 단 그만큼 보안이 취약해질 것이다.

유사한 헤더로 Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Headers 등이 있습니다. Request랑 Allow에서 Method 단수 복수 주의하자!

 

CORS 요청 시에는 미리 OPTIONS 주소로 서버가 CORS를 허용하는지 물어본다. 이때 Access-Control-Request-Method로 실제로 보내고자 하는 메서드를 알리고, Access-Control-Request-Headers로 실제로 보내고자 하는 헤더들을 알린다. Allow 친구들은 Request에 대응되는 애들로, 서버가 허용하는 메서드와 헤더를 응답하는 데 사용된다. Request랑 Allow가 일치하면 CORS 요청이 이루어지는 것이다.

Allow

Allow 헤더는 Access-Control-Allow-Methods랑 비슷하지만, CORS 요청 외에도 적용된다는 데에 차이가 있다.

즉 GET www.naver.com 은 되고, POST www.naver.com 은 허용하지 않는 경우, 405 Method Not Allowed 에러를 응답하면서 헤더로

Allow: GET

를 같이 보내면 된다. GET 요청만 받겠다는 뜻이다.

Content-Disposition

응답 본문을 브라우저가 어떻게 표시해야 할지 알려주는 헤더다. inline인 경우 웹페이지 화면에 표시되고, attachment인 경우 다운로드된다.

Content-Disposition: inline
Content-Disposition: attachment; filename='filename.csv'

다운로드되길 원하는 파일은 attachment로 값을 설정하고, filename 옵션으로 파일명까지 지정해줄 수 있다.

파일용 서버인 경우 이 태그를 자주 사용하게 될 것이다.

Location

300번대 응답이나 201 Created 응답일 때 어느 페이지로 이동할지를 알려주는 헤더이다.

HTTP/1.1 302 Found
Location: /

이런 응답이 왔다면 브라우저는 / 주소로 리다이렉트 한다.

Content-Security-Policy

다른 외부 파일들을 불러오는 경우, 차단할 소스와 불러올 소스를 여기에 명시할 수 있다. 하나의 웹 페이지는 다양한 외부 소스들을 불러온다. 이미지도 불러오고 script 태그로 자바스크립트 파일들도 불러온다. 폰트나 스타일, 아이프레임도 불러온다. 하지만 해커들에 의해 원하지 않는 파일을 불러오게 될 수도 있다. XSS 공격 같은 것이 하나의 예시다. 이럴 때 Content-Security-Policy로 허용할 외부 소스만 지정할 수 있다.

Content-Security-Policy: default-src 'self'
Content-Security-Policy: default-src https:
Content-Security-Policy: default-src 'none'

self로 지정하면 자신의 도메인의 파일들만 가져올 수 있다. www.google.com에서는 www.google.com/logo.jpg를 가져올 수 있지만, www.never.com/logo.jpg는 못 가져오는 것이다. https:로 지정하면 https를 통해서만 파일을 가져올 수 있게 된다. 'none'으로 지정하면 가져올 수 없다.

default-src는 모든 외부 소스에 대해 적용되는 것이고 각각 따로 지정할 수도 있다. 두 개나 세 개 정도만 추려서 지정할 수도 있다.

Content-Security-Policy: font-src 'self'; script-src https://www.naver.com 'unsafe-inline'; img-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none'

font-src, script-src, img-src, style-src, object-src 등이 있고, 소스 옵션으로는 도메인이나, https:, 'unsafe-inline'(인라인 태그 허용), 'unsafe-eval'(eval 함수 허용) 등이 있다. 옵션들이 매우 많으므로 자세한 내용은 여기 서 참고하자!

이 외에도 다양한 응답 헤더들이 있으나, 자주 보이는 것만 추려보았다.

 

3 - 6) body

 

  바디에는 실제 데이터가 담기게 된다.

  그냥 데이터가 담기므로 크게 신경 쓸 부분은 아닌 거 같다.

 

참고 : www.zerocho.com/category/HTTP/post/5b4c4e3efc5052001b4f519b, www.zerocho.com/category/HTTP/post/5b3ba2d0b3dabd001b53b9db,

developer.mozilla.org/ko/docs/Web/HTTP/Messages,

developer.mozilla.org/ko/docs/Web/HTTP/Headers

1. Web Architecture

 

  • Client : 서버에게 원하는 리소스를 요청하는 고객, 사용자
  • Server : 고객이 요청한 리소스를 응답하는 제공자
  • Database : 서버가 클라이언트에게 제공할 수 있는 리소스들이 있는 창고, 혹은 클라이언트가 서버에게 전달한 리소스가 저장될 곳
  • API : 서버가 클라이언트에게 제공할 수 있는 기능들, 브라우저를 통해 렌더된 웹 페이지의 UI로 접근할 수 있음
  • http : 클라이언트와 서버가 통신할 때 미리 정해놓은 규칙, 규약

  대부분의 웹은 위의 것들로 구성된다.

  음식점을 예로 들어보겠다.

  

  클라이언트는 맛있는 음식을 먹으러 온 손님이다.

  고객이 메뉴판을 보고 웨이터에게 주문을 한다. 여기서 메뉴판은 API이고 웨이터는 서버다.

  웨이터가 주방장으로 가서 주방장에게 이 메뉴를 만들어 달라고 한다.

  그러면 주방장은 창고에서 해당 메뉴를 만드는데 필요한 재료로 가공을 한 후 음식을 웨이터에게 전달한다.

  여기서 창고는 Database라고 할 수 있다. 그런데 만약 손님이 외국인이다. 안타깝지만 웨이터는 영어를 잘하지 못한다.

  즉 손님과 웨이터가 의사소통을 하기위해선 같은 언어를 써야 한다는 조건이 있다.

  여기서 같은 언어가 http 라고 할 수 있다.

 

  서버의 응답은 항상 클라이언트의 요청에 의해서 일어난다.

  손님이 음식을 주문하지도 않았는데 멋대로 웨이터가 음식을 가져다주는 경우는 없다.

  이처럼 클라이언트 - 서버 - 데이터베이스로 이루어진 3티어 아키텍처가 모던 웹의 주요한 구성이다.

 

web architecture

  

 

 

2. Ajax

 

  내가 처음 Ajax를 접했을 땐 Ajax가 특정 라이브러리나 프레임워크를 의미하는 것이라고 생각했다.

  Ajax는 특정 라이브러리 또는 프레임워크가 아닌 하나의 기술을 의미한다. 즉 패러다임이다.

 

  Ajax는 Asynchronus Javascript and XML을 의미한다.

  해석하자면 비동기적인 자바스크립트와 XML이 되는데 일단 XML은 크게 신경 쓰지 않아도 된다.

 

  현재 대부분의 모던 웹은 대부분 클라이언트와 서버가 데이터를 주고받을 때 json 형식의 데이터로 주고받는데 ajax가 도입됐을 당시는

  주고받는 데이터의 주요한 형식이 XML 이었을 뿐이다.

 

  즉 비동기처리 방식을 통해 서버에게 특정 부분의 데이터만을 받고 자바스크립트를 이용해 그 부분의 UI만을 갱신하는 방식을 말한다.

 

  그렇다면 어떻게 클라이언트가 서버로부터 원하는 데이터를 받아올 수 있을까?

  바로 window 객체에 내장되어 있는 fetch 메서드를 활용하면 된다.

 

  fetch의 첫 번째 전달 인자는 URL이다. 두 번째 전달 인자는 option 값으로 선택사항이다.

  fetch 메서드에 대한 자세한 내용은 mdn에 자세히 나와있다. mdn을 참고하자!

 

  developer.mozilla.org/ko/docs/Web/API/Fetch_API/Fetch%EC%9D%98_%EC%82%AC%EC%9A%A9%EB%B2%95

  

'CodeStates' 카테고리의 다른 글

IM 26일차 (CORS)  (0) 2021.02.06
IM 25일차 (http)  (0) 2021.02.06
IM 22일차 (Promise & Async/Await)  (0) 2021.02.02
IM 22일차 (자바스크립트 이벤트 루프)  (0) 2021.02.02
IM 18일차 (Back Tracking)  (0) 2021.01.29

+ Recent posts