[S2U10] Web Server ๊ธฐ์ดˆ

๐Ÿ‘ฝยท2024๋…„ 3์›” 29์ผ
0
post-thumbnail

๐Ÿ“–CH1. CORS

๐Ÿ“ŒCORS, SOP

SOP (Same-Origin Policy, ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…)

๐Ÿ”ธ ๊ฐ™์€ ์ถœ์ฒ˜(origin)์˜ ๋ฆฌ์†Œ์Šค๋งŒ ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅ.

๐Ÿ”ธ ์ถœ์ฒ˜๋Š” ํ”„๋กœํ† ์ฝœ, ํ˜ธ์ŠคํŠธ, ํฌํŠธ์˜ ์กฐํ•ฉ์œผ๋กœ, ์ด ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋‹ค๋ฅด๋ฉด ๋™์ผํ•œ ์ถœ์ฒ˜๋กœ ๋ณด์ง€ ์•Š์Œ.

๐Ÿ”ธ SOP๋Š” ์ž ์žฌ์ ์œผ๋กœ ํ•ด๋กœ์šธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์„œ๋ฅผ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ ๊ณต๊ฒฉ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ๋กœ๋ฅผ ์ค„์—ฌ์คŒ. ์ฆ‰, ํ•ดํ‚น ๋“ฑ์˜ ์œ„ํ˜‘์œผ๋กœ๋ถ€ํ„ฐ ๋ณด๋‹ค ์•ˆ์ „.

๐Ÿ”ธ ์ด๋Ÿฌํ•œ ๋ณด์•ˆ์ƒ ์ด์  ๋•Œ๋ฌธ์— SOP์€ ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์ •์ฑ….

  • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋„ค์ด๋ฒ„ ๊ฐ™์€ ์›น ํŽ˜์ด์ง€์— ๋กœ๊ทธ์ธํ•ด์„œ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•  ๋•Œ ์„œ๋น„์Šค ์ด์šฉ ์ค‘์ด ์•„๋‹ˆ๋”๋ผ๋„ ๋กœ๊ทธ์•„์›ƒ์„ ๊นœ๋นกํ–ˆ๊ฑฐ๋‚˜ ์ž๋™ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์œผ๋กœ ์ธํ•ด ๋ธŒ๋ผ์šฐ์ €์— ๋กœ๊ทธ์ธ ์ •๋ณด๊ฐ€ ๋‚จ์•„์žˆ์„ ์ˆ˜๋„ ์žˆ์„ ๊ฒƒ.
  • ๊ทธ ์ƒํƒœ์—์„œ ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ๋…ธ๋ฆฌ๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ๋Š” ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ์— ๋ฐฉ๋ฌธํ•˜๋ฉด, ํ•ด์ปค๋Š” ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ์ด์šฉํ•ด์„œ ๋„ค์ด๋ฒ„์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋จ.
  • ๊ทธ๋Ÿฌ๋‚˜ SOP๊ฐ€ ์กด์žฌํ•  ๊ฒฝ์šฐ ์• ์ดˆ์— ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ์™€์˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ ๋ฅผ ์ œํ•œํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋กœ๊ทธ์ธ ์ •๋ณด๊ฐ€ ํƒ€ ์‚ฌ์ดํŠธ์˜ ์ฝ”๋“œ์— ์˜ํ•ด์„œ ์ƒˆ์–ด๋‚˜๊ฐ€๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Œ.

๐Ÿ”ธ ํ•˜์ง€๋งŒ, ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ์ผ์ด ๋งŽ์Œ.

๐Ÿ”ธ ๊ฐœ๋ฐœํ•  ๋•Œ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๋ฅผ ๋”ฐ๋กœ ๊ฐœ๋ฐœํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๋‘˜์€ ์ถœ์ฒ˜๊ฐ€ ๋‹ฌ๋ผ์ง€๊ณ , API๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„๋•Œ, github ์ •๋ณด๋ฅผ ๋ฐ›์•„์™€์„œ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ, ๋ชจ๋‘ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ผ์ด ์ƒ๊น€.

๐Ÿ”ธ ์ด์™€ ๊ฐ™์€ ์ผ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด CORS ์‚ฌ์šฉ.

CORS (Cross-Origin-Resource Sharing, ๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ )

๐Ÿ”ธ ์ถ”๊ฐ€ HTTP ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•ด, ํ•œ ์ถœ์ฒ˜์—์„œ ์‹คํ–‰ ์ค‘์ธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์„ ํƒํ•œ ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋„๋ก ๋ธŒ๋ผ์šฐ์ €์— ์•Œ๋ ค์ฃผ๋Š” ์ฒด์ œ.

๐Ÿ”ธ CORS ์—๋Ÿฌ

๐Ÿ”ธ ์ฆ‰, CORS ์„ค์ •์„ ํ†ตํ•ด ์„œ๋ฒ„์˜ ์‘๋‹ต ํ—ค๋”์— Access-Control-Allow-Origin์„ ์ž‘์„ฑํ•˜๋ฉด ์ ‘๊ทผ ๊ถŒํ•œ์„ ์–ป์„ ์ˆ˜ ์žˆ์Œ.

๐Ÿ“Œ CORS ๋™์ž‘ ๋ฐฉ์‹

1. ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ (Preflight Request)

๐Ÿ”ธ ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „, OPTIONS ๋ฉ”์„œ๋“œ๋กœ ์‚ฌ์ „ ์š”์ฒญ์„ ๋ณด๋‚ด ํ•ด๋‹น ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผ ๊ถŒํ™˜์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ.

๐Ÿ”ธ ๋ธŒ๋ผ์šฐ์ €๋Š” ์„œ๋ฒ„์— ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „์— ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ , ์‘๋‹ต ํ—ค๋”์— Access-Control-Allow-Origin: ํ•ด๋‹น ์ถœ์ฒ˜๋ผ๊ณ  ์˜ค๋ฉด ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋ƒ„.

๐Ÿ”ธ ๋งŒ์•ฝ ์š”์ฒญ์„ ๋ณด๋‚ธ ์ถœ์ฒ˜๊ฐ€ ์ ‘๊ทผ ๊ถŒํ™˜์ด ์—†๋‹ค๋ฉด, ๋ธŒ๋ผ์šฐ์ €์—์„œ CORS ์—๋Ÿฌ๋ฅผ ๋„์šฐ๊ฒŒ ๋˜๊ณ , ์‹ค์ œ ์š”์ฒญ์€ ์ „๋‹ฌ๋˜์ง€ ์•Š์Œ.

