TIL ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป

์ˆ˜ํˆด๋ฆฌ ์–‘ยท2021๋…„ 6์›” 30์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
2/5

http์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜์—ฌ ์•Œ๋งž์€ ์‘๋‹ต์„ ๋ณด์—ฌ์ฃผ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์›น ์„œ๋ฒ„๋ผ๊ณ  ํ•จ

โ– CORS

=== Cross-origin resource sharing
์ด์ „์—๋Š” ์„œ๋ฒ„์—์„œ ๋‹ค์šด๋กœ๋“œ๋œ ํด๋ผ์ด์–ธํŠธ์œผ๋กœ ํ†ต์‹ ํ•˜์˜€์œผ๋‚˜, ์›น์•ฑ์ด ๊ณ ๋„ํ™”๋˜๋ฉด์„œ ์™ธ๋ถ€์˜ api๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋“ฑ ์—ฌ๋Ÿฌ ๊ณณ์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ํ™œ์šฉํ•  ํ•„์š”์„ฑ ์ฆ๊ฐ€
*same origin์ด ์•„๋‹Œ ๋‹ค๋ฅธ cross-origin์— request๋ฅผ ๋ณด๋‚ด๊ณ  response๋ฅผ ๋ฐ›๊ธฐ ์œ„ํ•ด ํ—ˆ์šฉํ•œ ๋ฒ”์œ„ ๋‚ด ๊ฐ€๋Šฅํ•˜๋„๋ก ์ˆ˜์ •๋จ
์›น์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜, ๋ธŒ๋ผ์šฐ์ €์˜ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•œ ๋ณด์•ˆ์ •์ฑ…

โ– node server ๊ตฌํ˜„