๐Ÿ’ก ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์˜ ํ•„์š”์„ฑ

  • ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „์— ๊ถŒํ•œ ํ™•์ธ์„ ๋ฏธ๋ฆฌ ํ™•์ธํ•จ์œผ๋กœ์จ, ์‹ค์ œ ์š”์ฒญ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ํ†ต์งธ๋กœ ๋ณด๋‚ด๋Š” ๊ฒƒ๋ณด๋‹ค ๋ฆฌ์†Œ์Šค ์ธก๋ฉด์—์„œ ํšจ์œจ์ .

  • CORS์— ๋Œ€๋น„๊ฐ€ ๋˜์–ด์žˆ์ง€ ์•Š์€ ์„œ๋ฒ„๋ฅผ ๋ณดํ˜ธํ•  ์ˆ˜ ์žˆ์Œ.
    CORS ์ด์ „์— ๋งŒ๋“ค์–ด์ง„ ์„œ๋ฒ„๋“ค์€ SOP ์š”์ฒญ๋งŒ ๋“ค์–ด์˜ค๋Š” ์ƒํ™ฉ์„ ๊ณ ๋ คํ•˜๊ณ  ๋งŒ๋“ค์–ด์กŒ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ์ถœ์ฒ˜์—์„œ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ ๋Œ€๋น„๊ฐ€ ๋˜์–ด์žˆ์ง€ ์•Š์Œ.

  • ์ด๋Ÿฐ ์„œ๋ฒ„์— ๋ฐ”๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด, ์‘๋‹ต์„ ๋ณด๋‚ด๊ธฐ ์ „์— ์šฐ์„  ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋จ. ๋ธŒ๋ผ์šฐ์ €๋Š” ์‘๋‹ต์„ ๋ฐ›์€ ํ›„์— CORS ๊ถŒํ™˜์ด ์—†๋‹ค๋Š” ๊ฒƒ์„ ์ธ์ง€ํ•˜์ง€๋งŒ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์—๋Ÿฌ๋ฅผ ๋„์šด ํ›„์—๋Š” ์ด๋ฏธ ์š”์ฒญ์ด ์ˆ˜ํ–‰๋œ ์ƒํƒœ.

  • CORS์— ๋Œ€๋น„๊ฐ€ ๋˜์–ด์žˆ์ง€ ์•Š์€ ์„œ๋ฒ„๋ผ๋„ ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์„ ๋จผ์ € ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด, ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์—์„œ CORS ์—๋Ÿฌ๋ฅผ ๋„์›€. ์‹คํ–‰๋ผ์„  ์•ˆ ๋˜๋Š” Cross-Origin ์š”์ฒญ์ด ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Œ. ์ด๋Ÿฐ ์ด์œ ๋กœ ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์ด CORS์˜ ๊ธฐ๋ณธ ์‚ฌ์–‘์œผ๋กœ ๋“ค์–ด๊ฐ€๊ฒŒ ๋จ.

2. ๋‹จ์ˆœ ์š”์ฒญ (Simple Request)

๐Ÿ”ธ ํŠน์ • ์กฐ๊ฑด์ด ๋งŒ์กฑ๋˜๋ฉด ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์„ ์ƒ๋žตํ•˜๊ณ  ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ.

๐Ÿ”ธ ์กฐ๊ฑด์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Œ. (๊ทธ๋Ÿฌ๋‚˜ ์ด ์กฐ๊ฑด๋“ค์„ ๋ชจ๋‘ ๋งŒ์กฑ์‹œํ‚ค๋Š” ๊ฒƒ์€ ์–ด๋ ค์›€)

  • GET, HEAD, POST ์š”์ฒญ ์ค‘ ํ•˜๋‚˜์—ฌ์•ผ ํ•จ.
  • ์ž๋™์œผ๋กœ ์„ค์ •๋˜๋Š” ํ—ค๋” ์™ธ์—, Accept, Accept-Language, Content-Language, Content-Type ํ—ค๋”์˜ ๊ฐ’๋งŒ ์ˆ˜๋™์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Œ
  • Content-Type ํ—ค๋”์—๋Š” application/x-www-form-urlencoded, multipart/form-data, ext/plain ๊ฐ’๋งŒ ํ—ˆ์šฉ

๐Ÿ”ธ ๋Œ€๋ถ€๋ถ„ HTTP API ์š”์ฒญ์€ ext/xml ์ด๋‚˜ application/json ์œผ๋กœ ํ†ต์‹ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— 3๋ฒˆ์งธ Content-Type์ด ์œ„๋ฐ˜๋จ.

3. ์ธ์ฆ์ •๋ณด๋ฅผ ํฌํ•จํ•œ ์š”์ฒญ (Credentialed Request)

๐Ÿ”ธ ์š”์ฒญ ํ—ค๋”์— ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด์•„ ๋ณด๋‚ด๋Š” ์š”์ฒญ.

๐Ÿ”ธ ์ถœ์ฒ˜๊ฐ€ ๋‹ค๋ฅผ ๊ฒฝ์šฐ์—, ๋ณ„๋„์˜ ์„ค์ •์„ ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฏผ๊ฐํ•œ ์ •๋ณด์ด๊ธฐ ๋•Œ๋ฌธ์— ์ฟ ํ‚ค๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์—†์Œ. ์ด ๊ฒฝ์šฐ ํด๋ผ์ด์–ธํŠธ, ์„œ๋ฒ„ ์–‘์ธก ๋ชจ๋‘ CORS ์„ค์ •์ด ํ•„์š”.

  • ํด๋ผ์ด์–ธํŠธ : ์š”์ฒญ ํ—ค๋”์— withCredentials : true๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•จ.
  • ์„œ๋ฒ„ : ์‘๋‹ต ํ—ค๋”์— Access-Control-Allow-Credentials : true๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•จ.
  • ์„œ๋ฒ„ ์ธก์—์„œ Access-Control-Allow-Origin์„ ์„ค์ •ํ•  ๋•Œ, ๋ชจ๋“  ์ถœ์ฒ˜๋ฅผ ํ—ˆ์šฉํ•œ๋‹ค๋Š” ๋œป์˜ ์™€์ผ๋“œ์นด๋“œ(*)๋กœ ์„ค์ •ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒ. ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ค๋ฃจ๋Š” ๋งŒํผ ์ถœ์ฒ˜๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์„ค์ •ํ•ด์ค˜์•ผ ํ•จ.

๐Ÿ“ŒCORS ์„ค์ • ๋ฐฉ๋ฒ•

1. Node.js ์„œ๋ฒ„

๐Ÿ”ธ Node.js๋กœ ๊ฐ„๋‹จํ•œ HTTP ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค ๊ฒฝ์šฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‘๋‹ต ํ—ค๋” ์„ค์ •.

const http = require('http');

const server = http.createServer((request, response) => {
// ๋ชจ๋“  ๋„๋ฉ”์ธ
  response.setHeader("Access-Control-Allow-Origin", "*");

// ํŠน์ • ๋„๋ฉ”์ธ
  response.setHeader("Access-Control-Allow-Origin", "https://codestates.com");

// ์ธ์ฆ ์ •๋ณด๋ฅผ ํฌํ•จํ•œ ์š”์ฒญ์„ ๋ฐ›์„ ๊ฒฝ์šฐ
  response.setHeader("Access-Control-Allow-Credentials", "true");
})

2. Express ์„œ๋ฒ„

๐Ÿ”ธ Express ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค ๊ฒฝ์šฐ, cors ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ CORS ์„ค์ •.

const cors = require("cors");
const app = express();

//๋ชจ๋“  ๋„๋ฉ”์ธ
app.use(cors());

//ํŠน์ • ๋„๋ฉ”์ธ
const options = {
  origin: "https://codestates.com", // ์ ‘๊ทผ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋Š” ๋„๋ฉ”์ธ
  credentials: true, // ์‘๋‹ต ํ—ค๋”์— Access-Control-Allow-Credentials ์ถ”๊ฐ€
  optionsSuccessStatus: 200, // ์‘๋‹ต ์ƒํƒœ 200์œผ๋กœ ์„ค์ •
};

app.use(cors(options));

//ํŠน์ • ์š”์ฒญ
app.get("/example/:id", cors(), function (req, res, next) {
  res.json({ msg: "example" });
});

๐Ÿ“–CH2. Refactor Express

MERN stack : ์›น ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ๊ธฐ์ˆ  ์Šคํƒ์œผ๋กœ MongoDB, Express, React, Node.js๋กœ ์ด๋ฃจ์–ด์ง.

Express

๐Ÿ”ธ Node.js ํ™˜๊ฒฝ์—์„œ ์›น ์„œ๋ฒ„, ๋˜๋Š” API ์„œ๋ฒ„๋ฅผ ์ œ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋ ˆ์ž„์›Œํฌ.

๐Ÿ”ธ Node.js HTTP ๋ชจ๋“ˆ๋กœ ์ž‘์„ฑํ•œ ์„œ๋ฒ„์™€ ๋‹ฌ๋ฆฌ Express๋กœ ๊ตฌํ˜„ํ•œ ์„œ๋ฒ„๋Š” ๋ฏธ๋“ค์›จ์–ด ์ถ”๊ฐ€ ๋ฐ ๋ผ์šฐํ„ฐ ๊ธฐ๋Šฅ์„ ์ œ๊ณต

๐Ÿ“ŒExpress ์‹œ์ž‘ํ•˜๊ธฐ

1. Express ์„ค์น˜ํ•˜๊ธฐ

์‹œ์ž‘ํ•˜๊ธฐ - ์„ค์น˜

npm install express

2. ๊ฐ„๋‹จํ•œ ์›น ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ

์‹œ์ž‘ํ•˜๊ธฐ - Hello world ์˜ˆ์ œ

const express = require('express')
const app = express()
const port = 3000

// ๋ฃจํŠธ URL(/) ๋˜๋Š” ๋ผ์šฐํŠธ์— ๋Œ€ํ•œ ์š”์ฒญ์— โ€œHello World!โ€๋กœ ์‘๋‹ต
app.get('/', (req, res) => { 
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

3. ๋ผ์šฐํŒ…: ๋ฉ”์„œ๋“œ์™€ url์— ๋”ฐ๋ผ ๋ถ„๊ธฐ(Routing)ํ•˜๊ธฐ

์‹œ์ž‘ํ•˜๊ธฐ - ๊ธฐ๋ณธ ๋ผ์šฐํŒ…

๋ผ์šฐํŒ… (Routing)

๐Ÿ”ธ ๋ฉ”์„œ๋“œ์™€ url(/lower, /upper ๋“ฑ)๋กœ ๋ถ„๊ธฐ์ ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ (๋ถ„๊ธฐ์  : ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ URL์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์„œ๋ฒ„์—์„œ ๋‹ค์–‘ํ•œ ๋™์ž‘ ๋˜๋Š” ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜๋กœ ๋ถ„๊ธฐํ•˜๋Š” ์ง€์ )

๐Ÿ”ธ ํด๋ผ์ด์–ธํŠธ๋Š” ํŠน์ •ํ•œ HTTP ์š”์ฒญ ๋ฉ”์„œ๋“œ(GET, POST ๋“ฑ)์™€ ํ•จ๊ป˜ ์„œ๋ฒ„์˜ ํŠน์ • URI(๋˜๋Š” ๊ฒฝ๋กœ)๋กœ HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ , ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์— ํ•ด๋‹นํ•˜๋Š” Endpoint์— ๋”ฐ๋ผ ์„œ๋ฒ„๊ฐ€ ์‘๋‹ตํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ.

๐Ÿ”ธ ๊ฐ ๋ผ์šฐํŠธ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Ÿฌํ•œ ํ•จ์ˆ˜๋Š” ๋ผ์šฐํŠธ๊ฐ€ ์ผ์น˜ํ•  ๋•Œ ์‹คํ–‰๋จ

๐Ÿ”ธ app.METHOD(path, handler)

  • app : express์˜ ์ธ์Šคํ„ด์Šค
  • METHOD : HTTP ์š”์ฒญ ๋ฉ”์†Œ๋“œ
  • path : ์„œ๋ฒ„์—์„œ์˜ ๊ฒฝ๋กœ
  • handler : ๋ผ์šฐํŠธ๊ฐ€ ์ผ์น˜ํ•  ๋•Œ ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜

์˜ˆ์‹œ ์ฝ”๋“œ

  • ์ˆœ์ˆ˜ํ•œ Node.js ์ฝ”๋“œ๋กœ ์ž‘์„ฑ์‹œ
const requestHandler = (req, res) => {
  if(req.url === '/lower') {
    if (req.method === 'GET') {
      res.end(data)
    } else if (req.method === 'POST') {
      req.on('data', (req, res) => {
        // do something
      })}}}
  • Express์˜ ๋ผ์šฐํ„ฐ๋ฅผ ํ™œ์šฉ
const router = express.Router()
router.get('/lower', (req, res) => {
  res.send(data);
})
router.post('/lower', (req, res) => {
  // do something
})

๐Ÿ“ŒMiddleware 1

๐Ÿ”ธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ๊ณผ ์„œ๋ฒ„์˜ ์‘๋‹ต ์‚ฌ์ด์—์„œ ๋™์ž‘ํ•˜๋Š” ์ค‘๊ฐ„ ์†Œํ”„ํŠธ์›จ์–ด ์ปดํฌ๋„ŒํŠธ.

๐Ÿ”ธ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์ „์— ์ค‘๊ฐ„ ๋‹จ๊ณ„์—์„œ ์ถ”๊ฐ€์ ์ธ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๊ฑฐ๋‚˜, ์„œ๋ฒ„์˜ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์ „์— ํ›„์† ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ.

๐Ÿ”ธ ๊ฐ๊ฐ์˜ ๋ฏธ๋“ค์›จ์–ด๋Š” next() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ๊ทธ ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ˆœ์„œ๋ฅผ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Œ.

๐Ÿ”ธ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ

  • POST ์š”์ฒญ ๋“ฑ์— ํฌํ•จ๋œ body(payload)๋ฅผ ๊ตฌ์กฐํ™”ํ•  ๋•Œ(์‰ฝ๊ฒŒ ์–ป์–ด๋‚ด๊ณ ์ž ํ•  ๋•Œ)
  • ๋ชจ๋“  ์š”์ฒญ/์‘๋‹ต์— CORS ํ—ค๋”๋ฅผ ๋ถ™์—ฌ์•ผ ํ•  ๋•Œ
  • ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด url์ด๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ™•์ธํ•  ๋•Œ
  • ์š”์ฒญ ํ—ค๋”์— ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ์žˆ๋Š”์ง€ ํ™•์ธํ•  ๋•Œ

๐Ÿ”ธ ๋ฏธ๋“ค์›จ์–ด์˜ ๊ตฌ์„ฑ

  • ์œ„์˜ ๊ทธ๋ฆผ์€ endpoint๊ฐ€ /์ด๋ฉด์„œ, ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ GET ์š”์ฒญ์„ ๋ฐ›์•˜์„ ๋•Œ ์ ์šฉ๋˜๋Š” ๋ฏธ๋“ค์›จ์–ด
  • ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ˆœ์„œ์— ์œ ์˜

POST ์š”์ฒญ ๋“ฑ์— ํฌํ•จ๋œ body(payload)๋ฅผ ๊ตฌ์กฐํ™”ํ•  ๋•Œ

๐Ÿ”ธ Node.js

  • HTTP body(payload)๋ฅผ ๋ฐ›์„ ๋•Œ Buffer๋ฅผ ์กฐํ•ฉํ•ด์„œ body๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Œ. ์ด๋•Œ ๋„คํŠธ์›Œํฌ์ƒ์˜ chunk๋ฅผ ํ•ฉ์น˜๊ณ , Buffer๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ž‘์—…์ด ํ•„์š”.
  • Buffer : ์ผ๋ จ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ž„์‹œ๋กœ ์ €์žฅํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // body ๋ณ€์ˆ˜์—๋Š” ๋ฌธ์ž์—ด ํ˜•ํƒœ๋กœ payload๊ฐ€ ๋‹ด๊ฒจ์ ธ ์žˆ์Œ.
});