=== node.js ๋‚ด์žฅ http๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ˆœํ•œ ์„œ๋ฒ„ ๊ตฌํ˜„

  • ์ผ์ข…์˜ ๋ฌธ๋ฒ•(http ์š”์ณฅ, ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฌธ์„œ ์ž‘์„ฑ)
    • createServer, writeHead ๋“ฑ
    • .on ์œผ๋กœ (addEventListener๊ณผ ๊ฐ™์€ ๋Š๋‚Œ์œผ๋กœ ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ ์ฝœ๋ฐฑ ์ˆ˜ํ–‰)

      Express ์—์„œ .next๊ฐ€ .then ๊ณผ ๊ฐ™์€ ๋Š๋‚Œ

    • .end() (์š”์ฒญ์ด ๋๋‚จ, 'endgame', .json(), .send()**express ๊ณผ ์ฐจ์ด๋ฅผ ๋…ผํ•˜๋Š” ๊ธ€์ด ๋งŽ์€ ๊ฑธ ๋ณด๋‹ˆ ์œ ์‚ฌํ•œ ๋“ฏ)
      - data๋Š” ์—ฌ๋Ÿฌ๋ฒˆ ์˜ฌ ์ˆ˜ ์žˆ์Œ, end๋Š” ํ•œ๋ฒˆ๋งŒ!(stream, buffer๊ฐœ๋…), chunk๋Š” buffer, request๊ฐ์ฒด๋Š” stream์ž„.(๊ณต์‹๋ฌธ์„œ ์ฐธ๊ณ )
      buffer : ๋ฐ์ดํ„ฐ์˜ ์กฐ๊ฐ๋“ค์ด ์Œ“์—ฌ์„œ ์ŠคํŠธ๋ฆฌ๋ฐํ•  ๋ฐ์ดํ„ฐ๊ฐ€ ์™„์ „ํžˆ ๋‹ค์šด๋กœ๋“œ๋จ(์š”์ฒญ์ด ํ•œ๋ฒˆ์— ๊ฐ€์ง€ ์•Š์Œ, ์‚ฌ์ง„img๋ฐ์ดํ„ฐ ํ•˜๋‚˜๋งŒ ์š”์ฒญํ•˜์—ฌ๋„
        .on('data', (chunk) => {
        body. push(chunk);
        }.on(...
      โ๏ธŽ ์ด ๋ถ€๋ถ„์ด ๋ฐ˜๋ณต๋˜๋Š” ๊ฒƒ์ž„

      * Node.js ์˜ buffer ํฌ๊ธฐ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ์ž์˜ ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ๊นŒ์ง€ ์œ ๋™์ ์œผ๋กœ ์ปค์ง„๋‹ค? fs ๋ชจ๋“ˆ์˜ stream ๊ด€๋ จ ํ•จ์ˆ˜๋“ค์€ ๊ธฐ๋ณธ์ ์œผ๋กœ 64kb์ด๊ณ  highwartermark๋กœ ๋”ฐ๋กœ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค๊ณ .

  • ๐Ÿ”— Nodejs ๊ณต์‹๋ฌธ์„œ์˜ HTTP ์š”์ฒญ/์‘๋‹ต ํ•ด๋ถ€
const http = require('http');
http.createServer((request, response) => {
// const { headers, method, url } = request;
  let body = [];
  request.on('error', (err) => {
    console.error(err);
  }).on('data', (chunk) => {
    body.push(chunk); // ๋ฒ„ํผ ์ถ•์ 
  }).on('end', () => {
    body = Buffer.concat(body).toString(); // ์ถ•์ ๋œ Buffer๋ฐ์ดํ„ฐ concat
    response.on('error', (err) => {
      console.error(err);
    });
    response.writeHead(200, {'Content-Type': 'application/json'})
//  const responseBody = { headers, method, url, body };
    response.end(JSON.stringify(responseBody))
  });
}).listen(8080); // 8080port์—์„œ

  • ํ—ค๋” ์„ธํŒ…
const defaultCorsHeader = {
  'Access-Control-Allow-Origin': '*', // ๋ชจ๋“  ์ฃผ์†Œ๋ฅผ ํด๋ผ์ด์–ธํŠธ๋กœ ํ—ˆ์šฉ
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', // ํ—ˆ์šฉํ•˜๋Š” ์š”์ฒญ๋ฉ”์†Œ๋“œ
  'Access-Control-Allow-Headers': 'Content-Type, Accept',
  'Access-Control-Max-Age': 10 // preflighted request๋Š” 10์ดˆ๊นŒ์ง€๋งŒ ํ—ˆ์šฉ, 10์ดˆ ์ด๋‚ด์— ์š”์ฒญ์ด ์™”๋‹ค๊ฐ”๋‹ค ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” preflight ์•ˆ ๋ณด๋‚ธ๋‹ค๋Š” ์˜๋ฏธ
};

** cors ํ—ค๋”๋„ express๋ฅผ ์ด์šฉํ•˜๋ฉด ๋ฏธ๋ฆฌ ์ผ์ผ์ด ์„ ์–ธํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

๐Ÿ”Ž header ๋‚ด 'Access-Control-Allow-Origin'์— ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์ฃผ์†Œ๋ฅผ ๋„ฃ๋Š”๋‹ค๋ฉด?
โ—๏ธ ํŠน์ • origin(ํด๋ผ์ด์–ธํŠธ ์ฃผ์†Œ) ์ง€์ • ์‹œ, ๋‹ค๋ฅธ ํฌํŠธ์—์„œ๋Š” ์ ‘๊ทผ ๋ถˆ๊ฐ€
serve ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ origin์„ ์„ค์ • npx serve -l 3000 > serve listen (Specify a URI endpoint on which to listen)

// client ์„œ๋ฒ„๊ฐ€, ์ง€์ •๋œ origin๊ณผ ๋ถˆ์ผ์น˜ ์‹œ ์ฝ˜์†”์ฐฝ์—์„œ ํ™•์ธ๋˜๋Š” ์—๋Ÿฌ
Access to fetch at 'http://localhost:3000/upper' from origin '~~' has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. 
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

๐Ÿ’ฑโžฟ When Harry met not Sally it's Error ๐Ÿ”ฃ โš ๏ธ
๋‚ด๊ฐ€ ๋งŒ๋‚œ ์—๋Ÿฌ

  • Content-type ๊ด€๋ จ
    Uncaught (in promise) SyntaxError: Unexpected token ${sth} in JSON at position 0
    json ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด์ฃผ๋Š” ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐํƒ€์ž…์ด json ํ˜•์‹์ž„์„ ๋ช…์‹œํ•˜์ง€ ์•Š์•„์„œ ๋ฑ‰๋Š” ์—๋Ÿฌ
    โ†’ fetch ํ•จ์ˆ˜ ๋‚ด header ํ•ญ๋ชฉ์˜ Content-type, Accept๋ฅผ ์„ค์ •ํ•ด์คŒ 'application/json'์œผ๋กœ ํ•ด๊ฒฐ
    ๐Ÿ”Ž 'text/plain'์œผ๋กœ ์„ค์ •ํ•œ๋‹ค๋ฉด? preflighted request(OPTIONS) ๋ณด๋‚ด์ง€ ์•Š์Œ ์ฆ‰ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ •ํ™•ํžˆ ์จ์ค˜์•ผ ๋œ๋‹ค๋Š” ์˜๋ฏธ๋กœ ๋ณด์ž„
    โ—๏ธ options์š”์ฒญ์€ cross-origin request๊ฐ€ ๋“ค์–ด์™”์„ ๋•Œ, ์„œ๋ฒ„๊ฐ€ allowํ•˜๋Š” ์กฐ๊ฑด์„ ์ถฉ์กฑํ•˜๋Š”์ง€ ์‚ฌ์ „์— ํ™•์ธํ•˜๋Š” 'preflighted request'์ด๋‹ค. MDN

  • Error ํ•ธ๋“ค๋ง ๊ด€๋ จ
// node terminal์—์„œ
xxxx.js:$$$
      throw er; // Unhandled 'error' event
      ...
Emitted 'error' event on Server instance at:
...

๐Ÿค” ์—๋Ÿฌ๋ฅผ throwํ•˜๊ณ  ์žˆ์œผ๋‚˜ ์—๋Ÿฌ๋ฅผ ํ•ธ๋“ค๋งํ•˜๋Š” ๊ฒŒ ์—†๋‹ค๋Š” ๋œป, createServer์‚ฌ์šฉํ•œ http์š”์ฒญ/์‘๋‹ต ์ฒ˜๋ฆฌ ํ•จ์ˆ˜ ๋‚ด ๋กœ์ง์—์„œ ์กฐ๊ฑด์ด ์ž˜๋ชป ๊ฑธ๋ฆฐ ๊ฒƒ์œผ๋กœ ๋ณด์—ฌ์ง.
๊ตฌํ˜„ํ•œ ์„œ๋ฒ„์˜ ํ…Œ์ŠคํŠธ์ผ€์ด์Šค๋กœ๋Š” ์—๋Ÿฌ๋ฐœ์ƒํ•  ๋กœ์ง์ด๋‚˜ ์ด๋ฒคํŠธ๊ฐ€ ์—†์–ด์„œ '์—๋Ÿฌ'๋กœ์„œ ํ•ธ๋“ค๋งํ•˜์ง€ ์•Š๊ณ , ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ์—๋Ÿฌ ์ฝ”๋“œ(http status code 400, 404, ..etc.,)๋ฅผ writeHead๋กœ ์ฒ˜๋ฆฌ.(?)

// console ์ฐฝ์—์„œ
ERR_STREAM_WRITE_AFTER_END

๐Ÿค” ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์˜ ํ˜•ํƒœ(GET/POST/..)์™€ ์ฃผ์†Œpath์— ๋”ฐ๋ฅธ ์กฐ๊ฑด๋ณ„๋กœ ์‘๋‹ต์„ end์ฒ˜๋ฆฌ ํ•  ๊ฒƒ์ž„(์กฐ๊ฑด์— ๋”ฐ๋ฅธ ๋ถ„๊ธฐ, ๋ผ์šฐํŒ…), ๋”ฐ๋ผ์„œ ์กฐ๊ฑด ์™ธ ํ•จ์ˆ˜ ๋‚ด ์ ค ๋ฐ”๊นฅ ์Šค์ฝ”ํ”„์—์„œ end๋กœ ์‘๋‹ต์ฒ˜๋ฆฌ๋ฅผ ํ•ด๋ฒ„๋ฆฐ ๊ฒƒ(์กฐ๊ฑด ๋กœ์ง ์œ„์—์„œ๋“  ๋งจ ๋งˆ์ง€๋ง‰์—์„œ๋“ )์ด ์—๋Ÿฌ๋ฅผ ๋ƒ„(์กฐ๊ฑด์„ ๋‹ค ๊ฑฐ์น˜๊ณ ๋„ ๋งˆ์ง€๋ง‰ ์‘๋‹ต์ฒ˜๋ฆฌ๊ฐ€ ๋’ค์ง‘์–ด์”Œ์›Œ์ง€๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ฐœ๊ฒฌ๋˜์—ˆ์Œ) ์‘๋‹ต์„ ํ•œ๋ฒˆ๋งŒ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด๋จ. ์‹ค์ˆ˜ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด return;์„ ํ•ด์ฃผ๊ธฐ๋„ ํ•จ


โ– ์›น ์„œ๋ฒ„์™€ ์•ฑ ์„œ๋ฒ„

์›น ์„œ๋ฒ„ (Web Server)
App Server๋Š” ์›น ์„œ๋ฒ„(Web Server), ์›น ์•ฑ ์„œ๋ฒ„(WAS, Web Application Server)๋ฅผ ํฌ๊ด„ํ•˜๋Š” ์ƒ์œ„ ๊ฐœ๋…
์›น ์„œ๋ฒ„๋Š” ์ •์ ์ธ ํŽ˜์ด์ง€ (์ด๋ฏธ์ง€, html, js ๋“ฑ ์ปดํ“จํ„ฐ ๋‚ด ํŒŒ์ผ)๋ฅผ ๋ฐ˜ํ™˜,
๋™์  ํŽ˜์ด์ง€๋Š” ๋“ค์–ด์˜จ ์š”์ฒญ์— ๋งž๊ฒŒ ๋™์ ์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ ์ปจํ…์ธ 
WAS๋Š” Database, ๋กœ์ง์„ ๊ฑฐ์ณ์•ผ ํ•˜๋ฏ€๋กœ ์ •์ ์ธ ์ปจํ…์ธ ๋Š” Web Server์— ์ฒ˜๋ฆฌํ•˜์—ฌ ๋น ๋ฅด๊ฒŒ ์ œ๊ณตํ•˜๋„๋ก => ๊ธฐ๋Šฅ์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์„œ๋ฒ„ ๋ถ€ํ•˜๋ฅผ ๋ฐฉ์ง€
๊ทธ ์™ธ ๋ฌผ๋ฆฌ์ ์œผ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•˜๋Š” ๋“ฑ ๊ฒฐ๋ก ์ ์œผ๋กœ, ์ž์› ์ด์šฉ์˜ ํšจ์œจ์„ฑ ๋ฐ ์žฅ์•  ๊ทน๋ณต, ๋ฐฐํฌ ๋ฐ ์œ ์ง€๋ณด์ˆ˜์˜ ํŽธ์˜์„ฑ์„ ์œ„ํ•ด Web Server, WAS๋ฅผ ๊ฐ๊ธฐ ์‚ฌ์šฉํ•œ๋‹ค.

  • ๋””๋ฒ„๊น…
    (์—๋””ํ„ฐ ๋‚ด ๋””๋ฒ„๊น… ๊ธฐ๋Šฅ๊ณผ ํฌ๋กฌ(์›น๋ธŒ๋ผ์šฐ์ €) ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์˜ node.js)
    package.json์—์„œ dependency

    • nodemon
      • " --inspect; ๋””๋ฒ„๊น…
      • " --inspect-brk ; ์ฝ”๋“œ ์ตœ์ดˆ ๋กœ๋“œ(์‹คํ–‰) ๋•Œ ๋ธŒ๋ ˆ์ดํฌ ํฌ์ธํŠธ ์žก์Œ
  • ์ฃผ์†Œ์ฐฝ์— ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ: GET ์š”์ฒญ์ž„

  • ์š”์ฒญ body ๋ฐ›๊ธฐ

    • ์‘๋‹ต body ๋ฐ›๊ธฐ์™€ ๋‹ฌ๋ฆฌ ์–ด๋ ค์›€
    • ๊ฐœ๋… ๋‘ ๊ฐ€์ง€ ๋“ฑ์žฅ
      • stream
      • buffer

๐Ÿ‘ฉ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป ๐Ÿ’ป
๋‚ด์ผ์€ Express Library๋กœ mini node ์„œ๋ฒ„๋ฅผ ๋ฆฌํŒฉํ† ๋งํ•  ์˜ˆ์ •.
์˜ค๋Š˜ fetch๋กœ์ง๊ณผ http์š”์ฒญ,์‘๋‹ต ์ฒ˜๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋“ฑ์˜ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„๋ฅผ ๊ตฌํ˜„ํ•ด๋ณธ ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ Express๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋‹จ์ˆœํ™”์‹œ์ผœ์ฃผ๋Š” ์ž‘์—…์ด ๋ฌด์—‡์ธ์ง€, ๊ทธ๋ฆฌ๊ณ  ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ค‘์ ์„ ๋‘๊ณ  ํ•™์Šต

profile
developer; not kim but Young

0๊ฐœ์˜ ๋Œ“๊ธ€