๐Ÿ”ธ body-parser ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ด์šฉํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ.

  • body-parser : ์„œ๋ฒ„๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์ด ๋ผ์šฐํŠธ ํ•ธ๋“ค๋Ÿฌ์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— request body๋ฅผ ํŒŒ์‹ฑํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ํŒจํ‚ค์ง€.
// ์„ค์น˜ 
npm install body-parser

const bodyParser = require('body-parser');
const jsonParser = bodyParser.json();

// ์ƒ๋žต
app.post('/users', jsonParser, function (req, res) {
})

๐Ÿ”ธ Express v4.16.0๋ถ€ํ„ฐ body-parser ์„ค์น˜ ๋Œ€์‹ , Express ๋‚ด์žฅ ๋ฏธ๋“ค์›จ์–ด์ธ express.json()์„ ์‚ฌ์šฉ

const express = require('express')
const app = express()

app.use(express.json())
  • express() : Express application๋ฅผ ์ƒ์„ฑ. express ๋ชจ๋“ˆ์—์„œ ์ตœ์ƒ์œ„ ํ•จ์ˆ˜๋ฅผ ๋‚ด๋ณด๋ƒ„.
  • express.json([options]) : ๋“ค์–ด์˜ค๋Š” JSON ํ˜•์‹์˜ ์š”์ฒญ์„ (body-parser๋ฅผ ํ†ตํ•ด) JavaScript ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ฒŒ ํ•ด์คŒ.
    • options - strict : ๋“ค์–ด์˜ค๋Š” JSON body๋ฅผ ํŒŒ์‹ฑํ•  ๋•Œ ์—„๊ฒฉํ•œ ๋ชจ๋“œ๋ฅผ ์‚ฌ์šฉํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •. ๊ธฐ๋ณธ๊ฐ’์€ true์ด๋ฉฐ, false๋กœ ์„ค์ •ํ•  ๊ฒฝ์šฐ JSON.parse๊ฐ€ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ํ˜•ํƒœ์˜ JSON์„ ํ—ˆ์šฉํ•จ. (๊ฐ์ฒด๋‚˜ ๋ฐฐ์—ด ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฌธ์ž์—ด, ์ˆซ์ž ๋“ฑ๋„ ๋  ์ˆ˜ ์žˆ์Œ)
  • express.urlencoded([options]) : HTML Form์„ ํ†ตํ•ด์„œ ์ „์†ก๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•จ.

๋ชจ๋“  ์š”์ฒญ/์‘๋‹ต์— CORS ํ—ค๋”๋ฅผ ๋ถ™์ผ ๋•Œ

๐Ÿ”ธ Node.js

  • CORS ํ—ค๋”๋ฅผ ๋ถ™์ด๋ ค๋ฉด ์‘๋‹ต ๊ฐ์ฒด์˜ response.writeHead(statusCode, {headers}) ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉ.
  • ๋ผ์šฐํŒ…๋งˆ๋‹ค ํ—ค๋”๋ฅผ ๋งค๋ฒˆ ๋„ฃ๊ณ  OPTIONS ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ๋ผ์šฐํŒ…๋„ ๋”ฐ๋กœ ๊ตฌํ˜„ํ•ด์•ผํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์žˆ์Œ.
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
};

// ์ƒ๋žต
if (req.method === 'OPTIONS') {
  res.writeHead(200, defaultCorsHeader);
  res.end()
}

๐Ÿ”ธ cors ๋ฏธ๋“ค์›จ์–ด

// ๐Ÿ“ 1. cors ๋ฏธ๋“ค์›จ์–ด ์„ค์น˜
npm install cors

// ๐Ÿ“ 2. ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด CORS ํ—ˆ์šฉ
const cors = require('cors');
app.use(cors());

// ๐Ÿ“ 3.ํŠน์ • ์š”์ฒญ์— ๋Œ€ํ•ด CORS ํ—ˆ์šฉ
const cors = require('cors')
app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
})

๐Ÿ’ก app.use๋Š” express ์•ฑ์—์„œ ์‹คํ–‰ํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด ์—ญํ• . ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ฃผ์†Œ๋ฅผ ๋„ฃ์–ด์ฃผ์ง€ ์•Š์œผ๋ฉด ๋ชจ๋“  ์š”์ฒญ์—์„œ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์‹คํ–‰๋จ.

๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด url์ด๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ™•์ธํ•  ๋•Œ

๐Ÿ”ธ ๋กœ๊ฑฐ(logger) : ๋””๋ฒ„๊น…์ด๋‚˜, ์„œ๋ฒ„ ๊ด€๋ฆฌ์— ๋„์›€์ด ๋˜๊ธฐ ์œ„ํ•ด console.log๋กœ ์ ์ ˆํ•œ ๋ฐ์ดํ„ฐ๋‚˜ ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ.

๐Ÿ”ธ ๋ฐ์ดํ„ฐ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๊ฑฐ์น˜๋Š” ๋™์•ˆ ์‘๋‹ตํ•  ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋ฉด, ๋ฏธ๋“ค์›จ์–ด ์‚ฌ์ด์‚ฌ์ด์— ๋กœ๊ฑฐ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ ํ˜„์žฌ ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•˜๊ฑฐ๋‚˜, ๋””๋ฒ„๊น…์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

const express = require('express');
const app = express();

// ๐Ÿ“ 1. ๋ชจ๋“  ์š”์ฒญ์— mount ๋˜๋Š” ๋ฏธ๋“ค์›จ์–ด
app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

// ๐Ÿ“ 2. ๋ชจ๋“  ์š”์ฒญ์— mount ๋˜๋Š” ๋ฏธ๋“ค์›จ์–ด
const myLogger = function (req, res, next) {
  console.log('LOGGED'); // ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด LOGGED๊ฐ€ ์ถœ๋ ฅ๋จ.
  next();
};

app.use(myLogger);

// ๐Ÿ“ 3. ํŠน์ • ๊ฒฝ๋กœ์— mount๋˜๋Š” ๋ฏธ๋“ค์›จ์–ด
app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000);

์š”์ฒญ ํ—ค๋”์— ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ์žˆ๋Š”์ง€ ํ™•์ธํ•  ๋•Œ

๐Ÿ”ธ HTTP ์š”์ฒญ์—์„œ ํ† ํฐ์ด ์žˆ๋Š”์ง€๋ฅผ ํŒ๋‹จํ•˜์—ฌ, ์ด๋ฏธ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์ผ ๊ฒฝ์šฐ ์„ฑ๊ณต, ์•„๋‹ ๊ฒฝ์šฐ ์—๋Ÿฌ๋ฅผ ๋ณด๋‚ด๋Š” ๋ฏธ๋“ค์›จ์–ด ์˜ˆ์ œ

app.use((req, res, next) => {
  // ํ† ํฐ์ด ์žˆ๋Š”์ง€ ํ™•์ธ, ์—†์œผ๋ฉด ๋ฐ›์•„์ค„ ์ˆ˜ ์—†์Œ.
  if(req.headers.token){
    req.isLoggedIn = true;
    next();
  } else {
    res.status(400).send('invalid user')
  }
})

๊ณผ์ œ Mini Node Server

๐Ÿ”ธ ๋ธŒ๋ผ์šฐ์ €์—๋Š” ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด fetch ๊ฐ™์€ HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋„๊ตฌ๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚ด์žฅ๋˜์–ด ์žˆ์Œ.

๐Ÿ”ธ Node.js๋Š” HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๊ฑฐ๋‚˜, ์‘๋‹ต์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋“ค์„ ์ œ๊ณต.

๐Ÿ”ธ HTTP ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‘๋‹ต์„ ๋ณด๋‚ด ์ฃผ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์›น ์„œ๋ฒ„(Web Server)๋ผ๊ณ  ํ•จ.

๐Ÿ”ธ ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)์˜ HTTP ์š”์ฒญ์— ๋งž๊ฒŒ ์‘๋‹ต์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•จ.

HTTP ๋ชจ๋“ˆ

App.js

class App {
  init() {
    document
      .querySelector('#to-upper-case')
      .addEventListener('click', this.toUpperCase.bind(this));
    document
      .querySelector('#to-lower-case')
      .addEventListener('click', this.toLowerCase.bind(this));
  }
  post(path, body) {
    fetch(`http://localhost:5001/${path}`, {
      method: 'POST',
      body: JSON.stringify(body),
      headers: {
        'Content-Type': 'application/json'
      }
    })
      .then(res => res.json())
      .then(res => {
        this.render(res);
      });

  }
  toLowerCase() {
    const text = document.querySelector('.input-text').value;
    this.post('lower', text);
  }
  toUpperCase() {
    const text = document.querySelector('.input-text').value;
    this.post('upper', text);
  }
  render(response) {
    const resultWrapper = document.querySelector('#response-wrapper');
    document.querySelector('.input-text').value = '';
    resultWrapper.innerHTML = response;
  }
}

const app = new App();
app.init();

node.js๋กœ ๊ตฌ์„ฑํ•œ ์„œ๋ฒ„

const http = require('http'); // ์„œ๋ฒ„๋ฅผ node.js์—์„œ ์ž‘๋™์„ ์‹œ์ผœ์•ผ ํ•˜๋ฏ€๋กœ http ๋ชจ๋“ˆ ์‚ฌ์šฉ

const PORT = 4999;

const ip = 'localhost';

const server = http.createServer((request, response) => { // http.createServer ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น์„œ๋ฒ„ ๊ฐ์ฒด ์ƒ์„ฑ. ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค ํ•ด๋‹น ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ
  // ์š”์ฒญ ๋ฉ”์„œ๋“œ์™€ ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰.
  // TODO:
  if(request.method === 'OPTIONS') { // preflight; ์š”์ฒญ์ด OPTIONS ๋ฉ”์„œ๋“œ์ธ ๊ฒฝ์šฐ CORS ์„ค์ •์„ ์œ„ํ•œ ์‘๋‹ต์„ ๋ณด๋‚ด๊ณ  ์ข…๋ฃŒ
    response.writeHead(200, defaultCorsHeader);
    response.end();
  }
  if(request.method === "POST" && request.url === "/upper") {  // POST ๋ฉ”์„œ๋“œ์ด๊ณ , ๊ฒฝ๋กœ๊ฐ€ /upper์ธ ๊ฒฝ์šฐ 
    let body = [];
    request.on('data', (chunk) => { // ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์š”์ฒญ ๋ฐ์ดํ„ฐ๊ฐ€ ๋„์ฐฉํ•  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๋Š” ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ. chunk ๋งค๊ฐœ๋ณ€์ˆ˜์—๋Š” ๋„์ฐฉํ•œ ๋ฐ์ดํ„ฐ ์ฒญํฌ(chunk)๊ฐ€ ์ „๋‹ฌ๋˜๋ฉฐ, chunk๋Š” bufferํ˜•ํƒœ๋กœ ์ œ๊ณต๋จ
      body.push(chunk); // body ๋ฐฐ์—ด์— ์ฒญํฌ ์ถ”๊ฐ€ 
    }).on('end', () => { // ์š”์ฒญ ๋ฐ์ดํ„ฐ์˜ ์ˆ˜์‹ ์ด ์™„๋ฃŒ๋์„ ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ. ์š”์ฒญ ๋ฐ์ดํ„ฐ์˜ ๋ชจ๋“  ์ฒญํฌ๊ฐ€ ์ˆ˜์‹ ๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ„.
      body = Buffer.concat(body).toString().toUpperCase(); // body ๋ฐฐ์—ด์— ์ €์žฅ๋œ ๋ชจ๋“  ์ฒญํฌ๋ฅผ ํ•˜๋‚˜์˜ ๋ฒ„ํผ๋กœ ํ•ฉ์นจ.
      response.writeHead(200, defaultCorsHeader); // ์ƒํƒœ์ฝ”๋“œ 200๊ณผ CORS ํ—ค๋”๋ฅผ ์‘๋‹ต์œผ๋กœ ์„ค์ •
      response.end(body) // ์‘๋‹ต์„ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณด๋ƒ„. ๋ณ€ํ™˜๋œ ๊ฒฐ๊ณผ๋ฅผ ์‘๋‹ต์œผ๋กœ ์ „์†ก
    });
  }
  else if(request.method === "POST" && request.url === "/lower") {  
    let body = [];
    request.on('data', (chunk) => {
      body.push(chunk);
    }).on('end', () => {
      body = Buffer.concat(body).toString().toLowerCase();
      response.writeHead(200, defaultCorsHeader);
      response.end(body)
    });
  }
  else if(request.method === "GET" && request.url === "/") {
    response.writeHead(200, defaultCorsHeader);
    response.end("! localhost:4999")
  }
  else { 
    // ๋‚˜๋จธ์ง€๋Š” ์—๋Ÿฌ์ฒ˜๋ฆฌ bad request
    response.statusCode = 404;
    response.end();
  }
  console.log(
    `http request method is ${request.method}, url is ${request.url}`
  );
});

server.listen(PORT, ip, () => { // ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ
  console.log(`http server listen on ${ip}:${PORT}`);
});

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
};

๐Ÿ”ธ http.createServer([requestListener]) : HTTP server๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋ฉฐ, http.Server์˜ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜.

  • requestListener : ์š”์ฒญ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋  ์ฝœ๋ฐฑ ํ•จ์ˆ˜

๐Ÿ”ธ listen() : Server ์ ‘์† ๋Œ€๊ธฐ ์‹œ์ž‘. ๋น„๋™๊ธฐ์ .

๐Ÿ”ธ response.writeHead(statusCode, headers) : http response์˜ header๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•œ http ๋ชจ๋“ˆ์˜ ๋ฉ”์„œ๋“œ

๐Ÿ”ธ .on(eventName, eventHandler) : ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋ฉ”์„œ๋“œ. ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ๋“ฑ๋ก๋œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ(eventHandler) ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ.

๐Ÿ”ธ .end([data], [encoding]) : ์‘๋‹ต์„ ์ข…๋ฃŒํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณด๋ƒ„. data๋Š” ์‘๋‹ต ๋ณธ๋ฌธ์— ํฌํ•จ๋  ๋ฐ์ดํ„ฐ๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์„ ํƒ์ ์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Œ. encoding์€ ๋ฐ์ดํ„ฐ์˜ ์ธ์ฝ”๋”ฉ ๋ฐฉ์‹์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์„ ํƒ์ ์œผ๋กœ ์ง€์ • ๊ฐ€๋Šฅ.

๐Ÿ’ก chunk, fetch๋Š” ์‹ค๋ฌด์—์„œ๋Š” ์‚ฌ์šฉ์„ ์ž˜ ์•ˆํ•˜๋ฉฐ, ์ฃผ๋กœ Axios๋ฅผ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ

Express๋กœ ๊ตฌํ˜„ํ•œ ์„œ๋ฒ„

const express = require('express')
const app = express(); // app ๊ฐ์ฒด ์ƒ์„ฑ
const PORT = 5001;
const ip = 'localhost';

const jsonParser = express.json({strict: false}); // req.body์˜ JSON ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•˜์—ฌ JS ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜; strict: false = ์ž˜๋ชป๋œ JSON ํ˜•์‹์ด ๋“ค์–ด์™€๋„ ํŒŒ์‹ฑ์‹œ๋„
app.use(jsonParser) // 
const cors = require('cors'); 
app.use(cors()); // ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด CORS ํ—ˆ์šฉ


app.get('/', (req, res) => {
    res.send("Hello !"); // res.send() : ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š”์ง€ ํŒŒ์•…์„ ํ•ด์„œ ์ด์— ์•Œ๋งž๊ฒŒ Contnet-Type์„ ์ง€์ •ํ•˜๊ณ  res๋ฅผ ๋ณด๋ƒ„.
})

app.post('/upper', (req, res) => {
    let data = req.body.toUpperCase() // req.body = express.json() ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŒŒ์‹ฑ๋œ JSON๋ฐ์ดํ„ฐ๋ฅผ req.body์— ์ €์žฅ
    res.json(data) // res.json() = JSON ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ JSON ๋ฌธ์ž์—ด ํ˜•์‹์œผ๋กœ ์‘๋‹ต. ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉ
    console.log(data)
})

app.post('/lower', (req, res) => {
    let data = req.body.toLowerCase()
    res.json(data)
    console.log(data)
})

app.listen(PORT, () => {
    console.log(`http server listen on ${ip}:${PORT}`)
})

๊ณผ์ œ StatesAirline Server

uuid()

๐Ÿ”ธ Universally Unique Identifier(๋ฒ”์šฉ ๊ณ ์œ  ์‹๋ณ„์ž)๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜.
๐Ÿ”ธ 128bit ์ˆซ์ž๋กœ ์ด๋ฃจ์–ด์ง„ ์‹๋ณ„์ž๋กœ์„œ, ์ผ๋ฐ˜์ ์œผ๋กœ ๊ณ ์œ ์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ.

//  ๐Ÿ“ 1. ์„ค์น˜ํ•˜๊ธฐ
npm install uuid

// ๐Ÿ“ 2. 'v4' ํ•จ์ˆ˜๋ฅผ uuid๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ๊ฐ€์ ธ์˜ด.
const { v4: uuidv4 } = require('uuid');

๐Ÿ”ธ UUID์—๋Š” ์—ฌ๋Ÿฌ ๋ฒ„์ „์ด ์žˆ์œผ๋ฉฐ, ๊ฐ ๋ฒ„์ „๋งˆ๋‹ค ๊ณ ์œ ํ•œ ํŠน์ง•๊ณผ ์ƒ์„ฑ ๋ฐฉ๋ฒ•์ด ์กด์žฌ. ๋ฒ„์ „ 4๋Š” ๋žœ๋คํ•˜๊ฒŒ ์ƒ์„ฑ๋˜๋Š” UUID๋กœ, ๋ณดํ†ต ์ผ๋ฐ˜์ ์ธ ์šฉ๋„์—์„œ ๋งŽ์ด ์‚ฌ์šฉ.

์ถ”๊ฐ€ ๊ณต๋ถ€

Content-Type

๐Ÿ”ธ HTTP ํ†ต์‹ ์—์„œ ์ „์†ก๋˜๋Š” ๋ฐ์ดํ„ฐ์˜ ํƒ€์ž…์„ ๋ช…์‹œํ•˜๊ธฐ ์œ„ํ•ด header์— ์‹ค๋ฆฌ๋Š” ์ •๋ณด๋กœ, request/response body์— ์‹ค์–ด ๋ณด๋‚ด๋Š” ๋ฐ์ดํ„ฐ ํƒ€์ž…์˜ ์ •๋ณด.
๐Ÿ”ธ Text ํƒ€์ž…, Message ํƒ€์ž…, Image ํƒ€์ž…, Audio ํƒ€์ž…, Video ํƒ€์ž…, file ํƒ€์ž…, Application ํƒ€์ž…, Multipart ํƒ€์ž…

application/x-www-form-urlencoded

๐Ÿ”ธ Content-Type์„ ๋”ฐ๋กœ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ์„ค์ •๋˜๋Š” Default ๊ฐ’.
๐Ÿ”ธ ๋ณดํ†ต Web Page๋ฅผ ๊ฐœ๋ฐœํ•  ๋•Œ, JavaScript/JQuery๋ฅผ ์‚ฌ์šฉํ•ด์„œ Ajax๋กœ ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๋Š” ๊ฒฝ์šฐ ํ˜น์€ html form์„ ์‚ฌ์šฉํ•ด์„œ ์š”์ฒญํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉ.
๐Ÿ”ธ key=value&key2=value2์˜ ํ˜•ํƒœ

application/json

๐Ÿ”ธ Android๋‚˜ iOS์•ฑ์„ ์œ„ํ•œ RestFul API๋ฅผ ๊ฐœ๋ฐœํ•  ๊ฒฝ์šฐ.
๐Ÿ”ธ {key: value}์˜ ํ˜•ํƒœ

request

req.body

๐Ÿ”ธ JSON ๋“ฑ์˜ body ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์„ ๋•Œ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ฃผ๋กœ POST๋กœ ์œ ์ €์˜ ์ •๋ณด ๋˜๋Š” ํŒŒ์ผ ์—…๋กœ๋“œ(formdata)๋ฅผ ๋ณด๋ƒˆ์„ ๋•Œ ์‚ฌ์šฉ. ์š”์ฒญ ๋ณธ๋ฌธ์— ์ œ์ถœ๋œ ํ‚ค-๊ฐ’ ๋ฐ์ดํ„ฐ ์Œ์„ ํฌํ•จํ•จ.

req.query

Query
๐Ÿ”ธ endpoint ์ฃผ์†Œ ์ดํ›„์— ?๋ฅผ ์“ฐ๋Š” ๊ฒƒ์œผ๋กœ query string์ด ์‹œ์ž‘ํ•จ์„ ์•Œ๋ฆผ.
๐Ÿ”ธ parameter=value ํ˜•ํƒœ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ๊ฐ’์„ ์ ์Œ
๐Ÿ”ธ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ์ผ ๊ฒฝ์šฐ, &๋ฅผ ๋ถ™์—ฌ ์—ฌ๋Ÿฌ๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Œ.
๐Ÿ”ธ endpoint์ฃผ์†Œ/?parameter=value&value

๐Ÿ”ธ ๊ฒฝ๋กœ์˜ ๊ฐ ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด ๋งค๊ฐœ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์†์„ฑ์ด ํฌํ•จ๋œ ๊ฐœ์ฒด (์ฃผ๋กœ GET ์š”์ฒญ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ).

  • ์˜ˆ๋ฅผ ๋“ค์–ด uri๊ฐ€ www.example.com/post/1/jun?title=hello! ์ด๋ฉด, title=hello! ๋ถ€๋ถ„์„ ๊ฐ์ฒด๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ๊ฐ€์ ธ์˜ด.
// ํด๋ผ์ด์–ธํŠธ ๋‹จ์—์„œ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ get์š”์ฒญ์„ ๋ณด๋ƒ„
// ๐Ÿ“ ๋ฐฉ์‹ 1
await axios.get(`www.example.com/post/1/jun?title=hello!`)

// ๐Ÿ“ ๋ฐฉ์‹ 2
await axios({
  method: "get",
  url: `www.example.com/post/1/jun`,
  params: { title: 'hello!' },
})

// ์š”์ฒญ์˜จ uri : www.example.com/public/100/jun?title=hello!
app.use(express.urlencoded({ extended: false })); // uri ๋ฐฉ์‹ ํผ ์š”์ฒญ ๋“ค์–ด์˜ค๋ฉด ํŒŒ์‹ฑ

router.get('/:id/:name', (req, res, next) => {
  
  // title=hello! ๋ถ€๋ถ„์ด ๋‹ด๊ธฐ๊ฒŒ ๋œ๋‹ค.
  console.log(req.query) // { title : 'hello!' }
});

req.params

๐Ÿ”ธ ๋ผ์šฐํ„ฐ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜.

  • ์˜ˆ๋ฅผ ๋“ค์–ด, /:id/:name ๊ฒฝ๋กœ๊ฐ€ ์žˆ์œผ๋ฉด, :id ์†์„ฑ๊ณผ :name ์†์„ฑ์„ req.params.id, req.params.name์œผ๋กœ ์‚ฌ์šฉ๊ฐ€๋Šฅ
// ์š”์ฒญ์˜จ url : www.example.com/public/100/jun

router.get('/:id/:name', (req, res, next) => {
  console.log(req.params)}); 
  // { id: '100', name: 'jun' }; ../100/jun ๋ถ€๋ถ„์ด ๋‹ด๊ธฐ๊ฒŒ ๋จ.

response

res.send([body])

๐Ÿ”ธ response๋ฅผ ๋ณด๋ƒ„. ๊ธฐ๋ณธ์ ์œผ๋กœ ์„œ๋ฒ„์—์„œ response๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ Content-type๋ฅผ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ, ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š”์ง€ ํŒŒ์•…ํ•ด์„œ ์•Œ๋งž๊ฒŒ ์ง€์ •ํ•ด์คŒ. ์ด๋Š” Buffer, String, Object, Array์ผ ์ˆ˜ ์žˆ์Œ.

res.json([body])

๐Ÿ”ธ JSON.stringify()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JSON ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜๋œ ์‘๋‹ต์„ ๋ณด๋ƒ„. body์—๋Š” ๊ฐœ์ฒด, ๋ฐฐ์—ด, ๋ฌธ์ž์—ด, boolean, ์ˆซ์ž ๋˜๋Š” Null์„ ํฌํ•จํ•œ ๋ชจ๋“  JSON ์œ ํ˜•์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค๋ฅธ ๊ฐ’์„ JSON์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜๋„ ์žˆ์Œ.

res.end([data[, encoding]][, callback])

๐Ÿ”ธ ๋ชจ๋“  ์‘๋‹ต ํ—ค๋”์™€ body๊ฐ€ ์„œ๋ฒ„์— ์ „์†ก๋์Œ์„ ์•Œ๋ ค์ฃผ๋ฉฐ, ๋ณด๋‚ด์ค„ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์„ ๋•Œ ์‚ฌ์šฉํ•จ. ์˜ˆ๋ฅผ ๋“ค์–ด, 404 ์—๋Ÿฌ์ฒ˜๋ฆฌ๋ฅผ ๋ฆฌํ„ดํ•ด์ค˜์•ผ ํ•  ๋•Œ. ํ•˜์ง€๋งŒ, res.json์ด๋‚˜ res.send๋ฅผ ์“ฐ๋ฉด ์‘๋‹ต์„ ์ข…๋ฃŒํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๊ตณ์ด ๋ช…์‹œ์ ์œผ๋กœ ํ‘œ์‹œํ•ด์ค„ ํ•„์š”๋Š” ์—†์Œ.

res.render()

๐Ÿ”ธ ์„œ๋ฒ„์—์„œ HTML์„ ์ƒ์„ฑํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌํ•˜๋Š”๋ฐ ์‚ฌ์šฉ. ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ํŽ˜์ด์ง€์˜ ์ฝ˜ํ…์ธ ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์„œ๋ฒ„ ์ธก์—์„œ ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•œ ํ›„ ์ „์†ก.

next()

๐Ÿ”ธ ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด, ๋ผ์šฐํ„ฐ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉฐ, ์ž‘์„ฑํ•˜์ง€ ์•Š์„ ์‹œ ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ.
๐Ÿ”ธ next๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š” ๋ฏธ๋“ค์›จ์–ด๋Š” res.send๋‚˜ res.sendFile ๋“ฑ์˜ ๋ฉ”์„œ๋“œ๋กœ ์‘๋‹ต์„ ๋ณด๋‚ด์•ผ ํ•จ.

HTTP ์ƒํƒœ ์ฝ”๋“œ

๐Ÿ”ธ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ์š”์ฒญ์˜ ์ฒ˜๋ฆฌ ์ƒํƒœ๋ฅผ ์‘๋‹ต์—์„œ ์•Œ๋ ค์คŒ. 3์ž๋ฆฌ ์ˆซ์ž๋กœ ๋งŒ๋“ค์–ด์ ธ ์žˆ์œผ๋ฉฐ, ์ฒซ๋ฒˆ์งธ ์ž๋ฆฌ๋Š” 1~5๋กœ ์ œ๊ณต๋จ.

์ข…๋ฅ˜

๐Ÿ”ธ 1xx(์ •๋ณด) : ์š”์ฒญ์„ ๋ฐ›์•˜์œผ๋ฉฐ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ณ„์† ์ฒ˜๋ฆฌ์ค‘

๐Ÿ”ธ2xx(์„ฑ๊ณต) : ์š”์ฒญ์„ ์„ฑ๊ณต์ ์œผ๋กœ ๋ฐ›์•˜์œผ๋ฉฐ ์ •์ƒ ์ฒ˜๋ฆฌ

๐Ÿ”ธ3xx(๋ฆฌ๋‹ค์ด๋ ‰์…˜) : ์š”์ฒญ ์™„๋ฃŒ๋ฅผ ์œ„ํ•ด ์ถ”๊ฐ€ ํ–‰๋™์ด ํ•„์š”

๐Ÿ”ธ4xx(ํด๋ผ์ด์–ธํŠธ ์˜ค๋ฅ˜) : ์ž˜๋ชป๋œ ๋ฌธ๋ฒ•์œผ๋กœ ์ธํ•ด ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Œ

๐Ÿ”ธ5xx(์„œ๋ฒ„ ์˜ค๋ฅ˜) : ์„œ๋ฒ„๊ฐ€ ์ •์ƒ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•จ

2xx ์ƒํƒœ์ฝ”๋“œ(Successful)

๐Ÿ”ธ ์š”์ฒญ์„ ์„ฑ๊ณต์ ์œผ๋กœ ๋ฐ›์•˜์œผ๋ฉฐ ์ •์ƒ ์ฒ˜๋ฆฌ
๐Ÿ”ธ 200 : ๋‹จ์ˆœ get
๐Ÿ”ธ 201 : post ์„ฑ๊ณต. ์ƒˆ๋กœ์šด ๋ฆฌ์†Œ์Šค๊ฐ€ ์ƒ์„ฑ๋จ.
๐Ÿ”ธ 202 : ์š”์ฒญ์ด ์ ‘์ˆ˜๋˜์—ˆ์ง€๋งŒ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜์ง€ ์•Š์Œ.
๐Ÿ”ธ 204 : ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์„ฑ๊ณต์ ์œผ๋กœ ์ˆ˜ํ–‰ํ–ˆ์ง€๋งŒ, ์‘๋‹ต ํŽ˜์ด๋กœ๋“œ์— ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Œ.

4xx ์ƒํƒœ์ฝ”๋“œ(Client Error)

๐Ÿ”ธ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ž˜๋ชป๋œ ๋ฌธ๋ฒ•์œผ๋กœ ์š”์ฒญํ•˜๋ฉด์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜
๐Ÿ”ธ 400 Bad Request : ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ž˜๋ชป๋œ ์š”์ฒญ์„ ํ•ด์„œ ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Œ
๐Ÿ”ธ 401 Unauthorized : ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ธ์ฆ ํ•„์š”

  • ์ธ์ฆ(Authentication, ๋ณธ์ธํ™•์ธ), ์ธ๊ฐ€(Authorization, ๊ถŒํ•œ ๋ถ€์—ฌ)

๐Ÿ”ธ 403 Forbidden : ์ธ์ฆ ์ž๊ฒฉ ์ฆ๋ช…์€ ์žˆ์ง€๋งŒ, ๊ถŒํ•œ์ด ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ.
๐Ÿ”ธ 404 Not Found : ์š”์ฒญ ๋ฆฌ์†Œ์Šค๊ฐ€ ์„œ๋ฒ„์— ์—†๋Š” ๊ฒฝ์šฐ. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ถŒํ•œ์ด ๋ถ€์กฑํ•œ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ–ˆ๋Š”๋ฐ, ํ•ด๋‹น ๋ฆฌ์†Œ์Šค๋ฅผ ์ˆจ๊ธฐ๊ณ  ์‹ถ์„ ๋•Œ.
๐Ÿ”ธ 415 Unsupported Media Type : ๋ฐ์ดํ„ฐ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ค์ •์ด ์ž˜๋ชป ๋˜์—ˆ์„ ๊ฒฝ์šฐ ๋ฐœ์ƒ. ์˜ˆ๋ฅผ ๋“ค์–ด, Content-Type์ด ์ž˜๋ชป ์„ค์ •๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ.

5xx ์ƒํƒœ์ฝ”๋“œ(Server Error)

๐Ÿ”ธ ์„œ๋ฒ„๋ฌธ์ œ๋กœ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ
๐Ÿ”ธ 500 Internal Server Error : ์„œ๋ฒ„ ๋ฌธ์ œ๋กœ ์˜ค๋ฅ˜ ๋ฐœ์ƒ.
๐Ÿ”ธ 503 Service Unavailable : ์„œ๋ฒ„๊ฐ€ ์ผ์‹œ์ ์ธ ๊ณผ๋ถ€ํ•˜๋‚˜ ์˜ˆ์ •๋œ ์ž‘์—…์œผ๋กœ ์ž ์‹œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Œ

profile
์ฝ”๋ฆฐ์ด๐Ÿ‘ฝ

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