Asp.Net Core's What & Why

์†Œ๊ฐœ

์ด ์Šฌ๋กœ๊ทธ์˜ ๋ชฉ์ ์€ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์šฉ์–ด์™€ ๊ฐœ๋…๋“ค์„ ์•Œ์•„ ๋ณด๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์„ค๋ช…์„ ์œ„ํ•ด, Asp.Net Core ์›น์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ, ํ”„๋กœ์ ํŠธ์˜ ์™„์„ฑ์ด ๋ชฉ์ ์ด ์•„๋‹ˆ๋ผ, ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ ๊ฐ ๋‹จ๊ณ„ ๋งˆ๋‹ค ์‚ผ์ฒœํฌ๋กœ ๋น ์ ธ์„œ, ๊ทธ ๋‹จ๊ณ„์™€ ๊ด€๋ จ๋œ ๊ฐœ๋…์„ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์ด ๋ชฉ์ ์ž…๋‹ˆ๋‹ค.

์„ ์ˆ˜ ์ง€์‹

  1. ๊ฐ„ํ˜น ์žˆ์„ ์ˆ˜ ์žˆ๋Š” ์˜ˆ์ œ ์ฝ”๋“œ๋Š” C#์œผ๋กœ ์ž‘์„ฑ๋  ๊ฒƒ์ด๊ธฐ์—, C#์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  2. ๋Œ€๋ถ€๋ถ„ ์œˆ๋„์šฐ ํ™˜๊ฒฝ์„ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.
  3. ์ฃผ๋กœ ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค 2022 ๋ฒ„์ „์„ ๊ธฐ์ค€์œผ๋กœ ์„ค๋ช…๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Https ์— ๋Œ€ํ•œ ๊ตฌ์„ฑ

๋‹ท๋„ท์—์„œ ์ œ๊ณตํ•˜๋Š” ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒƒ๋“ค์ด ์žˆ๊ณ , ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค์—์„œ ๊ฐœ๋ฐœํ•œ๋‹ค๋ฉด, ์ด ์ค‘์— ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒƒ์œผ๋กœ๋ถ€ํ„ฐ ๊ฐœ๋ฐœ์€ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.

image

์ด์ค‘์— ์–ด๋–ค ๊ฒƒ์„ ์„ ํƒํ•ด๋„, ํ”„๋กœ์ ํŠธ ์„ค์ •์˜ ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ [์ถ”๊ฐ€ ์ •๋ณด] ์„ค์ •์ž…๋‹ˆ๋‹ค.

image

๋นจ๊ฐ„ ์ƒ‰ ๋ฐ•์Šค์˜ Https ์— ๋Œ€ํ•œ ๊ตฌ์„ฑ์ด ์ด ๊ธ€์˜ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค.

Https ํ†ต์‹ 

Https ํ†ต์‹ ์€ Http ๋ฉ”์‹œ์ง€๊ฐ€ ์•”ํ˜ธํ™”๋˜์–ด ์†ก/์ˆ˜์‹ ๋˜๋Š” ๋ฐฉ์‹ ์ฏค์œผ๋กœ ๊ฐ„๋‹จํžˆ ์ •์˜ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

[Https ์— ๋Œ€ํ•œ ๊ตฌ์„ฑ] ์˜ต์…˜์€ ์›น์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด Https ํ†ต์‹ ์„ ํ•  ๊ฒƒ์ธ์ง€, ๋ง ๊ฒƒ์ธ์ง€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์˜ต์…˜์ด ์„ ํƒ๋˜๋ฉด Https ํ†ต์‹ ์„ ์œ„ํ•œ ๊ธฐ๋ฐ˜ ์ž์›๋“ค์ด ์„ค์ •๋˜๊ณ , ๊ทธ์— ์ƒ์‘ํ•˜๋Š” ๋ผˆ๋Œ€ ์ฝ”๋“œ๊ฐ€ ํ”„๋กœ์ ํŠธ์— ์‚ฝ์ž…๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Https ํ†ต์‹ ์„ ์œ„ํ•œ ๊ธฐ๋ฐ˜ ์ž์› ์ค‘์— ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ "SSL ์ธ์ฆ์„œ"์ž…๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด, Https ํ†ต์‹  ๊ณผ์ •์€ "SSL ์ธ์ฆ์„œ"๋ฅผ ๊ตํ™˜ํ•˜๋Š” ์ ˆ์ฐจ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ, ์ƒ์šฉ ์„œ๋น„์Šค๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•œ ํ•ญ๋ชฉ์ด๊ณ , ์œ ๋ฃŒ๋กœ ๊ตฌ๋งคํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ

SSL ์ธ์ฆ์„œ๋ฅผ ๊ฐœ๋ฐœ ์‹œ์ ๋ถ€ํ„ฐ ์œ ๋ฃŒ๋กœ ๊ตฌ๋งคํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ถ€๋‹ด์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋Œ€๋ถ€๋ถ„์€ Https ํ†ต์‹ ์„ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ ๊ตฌ์ƒ‰์„ ๊ฐ–์ถ”๊ธฐ ์œ„ํ•ด ๋ฌด๋ฃŒ์ธ ์ธ์ฆ์„œ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋ฌด๋ฃŒ์ธ ์ธ์ฆ์„œ๋Š” ๋ณดํ†ต OpenSSL ์ด๋ผ๋Š” ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑํ•˜๋Š”๋ฐ, ๋‹ท๋„ท์€ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ ๊ฐ„ํŽธํ•˜๊ฒŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

[Https ์— ๋Œ€ํ•œ ๊ตฌ์„ฑ] ์˜ต์…˜์ด ์„ ํƒ๋˜๋ฉด, ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค๋Š” ๊ฐœ๋ฐœ PC์— "๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ"๊ฐ€ ์žˆ๋Š” ์ง€ ๊ฒ€์ƒ‰ํ•˜๊ณ , ์—†๋‹ค๋ฉด ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค๊ฐ€ ์ƒ์„ฑํ•œ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋Š” ๋ชจ๋“  Asp.Net Core ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœ์ ํŠธ๊ฐ€ ๊ณต์œ ํ•˜๋„๋ก ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. .

๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค๊ฐ€ ์ƒ์„ฑํ•œ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ์˜ ์‹ค๋ฌผ์„ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์€:
(์œˆ๋„์šฐ ๊ธฐ์ค€)

  1. ์œˆ๋„์šฐ ๊ฒ€์ƒ‰ ์ฐฝ์— "์ธ์ฆ์„œ"๋ฅผ ์ž…๋ ฅํ•˜๋ฉด
    ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์ตœ์ƒ๋‹จ์— "์‚ฌ์šฉ์ž ์ธ์ฆ์„œ ๊ด€๋ฆฌ"๋ผ๋Š” ์ œ์–ดํŒ ํ•ญ๋ชฉ์ด ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
    image

  2. ์ธ์ฆ์„œ ๊ด€๋ฆฌ์ž๋ฅผ ํด๋ฆญํ•˜๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์ด ์ธ์ฆ์„œ ๊ด€๋ฆฌ์ž๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
    image

์œ„ ์ฐฝ์˜ ์™ผ์ชฝ ๋ถ„๋ฉด์˜ ์ตœ ์ƒ๋‹จ์— ์žˆ๋Š” โ€œ๊ฐœ์ธ์šฉโ€ ํด๋”๋ฅผ ํ™•์žฅํ•˜๋ฉด, โ€œ์ธ์ฆ์„œโ€ ํด๋”๊ฐ€ ๋‚˜์˜ค๋Š”๋ฐ, ์ด๊ณณ์ด ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค๊ฐ€ ์ƒ์„ฑํ•œ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๊ฐ€ ์ €์žฅ๋˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค.
image
์œ„ ๊ทธ๋ฆผ์—์„œ, ๋นจ๊ฐ„ ์ƒ‰ ๋ฐ•์Šค๋กœ ํ‘œ์‹œ๋œ ์ธ์ฆ์„œ๊ฐ€, ์ƒ์„ฑ๋œ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ ์‹ค๋ฌผ์ž…๋‹ˆ๋‹ค.

์ด ํด๋”์˜ ์ธ์ฆ์„œ๋“ค์€ ๋Œ€๋ถ€๋ถ„ ๋ฐœ๊ธ‰์ž์™€ ๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž๊ฐ€ ๋‹ค๋ฅด์ง€๋งŒ, ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋Š” ์ด๋“ค์ด ๋ชจ๋‘ โ€œlocalhostโ€ ๋กœ ๋™์ผํ•˜๊ฒŒ ํ‘œ์‹œ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Š” ์ž์‹ ์˜ ์ฆ๋ช…์„œ๋ฅผ ์ž๊ธฐ ๋„์ž‘์„ ์ฐ์–ด์„œ ๋ฐœํ–‰ํ•œ ๊ฒƒ๊ณผ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ž์‹ ์„ ์œ„ํ•ด ๋ฐœ๊ธ‰ํ•œ ์ธ์ฆ์„œ๋ฅผ "์ž๊ฐ€ ์„œ๋ช… ์ธ์ฆ์„œ(Self-signed Certificate)"์ด๋ผ๊ณ  ๋ถ€๋ฅด๋Š”๋ฐ, ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋“ค์ด ๋ณดํŽธ์ ์œผ๋กœ ๊ฐ–๋Š” ํŠน์ง•์ž…๋‹ˆ๋‹ค.

์ธ์ฆ์„œ๋Š” Https ํ†ต์‹ ์ด ์‹œ์ž‘๋˜๋ฉด, ์„œ๋ฒ„์—์„œ ๋ธŒ๋ผ์šฐ์ €๋กœ ์ „๋‹ฌ๋˜๊ณ , ๋ธŒ๋ผ์šฐ์ €๋Š” ์ด ์ธ์ฆ์„œ๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ธ์ฆ์„œ๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ์ผ์ฐจ์ ์ธ ์ด์œ ๋Š”, ํ˜„์žฌ ์ ‘์† ์ค‘์ธ ๋„๋ฉ”์ธ(URL)์˜ ์†Œ์œ ์ž๊ฐ€ ์ œ๊ณต๋œ ์ธ์ฆ์„œ์˜ "๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž"์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฆ‰, ํ†ต์‹  ์ƒ๋Œ€๋ฐฉ์ด ์ง„์งœ URL ์†Œ์œ ์ž(origin)์ธ์ง€ ์•„๋‹Œ ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.

origin ์ž„์ด ํ™•์ธ๋˜๋ฉด, ์„œ๋ฒ„์™€ ๋ธŒ๋ผ์šฐ์ €๋Š” ํ–ฅํ›„ ์ฃผ๊ณ  ๋ฐ›์„ ๋ฉ”์‹œ์ง€๋ฅผ ์•”ํ˜ธํ™”ํ•  ๋น„๋ฐ€ํ‚ค๋ฅผ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ ๋‹ค์Œ๋ถ€ํ„ฐ๋Š”, ์†ก์‹ ์ธก์€ ๊ณต์œ ๋œ ๋น„๋ฐ€ํ‚ค๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์•”ํ˜ธํ™”ํ•œ ํ›„ ์†ก์‹ ํ•˜๊ณ , ์ˆ˜์‹ ์ธก์€ ๋น„๋ฐ€ํ‚ค๋กœ ๋ณต์›ํ•ด์„œ ๋ฉ”์‹œ์ง€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ฒƒ์ด Https ๋ฅผ ํ†ตํ•ด ์ด๋ค„์ง€๋Š” ์•”ํ˜ธํ™” ํ†ต์‹ ์˜ ๋Œ€๋žต์ž…๋‹ˆ๋‹ค.

์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฃจํŠธ ์ธ์ฆ๊ธฐ๊ด€

์ธ์ฆ์„œ ์ €์žฅ ํด๋” ์ค‘์— ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ณณ์€ [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฃจํŠธ ์ธ์ฆ๊ธฐ๊ด€] ์ž…๋‹ˆ๋‹ค.
image

์ด ํด๋”๋Š” ๋ฐœ๊ธ‰ ๊ธฐ๊ด€ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ํŠน์ˆ˜ ํด๋”๊ฐ€ ์•„๋‹ˆ๋ผ, ๊ทธ๋ƒฅ ๋˜‘ ๊ฐ™์ด ์ธ์ฆ์„œ๋“ค์„ ์ €์žฅํ•˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ์—ฌ๊ธฐ์— ์žˆ๋Š” ์ธ์ฆ์„œ๋“ค์„ ์ž์„ธํžˆ ๋ณด๋ฉด, ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ์™€ ๊ฐ™์ด ๋ฐœ๊ธ‰์ž์™€ ๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž๊ฐ€ ๋ชจ๋‘ ๋™์ผํ•œ, ์ž๊ฐ€ ์„œ๋ช… ์ธ์ฆ์„œ์ž„์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ณดํ†ต ์ธ์ฆ์„œ๋Š” ๋ฐœ๊ธ‰์ž์™€ ๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž๊ฐ€ ๋‹ค๋ฅธ ๊ฒŒ ์ •์ƒ์ด์ง€๋งŒ, ๋ฐœ๊ธ‰์ž๋ฅผ ์ธ์ฆํ•ด ์ค„ ์ƒ์œ„ ๋ฐœ๊ธ‰์ž๊ฐ€ ๋” ์ด์ƒ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ์Šค์Šค๋กœ์—๊ฒŒ ์ธ์ฆ์„œ๋ฅผ ๋ฐœ๊ธ‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ˜•์‹์œผ๋กœ ๋ฐœ๊ธ‰๋œ ์ธ์ฆ์„œ๋ฅผ "๋ฃจํŠธ ์ธ์ฆ์„œ"๋ผ๊ณ , ๋ฃจํŠธ ์ธ์ฆ์„œ์˜ ๋ฐœ๊ธ‰์ž๋ฅผ "๋ฃจํŠธ ๋ฐœ๊ธ‰์ž(๊ธฐ๊ด€)"๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋„ ํ˜•์‹์ ์œผ๋กœ๋Š” ๋ฃจํŠธ ์ธ์ฆ์„œ์ด๊ณ , ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ์˜ ๋ฐœ๊ธ‰์ž์ธ localhost ๋„ ๋ฃจํŠธ ๋ฐœ๊ธ‰์ž์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜, ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ์˜ ๋ฐœ๊ธ‰์ž โ€œlocalhostโ€ ์™€ ์ด ํด๋”์— ์žˆ๋Š” ๋ฐœ๊ธ‰์ž๋“ค์€ ๊ธ‰์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
์ด๋“ค์€ ๋ณดํŽธ์ ์œผ๋กœ ๋งŽ์€ ์šด์˜์ฒด์ œ๋“ค์ด ์‹ ๋ขฐํ•˜๋Š” ํšŒ์‚ฌ-์กฐ์ง์œผ๋กœ, ์ด๋“ค์ด ๋ฐœ๊ธ‰ํ•œ ๋ฃจํŠธ ์ธ์ฆ์„œ๋Š” ์šด์˜์ฒด์ œ๊ฐ€ ์„ค์น˜๋  ๋•Œ, ํ˜น์€ ๋‚˜์ค‘์—๋ผ๋„ ์ž์œ ๋กญ๊ฒŒ ์ด ํด๋”์— ๋ชจ์…”์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ํด๋” ์ด๋ฆ„๋„ [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฃจํŠธ ์ธ์ฆ ๊ธฐ๊ด€]์ž…๋‹ˆ๋‹ค.

์ด๋“ค์ด ๋ฐœ๊ธ‰ํ•œ ์ธ์ฆ์„œ๋Š” Https ํ†ต์‹ ์—์„œ ๋Œ€๋ถ€๋ถ„ ๊ฒ€์ฆ์„ ํ†ต๊ณผํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ, ๋ˆ์„ ์ฃผ๊ณ  ์ด๋“ค์—๊ฒŒ ์‚ฌ์ดํŠธ์— ๋Œ€ํ•œ ์ธ์ฆ์„œ๋ฅผ ๋ฐœ๊ธ‰ ๋ฐ›์•„์•ผ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ์ด ํด๋”๊ฐ€ ๋“ฃ๋ณด์žก ๋ฐœ๊ธ‰์ž์ธ "localhost"๋ฅผ "์‹ ๋ขฐํ•˜๋Š” ๋ฃจํŠธ ์ธ์ฆ๊ธฐ๊ด€"์œผ๋กœ ๊ฒฉ์ƒ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์‹ค๋งˆ๋ฆฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค๊ฐ€ ์ƒ์„ฑํ•œ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ์˜ ์‚ฌ๋ณธ์„ ์ด ํด๋”์— ๋„ฃ๊ธฐ๋งŒ ํ•˜๋ฉด, ๊ทธ ์ธ์ฆ์„œ์˜ ๋ฐœํ–‰์ž์ธ "localhost"๊ฐ€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฃจํŠธ ๋ฐœ๊ธ‰์ž๋กœ ๋‘”๊ฐ‘ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด์ฃ .

์‚ฌ์‹ค, ์ด ๊ฒƒ์ด ๋ฌด๋ฃŒ์ธ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ ์‚ฌ์šฉํ•ด๋„, ์•„๋ฌด ๋ฌธ์ œ ์—†์ด https ํ†ต์‹ ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ์›๋ฆฌ์ž…๋‹ˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ €๋Š” https ํ†ต์‹ ์„ ๊ฐœ์‹œํ•  ๋•Œ, ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์ธ์ฆ์„œ์˜ ๋ฐœ๊ธ‰์ž๊ฐ€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์ง€ ํ™•์ธํ•˜๋Š”๋ฐ, ํ™•์ธ์˜ ๊ทผ๊ฑฐ๋Š” ๊ทธ ์ธ์ฆ์„œ์˜ ๋ฐœ๊ธ‰์ž๊ฐ€ [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฃจํŠธ ์ธ์ฆ ๊ธฐ๊ด€]์— ์žˆ๊ธฐ๋งŒ ํ•˜๋ฉด ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค๋งŒ ์ด๋Ÿฌํ•œ ํšจ๊ณผ๋Š” ๊ทธ PC์—๋งŒ ํ•ด๋‹น๋˜๋Š” ์–˜๊ธฐ์ž…๋‹ˆ๋‹ค.
๋งŒ์•ฝ, ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ ์ „์„ธ๊ณ„ ๋ชจ๋“  PC์˜ [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฃจํŠธ ์ธ์ฆ ๊ธฐ๊ด€] ํด๋”์— ์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, ์œ ๋ฃŒ ์ธ์ฆ์„œ์™€ ๋‹ค๋ฅธ ์ ์€ ์—†์Šต๋‹ˆ๋‹ค.

์œˆ๋„์šฐ์˜ ๊ฒฝ์šฐ, ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฃจํŠธ ์ธ์ฆ ๊ธฐ๊ด€] ํด๋”๋กœ ์˜ฎ๊ธฐ๋Š” ์ž‘์—…์€ ์ธ์ฆ์„œ ๊ด€๋ฆฌ์ž์˜ ๋‚ด๋ณด๋‚ด๊ธฐ, ๊ฐ€์ ธ์˜ค๊ธฐ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

๋งŒ์•ฝ, ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค์—์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ทธ ํ”„๋กœ์ ํŠธ๋กœ ์ธํ•ด ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๊ฒฝ์šฐ๋ผ๋ฉด, ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ตœ์ดˆ๋กœ ์‹คํ–‰ํ•  ๋•Œ, ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค๋Š” ์•„๋ž˜์˜ ์งˆ๋ฌธ์„ ํ•ฉ๋‹ˆ๋‹ค.
image

โ€œ์ผ๋‹จ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ ํ•˜๋‚˜ ์ƒ์„ฑํ•˜๊ธฐ๋Š” ํ–ˆ๋Š”๋ฐ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ด ์ธ์ฆ์„œ๋ฅผ ์‹ ๋ขฐํ•˜๊ฒŒ ๋งŒ๋“ค๋ ค๋ฉด [์‹ ๋ขฐํ•  โ€ฆ] ํด๋”์— ๋„ฃ์–ด์•ผ ๋ผ. ๋„ฃ์„๊นŒ?โ€ ๋ผ๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

[์˜ˆ]๋ฅผ ์„ ํƒํ•˜๋ฉด, ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค๋Š” ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ์˜ ์‚ฌ๋ณธ์„ [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฃจํŠธ ์ธ์ฆ๊ธฐ๊ด€] ํด๋”์— ์ €์žฅํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ์šด์˜์ฒด์ œ์— ์ธ์ฆ์„œ๋ฅผ ์„ค์น˜ํ•˜๋Š” ๊ฒƒ์€ ์ค‘์š”ํ•œ ๋ณด์•ˆ ํ–‰์œ„์ด๋ฏ€๋กœ, ์•„๋ž˜์™€ ๊ฐ™์€ ์šด์˜ ์ฒด์ œ์˜ ๋ณด์•ˆ ๊ฒฝ๊ณ ๊ฐ€ ํ•œ๋ฒˆ ๋” ๋œน๋‹ˆ๋‹ค.
image

๋‹ค์‹œ [์˜ˆ]๋ฅผ ์„ ํƒํ•˜๋ฉด, ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๊ฐ€ [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š”โ€ฆ] ํด๋”์— ๋ณต์‚ฌ๋ฉ๋‹ˆ๋‹ค.
image

์‹คํ–‰๋œ ์›น์•ฑ์€ ๊ฐœ์ธ์šฉ-๋ณด์ฆ์„œ ํด๋”์— ์žˆ๋Š” ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ https ํ†ต์‹  ๊ฐœ์‹œ ์‹œ์ ์— ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐ›์€ ๋ธŒ๋ผ์šฐ์ €๋Š”

  1. ์ธ์ฆ์„œ์˜ ๋ฐœ๊ธ‰์ž๊ฐ€ [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š”โ€ฆ] ํด๋”์— ์žˆ๋Š” ๋ฐœ๊ธ‰์ž์ธ์ง€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  2. ํ™•์ธ์ด ๋˜๋ฉด, ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ ์‹ ๋ขฐํ•˜๊ณ , ๊ทธ ์ธ์ฆ์„œ์˜ ๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž์ธ localhost๋ฅผ origin์ด๋ผ๊ณ  ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์‹ค ํ•˜๋‚˜์˜ ์ธ์ฆ์„œ๋กœ ๋ถ์น˜๊ณ  ์žฅ๊ตฌ์น˜๊ณ  ํ•˜๋Š” ๊ฒƒ์ด์ฃ .

๊ทธ ๊ฒฐ๊ณผ๋กœ https ํ†ต์‹ ์€ ๊ฐœ์‹œ๋˜๊ณ , ์šฐ๋ฆฌ์˜ ์ฝ”๋“œ ๊ฒฐ๊ณผ๋ฅผ ํ™”๋ฉด์— ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์œ ํšจ ๊ธฐํ•œ

๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ์˜ ๋งŒ๋ฃŒ ๋‚ ์งœ๋ฅผ ๋ณด์‹œ๋ฉด ์œ ํšจ๊ธฐ๊ฐ„์ด 1๋…„ ์งœ๋ฆฌ์ž…๋‹ˆ๋‹ค.

๋งŒ์•ฝ, ์ด์ „์— ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•œ ์ ์ด ์žˆ๊ณ , ๊ทธ ๋•Œ ๋ฐœ๊ธ‰๋œ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ์˜ ์œ ํšจ๊ธฐ๊ฐ„์ด ๋งŒ๋ฃŒ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ ์ƒ์„ฑ ๋‹จ๊ณ„๋Š” ์ƒ๋žต๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ์ธ์ฆ์„œ๋ฅผ ์‹ ๋ขฐํ•  ๊ฒƒ์ด๋ƒ๋Š” ์งˆ๋ฌธ๋„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ, [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š”โ€ฆ] ํด๋”์— ์‚ฌ๋ณธ์ด ๋“ค์–ด๊ฐ€ ์žˆ์„ ํ…Œ๋‹ˆ๊นŒ์š”.

๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋Š” ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์ฒ˜์Œ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜, ๊ธฐ์กด์— ๋ฐœ๊ธ‰๋œ ์ธ์ฆ์„œ์˜ ์œ ํšจ๊ธฐ๊ฐ„์ด ๊ฒฝ๊ณผ๋œ ๊ฒฝ์šฐ์—๋งŒ ์ƒˆ๋กœ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ฐœ๊ธ‰์ž๋ฅผ ์‹ ๋ขฐํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ˆ˜์‹ ํ•œ ์ธ์ฆ์„œ์˜ ๋ฐœ๊ธ‰์ž๋ฅผ ์‹ ๋ขฐํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋ฅผ ์‚ดํŽด๋ณด๊ธฐ ์œ„ํ•ด, [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š”โ€ฆ] ํด๋”์—์„œ ๋ฐฉ๊ธˆ ๋ณต์‚ฌ๋œ ์ธ์ฆ์„œ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. ์‚ญ์ œ ๋ฐฉ๋ฒ•์€ ์ธ์ฆ์„œ ๊ด€๋ฆฌ์ž์—์„œ, ์ธ์ฆ์„œ๋ฅผ ์„ ํƒํ•˜๊ณ  delete ํ‚ค๋ฅผ ๋ˆ„๋ฅด๊ฑฐ๋‚˜, ์šฐํด๋ฆญ>์‚ญ์ œ๋ฅผ ํ•˜๊ฑฐ๋‚˜, ๊ด€๋ฆฌ์ž ๋ฉ”๋‰ด์˜ ์‚ญ์ œ ๋ฒ„ํŠผ, ์•„๋ฌด๊ฑฐ๋‚˜ ๋‹ค ๋ฉ๋‹ˆ๋‹ค.

์ธ์ฆ์„œ๋ฅผ ์‚ญ์ œํ•˜๋Š” ๊ฒƒ๋„ ๋ณด์•ˆ ๋ฌธ์ œ๋ผ, ์‚ญ์ œ ์‹œ์—๋„ ์šด์˜์ œ์ฒด๋Š” ๋ณด์•ˆ ๊ฒฝ๊ณ ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
๋ณด์•ˆ ๊ฒฝ๊ณ ์—์„œ, [์˜ˆ]๋ฅผ ์„ ํƒํ•˜๋ฉด ๋น„๋กœ์†Œ ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค.

์ธ์ฆ์„œ์˜ ์‹ค์ œ ์‚ฌ์šฉ์ž๋Š” ๋ธŒ๋ผ์šฐ์ €์ธ๋ฐ, ๋ธŒ๋ผ์šฐ์ €๋Š” ์‹คํ–‰ํ•  ๋•Œ ์‹ ๋ขฐํ•˜๋Š” ์ธ์ฆ์„œ๋ฅผ ์บ์‹ฑํ•ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ, ๋ธŒ๋ผ์šฐ์ € ์บ์‹ฑ์—์„œ ์‚ญ์ œํ•˜์ง€ ์•Š์œผ๋ฉด, ์•„๋ฌด๋Ÿฐ ํšจ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ € ์บ์‹ฑ์—์„œ ์‚ญ์ œํ•˜๋ ค๋ฉด, ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋‹ซ๊ณ  ์žฌ์‹คํ–‰ํ•˜์—ฌ, ์ƒˆ๋กญ๊ฒŒ ์บ์‹ฑํ•˜๋„๋ก ๋งŒ๋“ค๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ด์ œ ์•ฑ์„ ์‹คํ–‰ํ•ด๋ณด๋ฉด, ์ธ์ฆ์„œ๋ฅผ ์‹ ๋ขฐํ•˜๊ฒ ๋ƒ๋Š” ์งˆ๋ฌธ์„ ๋‹ค์‹œ ํ•˜๋Š”๋ฐ, ์ด๋ฒˆ์—๋Š” [์•„๋‹ˆ์˜ค]๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
image

์ด์ œ ๋ฐœ๊ธ‰์ž localhost๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์‹ ๋ขฐํ•˜์ง€ ์•Š๋Š” ๋ฐœ๊ธ‰์ž๋กœ ์ „๋ฝํ–ˆ๊ธฐ์—, ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ ๋ณด๋‚ธ ์„œ๋ฒ„์— ๋Œ€ํ•œ ๋Œ€์šฐ๊ฐ€ ์™„์ „ํžˆ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
image

๋ฉ”์‹œ์ง€์˜ ๋‚ด์šฉ์€ ์„ฌ๋œฉํ•˜์ง€๋งŒ, ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” โ€œ๋“ฃ๋ณด์žกโ€ ๋ฐœ๊ธ‰์ž "localhost"๊ฐ€ ๋ฐœํ–‰ํ•œ ์ธ์ฆ์„œ๋ฅผ ๋ฐ›์•˜๋‹ค๋Š” ์˜๋ฏธ์— ์ง€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ํ™”๋ฉด์—์„œ [๊ณ ๊ธ‰] ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด, ์œ„ํ—˜์„ ๊ฐ์ˆ˜ํ•˜๊ณ  https ํ†ต์‹ ์„ ๊ณ„์† ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.(์ƒ๋žต)

Https ๋กœ ๊ตฌ์„ฑ๋œ ์•ฑ์ด (๊ฐœ๋ฐœ์šฉ)์ธ์ฆ์„œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ

์ด๋ฒˆ์—๋Š” ๊ฐœ์ธ์šฉ-์ธ์ฆ์„œ ํด๋”์— ์ €์žฅ๋œ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ ์ง€์›Œ ์›น์•ฑ์ด ์ธ์ฆ์„œ๋ฅผ ๋ชป ์ฐพ๊ฒŒ ํ•ด๋ด…๋‹ˆ๋‹ค.
image

์ด ์ƒํƒœ์—์„œ ์•ฑ์„ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
image

์‚ฌ์‹ค, ์ด ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€๊ฐ€ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ์— ๊ด€ํ•œ ์‹ค์งˆ์„ ์ž˜ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

Https ์—”๋“œ ํฌ์ธํŠธ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์—†์Œ. ๊ทธ ์ด์œ ๋Š”:
์„œ๋ฒ„ ์ธ์ฆ์„œ๋„ ์ฐพ์„ ์ˆ˜ ์—†๊ณ , ๊ธฐ๋ณธ์ ์ธ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋„ ์ฐพ์„ ์ˆ˜ ์—†๊ฑฐ๋‚˜ ์œ ํšจ๊ธฐ๊ฐ„์ด ๋งŒ๋ฃŒ๋จ.
๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด, ๋ช…๋ น ํ”„๋กฌํ”„ํŠธ์— โ€˜dotnet dev-certs httpsโ€™ ๋ฅผ ์‹คํ–‰ํ•ด๋ผ.
(์œˆ๋„์šฐ ๋งฅOS ํ•œ์ •) ์ƒ์„ฑ๊ณผ ๋™์‹œ์— ์‹ ๋ขฐํ•˜๋ ค๋ฉด, 'dotnet dev-certs https --trustโ€™๋ฅผ ์‹คํ–‰ํ•ด๋ผ.
์ž์„ธํ•œ ์‚ฌํ•ญ์€ Enforce HTTPS in ASP.NET Core | Microsoft Learn ์œผ๋กœ ๊ฐ€๋ผ

์œ„ ๋งํฌ๋ฅผ ๋”ฐ๋ผ๊ฐ€ ๋ณด๋ฉด ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€์™€ ๋น„์Šทํ•œ ๋‚ด์šฉ์„ ๋ณด์—ฌ ์ฃผ๋Š” ๋ฌธ์„œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์‹ค, "Https ์— ๋Œ€ํ•œ ๊ตฌ์„ฑ"์„ ์„ ํƒํ•˜๋ฉด, ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค๋Š” โ€˜dotnet dev-certs httpsโ€™ ์ฝ˜์†” ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ ๋ฟ์ž…๋‹ˆ๋‹ค. ์ด๋•Œ, ์•„์ฃผ ์ž ๊น ๋™์•ˆ ์ฝ˜์†”์ฐฝ์ด ์—ด๋ ธ๋‹ค๊ฐ€ ์ˆœ์‹ ๊ฐ„์— ์‚ฌ๋ผ์ง€๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ˜์†”์ฐฝ์„ ์—ด๋Ÿฌ, ์‹œํ‚ค๋Š” ๋Œ€๋กœ ๋™์ผํ•œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๊ณ ,
image

์ธ์ฆ์„œ ๊ด€๋ฆฌ์ž๋ฅผ ๋‹ค์‹œ ๋ณด๋ฉด, ์ธ์ฆ์„œ๊ฐ€ ๋‹ค์‹œ ์ƒ์„ฑ๋˜์—ˆ์Œ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
image

์ด์ œ ์•ฑ์„ ๋‹ค์‹œ ์‹คํ–‰ํ•ด ๋ณด๋ฉด, ์ด์ „๊ณผ ๊ฐ™์€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ , ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ ์‹ ๋ขฐํ•˜๋ƒ๋Š” ์งˆ๋ฌธ ๋‹จ๊ณ„๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค.

์ด๋•Œ, ์•„๋ฌด๊ฒƒ๋„ ๋ˆ„๋ฅด์ง€ ์•Š๊ณ , ์•ฑ์„ ์ข…๋ฃŒํ•œ ํ•˜๊ณ , ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €์˜ ์ฐฝ์„ ๋‹ซ์Šต๋‹ˆ๋‹ค.
๊ทธ ๋‹ค์Œ, ๋‹ค์‹œ ์ƒ์„ฑ๋œ ์ธ์ฆ์„œ๋ฅผ ๋ณต์‚ฌํ•ด์„œ, [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š”โ€ฆ] ํด๋”์— ๋ถ™์—ฌ ๋„ฃ๊ธฐ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ๋‹ค์Œ, ๋‹ค์‹œ ์•ฑ์„ ์‹คํ–‰ํ•ด ๋ณด๋ฉด, ์‹ ๋ขฐํ• ๊ฑฐ๋ƒ๋Š” ์งˆ๋ฌธ ๋‹จ๊ณ„๋„ ๊ฑด๋„ˆ ๋„๊ณ  index ๋ทฐ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์›๊ฒฉ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ

๋งŒ์•ฝ ์„œ๋ฒ„์•ฑ์ด ์‹คํ–‰๋˜๋Š” PC์™€ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์‹คํ–‰๋˜๋Š” PC ๊ฐ€ ๋‹ค๋ฅธ ๊ฒฝ์šฐ์—๋Š” ์„œ๋ฒ„ PC์˜ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ ์‚ฌ๋ณธ์„ ๋ธŒ๋ผ์šฐ์ € PC์˜ [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š”โ€ฆ] ํด๋”์— ์ €์žฅํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„ PC๊ฐ€ ์œˆ๋„์šฐ์ธ ๊ฒฝ์šฐ, ์ธ์ฆ์„œ ๊ด€๋ฆฌ์ž์˜ ๋‚ด๋ณด๋‚ด๊ธฐ๋ฅผ ์„ ํƒํ•˜๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์ด ์ธ์ฆ์„œ ๋‚ด๋ณด๋‚ด๊ธฐ ๋งˆ๋ฒ•์‚ฌ๊ฐ€ ์‹คํ–‰๋˜๊ณ , ์•„๋ž˜ ๊ทธ๋ฆผ ๋Œ€๋กœ ์ˆœ์ฐจ์ ์œผ๋กœ ๋”ฐ๋ผํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
image

๊ฐœ์ธํ‚ค๋ฅผ ๋‚ด๋ณด๋‚ด์ง€ ์•Š๋Š” ์„ ํƒ์„ ํ•˜๊ณ ,
image

ํŒŒ์ผ ํ˜•์‹์€ X.509 ํ˜•์‹์œผ๋กœ,
image

๋‚ด๋ณด๋‚ผ ํด๋”๋ฅผ ์„ ํƒํ•˜๊ณ , ํŒŒ์ผ ์ด๋ฆ„์„ ์„ ํƒํ•˜๋ฉด,
image

์•„๋ž˜์™€ ๊ฐ™์ด ์ธ์ฆ์„œ ์‚ฌ๋ณธ ํŒŒ์ผ์ด ๋ณต์‚ฌ๋ฉ๋‹ˆ๋‹ค.
image

์ด ํŒŒ์ผ์„ USB์— ์ €์žฅํ•˜๋“ , ๋ฉ”์ผ๋กœ ๋ณด๋‚ด๋“  ๋ธŒ๋ผ์šฐ์ € PC์— ์ €์žฅํ•œ ํ›„, ์ธ์ฆ์„œ ๊ด€๋ฆฌ์ž๋ฅผ ํ†ตํ•ด [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š”โ€ฆ] ํด๋”๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ์›๊ฒฉ ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœ์šฉ ์ธ์ฆ์„œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ณด์•ˆ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด์— ๊ด€ํ•ด์„œ๋Š” ์œ„์— ๋งํฌ๋œ ๋ฌธ์„œ์—์„œ ์„ค๋ช…ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

16๊ฐœ์˜ ์ข‹์•„์š”

์ธ์ฆ์„œ

์ธ์ฆ์„œ๋ž€ ์ธ์ฆ์„œ ์†Œ์œ ์ž์— ๋Œ€ํ•œ ํ™•์ธ์„œ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ธ์ฆ์„œ
์ผ๋ จ๋ฒˆํ˜ธ : 20220921 - 1
๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž : www.biden.com
๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž๋Š” ์ง„์‹คํ•จ์„ ํ™•์ธํ•จ.
๋ฐœ๊ธ‰์ž : www.mmbbcc.com

๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž๊ฐ€ ์ธ์ฆ์„œ๋ฅผ ํ†ตํ•ด ํ™•์ธ๋˜๋Š” ์†Œ์œ ์ž์ž…๋‹ˆ๋‹ค.


์ธ์ฆ์„œ์™€ ๊ด€๋ จํ•ด์„œ๋Š” ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€ ๋ณด์•ˆ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ๋ฌธ์ œ๋Š” ์ธ์ฆ์„œ์˜ ์œ„์กฐ์ž…๋‹ˆ๋‹ค.
์ธ์ฆ์„œ๊ฐ€ ๋ฐœ๊ธ‰๋œ ํ›„, ์ธ์ฆ์„œ์˜ ๋‚ด์šฉ ์ค‘ ์ผ๋ถ€, ์ฃผ๋กœ ๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž๋ฅผ ์œ„์กฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ธ์ฆ์„œ
์ผ๋ จ๋ฒˆํ˜ธ : 20220921 - 1
๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž : www.nalimyeon.com
๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž๋Š” ์ง„์‹คํ•จ์„ ํ™•์ธํ•จ.
๋ฐœ๊ธ‰์ž : www.mmbbcc.com

๋‘ ๋ฒˆ์งธ๋Š” ๋ฐœ๊ธ‰์ž์˜ ๊ถŒ์œ„์ž…๋‹ˆ๋‹ค.
๋ฐœ๊ธ‰์ž์—๊ฒŒ ์‹ ๋ง์ด ์—†๋Š” ๊ฒฝ์šฐ, ์ธ์ฆ์„œ๋Š” ๋ฌธ์„œ ์ชผ๊ฐ€๋ฆฌ์— ์ง€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ธ์ฆ์„œ
์ผ๋ จ๋ฒˆํ˜ธ : 20220923 - 1
๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž : www.nalimyeon.com
๋ฐœ๊ธ‰ ๋Œ€์ƒ์ž๋Š” ์ง„์‹คํ•จ์„ ํ™•์ธํ•จ.
๋ฐœ๊ธ‰์ž : www.mmbbnn.com

์ธ์ฆ์„œ๋Š” ์ด๋Ÿฌํ•œ ๋ณด์•ˆ ์œ„ํ—˜์— ๋Œ€ํ•œ ๊ฒ€์ฆ ์žฅ์น˜๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š”๋ฐ, "๋””์ง€ํ„ธ ์„œ๋ช…"์ด๋ผ๋Š” ๊ฒƒ์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๋””์ง€ํ„ธ ์„œ๋ช…

๋””์ง€ํ„ธ ์„œ๋ช…์€ ์ˆ˜๊ธฐ ์„œ๋ช…์„ ๋””์ง€ํ„ธ ๋ฐฉ์‹์œผ๋กœ ๋ณ€ํ™˜ํ•œ ๊ฒƒ์œผ๋กœ, ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜

ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ˆ˜ํ•™์  ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๊ฐ€๋ณ€ ๊ธธ์ด ๋ฌธ์ž์—ด์„ ๋‹จ์ผํ•œ ๊ธธ์ด์˜ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, 100 ๊ธ€์ž๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์žˆ๋‹ค๋ฉด, ํ•œ ๊ธ€์ž๋ฅผ ์ž…๋ ฅํ•˜๋“  ์ฑ… ํ•œ๊ถŒ์„ ์ž…๋ ฅํ•˜๋“  100๊ธ€์ž๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€:

  • ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์ด ๊ณ ์œ ํ•œ ๊ด€๊ณ„์ž„์„ ๋ณด์ฆํ•ฉ๋‹ˆ๋‹ค.
    ์˜ˆ๋ฅผ ๋“ค์–ด, ์ฑ… ํ•œ๊ถŒ์—์„œ ๋งˆ์นจํ‘œ ํ•˜๋‚˜๋งŒ ๋น ์ ธ๋„, ์ถœ๋ ฅ์€ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
    (์ฐธ๊ณ , ์‹ค์ œ๋กœ๋Š” ๊ฑฐ์˜ ๋Œ€๋ถ€๋ถ„ ๊ณ ์œ ํ•˜์ง€๋งŒ, ์„œ๋กœ ๋‹ค๋ฅธ ์ž…๋ ฅ์ด ํ•˜๋‚˜์˜ ์ถœ๋ ฅ์œผ๋กœ ๋‚˜์˜ฌ ๊ฐ€๋Šฅ์„ฑ์ด ์—†์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.)

  • ๋™์ผํ•œ ์ž…๋ ฅ์— ๋Œ€ํ•ด ํ•ญ์ƒ ๋™์ผํ•œ ์ถœ๋ ฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • ์ถœ๋ ฅ์œผ๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ์„ ์œ ์ถ”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ํŠน์ง•์„ ์ธ์ฆ์„œ์— ์ ์šฉํ•ด ๋ณด๋ฉด, ๋™์ผํ•œ ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ์ธ์ฆ์„œ๋กœ๋ถ€ํ„ฐ ์–ป์€ ํ•ด์‹œ ๊ฐ’์€ ์–ธ์ œ๋‚˜ ๊ฐ™์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋งŒ์•ฝ, ์ธ์ฆ์„œ๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ์ตœ์ดˆ๋กœ ์–ป์€ ํ•ด์‹œ๊ฐ’๊ณผ ์ธ์ฆ์„œ๊ฐ€ ๋ฐœ๊ธ‰๋œ ํ›„ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์–ป์€ ํ•ด์‹œ๊ฐ’์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, ๋ˆ„๊ตฐ๊ฐ€ ์ธ์ฆ์„œ์˜ ๋‚ด์šฉ์„ ์œ„์กฐํ•œ ๊ฒƒ์œผ๋กœ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ธ์ฆ์„œ๋Š” ์ด๋Ÿฌํ•œ ์œ„์กฐ๋ฅผ ๋ˆ„๊ตฌ๋‚˜ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก, ์ธ์ฆ์„œ ๋ฐœ๊ธ‰์ž๊ฐ€ ์‚ฌ์šฉํ•œ ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๋ฐœ๊ธ‰์ž๊ฐ€ ์–ป์€ ์ตœ์ดˆ์˜ ํ•ด์‹œ๊ฐ’์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
image
image

์ธ์ฆ์„œ ์ง€๋ฌธ

์ธ์ฆ์„œ์— ํฌํ•จ๋œ ํ•ด์‹œ๊ฐ’์€ ์‚ฌ์‹ค ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๊ฒฐ๊ณผ๋ฌผ ๊ทธ๋Œ€๋กœ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

์™œ๋ƒํ•˜๋ฉด, ์ธ์ฆ์„œ ์œ„์กฐ์ž๊ฐ€ ๋ฐœ๊ธ‰์ž์˜ ํ•ด์‹œ๊ฐ’์„ ์ง€์šฐ๊ณ , ์œ„์กฐ๋œ ์ธ์ฆ์„œ๋กœ๋ถ€ํ„ฐ ์–ป์€ ํ•ด์‹œ๊ฐ’์„ ์‚ฝ์ž…ํ•œ๋‹ค๋ฉด, ๊ทธ ๋‹ค์Œ๋ถ€ํ„ฐ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ํ•ด์‹œ๊ฐ’์€ ์œ„์กฐ์ž์˜ ํ•ด์‹œ๊ฐ’๊ณผ ํ•ญ์ƒ ๋™์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์œ„์กฐ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์ฆํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, ์ธ์ฆ์„œ ๋ฐœ๊ธ‰์ž๋Š” ์ตœ์ดˆ๋กœ ์–ป์€ ํ•ด์‹œ๊ฐ’์„ ์•”ํ˜ธํ™”ํ•˜์—ฌ ์ธ์ฆ์„œ์— ์‚ฝ์ž…ํ•˜๋Š”๋ฐ, ์ด ์•”ํ˜ธํ™”๋œ ํ•ด์‹œ๊ฐ’์ด ์ธ์ฆ์„œ์˜ โ€œ์ง€๋ฌธโ€ ํ•ญ๋ชฉ์— ์ €์žฅ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•ด์‹œ๊ฐ’์„ ์ง€๋ฌธ์œผ๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ์•”ํ˜ธํ™” ๋ฐฉ์‹์€ ๊ณต๊ฐœํ‚ค ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค.

๊ณต๊ฐœํ‚ค ์•Œ๊ณ ๋ฆฌ์ฆ˜

๋น„๋Œ€์นญํ‚ค ๋ฐฉ์‹์œผ๋กœ๋„ ๋ถˆ๋ฆฌ๋Š” ์ด ์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ํ‰๋ฌธ์„ ์•”ํ˜ธ๋ฌธ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ‚ค์™€ ์•”ํ˜ธ๋ฌธ์„ ํ‰๋ฌธ์œผ๋กœ ๋ณต์›ํ•˜๋Š” ํ‚ค๊ฐ€ ๋ถ„๋ฆฌ๋œ ์•”ํ˜ธํ™” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ, key ๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ์™€ ๊ฐ™์€ ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

๊ณต๊ฐœํ‚ค ๋ฐฉ์‹์—์„œ๋Š”,

ํ‰๋ฌธ์„ ์•”ํ˜ธ๋ฌธ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•˜๋Š” ํ‚ค๋ฅผ ๊ฐœ์ธ ํ‚ค(Private Key)๋ผ๊ณ  ๋ถ€๋ฅด๊ณ ,
์•”ํ˜ธ๋ฌธ์„ ํ‰๋ฌธ์œผ๋กœ ํ™˜์›ํ•˜๋Š” ํ‚ค๋ฅผ ๊ณต๊ฐœํ‚ค(Public Key)๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

๊ฐœ์ธ ํ‚ค์™€ ๊ณต๊ฐœ ํ‚ค๋Š” ํ•ญ์ƒ ๊ณ ์œ ํ•œ ์Œ์„ ์ด๋ฃจ๋„๋ก, ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋ณด์ฆํ•ฉ๋‹ˆ๋‹ค.

ํ‚ค์˜ ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, ๊ฐœ์ธํ‚ค๋Š” ์™ธ๋ถ€๋กœ ๋…ธ์ถœํ•˜์ง€ ์•Š๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ์ด๊ณ , ๊ณต๊ฐœํ‚ค๋Š” ์™ธ๋ถ€๋กœ ๋…ธ์ถœํ•˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค. ๋น„๋ฐ€๋ฒˆํ˜ธ์˜ ์ผ๋ถ€๋ฅผ ์™ธ๋ถ€๋กœ ๋…ธ์ถœํ•˜๋Š” ํŠน์ง• ๋•Œ๋ฌธ์— ๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™” ๋ฐฉ์‹์œผ๋กœ ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

๋‹ค์‹œ ์ธ์ฆ์„œ๋กœ ๋Œ์•„์™€์„œ, ์ธ์ฆ์„œ ๋ฐœ๊ธ‰์ž๋Š” ์ง€๋ฌธ์„ ์ƒ์„ฑํ•  ๋•Œ, ์‚ฌ์šฉํ–ˆ๋˜ ๊ณต๊ฐœํ‚ค ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ
image

์ง€๋ฌธ์„ ํ‰๋ฌธ ํ•ด์‹œ๊ฐ’์œผ๋กœ ๋ณต์›ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๊ณต๊ฐœํ‚ค๋ฅผ ์ธ์ฆ์„œ์— ์ฒจ๋ถ€ํ•ฉ๋‹ˆ๋‹ค.
image

์ฐธ๊ณ ๋กœ, ์ธ์ฆ์„œ ํ•ญ๋ชฉ์˜ ์ด๋ฆ„์„ ๋ณด๋ฉด, ํ•ด์‹œ๊ฐ’์„ ์•”ํ˜ธํ™”ํ•  ๋•Œ ์‚ฌ์šฉํ–ˆ๋˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ "์„œ๋ช… ์•Œ๊ณ ๋ฆฌ์ฆ˜"์œผ๋กœ ๋ถ€๋ฅด๊ณ  ์žˆ๋Š”๋ฐ, ์ด๋ฅผ ํ†ตํ•ด ์ธ์ฆ์„œ์—์„œ๋Š” ํ•ด์‹œ๊ฐ’์„ ์•”ํ˜ธํ™”ํ•˜๋Š” ๊ฒƒ์„ "๋””์ง€ํ„ธ ์„œ๋ช…"์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„์กฐ ๊ฒ€์ฆ

์ธ์ฆ์„œ ์ˆ˜์ทจ์ธ์ด ์ธ์ฆ์„œ๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๋ฐฉ์‹์€

  1. ์ธ์ฆ์„œ์— ํ‘œ์‹œ๋œ ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ, ์ธ์ฆ์„œ์˜ ํ•ด์‹œ๊ฐ’์„ ๊ตฌํ•ฉ๋‹ˆ๋‹ค.
  2. ์ธ์ฆ์„œ์— ํ‘œ์‹œ๋œ ๊ณต๊ฐœํ‚ค ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๊ณต๊ฐœํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, ์ง€๋ฌธ์„ ๋ณต์›ํ•ด์„œ ์›๋ž˜ ํ•ด์‹œ๊ฐ’์„ ๊ตฌํ•ฉ๋‹ˆ๋‹ค.

์ด ๋‘ ํ•ด์‹œ๊ฐ’์ด ๊ฐ™๋‹ค๋ฉด, ์ธ์ฆ์„œ๋Š” ๋ฐœ๊ธ‰์‹œ์ ๋ถ€ํ„ฐ ์ง€๊ธˆ๊นŒ์ง€ ๋ณ€์กฐ๋œ ์ ์ด ์—†๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ๋‹ค์‹œ ์œ„์กฐ ๊ฐ€๋Šฅ์„ฑ์— ๋Œ€ํ•ด ์•Œ์•„ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์œ„์กฐ์ž๊ฐ€ ์ธ์ฆ์„œ๋ฅผ ์œ„์กฐํ•œ ๋‹ค์Œ, ์œ„์กฐ๋œ ์ธ์ฆ์„œ์˜ ํ•ด์‹œ๊ฐ’์„ ๊ตฌํ•˜๊ณ , ์ด๋ฅผ ์ž์‹ ๋งŒ์˜ ๊ฐœ์ธํ‚ค๋กœ ์„œ๋ช…ํ•œ ๋‹ค์Œ, ์œ„์กฐ ๊ฐœ์ธํ‚ค์™€ ์Œ์„ ์ด๋ฃจ๋Š” ์œ„์กฐ ๊ณต๊ฐœํ‚ค๋ฅผ ์ธ์ฆ์„œ์— ๋„ฃ์œผ๋ฉด, ์—ฌ์ „ํžˆ ์œ„์กฐ ๊ฐ€๋Šฅ์„ฑ์€ ์—ด๋ ค ์žˆ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐœ๊ธ‰์ž์˜ ๊ถŒ์œ„

์‚ฌ์‹ค, SSL ์ธ์ฆ์„œ๋ฅผ ํ†ตํ•œ ์ธ์ฆ ์‹œ์Šคํ…œ์„ ๋– ๋ฐ›์น˜๋Š” ํ•ต์‹ฌ์€ ์ธ์ฆ์„œ ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ, ๋ฐœ๊ธ‰์ž์˜ ๊ถŒ์œ„๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ์‹ ๋ขฐ ๋ฐ›๋Š” ๋ฃจํŠธ ์ธ์ฆ ๊ธฐ๊ด€์ด ๋ฐœํ–‰ํ•œ ๋ฃจํŠธ ์ธ์ฆ์„œ์˜ ์œ ํ†ต ๊ฒฝ๋กœ๋Š” ๋งค์šฐ ์งง์Šต๋‹ˆ๋‹ค.
์—ฌ๊ธฐ์—์„œ, ์‹ ๋ขฐ๋ž€ ๋ฐœ๊ธ‰์ž์™€ ์šด์˜์ฒด์ œ ์‚ฌ์ด์˜ ์‹ ๋ขฐ๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค.

์‹ ๋ขฐ๋ฐ›๋Š” ๊ธฐ๊ด€๋“ค์€ ์ž์‹ ๋“ค์˜ ๋ฃจํŠธ ์ธ์ฆ์„œ๊ฐ€ ์˜ค์—ผ๋˜์ง€ ์•Š์€ ์ฑ„ ์šด์˜์ฒด์ œ์—๊ฒŒ ์ „๋‹ฌ๋จ์„ ๋ณด์ฆํ•˜๊ณ , ์šด์˜์ฒด์ œ๋Š” ์ „๋‹ฌ ๋ฐ›์€ ๋ฃจํŠธ ์ธ์ฆ์„œ๊ฐ€ ์œ„์กฐ๋˜์ง€ ์•Š์Œ์„ ๋ณด์ฆํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฃจํŠธ ๋ฐœ๊ธ‰์ž๋“ค์€ ๊ทธ ์šด์˜์ฒด์ œ์—์„œ ์‹คํ–‰๋˜๋Š” ๋ชจ๋“  ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ๋ถ€ํ„ฐ ์ง€์ง€๋ฅผ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

โ€œ๋‹ˆ๋“ค์ด ๋ฐœ๊ธ‰ํ•œ ๊ฒƒ์€ ๋ฏฟ์„ ์ˆ˜ ์žˆ์ง€โ€

์ฆ‰, ์ด๋ ‡๊ฒŒ ์œ ํ†ต๋œ ๋ฃจํŠธ ์ธ์ฆ์„œ์— ๋ช…์‹œ๋œ ๋ฐœ๊ธ‰์ž๋งŒ์ด ๋ฐœ๊ธ‰์ž๋กœ์„œ์˜ ๊ถŒ์œ„๋ฅผ ๊ฐ–๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ธ์ฆ์„œ์— ์‚ฝ์ž…๋œ ์ง€๋ฌธ, ๊ณต๊ฐœํ‚ค, ๊ณต๊ฐœํ‚ค ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋ˆ„๊ตฌ๋‚˜ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ด๋“ค์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง€๋ฌธ์„ ์›๋ž˜์˜ ํ•ด์‹œ๊ฐ’์œผ๋กœ ๋ณต์›ํ•˜๋Š” ๊ฒƒ๋„ ๋งค์šฐ ์‰ฌ์šด ์ผ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜, ์ด ๋ชจ๋“  ๊ฒƒ๋“ค์„ ๋‹ค ์•Œ ์ˆ˜ ์žˆ์–ด๋„ ๋”ฑ ํ•˜๋‚˜ ์•Œ ์ˆ˜ ์—†๋Š” ๊ฒƒ์ด ์žˆ๋Š”๋ฐ, ๊ทธ๊ฒƒ์€ ์„œ๋ช…์— ์‚ฌ์šฉ๋œ "๊ฐœ์ธํ‚ค"์ž…๋‹ˆ๋‹ค.

๊ณต๊ฐœํ‚ค ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ํ‰๋ฌธ-๊ฐœ์ธํ‚ค-์•”ํ˜ธ๋ฌธ-๊ณต๊ฐœํ‚ค์˜ ์กฐํ•ฉ์ด ์œ ์ผํ•จ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด,
์•„๋ž˜์˜ ์œ„์กฐ๋Š” ๊ถŒ์œ„ ์žˆ๋Š” ๋ฃจํŠธ ๋ฐœ๊ธ‰์ž์˜ ์›๋ž˜ ๊ณต๊ฐœํ‚ค๋กœ ์ธํ•ด ์œ„์กฐ๊ฐ€ ๊ธˆ๋ฐฉ ๋“œ๋Ÿฌ๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์œ„์กฐ์ž๊ฐ€ ์ธ์ฆ์„œ๋ฅผ ์œ„์กฐํ•œ ๋‹ค์Œ, ์œ„์กฐ๋œ ์ธ์ฆ์„œ์˜ ํ•ด์‹œ๊ฐ’์„ ๊ตฌํ•˜๊ณ , ์ด๋ฅผ ์ž์‹ ๋งŒ์˜ ๊ฐœ์ธํ‚ค๋กœ ์„œ๋ช…ํ•œ ๋‹ค์Œ, ์œ„์กฐ ๊ฐœ์ธํ‚ค์™€ ์Œ์„ ์ด๋ฃจ๋Š” ์œ„์กฐ ๊ณต๊ฐœํ‚ค๋ฅผ ์ธ์ฆ์„œ์— ๋„ฃ์œผ๋ฉด, ์—ฌ์ „ํžˆ ์œ„์กฐ ๊ฐ€๋Šฅ์„ฑ์€ ์—ด๋ ค ์žˆ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Š”, ์œ„์กฐ์ž๋Š” ์ธ์ฆ์„œ ์ž์ฒด๋ฅผ ์œ„์กฐํ•  ์ˆ˜ ์žˆ์„ ์ง€๋Š” ๋ชฐ๋ผ๋„, ๊ทธ ๊ถŒ์œ„๊นŒ์ง€ ์ฐจ์šฉํ•˜์ง€๋Š” ๋ชปํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

์ด์ „ ๊ธ€์—์„œ ์ž์ฃผ ์–ธ๊ธ‰๋œ [์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฃจํŠธ ์ธ์ฆ๊ธฐ๊ด€] ํด๋”๋Š” ๊ถŒ์œ„ ์žˆ๋Š” ๋ฐœ๊ธ‰์ž๋“ค์˜ ์„œ๋ช… ์ •๋ณด๋ฅผ ๋ชจ์•„ ๋†“๋Š” ๊ณณ์ด๋ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ณ„ ์šด์˜์ฒด์ œ์˜ ๊ด€๋ฆฌ์ž๋Š” ์ž์‹ ์ด ๊ฐœ์ธ์ ์œผ๋กœ ์ง€์ง€ํ•˜๋Š” ๋ฃจํŠธ ๋ฐœ๊ธ‰์ž์˜ ๋ฃจํŠธ ์ธ์ฆ์„œ๋ฅผ ์ด ํด๋”์— ๋“ฑ๋กํ•จ์œผ๋กœ์จ, ๊ทธ ์ธ์ฆ์„œ์— ๊ถŒ์œ„๋ฅผ ๋ถ€์—ฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ทธ ๊ฒฐ๊ณผ๋กœ, ๊ทธ ์šด์˜์ฒด์ œ์—์„œ ์‹คํ–‰๋˜๋Š” ๋ธŒ๋ผ์šฐ์ €๋Š” ๊ทธ ๋ฐœ๊ธ‰์ž๋ฅผ ์‹ ๋ขฐํ•˜๊ฒŒ ๋˜๊ณ , Https ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์ธ์ฆ์„œ๊ฐ€ ๊ทธ ๋ฐœ๊ธ‰์ž๊ฐ€ ๋ฐœํ–‰ํ•œ ๊ฒƒ์ด ํ™•์ธ๋˜๋ฉด, ๊ทธ ์ธ์ฆ์„œ๋ฅผ ์ธ์ •ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

10๊ฐœ์˜ ์ข‹์•„์š”

Identity


์ง์—ญ์„ ํ•˜๋ฉด "์ •์ฒด" ํ˜น์€ "์‹ ์›" ํ˜น์€ "์‹ ๋ถ„"์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โ€œ๋„ˆ๋Š” ๋ˆ„๊ตฌ๋ƒ?โ€
ํ–‰์ธ 1 : โ€œ๋‚œ ์œจ๋„๊ตญ์˜ ์™•์ธ ํ™๊ธธ๋™์ด๋‹คโ€

โ€œ์ € ์‚ฌ๋žŒ ๋ˆ„๊ตฌ์•ผ?โ€
๋ถ€๋ž„ 1 : โ€œ์Ÿค ์œจ๋„๊ตญ์˜ ์™• ํ™๊ธธ๋™์ด์ž–์•„โ€

์ •์ฒด๋ฅผ ๋ฌป๋Š” ์šฐ๋ฆฌ์˜ ์งˆ๋ฌธ์— ๋ˆ„๊ฐ€ ๋‹ต๋ณ€์„ ํ•˜๋“ , ๊ทธ ๋‹ต๋ณ€์€ ๋‹ต๋ณ€์ž์˜ ์ฃผ์žฅ์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ฒ˜์Œ ๋งŒ๋‚œ ๊ธธ๊ฑฐ๋ฆฌ ํ–‰์ธ๋ณด๋‹ค๋Š” ์˜ค๋žœ ์นœ๊ตฌ๋ฅผ ๋” ์‹ ๋ขฐํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜, ๋” ์‹ ๋ขฐํ•˜๋Š” ์นœ๊ตฌ์˜ ๋‹ต๋ณ€์ผ์ง€๋ผ๋„, ์ฃผ์žฅ์— ๋ถˆ๊ณผํ•˜๋‹ค๋Š” ์‚ฌ์‹ค์—๋Š” ๋ณ€ํ•จ์ด ์—†์Šต๋‹ˆ๋‹ค.

Claim

์ด๋ฆ„์ด ํ™๊ธธ๋™์ธ ์‚ฌ๋žŒ์— ๊ด€ํ•œ ์ฃผ์žฅ์€ ์‚ฌ์‹ค ์—ฌ๋Ÿฌ ์„ธ๋ถ€ ์ฃผ์žฅ์˜ ์ง‘ํ•ฉ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์žฅ 1 : โ€œ์ด๋ฆ„์€ ํ™๊ธธ๋™์ž„!!โ€
์ฃผ์žฅ 2 : โ€œ๊ตญ์ ์€ ์œจ๋„๊ตญ์ž„!!โ€
์ฃผ์žฅ 3 : โ€œ๊ณ„๊ธ‰์€ ์™•์ž„!!โ€

๊ฐ ์ฃผ์žฅ์€ ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์œผ๋กœ ๊ตฌ๋ถ„ํ•ด์„œ ํ˜•์‹ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

[์ œ๋ชฉ] : [๋‚ด์šฉ]
์ด๋ฆ„ : ํ™๊ธธ๋™
๊ณ„๊ธ‰ : ์™•
์†Œ์† : ์œจ๋„๊ตญ

์ฃผ์žฅ์„ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ ํ‘œํ˜„ํ•˜๋ฉด, ์ œ๋ชฉ์„ "ํ‚ค"๋กœ, ๋‚ด์šฉ์„ "๊ฐ’"์œผ๋กœ ๋ณด์œ ํ•œ ํ‚ค-๊ฐ’ ์Œ์ด ๊ฐ€์žฅ ์ ์ ˆํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

claim : {
   {key} : {value}
}

Claims Idendity

์–ด๋–ค ์‚ฌ๋žŒ์ด ๊ฐ€์ง„ ์‹ ๋ถ„์€ ์•„๋ž˜์™€ ๊ฐ™์ด ํ‚ค-๊ฐ’ ์Œ์ธ ์ฃผ์žฅ ๊ฐ์ฒด์˜ ์ง‘ํ•ฉ์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์™• ์‹ ๋ถ„ : {
    "์ด๋ฆ„":"ํ™๊ธธ๋™", 
    "์˜ํ† ":"์œจ๋„๊ตญ"
}

์ฃผ์žฅ์˜ ์ง‘ํ•ฉ์œผ๋กœ ํ‘œํ˜„๋œ ์‹ ๋ถ„์„ "์ฃผ์žฅ ์‹ ๋ถ„(Claims Identity)"์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
์ฃผ์žฅ ์‹ ๋ถ„์€ ์ฃผ์žฅ์ด๋ผ๋Š” ์ •๋ณด ๋งค๊ฐœ์ฒด๋ฅผ ํ†ตํ•ด ํ‘œํ˜„๋œ ์‹ ๋ถ„์ด๋ผ๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

Principal

์ฃผ์žฅ์˜ ๋Œ€์ƒ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒƒ์œผ๋กœ ์ฃผ์žฅ์˜ "์ฃผ์ฒด(Pricipal)"์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
์ฃผ์žฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์•„๋ž˜์˜ ๋ฌธ์žฅ์—์„œ ๋ฌธ์žฅ์˜ ์ฃผ์–ด๊ฐ€ ์ฃผ์ฒด์ž…๋‹ˆ๋‹ค.

๋‚œ ์œจ๋„๊ตญ์˜ ์™•์ธ ํ™๊ธธ๋™์ด๋‹ค

์Ÿค ์œจ๋„๊ตญ์˜ ์™• ํ™๊ธธ๋™์ด์ž–์•„

Claims Principal

์ฃผ์žฅ ์ฃผ์ฒด๋Š” ์ฃผ์žฅ๋“ค์˜ ์ง‘ํ•ฉ์œผ๋กœ ํ‘œํ˜„๋œ ์ฃผ์ฒด์ž…๋‹ˆ๋‹ค.
์ด ์ง‘ํ•ฉ์— ํฌํ•จ๋œ ์ฃผ์žฅ๋“ค์€ ๋ชจ๋‘ ์ฃผ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

์™ธํ˜•์ ์œผ๋กœ๋Š” ์•ž์„œ ๋ณด์•˜๋˜ ์ฃผ์žฅ ์‹ ๋ถ„(Claims Idendity)๊ณผ ์™„์ „ํžˆ ๋™์ผํ•œ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.

๋‹ค๋งŒ, ์ฃผ์žฅ ์‹ ๋ถ„์€ ์ฃผ์žฅ ์ง‘ํ•ฉ์„ "์‹ ๋ถ„(Idendity)"์œผ๋กœ ๋ฐ”๋ผ๋ณด๊ณ , ์ฃผ์žฅ ์ฃผ์ฒด(Claims Principal)๋Š” ๊ทธ "์‹ ๋ถ„"์˜ ์†Œ์œ ์ž(Principal)๋กœ ๋ฐ”๋ผ๋ณธ๋‹ค๋Š” ๊ด€์ ์  ์ฐจ์ด๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ ์ฃผ์ฒด๊ฐ€ ํ•˜๋‚˜์˜ ์‹ ๋ถ„๋งŒ ๊ฐ€์ง„๋‹ค๋ฉด, ์ฃผ์žฅ ์ฃผ์ฒด - ์ฃผ์žฅ ์‹ ๋ถ„ - ์ฃผ์žฅ ์ง‘ํ•ฉ์€ ๋ชจ๋‘ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

ํ™๊ธธ๋™ ์ฃผ์ฒด : 
{
    ์ด๋ฆ„ : ํ™๊ธธ๋™,
    ๊ณ„๊ธ‰ : ์™•,
    ๊ตญ์  : ์œจ๋„๊ตญ,
}

๊ด€๊ณ„

์ง€๊ธˆ๊นŒ์ง€ ๋“ฑ์žฅํ–ˆ๋˜ ์‹ ๋ถ„๊ณผ ๊ด€๋ จํ•œ ๊ฐœ๋…๋“ค์„ ๊ฐ์ฒด๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฃผ์ฒด๋Š” ๊ฐœ๋…์ ์œผ๋กœ ํ•˜๋‚˜ ์ด์ƒ์˜ ์‹ ๋ถ„์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

class Principal
{
    List<Identity> Identities;
}

class Identity 
{
    List<Claim> Claims;
}

์ฃผ์žฅ ์ฃผ์ฒด๋Š”,

๋Œ€ํ‘œ ์‹ ๋ถ„์„ ๋‚˜ํƒ€๋‚ด๋Š” "์ฃผ์žฅ ์ง‘ํ•ฉ"๊ณผ,
์ถ”๊ฐ€์ ์ธ ์‹ ๋ถ„์„ ๋‚˜ํƒ€๋‚ด๋Š” "์ฃผ์žฅ ์‹ ๋ถ„ ์ง‘ํ•ฉ"์˜ ํ•ฉ์„ฑ์ฒด๋กœ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class ClaimsPrincipal
{
    List<Claims> Claims;
    List<ClaimsIdentity> Identities;
}
class ClaimsIdendity : Identity
{
    List<Claim> Claims;
}

class Claim
{
    object Key;
    object Value;
}

Role ์—์„œ Claim ์œผ๋กœ์˜ ์ „ํ™˜

Asp.Net ์—์„œ๋Š” ์ธ์ฆ๊ณผ ๊ด€๋ จํ•˜์—ฌ ๊ณผ๊ฑฐ์—๋Š” Role ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํ–ˆ์œผ๋‚˜, ์‹œ๋Œ€์  ํ๋ฆ„์ด Claim ๊ธฐ์ค€์œผ๋กœ ์˜ฎ๊ฒจ ๊ฐ€๋ฉด์„œ, Asp.Net Core ๋ถ€ํ„ฐ๋Š” Claim ๊ธฐ์ค€์œผ๋กœ ์ธ์ฆ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ณ€ํ™”์˜ ๊ณผ์ • ์ค‘์— ๋‹ท๋„ท์˜ ์ธ์ฆ์— ์‚ฌ์šฉ๋œ Role ๊ณผ ๊ด€๋ จํ•œ ๊ฐ์ฒด๋“ค์ด Claim ๊ณผ ๊ด€๋ จํ•œ ๊ฐ์ฒด๋“ค (ClaimsPrincipal ๋˜๋Š” ClaimsIdentity) ๋กœ ๋Œ€์ฒด๋œ ๋“ฏ ๋ณด์ž…๋‹ˆ๋‹ค.

๋‹ท๋„ท์˜ ์œ ๊ตฌํ•œ ์—ญ์‚ฌ๋ฅผ ๊ณ„์† ์ง€์ผœ๋ณด์ง€ ์•Š์•˜๋‹ค๋ฉด, ๋‹ท๋„ท์˜ ์ธ์ฆ๊ณผ ๊ด€๋ จํ•œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์— ํฌํ•จ๋œ ๋ ˆ๊ฑฐ์‹œ ์ •๋ณด๋‚˜, ์ตœ์‹  ๋ฌธ์„œ์— ํฌํ•จ๋œ ๋ ˆ๊ฑฐ์‹œ ํ‚ค์›Œ๋“œ๋ฅผ ์†Ž์•„ ๋‚ด๋Š” ๊ฒƒ์€ ๊ฒฐ์ฝ” ์‰ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํŠนํžˆ, 2019 ๋…„๋ถ€ํ„ฐ ๋‹ท๋„ท์„ ์‹œ์ž‘ํ•œ ์ €๋Š” ๊ทธ๋Ÿฌํ•œ ๊ฐ๊ฐ์ด ์ „ํ˜€ ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ท๋„ท ๋ฌธ์„œ๋งŒ์œผ๋กœ ๋‹ท๋„ท์˜ ์ธ์ฆ ์‹œ์Šคํ…œ์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ๊ฒฐ์ฝ” ์‰ฝ์ง€๋Š” ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜, ์‹œ๋Œ€์  ๋ณ€ํ™”๋กœ ์ธํ•ด ์ธ์ฆ์— ์‚ฌ์šฉ๋œ ๋‹ท๋„ท ๊ฐ์ฒด๋“ค์—๋„ ๋ณ€ํ™”๊ฐ€ ์žˆ์—ˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ณ  ๋‚˜๋‹ˆ, ๋‹ท๋„ท ๋ฌธ์„œ๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์กฐ๊ธˆ์€ ์ˆ˜์›”ํ•ด์กŒ์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€์€ ๊ทธ Claim ์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

JWT Claims

์ฃผ์žฅ ๊ธฐ๋ฐ˜์˜ ์ธ์ฆ (์‹ ๋ถ„ ํ™•์ธ ์ฒด๊ณ„)์ด ์‹œ๋Œ€์  ํ๋ฆ„์ด๋ผ๊ณ  ์–ธ๊ธ‰ํ–ˆ๋Š”๋ฐ, ๊ทธ ํ๋ฆ„์˜ ๊ฐ€์žฅ ํฐ ์›์ธ์€ ์ฃผ์žฅ์ด ๋” ์œ ์—ฐํ•œ ์ •๋ณด ๋งค๊ฐœ์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์œ ์—ฐ์„ฑ์—๋Š” ๊ณผ๊ฑฐ์— ์‚ฌ์šฉํ•˜๋˜ Role ์ •๋ณด๋„ ์ฃผ์žฅ์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๊ธฐ์—, ํ•˜๋ฐฉ ํ˜ธํ™˜์„ฑ ์œ ์ง€๋ผ๋Š” ์žฅ์ ๋„ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ ์ธ์ฆ ์ •๋ณด ๋งค๊ฐœ์ฒด๋กœ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” JWT ๋„ ์ฃผ์žฅ์„ ๊ธฐ๋ฐ˜ํ•œ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.

RFC 7519 - JSON Web Token (JWT) (ietf.org)

์ด ๋ฌธ์„œ์—๋Š” ํ‘œ์ค€ JWT์— ํฌํ•จ๋˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ฃผ์žฅ์„ ์‚ฌ์ „์— ์ •์˜ํ•ด ๋†“์•˜์Šต๋‹ˆ๋‹ค.

  1. Registered Claim Names

๋ณด์‹œ๋‹ค์‹œํ”ผ, JWT ์˜ ๋ฉ”ํƒ€ ์ •๋ณด์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

JWT ํ‘œ์ค€์„ ์ค€์ˆ˜ํ•˜๋Š” ํ† ํฐ์€ ์œ„์— ๋‚˜์—ด๋œ ๋ฉ”ํƒ€ ์ •๋ณด๋ฅผ ํ† ํฐ์— ํฌํ•จ์‹œํ‚ฌ ๋•Œ๋Š” ๋“ฑ๋ก๋œ ์ฃผ์žฅ ์ œ๋ชฉ(Registered Claim Names)์„ ์“ฐ๋ผ๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

ํ‘œ์ค€์— ๋“ฑ๋ก๋œ ์ฃผ์žฅ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ดํŽด ๋ณด๋ฉด,

4.1.1. โ€œissโ€ (Issuer) Claim
The โ€œissโ€ (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific. The โ€œissโ€ value is a case-sensitive string containing a StringOrURI value. Use of this claim is OPTIONAL.

4.1.1 iss(ํ† ํฐ ๋ฐœํ–‰์ž) ์ฃผ์žฅ
iss ์ฃผ์žฅ์€ JWT ๋ฅผ ๋ฐœํ–‰ํ•œ ์ฃผ์ฒด ์‹๋ณ„์šฉ์ด๋‹ค. ์ด ์ฃผ์žฅ์€ ๋ณดํ†ต ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋”ฐ๋ผ ๋‹ฌ๋ฆฌ ์ทจ๊ธ‰๋œ๋‹ค. ์ด ์ฃผ์žฅ์˜ ๊ฐ’์€ ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ณ„ํ•˜๋Š” ๋ฌธ์ž์—ด๋กœ, ๋ฌธ์ž์—ด ๋˜๋Š” Uri ๊ฐ’์ด๋‹ค. ์ด ์ฃผ์žฅ์„ ํ† ํฐ์— ํฌํ•จํ•˜๋Š” ๊ฒƒ์€ ์„ ํƒ์ ์ด๋‹ค.


์ฃผ์žฅ, ์‹ ๋ถ„, ์ฃผ์ฒดโ€ฆ ์ด๋Ÿฌํ•œ ๊ฐœ๋…์ด C# ์œ ์ €์—๊ฒŒ๋Š” ์–ด๋–ค ์†Œ์šฉ์ด ์žˆ์„๊นŒ์š”?

HttpContext.User

Asp.Net Core ์˜ ์ธ์ฆ/์ธ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด๋Š” HttpContext.User ์— ๋‹ด๊ธด ์ •๋ณด๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ธ์ฆ๊ณผ ์ธ๊ฐ€๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ, ์ธ์ฆ/์ธ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด์— ๋Œ€ํ•ด ์งค๋ง‰ํ•˜๊ฒŒ ์‚ดํŽด๋ณด๋ฉด,

  • ์ธ์ฆ ๋ฏธ๋“ค์›จ์–ด๋Š” ์‹œํฌ๋ฆฟ(๋น„๋ฐ€ ๋ฒˆํ˜ธ ์ž…๋ ฅ ๋“ฑ)์œผ๋กœ ์ธ์ฆ์„ ํ†ต๊ณผํ•œ ์‚ฌ์šฉ์ž์˜ ์ •๋ณด๋ฅผ ์ด ์†์„ฑ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์„ค์ •์— ๋”ฐ๋ผ ์†์„ฑ์˜ ๊ฐ’์€ ์ฟ ํ‚ค ๋˜๋Š” JWT ํ† ํฐ ๋“ฑ๊ณผ ๊ฐ™์€ ์‹ค๋ฌผ ์ €์žฅ ๋งค์ฒด์— ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

  • ์ธ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด๋Š” ์ด ์†์„ฑ์— ์ €์žฅ๋œ ์‚ฌ์šฉ์ž์˜ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํŠน์ • ์—”๋“œํฌ์ธํŠธ์— ๋Œ€ํ•œ ์ ‘๊ทผ ํ—ˆ์šฉ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด ์†์„ฑ์˜ ์ž๋ฃŒํ˜•์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

public abstract ClaimsPrincipal User { get; set; }

์–ด๋””์„œ ๋งŽ์ด ๋ณธ ๊ฒƒ์ด์ฃ ?

ClaimsPrincipal ๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง€๋Š” ๋Œ€ํ‘œ์ ์ธ ์†์„ฑ ๋‘๊ฐœ๋ฅผ ์‚ดํŽด๋ณด๋ฉด,

public virtual IEnumerable<Claim> Claims { get; }
public virtual IEnumerable<ClaimsIdentity> Identities { get; }

์ด๋“ค๋„ ๋งŽ์ด ๋ณธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด, Asp.Net Core๋Š” ์ฃผ์žฅ ๊ธฐ๋ฐ˜ - ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋‹ด๋Š” ์ปจํ…Œ์ด๋„ˆ๋กœ ์ฃผ์žฅ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ด ๊ฐ์ฒด์— ํฌํ•จ๋œ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ - ์ธ์ฆ/์ธ๊ฐ€๋ฅผ ์ˆ˜ํ–‰ํ•จ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ฃผ์žฅ ๊ธฐ๋ฐ˜ ์ธ์ฆ์„ ์ง€์›ํ•˜๋Š” ๊ฐ์ฒด๋“ค์€ ์‚ฌ์‹ค ์•„๋ž˜์˜ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ๋‹ค ๋ชจ์•„์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

image

์ธ์ฆ ์„ค์ •

Asp.Net Core ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ, ๋งˆ์ง€๋ง‰์— ๋‚˜ํƒ€๋‚˜๋Š” ์ถ”๊ฐ€ ์„ค์ • ์ฐฝ์˜ [์ธ์ฆ ์œ ํ˜•] ํ•ญ๋ชฉ์€
image

์ธ์ฆ๊ณผ ๊ด€๋ จํ•œ ์ œ๋ฐ˜ ๋ผˆ๋Œ€ ์ฝ”๋“œ๋ฅผ ํ”„๋กœ์ ํŠธ์— ์‚ฝ์ž… ์‹œํ‚ต๋‹ˆ๋‹ค.

์ด ๋ผˆ๋Œ€ ์ฝ”๋“œ๋“ค์€ ๊ฒฐ๊ตญ์—” HttpContext.User ๋กœ ๊ท€๊ฒฐ๋˜๊ธฐ์—, ์ฃผ์žฅ ๊ฐ์ฒด๋ฅผ ๊ธฐ๋ฐ˜ํ•ฉ๋‹ˆ๋‹ค.
Asp.Net Core ์˜ ์ธ์ฆ ์œ ํ˜• ์ฒ˜๋ฆฌ์ž๊ฐ€ ๋’ค์—์„œ ๋ฌด์Šจ ์ผ์„ ๋ฒŒ์ด๊ฑด, ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ž˜ ์ •๋ฆฌํ•ด์„œ ClaimsPrincipal ๊ฐ์ฒด๋กœ ์ œ๊ณตํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.


Identity

๋‹ค์‹œ ์ฒซ ์ œ๋ชฉ์œผ๋กœ ๋Œ์•„ ์™”์Šต๋‹ˆ๋‹ค.

ํ˜น์ž๋Š” ๊ทธ๋Ÿฐ ๋ง์„ ํ•ฉ๋‹ˆ๋‹ค.

โ€œ์›น์•ฑ์€ ๋ญโ€ฆ ๋กœ๊ทธ์ธ๊ณผ ๊ธฐํƒ€ ๋“ฑ๋“ฑ์ด์ง€โ€

๊ทธ๋งŒํผ ์‚ฌ์šฉ์ž ์ธ์ฆ๊ณผ ์ธ์ฆ์„ ์œ„ํ•œ ์‚ฌ์šฉ์ž ์ •๋ณด ๊ด€๋ฆฌ๊ฐ€ ํž˜๋“ค๋‹ค๋Š” ์˜๋ฏธ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž (์ธ์ฆ) ์ •๋ณด๋Š” ์•…์˜์  ๊ณต๊ฒฉ์˜ ์ฃผ ๋Œ€์ƒ์ด๋ผ, ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง ๋ชป์ง€ ์•Š์€ ๋ณด์•ˆ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๊ณ , ๋˜ํ•œ ์šฐ๋ฆฌ๋‚˜๋ผ์˜ ๋ฒ•๋„ ์‚ฌ์šฉ์ž์˜ ๊ฐœ์ธ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์›น ์‚ฌ์ดํŠธ๋Š” ์•”ํ˜ธํ™” ํ†ต์‹  = https ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ฐ•์ œํ•  ์ •๋„์ด๋‹ˆ, User ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๋Š” ์ˆœ๊ฐ„ ๋ฒ•์ ์ธ ๋ฌธ์ œ๋„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ท๋„ท๋„ ์‚ฌ์šฉ์ž ์ •๋ณด ๊ด€๋ฆฌ์— ๊ด€ํ•œ ๋งŽ์€ ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ์ด๋Ÿฌํ•œ ์†”๋ฃจ์…˜์— ๊ด€ํ•œ ๋ฌธ์„œ๋“ค์˜ ๊ณตํ†ต์ ์€ โ€œIdendityโ€ ๋ผ๋Š” ํ‚ค์›Œ๋“œ๊ฐ€ ๋ผ์–ด ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.
Asp.Net Core ์ž์ฒด์—์„œ ์‚ฌ์šฉ์ž๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด๋“ , OAuth ๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋“ , ์ด ๋‹จ์–ด๊ฐ€ ํ•ญ์ƒ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜, ์ด๋“ค ๋ฌธ์„œ์— ๋‚˜ํƒ€๋‚œ "Identity"๋ผ๋Š” ๋‹จ์–ด๋Š”, ๋‹จ์ˆœํžˆ ํŠน์ • ๊ฐ์ฒด๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, ์ธ์ฆ๊ณผ ๊ด€๋ จํ•œ ํ†ตํ•ฉ ์‹œ์Šคํ…œ, ํ˜น์€ ํ†ตํ•ฉ ์‹œ์Šคํ…œ์„ ์ œ๊ณตํ•˜๋Š” ์™ธ๋ถ€ ์„œ๋น„์Šค๋ฅผ ์ง€์นญํ•  ๋•Œ๊ฐ€ ๋งŽ์€๋ฐ, ์—ฌ๊ธฐ์—๋Š” ์ˆ˜๋งŽ์€ ๊ฐœ๋…๊ณผ ๊ฐ์ฒด๊ฐ€ ๋‚œ๋ฌดํ•˜๊ณ , ๋•Œ๋กœ๋Š” ์œ ๋ฃŒ ์„œ๋น„์Šค๋ฅผ ์ ๊ทน ์ถ”์ฒœํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋‹ท๋„ท์˜ ์ธ์ฆ ์†”๋ฃจ์…˜์„ ๋งˆ์Šคํ„ฐํ•˜๊ธฐ๋ฅผ ์›ํ•˜์‹ ๋‹ค๋ฉด, ์•„๋ž˜์˜ ๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ๋ฅผ ์ ๊ทน ์‚ฌ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

C# Indentity

๊ทธ๋Ÿฌ๋‚˜, ์‚ฌ์šฉ์ž ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด ์ข€ ๋” ํ˜„์‹ค์ ์ด๊ณ  ๊ฒฝ์ œ์ ์ธ ๋ฐฉ๋ฒ•์„ ์ฐพ์œผ์‹ ๋‹ค๋ฉด, ์•„๋ž˜์— ๋‚˜์—ด๋œ ์ˆœ์„œ ๋Œ€๋กœ ํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰์„ ํ•˜์‹ค ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

C# HttpContext.User
C# Authentication Middleware,
C# SignIn
C# SignOut
C# Authentication Scheme,
C# Authorization Middleware
C# Authorization Policy
C# Cookie vs Session

13๊ฐœ์˜ ์ข‹์•„์š”

๋‚ด์šฉ์ด ์ž˜ ์ •๋ฆฌ๋˜์„œ ํ•œ๋ฒˆ์— ์ฝํ˜”์–ด์š”:+1:

3๊ฐœ์˜ ์ข‹์•„์š”

Entity Framework Core

๋‹ท๋„ท์˜ ๋Œ€ํ‘œ์ ์ธ Full-ORM(Object Relational Mapper) ์œผ๋กœ, ๋‹ท๋„ท ๊ฐœ๋ฐœ ๋„๊ตฌ ์‚ฌ์šฉ์ž๋ผ๋ฉด ๋ฐ˜๋“œ์‹œ ํ•œ ๋ฒˆ ์€ ์‚ฌ์šฉํ•  ์ผ์ด ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.

Entity

๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์˜๋ฏธ ์žˆ๋Š” โ€œ์„ธํŠธ(Set)โ€ ๋‹จ์œ„๋กœ ๋ฌถ์–ด์„œ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
์ด๋ ‡๊ฒŒ ํ•˜๋‚˜๋กœ ๋ฌถ์ธ ๋ฐ์ดํ„ฐ ๋ฌถ์Œ์„ "์—”ํ‹ฐํ‹ฐ(Entity)"๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

ํ•˜๋‚˜์˜ ์—”ํ‹ฐํ‹ฐ๋Š” ๋‹ค๋ฅธ ์—”ํ‹ฐํ‹ฐ์™€ ์—ฐ๊ด€๋˜์–ด(Assoicated) ์žˆ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋ฅผ (์—”ํ‹ฐํ‹ฐ) ๊ด€๊ณ„(Relatioinship)์ด๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ์ด ๊ด€๊ณ„๋Š” ๋ณดํ†ต ์ข…์†์„ฑ(Princial-Dependent)๊ณผ ๋ณต์ˆ˜์„ฑ(Multiplicity, ํ˜น์€ Cardinality)์„ ํ†ตํ•ด ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.

์—”ํ‹ฐํ‹ฐ ๊ด€๊ณ„๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ผ๋ฐ˜์ ์ธ ๊ฐ์ฒด (์ดํ•˜ "์˜ค๋ธŒ์ ํŠธ"๋ผ ์นญํ•จ) ์‚ฌ์ด์˜ ๊ด€๊ณ„์™€๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

์˜ค๋ธŒ์ ํŠธ๋Š” ๋ณดํ†ต ์ƒ์†(Inheritance)๊ณผ ๊ฒฐํ•ฉ(Association)์ด๋ผ๋Š” ๋‘ ๊ฐ€์ง€์˜ ๊ด€๊ณ„๋ฅผ ๋งบ๊ณ , ๊ฒฐํ•ฉ์€ ๋‹ค์‹œ, ํ•ฉ์„ฑ(Composition)๊ณผ ์ง‘์„ฑ(Aggregation)์ด๋ผ๋Š” ํŠน์ด ์ผ€์ด์Šค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹คโ€ฆ

์šฐ๋ฆฌ์˜ ์ฝ”๋“œ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ์ƒ์„ฑํ•œ ์ธ์Šคํ„ด์Šค๋“ค์€ ์˜ค๋ธŒ์ ํŠธ์˜ ๊ด€๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฐ˜๋ฉด, ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ๋ฌถ์Œ์€ ์—”ํ‹ฐํ‹ฐ ๊ด€๊ณ„๋ฅผ ๋งบ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ๊ฐ€ ์ €์žฅ์†Œ์˜ ๋ฐ์ดํ„ฐ์™€ ํ˜‘์—…ํ•˜๊ธฐ ์œ„ํ•ด๋Š”, ์˜ค๋ธŒ์ ํŠธ์˜ ๊ด€๊ณ„๋ฅผ ์—”ํ‹ฐํ‹ฐ ๊ด€๊ณ„๋กœ ๋ณ€ํ™˜(ํ•˜๊ฑฐ๋‚˜, ํ˜น์€ ๊ทธ ๋ฐ˜๋Œ€๋กœ ๋ณ€ํ™˜)ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ด๋ฅผ ์˜ค๋ธŒ์ ํŠธ-๊ด€๊ณ„(Object-Relationship) ๋งตํ•‘์ด๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
(์ดํ•˜ "๊ด€๊ณ„ ๋งตํ•‘"์œผ๋กœ ์ค„์—ฌ์„œ ๋ถ€๋ฆ…๋‹ˆ๋‹ค)

์ด๋Ÿฌํ•œ ๋งตํ•‘์„ ๋„์™€ ์ฃผ๋Š” ๋„๊ตฌ๋ฅผ ORM(Object Relational Mapper) ๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
ORM์ด ํ•˜๋Š” ์—ญํ• ์€

  • ๋ฉ”๋ชจ๋ฆฌ์— ์กด์žฌํ•˜๋Š” ์˜ค๋ธŒ์ ํŠธ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ์ดํ„ฐ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ €์žฅ์†Œ์— ์ €์žฅํ•˜๊ฑฐ๋‚˜,
  • ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์˜ค๋ธŒ์ ํŠธ์˜ ์ธ์Šคํ„ด์Šค๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ์— ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

DbContext

EF Core ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ORM ์„ ์ถ”์ƒํ™”ํ•œ ๊ฐ์ฒด์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ, ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์„ธ๊ณ„์—์„œ "์ปจํ…์ŠคํŠธ(Context)"๋ผ๋Š” ๋‹จ์–ด๋Š” ๋ณดํ†ต "๋…๋ฆฝ์ ์ธ ์‹คํ–‰ ์ค„๊ธฐ"๋ผ๋Š” ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ, DbContext ๋Š” ๊ด€๊ณ„ ๋งตํ•‘์ด ์ง„ํ–‰๋˜๋Š” ์‹คํ–‰ ์ค„๊ธฐ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์‚ฌ์‹ค ์ด ๊ฐ์ฒด๋Š” ๋งˆํ‹ด ํŒŒ์šธ๋Ÿฌ์˜ โ€œUnit of Workโ€ ๊ฐœ๋…์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ถ”์ƒ ๋ ˆ์ด์–ด๋กœ, ๊ด€๊ณ„ ๋งตํ•‘, ๊ด€๊ณ„ ๋ณ€ํ™” ์ถ”์ , ์ €์žฅ๊นŒ์ง€ ๋‹จ์ผ ์—…๋ฌด๋กœ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ "๋‹จ์œ„์„ฑ"์€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋กœ์ง ์ฝ”๋“œ์—์„œ ๊ด€๊ณ„ ๋งตํ•‘ ์ฝ”๋“œ๋ฅผ ๋“ค์–ด ๋‚ด์ฃผ๋Š” ์žฅ์ ์ด ์žˆ๋Š” ๋ฐ˜๋ฉด, ๋™์‹œ์„ฑ(Concurrency) ๋ฌธ์ œ์— ์ทจ์•ฝํ•ด์ง€๋Š” ํ๋‹จ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

DbContext์˜ ๋™์‹œ์„ฑ ๋ฌธ์ œ๋Š” ํŠนํžˆ UI ์Šค๋ ˆ๋“œ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋  ๋•Œ ์ž์ฃผ ๋‚˜ํƒ€๋‚˜๊ธฐ์— ํ•ญ์ƒ ํŠน๋ณ„ํ•œ ์ฃผ์˜๋ฅผ ํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์œผ๋กœ, ์ž ์‹œ ํ›„์— ์ž์„ธํžˆ ์–ธ๊ธ‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ด€๊ณ„ ๋งตํ•‘

์˜ค๋ธŒ์ ํŠธ ๊ด€๊ณ„๋ฅผ ์—”ํ‹ฐํ‹ฐ ๊ด€๊ณ„๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ž‘์—…์€ ์‚ฌ์‹ค ๋ช…ํ™•ํ•˜์ง€ ์•Š์œผ๋ฉฐ, ์ •๋‹ต์ด ์—†๋‹ค๊ณ ๋„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด,

์ƒ์† ๊ด€๊ณ„์ธ ๋‘ ์˜ค๋ธŒ์ ํŠธ Parent, Child๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‘ ์˜ค๋ธŒ์ ํŠธ์˜ ์ธ์Šคํ„ด์Šค๋“ค์€ ๊ฐ ์†์„ฑ์— ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๊ฐ’๋“ค์„ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์–ด๋–ป๊ฒŒ ์ €์žฅํ•˜๋ฉด ์ข‹์„ ์ง€ ๊ณ ๋ฏผํ•ด๋ณด์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์‰ฌ์šด ๋ฌธ์ œ์˜€๋‹ค๋ฉด, ์ด ๊ฒฝ์šฐ๋Š” ์–ด๋–จ๊นŒ์š”?

Child๋Š” Heart์™€ ํ•ฉ์„ฑ ๊ด€๊ณ„๋ฅผ, School ๊ณผ๋Š” ์ง‘์„ฑ ๊ด€๊ณ„๋ฅผ ๋งบ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ๋„ ์‰ฌ์šด ๋ฌธ์ œ์˜€๋‹ค๋ฉด, ์ด ๊ฒฝ์šฐ๋Š” ์–ด๋–จ๊นŒ์š”?

Child๋Š” School ์—์„œ๋Š” Student์˜ ์‹ ๋ถ„์„ ๊ฐ–๊ณ , Class์—์„œ Teacher ์™€ ๊ฒฐํ•ฉ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„ ์งˆ๋ฌธ์— ์–ด๋–ค ๋Œ€๋‹ต์„ ํ–ˆ๋”๋ผ๋„, ๊ทธ๊ฒƒ์ด ๋งž๋‹ค ํ˜น์€ ํ‹€๋ฆฌ๋‹ค ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ๊ทธ ๋Œ€๋‹ต์— ์—”ํ‹ฐํ‹ฐ ๊ด€๊ณ„ ์„ค์ •์˜ ํ•ต์‹ฌ ๊ณ ๋ ค ์‚ฌํ•ญ์ธ **ํ‰ํƒ„ํ™”(Normalization)**๊ฐ€ ๊ณ ๋ ค๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ๊ฒฐ์ฝ” ๋งž๋‹ค๊ณ  ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. (ํ‰ํƒ„ํ™”๋Š” ์ด ๊ธ€์˜ ๋ฒ”์œ„๋ฅผ ๋„˜์–ด์„œ๋Š” ๊ฒƒ์ด๋‹ˆ, ๊ฐ์ž ๊ฒ€์ƒ‰ํ•ด๋ณด์‹œ๊ธฐ๋ฅผ)

Convention

ORM์€ ์œ„์˜ ์งˆ๋ฌธ๋“ค์— ๊ฐ€์žฅ ์ ์ •ํ•˜๋‹ค๊ณ  ์—ฌ๊ฒจ์ง€๋Š” ๋‹ต๋ณ€์„ ์ด๋ฏธ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ, ์ด๋ฅผ ๋งตํ•‘ ๊ด€์Šต(Convention)์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ, ๊ด€์Šต ๋งŒ์œผ๋กœ๋„ ๋ฌธ์ œ ์—†๋Š” ๋งตํ•‘์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ๊ด€์Šต์ด ๋ง˜์— ๋“ค์ง€ ์•Š๋Š” ๊ฒฝ์šฐ, ๊ด€์Šต๊ณผ ๋‹ค๋ฅธ ๋งตํ•‘ ๊ทœ์น™์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ, DbContext๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์„ค์ •ํ•œ ๊ทœ์น™์„ ๊ด€์Šต์— ์šฐ์„ ํ•˜์—ฌ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ORM์—๋Š” ๋„๋ฆฌ ์•Œ๋ ค์ง„ ๊ฒฉ์–ธ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์‹œ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.

์ „๋ถ€ ์„ค์ •ํ•˜๋ ค ๋“ค์ง€ ๋งˆ๋ผ

๊ฐ€๊ธ‰์  ๊ด€์Šต์— ๋งž๊ธฐ๊ณ , ๊ด€์Šต๊ณผ ๋‹ค๋ฅธ ๊ทœ์น™์„ ์ตœ์†Œํ™”ํ•˜๋ผ๋Š” ์„ ๋ฐฐ๋‹˜๋“ค์˜ ์กฐ์–ธ์ž…๋‹ˆ๋‹ค.
์šฐ๋ฆฌ์•ผ ๋•กํ์ฃ .

๊ฐœ์ธ์ ์œผ๋กœ, ์ €๋Š” ๊ด€์Šต์„ ์ ์šฉํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ณณ๋งŒ ํ•ด๊ฒฐํ•˜๋Š” ๊ทœ์น™ ๋งŒ์„ ๋ณ„๋„๋กœ ์ •์˜ํ•˜๊ณค ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ๊ด€๋ฆฌ ๋„๊ตฌ

EF Core๋ฅผ ๋‹จ์ˆœํ•œ ORM์ด ์•„๋‹Œ, Full-ORM ์œผ๋กœ ๋ถ€๋ฅด๋Š” ์ด์œ ๋Š”, ๋‹จ์ˆœํ•œ ๋งตํ•‘์„ ๋„˜์–ด์„œ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋„๊ตฌ๋„ ํ•จ๊ป˜ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

EF Core๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ๊ด€๋ฆฌ ๋„๊ตฌ(์ดํ•˜ "๊ด€๋ฆฌ ๋„๊ตฌ"๋กœ ์นญํ•จ)๋Š” ๋‹ท๋„ท ์ฝ”์–ด CLI ๋„๊ตฌ์— ์„ค์น˜ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ "๋ˆ„๊ฒŸ ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ € ์ฝ˜์†”"์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ €๋Š” ์†Œ์Šค ์ฝ”๋“œ์— ๋”ฐ๋ผ ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค์™€ ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค ์ฝ”๋“œ๋ฅผ ๋ณ‘ํ–‰ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋‹ท๋„ท ์ฝ”์–ด CLI ๋„๊ตฌ์— ์„ค์น˜ํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.

๊ด€๋ฆฌ ๋„๊ตฌ๋Š” ์ „์—ญ ์„ค์ •์œผ๋กœ ํ•œ ๋ฒˆ๋งŒ ์„ค์น˜ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ๋งํฌ์— ์„ค์น˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋‚˜์™€ ์žˆ์Šต๋‹ˆ๋‹ค.

EF Core ๋„๊ตฌ ์ฐธ์กฐ(.NET CLI) - EF Core | Microsoft Learn

๊ด€๋ฆฌ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, dotnet ๋“œ๋ผ์ด๋ฒ„๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ โ€œefโ€ ํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , ๊ทธ ๋‹ค์Œ์— ์ด ๋„๊ตฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๋ง๋ถ™์ž…๋‹ˆ๋‹ค.

~\ dotnet ef migrations โ€ฆ
~\ dotnet ef database โ€ฆ

์ฝ”๋“œ ์šฐ์„  vs ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์šฐ์„ 

๊ด€๋ฆฌ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ๊ฐœ๋ฐœ ์ปจํ…์ŠคํŠธ์˜ ๊ตฌ๋ถ„์€ ์•„๋ž˜์™€ ๊ฐ™์ด ํ™•์žฅ๋ฉ๋‹ˆ๋‹ค.

(๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค) ๋””์ž์ธ ํƒ€์ž„ => ์ปดํŒŒ์ผ ํƒ€์ž„ => ๋Ÿฐ ํƒ€์ž„

๊ด€๋ฆฌ ๋„๊ตฌ๋Š” ๋””์ž์ธ ํƒ€์ž„์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ๊ด€๋ฆฌ ๋ฐฉ๋ฒ•์œผ๋กœ ์•„๋ž˜ ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  1. DbContext + ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค => ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์ƒ์„ฑ
    ์†Œ์Šค ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•œ ํด๋ž˜์Šค๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์‹ค๋ฌผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  2. ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค => DbContext + ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค ์ƒ์„ฑ
    ๊ธฐ์กด์— ์ด๋ฏธ ์‚ฌ์šฉ ์ค‘์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋ฆฌ๋ฒ„์Šค ์—”์ง€๋‹ˆ์–ด๋ง์„ ํ†ตํ•ด DbContext์™€ ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ๋ฅผ "์ฝ”๋“œ ์šฐ์„  ์ ‘๊ทผ๋ฒ•"์ด๋ผ๊ณ  ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ๋ฅผ "๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์šฐ์„  ์ ‘๊ทผ๋ฒ•"์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์œ„ ์ ‘๊ทผ๋ฒ•๋“ค์˜ ๊ตฌ๋ถ„์€ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์™€ DbContext ์‚ฌ์ด์— ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•œ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ ์‹œ์—๋งŒ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™๊ธฐํ™” ๋œ ์ดํ›„์—๋Š” ์ฝ”๋“œ ์šฐ์„  ์ ‘๊ทผ๋ฒ•๋งŒ ์ ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ฆ‰, DbContext์™€ ์‹ค๋ฌผ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๊ฐ€ ๋™๊ธฐํ™”๊ฐ€ ์ด๋ค„์ง€๋ฉด, DbConext๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํŒจํ„ด์ด ๊ณ„์†๋ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์šฐ์„  ์ ‘๊ทผ๋ฒ•์„ ์ฑ„ํƒํ•  ๋•Œ๋Š” ์•„๋ž˜์˜ EF ๋„๊ตฌ๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
(Usage ํ•ญ๋ชฉ์„ ๋ณด์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค)
image

์ œ ๊ฐœ์ธ์ ์œผ๋กœ ๊ธฐ์กด์˜ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ์ž‘์—…์„ ํ•œ ๊ฒฝํ—˜์ด ์—†๊ธฐ๋„ ํ•˜๊ณ , ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ ๊ณผ์ • ์ค‘์—๋Š” "์ฝ”๋“œ ์šฐ์„  ์ ‘๊ทผ๋ฒ•"์ด ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์•„๋ž˜์˜ ๋‚ด์šฉ์€ ๋ชจ๋‘ "์ฝ”๋“œ ์šฐ์„  ์ ‘๊ทผ๋ฒ•"์„ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

Blazor Server ์•ฑ

์˜ˆ์ œ๋ฅผ ์œ„ํ•ด ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค์—์„œ ๋ธ”๋ ˆ์ด์ € ์„œ๋ฒ„ ์•ฑ ํƒฌํ”Œ๋ฆฟ์„ ํ†ตํ•ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
์ด ๋•Œ [์ธ์ฆ ์œ ํ˜•]์„ "๊ฐœ๋ณ„ ์ธ์ฆ"์œผ๋กœ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์˜!! : ์˜ˆ์ œ๋กœ ๊ฐœ๋ณ„ ์ธ์ฆ์ด ์„ค์ •๋œ ๋ธ”๋ ˆ์ด์ € ์„œ๋ฒ„์•ฑ์„ ์„ ์ •ํ•œ ์ด์œ ๋Š” DbContext์˜ ๋™์‹œ์„ฑ ๋ฌธ์ œ๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. ์ด ๊ธ€์„ ๋ณด๋ฉด์„œ, ๋”ฐ๋ผ ํ•˜์‹œ๋Š” ๋ถ„๋“ค(์ด ์žˆ์œผ๋ ค๋‚˜โ€ฆ)์€ ์œ„์— ์–ธ๊ธ‰ํ•œ ๋Œ€๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ, ์ œ๊ฐ€ ์ƒ์„ฑํ•œ ํ”„๋กœ์ ํŠธ๋Š” .Net 7.0 ์— ๊ธฐ๋ฐ˜ํ•œ ์•ฑ์ž…๋‹ˆ๋‹ค.
image

๊ตฌํ˜„ ์ œ๊ณต์ž

EF์˜ DbContext ๋Š” ์‚ฌ์‹ค ์ถ”์ƒ ๋ ˆ์ด์–ด์ž…๋‹ˆ๋‹ค.
๊ฐœ๋ฐœ์ž๋Š” ์ถ”์ƒ์„ ํ†ตํ•ด ๊ตฌํ˜„์„ ์†Œ๋น„ํ•˜๊ธฐ๋งŒ ํ•  ๋ฟ์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž๊ฐ€ ์†Œ๋น„ํ•  DbContext ๊ตฌํ˜„์€ ๊ฐ๊ฐ์˜ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์ œํ’ˆ์ด ์ œ๊ณตํ•˜๋Š”๋ฐ, ์ด๋“ค์„ "๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์ œ๊ณต์ž"๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

์•ž์„œ ์ƒ์„ฑํ•œ ํ”„๋กœ์ ํŠธ์—๋Š” ์ด ์ œ๊ณต์ž๋กœ SQL ์„œ๋ฒ„(์ œํ’ˆ)์ด ์„ ํƒ๋˜์—ˆ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

image

SQL ์„œ๋ฒ„ ๊ตฌํ˜„์ด ์„ ํƒ๋œ ์ด์œ ๋Š”, "๊ฐœ๋ณ„ ์ธ์ฆ"์ด ์„ค์ •๋œ ํ”„๋กœ์ ํŠธ๋Š” Asp.Net Core Identity ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํฌํ•จ๋˜๋Š”๋ฐ, ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค๋Š” ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•  ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋กœ localDb(๋ผ๋Š” ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์ œํ’ˆ)๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

โ€œlocalDbโ€ ๋Š” ๋น„์ฃผ์–ผ ์ŠคํŠœ๋””์˜ค๊ฐ€ ์„ค์น˜๋  ๋•Œ ํ•จ๊ป˜ ์„ค์น˜๋˜๋Š” ์†Œํ˜•/๋ฌด๋ฃŒ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์ธ๋ฐ, ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ๊ฐ€ ์ œ๊ณตํ•˜๋Š” SQL Server ์ œํ’ˆ๊ตฐ ์ค‘์— ํ•˜๋‚˜ ์ž…๋‹ˆ๋‹ค. (SQL Server Express ์™€ ๊ฐ™์€ ๋“ฑ๊ธ‰์ž…๋‹ˆ๋‹ค)

์ด๋Ÿฐ ์ด์œ ๋กœ, ApplicationDbContext ์— ๋Œ€ํ•œ ๊ตฌํ˜„์€ SQL Server ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

DbContext ์„ค์ •

EF ๋Š” Full-ORM ์ด๊ธฐ์—, ์„ค์ •๋„ ๋‘ ๊ฐ€์ง€๋กœ ๊ตฌ๋ถ„๋ฉ๋‹ˆ๋‹ค.
ํ•˜๋‚˜๋Š” ์ด ๊ฐ์ฒด์™€ ๋™๊ธฐํ™”๋  ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ๊ด€ํ•œ ์„ค์ •์ด๊ณ , ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๊ด€๊ณ„ ๋งตํ•‘์— ๊ด€ํ•œ ์„ค์ •์ž…๋‹ˆ๋‹ค.

EF ๋Š” ๊ฐ ์„ค์ •์„ ์œ„ํ•œ ํ—ฌํผ ๊ฐ์ฒด๋กœ ์•„๋ž˜์˜ ๋‘ ๊ฐ€์ง€ ์ข…๋ฅ˜์˜ ๊ฐ์ฒด๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  1. ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ๊ด€ํ•œ ์„ค์ •
  • DbContextOptions (DbContextOptions<T>),
  • DbContextOptionsBuilder (DbContextOptionBuilder<T>)
  1. ๊ด€๊ณ„ ๋งตํ•‘์— ๊ด€ํ•œ ์„ค์ •
  • ModelBuilder

์šฐ์„  ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„ค์ •์— ๊ด€ํ•œ ๊ฒƒ์„ ์•Œ์•„ ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„ค์ •

์ƒ์„ฑ๋œ ํ”„๋กœ์ ํŠธ์—์„œ DbContext ์— ๋™๊ธฐํ™”ํ•  ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐธ์กฐํ•  ๋งŒํ•œ ์ฝ”๋“œ๋Š” ์•„๋ž˜์˜ ๋”ฑ ํ•œ ์ค„์ž…๋‹ˆ๋‹ค.

// program.cs ์—์„œ
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));

์œ„์˜ ์ฝ”๋“œ์—์„œ connectionString ์€ appsetting.json ํŒŒ์ผ์— ์žˆ์Šต๋‹ˆ๋‹ค.

// appsettings.json ์—์„œ
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-DbContextSetup-40b054cc-657b-43b9-b8b3-e31ff1786815;Trusted_Connection=True;MultipleActiveResultSets=true"
  },

์œ„ ํŒŒ์ผ์— ์ ์ธ ์—ฐ๊ฒฐ ๋ฌธ์ž์—ด์˜ ๋‚ด์šฉ์€, ๋กœ์ปฌ์—์„œ ์‹คํ–‰ ์ค‘์ธ localDb ์„œ๋ฒ„์˜ โ€œaspnet-DbContextSetupโ€ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์ ‘์†ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
์ด ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์ธ์Šคํ„ด์Šค๊ฐ€ ApplicationDbContext ์— ๋™๊ธฐํ™”๋  ๋Œ€์ƒ์ž…๋‹ˆ๋‹ค.

๋งŒ์•ฝ, ์ด ์ด๋ฆ„์„ ๊ฐ€์ง„ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๊ฐ€ ์„œ๋ฒ„์— ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๋””์ž์ธ ํƒ€์ž„์— ์ด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ, ์—ฐ๊ฒฐ ๋ฌธ์ž์—ด์— ๋‚˜ํƒ€๋‚œ (๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„œ๋ฒ„) ๋กœ๊ทธ์ธ ๊ณ„์ •์ด, ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๊ถŒํ•œ์ด ์—†๋‹ค๋ฉด ๋””์ž์ธ ํƒ€์ž„์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜, localDb ์ œํ’ˆ์€ โ€œ๊ณ„์ • ๊ด€๋ฆฌโ€ ๊ฐ™์€ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ๋”ฐ์œ„๋Š” ์—†๊ธฐ์—, ๊ณ„์ • ๊ด€๋ จ ๋ฌธ์ œ๋Š” ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, Program.cs ์˜ ์ฝ”๋“œ ์ค‘, AddDbContext<T> ๋ฉ”์„œ๋“œ๋Š” SQL Server ์ œ๊ณต์ž๊ฐ€ ์ •์˜ํ•œ (IServiceCollections ์˜) ํ™•์žฅ ๋ฉ”์„œ๋“œ๋กœ ์•„๋ž˜์™€ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ๊ฐ„๋žตํ•˜๊ฒŒ ๋งŒ๋“ค์–ด ๋†“์€ ๊ฒƒ์— ์ง€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

builder.Services.AddScoped<ApplicationDbContext>(services =>
{
    var dbOptionsBuilder = services.GetRequired<DbContextOptionsBuilder<ApplicationDbContext>>();

    dbOptionsBuilder.UseSqlServer(connectionString);
    return new ApplicationDbContext(dbOptionsBuilder.Options);
});

์ฆ‰, ๋™๊ธฐํ™”๋  ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ๊ด€ํ•œ ์‚ฌํ•ญ์„ DbContext ์˜ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„ค์ •

์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„ค์ •์€ DbContext ์†Œ๋น„์ž์—๊ฒŒ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„ค์ • ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค.

์•ž์„œ ์ƒ์„ฑํ•œ ๋ธ”๋ ˆ์ด์ € ํ”„๋กœ์ ํŠธ๋Š” DbContext์˜ ์†Œ๋น„์ž์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
๋ธ”๋ ˆ์ด์ € ๊ฐœ๋ฐœ์ž๋Š” ์•ฑ์ด ์‚ฌ์šฉํ•  ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ์ด ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ๋ง˜๋Œ€๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ๋ธ”๋ ˆ์ด์ € ํ”„๋กœ์ ํŠธ๋Š” UI ๊ณ„์ธต์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” UI ๊ณ„์ธต์€ ๋ณดํ†ต front-end ๋กœ ๋ถ„๋ฅ˜๋˜๊ณ , ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋Š” back-end ๋กœ ๋ถ„๋ฅ˜๋ฉ๋‹ˆ๋‹ค.

Asp.Net Core ๋Š” Full-stack ๋„๊ตฌ์ด๊ธฐ ๋•Œ๋ฌธ์—, ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ์— ํ”„๋ก ํŠธ์™€ ๋ฐฑ์—”๋“œ์˜ ์ฝ”๋“œ๊ฐ€ ์„ž์—ฌ ์žˆ๋Š” ํ˜•ํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

์ƒ์„ฑํ•œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ๊ด€ํ•ด ๋” ์ด์ƒ ์ฐธ๊ณ ํ•  ๋งŒํ•œ ์ฝ”๋“œ๊ฐ€ ์—†๊ธฐ๋„ ํ•˜๊ณ , ๋ฐฑ์•ค๋“œ ์ฝ”๋“œ๋ฅผ ๋ณ„๋„์˜ ํ”„๋กœ์ ํŠธ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ๊ด€๋ฆฌํ•œ๋‹ค๋Š” ๋ช…๋ชฉ ํ•˜์— ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ๊ด€ํ•œ ์ฝ”๋“œ๋ฅผ ๋ณ„๋„์˜ ํ”„๋กœ์ ํŠธ๋กœ ์ด๊ด€ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ปจํ…์ŠคํŠธ ๋‚ด๋ถ€์—์„œ ์„ค์ •

์†”๋ฃจ์…˜์— ํด๋ž˜์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋‚˜ ๋” ์ƒ์„ฑํ•˜๊ณ , ์ƒ์„ฑ๋œ ํ”„๋กœ์ ํŠธ์— ์•„๋ž˜์ฒ˜๋Ÿผ ๋ˆ„๊ฒŸ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
image

๋ณด์‹œ๋‹ค์‹œํ”ผ, Npgsql ํŒจํ‚ค์ง€๋ฅผ ์„ ํƒํ–ˆ๋Š”๋ฐ, ์ด๋Š” PostgreSQL ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ์œ„ํ•œ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์ œ๊ณต์ž์ž…๋‹ˆ๋‹ค.

์ฆ‰, ์ด๋ฒˆ์—๋Š” ๊ฐœ๋ฐœ์šฉ์ธ localDb๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , (๋ฌด๋ฃŒ) ์ƒ์—…์šฉ์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ธ PostgreSQL์„ ์‚ฌ์šฉํ•˜๋„๋ก ํ•œ ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

์ƒ์„ฑ๋œ ํ”„๋กœ์ ํŠธ์— DataDbContext ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋‚ด์šฉ์„ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

using DbContextSetup.PostgreSQL.Entities;
using Microsoft.EntityFrameworkCore;

namespace DbContextSetup.PostgreSQL;

public class DataDbContext : DbContext
{
    //์ƒ์„ฑ์ž ์—†์Œ => ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„ค์ • ์ฐจ๋‹จ.

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // DbContext.ObConfiguring()์€ ํ•˜๋Š” ์ผ ์—†์Œ
        // base.OnConfiguring(optionsBuilder);

        var connectionString =
            "User ID=postgres;Password=....;Host=localhost;Port=5432;Database=applicationdata";

        optionsBuilder.UseNpgsql(connectionString);
    }
}

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์•„์‹œ๊ฒ ์ง€๋งŒ, DbContext.OnConfiguring ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜๊ณ , ๊ทธ ๋‚ด๋ถ€์—์„œ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„ค์ •์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ, ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„ค์ •์„ ๋ฐ›์•„ ๋“ค์ด๋Š” ์ƒ์„ฑ์ž๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š๊ณ  ์žˆ๋Š”๋ฐ, ์ด๋Š” ์ด ๊ฐ์ฒด์˜ ์†Œ๋น„์ž๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„ค์ • ๊ถŒํ•œ์„ ๋ฐ•ํƒˆํ•˜๋Š” ํšจ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋กœ ์ธํ•ด, ๋ธ”๋ ˆ์ด์ € ๊ฐœ๋ฐœ์ž๋Š” ๊ธฐ์กด์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๋ฅผ ์„ ํƒํ•  ํ•  ์ˆ˜ ์—†๊ณ , ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค๊ฐ€ ์ด๋ฏธ ์„ค์ •๋œ DbContext ๋งŒ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

// ๋ธ”๋ ˆ์ด์ € ํ”„๋กœ์ ํŠธ์˜ program.cs ์—์„œ

// ์—๋Ÿฌ๋‚จ
// builder.Services.AddDbContext<DataDbContext>(options =>
//    options.UseSqlServer(connectionString));

builder.Services.AddDbContext<DataDbContext>();

์ฐธ๊ณ ๋กœ, DataDbContext ํด๋ž˜์Šค์— ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„ค์ •์„ ๋ฐ›์•„ ๋“ค์ด๋Š” ์ƒ์„ฑ์ž๋ฅผ ์ •์˜ํ•œ๋‹ค ํ•˜๋”๋ผ๋„, OnConfiguring ์žฌ์ •์˜๋ฅผ ํ†ตํ•œ ์„ค์ •์ด ์šฐ์„ ๊ถŒ์„ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ•ํƒˆ์˜ ํšจ๊ณผ๋Š” ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

์˜์กด์„ฑ ํ•ด์ƒ๋„

๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์„ค์ •์„ ๋™์™€์ฃผ๋Š” ํ•ผํผ ๊ฐ์ฒด์—๋Š” ์ œ๋„ˆ๋ฆญ ๋ฒ„์ „๊ณผ ๋น„ ์ œ๋„ˆ๋ฆญ ๋ฒ„์ „์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • DbContextOptions (DbContextOptions<T>),
  • DbContextOptionBuilder (DbContextOptionBuilder<T>)

๋ธ”๋ ˆ์ด์ € ํ”„๋กœ์ ํŠธ์˜ ApplicationDbContext๋Š” ์ œ๋„ˆ๋ฆญ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ ,

public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
// ...

์ถ”๊ฐ€ํ•œ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ํ”„๋กœ์ ํŠธ๋Š” ๋น„ ์ œ๋„ˆ๋ฆญ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

public class DataDbContext : DbContext
{
    //...
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // ...

์ œ๋„ˆ๋ฆญ ๋ฒ„์ „์˜ ์กด์žฌ ์ด์œ ๋Š” ์˜์กด์„ฑ ์ฃผ์ž…๊ธฐ๊ฐ€ ์ฃผ์ž…ํ•  ์˜ต์…˜ ๊ฐ์ฒด๋ฅผ ์ข€ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•จ์ธ๋ฐ, ๋ณต์ˆ˜์˜ DbContext ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์˜์กด์„ฑ ์ฃผ์ž…๊ธฐ๊ฐ€ ์‹ค์ˆ˜ํ•˜์ง€ ์•Š๋„๋ก, ์ œ๋„ˆ๋ฆญ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜, ๋ณต์ˆ˜์˜ DbContext ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค ํ• ์ง€๋ผ๋„, ์˜์กด์„ฑ ์ฃผ์ž…๊ธฐ์˜ ๋„์›€ ์—†๋Š” ์„ค์ • - DbContext ๋‚ด๋ถ€์—์„œ ์„ค์ •ํ•˜๋ฉด ์ œ๋„ˆ๋ฆญ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์‚ฌ์‹ค, OnConfiguring ๋ฉ”์„œ๋“œ๋Š” ์ œ๋„ˆ๋ฆญ ๋ฒ„์ „์˜ ์˜ต์…˜์„ ๋ฐ›์•„ ๋“ค์ด๋Š” ์˜ค๋ฒ„๋ผ์ด๋“œ๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š์•„, ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•ด๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋„๋ก ๋งŒ๋“ค์–ด ๋†จ์Šต๋‹ˆ๋‹ค. (์–‘๋†ˆ๋“ค์˜ ์ฃผ๋„ ๋ฉด๋ฐ€ํ•จ์ด๋ž€โ€ฆ)

๊ธ€์ด ๊ธธ์–ด์ ธ, ๊ด€๊ณ„ ๋งตํ•‘ ์„ค์ •์— ๊ด€ํ•ด์„œ๋Š” ๋‹ค๋ฅธ ๊ธ€์—์„œ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค.

9๊ฐœ์˜ ์ข‹์•„์š”

์ธ์ฆ/์ธ๊ฐ€

์ฐธ ์–ด๋ ต๊ณ  ๊ด‘๋ฒ”์œ„ํ•œ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค๋งŒ, Asp.Net Core ๋Š” ๊ด€๋ จ ์ธํ”„๋ผ๊ฐ€ ์ž˜ ๋˜์–ด ์žˆ์–ด์„œ, ์‰ฝ๊ฒŒ ์ƒ๊ฐํ•˜๋ฉด ์‰ฌ์šด ์ฃผ์ œ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค๋งŒ, ๋น„๋‹ท๋„ท ํ”„๋ ˆ์ž„์›Œํฌ์™€์˜ ํ˜‘์—…์„ ์œ„ํ•ด์„œ๋Š” ์ธํ”„๋ผ์˜ ๋ฐ‘๋ฐ”ํƒ•์— ํ๋ฅด๋Š” ์›๋ฆฌ์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ ํ•„์š”ํ•˜๊ธฐ์—, ๊ณต๋ถ€ํ•œ ๊ฒƒ์„ ์ •๋ฆฌํ•ด ๋ด…๋‹ˆ๋‹ค.

์ฃผ์ฒด๋Š” ์„œ๋ฒ„

์ธ์ฆ(Authentication)/์ธ๊ฐ€(Authorization) ์—์„œ ํ•ต์‹ฌ์€ ์ธ๊ฐ€์ž…๋‹ˆ๋‹ค. ์ธ์ฆ์€ ์ธ๊ฐ€๋ฅผ ์œ„ํ•œ ์žฌ๋ฃŒ์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค.

์ธ๊ฐ€๋Š” ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ ๋ณด์•ˆ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ ์•ฑ - ํ”„๋ก ํŠธ ์—”๋“œ ์›น์•ฑ, ๋ฐ์Šคํฌํƒ‘ ์•ฑ, ๋ชจ๋ฐ”์ผ ์•ฑ - ์—์„œ์˜ ์ธ์ฆ/์ธ๊ฐ€๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ๋Š” ์„œ๋ฒ„์˜ ์ธ์ฆ/์ธ๊ฐ€์˜ ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ์š”๊ตฌ ์‚ฌํ•ญ์„ ๋”ฐ๋ฅด๋Š” ๊ฒƒ ๋ฟ ์ž…๋‹ˆ๋‹ค.

๋งŒ์•ฝ, โ€œ๋ธ”๋ ˆ์ด์ € ์™€์ฆ˜์•ฑ์—์„œ JWT ํ† ํฐ ์ธ์ฆโ€ ์ด๋ž€ ๊ธ€์ด๋‚˜ ์˜์ƒ์ด ์žˆ๋‹ค๋ฉด, ๊ทธ ๋‚ด์šฉ์€ ์„œ๋ฒ„๊ฐ€ ๋ฐœํ–‰ํ•œ JWT ํ† ํฐ์„ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—์„œ ์–ด๋–ป๊ฒŒ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ง€์— ๋Œ€ํ•œ ๋‚ด์šฉ์œผ๋กœ ์ดํ•ดํ•ด์•ผ ํ•˜์ง€, ์ธ์ฆ/์ธ๊ฐ€๋ฅผ ํด๋ผ์ด์–ธํŠธ์—์„œ ์ˆ˜ํ–‰(JWT ์˜ ๋ฐœํ–‰)ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์˜คํ•ดํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ, ๊ทธ๋Ÿฌํ•œ ์ฝ”๋“œ๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ๋„ฃ๊ฒŒ ๋˜๋ฉด, ๊ด€๋ จ ์‹œํฌ๋ฆฟ์ด ์ƒ๋Œ€์ ์œผ๋กœ ๋ณด์•ˆ์ด ์ทจ์•ฝํ•œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ๋‚จ๊ฒŒ ๋˜์–ด, ์ธ์ฆ/์ธ๊ฐ€๊ฐ€ ์˜๋ฏธ๊ฐ€ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ ์•ฑ์€ ์„œ๋ฒ„์˜ ๋ณด์•ˆ์— ์ข…์†์ ์ด๋ผ๋Š” ์ ์„ ์ „์ œํ•˜๋Š” ๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค.

JWT ์ธ์ฆ / ์ฟ ํ‚ค ์ธ์ฆ

๋งŽ์€ ๊ธ€์—์„œ JWT ์ธ์ฆ์ด ์ฟ ํ‚ค ์ธ์ฆ์˜ ์ฐจ ์„ธ๋Œ€ ํ˜น์€ ์ƒ์œ„ ๋ฒ„์ „์ด๋ผ๋Š” ๋‰˜์•™์Šค๋ฅผ ํ’๊ธฐ๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

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

์ข‹์€ ์„ ํƒ์ด ์•„๋‹Œ ์ด์œ ๋Š”, ํ† ํฐ์€ ํ•œ๋ฒˆ ๋ฐœํ–‰๋˜๋ฉด ์œ ํšจ ๊ธฐ๊ฐ„ ์ด์ „์— ๋ฌดํšจํ™”๋‚˜ ์ทจ์†Œ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ฟ ํ‚ค๋Š” ์œ ์ € ์—์ด์ „ํŠธ(๋ธŒ๋ผ์šฐ์ €)์™€ ์„œ๋ฒ„ ์‚ฌ์ด์—์„œ๋งŒ ๊ด€๋ฆฌ๋˜๋Š”๋ฐ, ์„œ๋ฒ„๊ฐ€ ์ €์žฅํ•˜๋ผ๊ณ  ํ•˜๋ฉด, ๋ธŒ๋ผ์šฐ์ €๋Š” ์ €์žฅํ•˜๊ณ , ์„œ๋ฒ„๊ฐ€ ์ง€์šฐ๋ผ๊ณ  ํ•˜๋ฉด ์ง€์›๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ์ฟ ํ‚ค์˜ ๋ฌดํšจํ™”๊ฐ€ ํ† ํฐ๋ณด๋‹ค๋Š” ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค.

์•…์˜์ ์ธ ๊ณต๊ฒฉ์ž๋Š” ๋ณดํ†ต ์†Œ๋น„์ž๋ฅผ ๊ฒจ๋ƒฅํ•˜๋Š”๋ฐ, ์•…์˜์ ์ธ ๊ณต๊ฒฉ์ž์— ํ† ํฐ์ด ๋„˜์–ด ๊ฐ„ ๊ฒฝ์šฐ, ์„œ๋ฒ„๋Š” ์ด์— ๋Œ€ํ•ญํ•˜๋Š” ๊ฒŒ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

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

์–ด๋–ป๊ฒŒ ํ•˜๋“ , ์„œ๋ฒ„์—์„œ ๊ด€๋ฆฌํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” JWT์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์ด ์‚ฌ๋ผ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ๋งค ์š”์ฒญ ์‹œ๋งˆ๋‹ค ์ €์žฅ๋œ ํ† ํฐ๊ณผ ๋น„๊ตํ•ด์•ผ ํ•ด์„œ ์„œ๋ฒ„์˜ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ํ”ผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, B2B์—์„œ๋Š” ์–˜๊ธฐ๊ฐ€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๊ธฐ์—… A์˜ ์„œ๋ฒ„๊ฐ€ ๋‹ค๋ฅธ ๊ธฐ์—…๋“ค์˜ ์„œ๋ฒ„์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒฝ์šฐ, ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณต ๋ฐ›์„ ์„œ๋ฒ„๋“ค์€ ๊ธฐ์—… A์—๊ฒŒ ์ต๋ช…์ ์ด์ง€ ์•Š์„ ํ™•๋ฅ ์ด ๋†’์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, ๊ธฐ์—… A๊ฐ€ ๋ฐœํ–‰ํ•œ JWT๋Š” ํ™•์ธ๋œ ๊ธฐ์—…๋“ค์—๊ฒŒ๋งŒ ์ „๋‹ฌ๋˜๊ธฐ์—, ํ† ํฐ์ด ์†Œ๋น„์ž์—๊ฒŒ ๋„˜์–ด ๊ฐ€์„œ ๊ณต๊ฒฉ์ž์—๊ฒŒ ํƒˆ์ทจ๋‹นํ•˜๊ฑฐ๋‚˜, ๊ณต๊ฒฉ์ž๊ฐ€ ๊ธฐ์—…๋“ค์˜ ์„œ๋ฒ„์—์„œ ํ† ํฐ์„ ํƒˆ์ทจํ•  ํ™•๋ฅ ์€ ๋‚ฎ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฆ‰ B2B์—์„œ๋Š” JWT์˜ ๋‹จ์ ์ด ์‚ฌ๋ผ์ง€๊ณ , ๊ณ ์œ ์˜ ์žฅ์ ๋งŒ ๋ถ€๊ฐ๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ์˜ ์„œ๋น„์Šค๊ฐ€ ์ผ๋ฐ˜ ์†Œ๋น„์ž์™€ ๊ธฐ์—… ์†Œ๋น„์ž๋ฅผ ๋ชจ๋‘ ์ปค๋ฒ„ํ•œ๋‹ค๋ฉด, ์ „์ž๋Š” ์ฟ ํ‚ค๋ฅผ, ํ›„์ž๋Š” JWT๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ธ์ฆ ์ˆ˜๋‹จ 2์ค‘ํ™”๋ฅผ ์ฑ„ํƒํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ์„ ํƒ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜๋„ JWT๋ฅผ ์จ์•ผ ํ•œ๋‹ค๋ฉด

JWT๋Š” ํŽ˜์ด๋กœ๋“œ๊ฐ€ ์žˆ์–ด, ์ธํ„ฐ๋„ท์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๊ณ ์ž ํ•  ๋•Œ ์œ ์šฉํ•˜๊ธฐ๋Š” ํ•ฉ๋‹ˆ๋‹ค.

JWT์— ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„์„œ ๋ณด๋‚ด๋Š” ์ด์œ ๋Š” ํ† ํฐ ๋ฐœํ–‰์ž๊ฐ€ ์•„๋‹ˆ๋ผ ์ˆ˜์ทจ์ธ์„ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. JWT์˜ ์ˆ˜์ทจ์ธ์€ "ํ† ํฐ์ด ๋ฐœํ–‰์ž๊ฐ€ ๋ณด๋‚ธ ๊ทธ๋Œ€๋กœ"์ธ์ง€ ์•„๋‹Œ ์ง€๋ฅผ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์–ด, ํŽ˜์ด๋กœ๋“œ์˜ ๋‚ด์šฉ์„ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜, JWT์˜ ํŽ˜์ด๋กœ๋“œ๋Š” ๋ˆ„๊ตฌ๋‚˜ ๋ณผ ์ˆ˜ ์žˆ์–ด์„œ, ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋กœ ์ „์†กํ•˜๋Š” ๊ฒƒ๊ณผ ํ•˜๋“ฑ ์ฐจ์ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, JWT๋ฅผ ๋ฌด์–ธ๊ฐ€ ์ „๋‹ฌํ•˜๋ ค๋Š” ์šฉ๋„๋กœ ์“ด๋‹ค๋ฉด, ์ผ๋ฐ˜ ์†Œ๋น„์ž์™€ ๊ฒฉ๋ฆฌ๋œ ๊ฒฝ๋กœ๋กœ๋งŒ ์œ ํ†ต๋จ์„ ๋ณด์žฅํ•˜๋Š” ๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค.

๋‹ท๋„ท ํด๋ผ์ด์–ธํŠธ์˜ ์ฟ ํ‚ค ํ•ธ๋“ค๋ง

์ฟ ํ‚ค๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์„ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ๋ฐ, ๋‹ท๋„ท์˜ HttpClient ๋Š” ์ฟ ํ‚ค๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

HttpClientHandler.CookieContainer Property (System.Net.Http) | Microsoft Learn

์ด๋ฅผ ์ด์šฉํ•˜๋ฉด, ์ฟ ํ‚ค๋ฅผ ์ธ์ฆ ์ˆ˜๋‹จ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์–ด๋–ค ์„œ๋ฒ„์—๋„ ๋‹ท๋„ท ์•ฑ์€ ๋ฌธ์ œ ์—†์ด ์ ‘์†์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ œ๋กœ ์ฟ ํ‚ค ์ธ์ฆ์„ ํ•˜๋Š” ์„œ๋ฒ„๋กœ, ๋ฏธ๋‹ˆ๋ฉ€ API ์•ฑ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

        var builder = WebApplication.CreateBuilder(args);

        string AuthScheme = "cookie";

        builder.Services.AddAuthentication(AuthScheme)
            .AddCookie(AuthScheme);

        var app = builder.Build();

        app.UseAuthentication();

        app.MapGet("/secret", (HttpContext http) =>
        {
            var name = http.User.FindFirstValue("name");

            if (name == null)
            {
                http.Response.StatusCode = 403;
                return "Know the dark force";
            }

            http.Response.StatusCode = 200;
            return $"{name}, I am your father!";
        });

        app.MapGet("/login", async (HttpContext http) =>
        {
            var nameClaim = new Claim("name", "Luke");
            var claimIdenty = new ClaimsIdentity([nameClaim], AuthScheme);
            var claimPrincipal = new ClaimsPrincipal(claimIdenty);
            await http.SignInAsync(claimPrincipal);
            return "Logged in";
        });

        app.MapGet("/logout", async (HttpContext http) =>
        {
            await http.SignOutAsync(AuthScheme);
            return "Logged out";
        });
    
        app.Run();

๊ทธ๋ฆฌ๊ณ , ํด๋ผ์ด์–ธํŠธ๋กœ ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ˜์†” ์•ฑ์ž…๋‹ˆ๋‹ค.

using System.Net;


var handler = new HttpClientHandler() 
{ 
    UseDefaultCredentials = true,
    CookieContainer = new CookieContainer(),
};

var http = new HttpClient(handler)
{
    BaseAddress = new Uri("http://localhost:5011"),
};


while (true)
{
    Console.Clear();
    Console.WriteLine();
    Console.WriteLine("Type 'l' to login, 'o' to logout, 's' to get secret or 'x' to exit");
    
    var key = Console.ReadKey(true).KeyChar;

    switch (key)
    {
        case 'l':
            var message = await http.GetStringAsync("/login");
            Console.Write(message);
            Console.ReadKey(true);
            break;
        case 'o':
            message = await http.GetStringAsync("/logout");
            Console.Write(message);
            Console.ReadKey(true);
            break;
        case 's':
            var response = await http.GetAsync("/secret");
            Console.Write(await response.Content.ReadAsStringAsync());
            Console.ReadKey(true);
            break;
        case 'x':
            Environment.Exit(0);
            break;
    }
}

๊ฒฐ๊ณผ

  • ๋กœ๊ทธ์ธ ์ „ โ€˜sโ€™ ์ž…๋ ฅ

Type โ€˜lโ€™ to login, โ€˜oโ€™ to logout, โ€˜sโ€™ to get secret or โ€˜xโ€™ to exit
Know the dark force

  • ๋กœ๊ทธ์ธ ํ›„, โ€˜sโ€™ ์ž…๋ ฅ

Type โ€˜lโ€™ to login, โ€˜oโ€™ to logout, โ€˜sโ€™ to get secret or โ€˜xโ€™ to exit
Luke, I am your father!

8๊ฐœ์˜ ์ข‹์•„์š”

์ž˜์ฝ์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

4๊ฐœ์˜ ์ข‹์•„์š”

์ธ์ฆ/์ธ๊ฐ€ 2

์ธ์ฆ/์ธ๊ฐ€์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ์ธ๊ฐ€๋ผ๊ณ  ๋ง์”€๋“œ๋ ธ์Šต๋‹ˆ๋‹ค.
์ธ๊ฐ€๋Š” ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ ๋ณดํ˜ธ ํ–‰์œ„์ธ๋ฐ, ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๊ตฌํ˜„ ๋ฐฉ์‹์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ค€๋น„๋ฌผ

API๋ฅผ ์‹คํ–‰ํ•˜๊ณ , ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด, VS Code ํ”Œ๋Ÿฌ๊ทธ์ธ ์ค‘, Thunder Client ๋ฅผ ์„ค์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

Lightweight Rest API Client Extension for VS Code - Thunder Client

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ์‹

์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” ๋ฏธ๋‹ˆ๋ฉ€ API ์ฝ”๋“œ๋กœ, user-secret ์—”๋“œ ํฌ์ธํŠธ๋Š” ์‚ฌ์šฉ์ž์˜ ๋น„๋ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณดํ˜ธํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์—ด๋žŒํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์—”๋“œ ํฌ์ธํŠธ์— ๋น„๋ฐ€ํ‚ค๋ฅผ ์ œ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

namespace AspNetAuth;

class User(string name, string secret)
{
    public string Name => name;
    public string Secret { get; set; } = secret;
}
using Microsoft.AspNetCore.Mvc;
namespace AspNetAuth;

public class ManualAuth
{
    static readonly List<User> s_userRepo =
    [
        new User("Luke", "Darth Vader is your father"),
        new User("Leia", "Luke is your brother"),
    ];

    public static void Run(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        var app = builder.Build();

        // ๋ณดํ˜ธํ•  ๋ฐ์ดํ„ฐ
        app.MapGet("/user-secret", ([FromHeader]string credential, HttpContext http) =>
        {
            var user = s_userRepo.FirstOrDefault(u => u.Name == credential);

            // credential ๊ฒ€์ฆ ์‹คํŒจ
            if (user == null) return Results.BadRequest(); // 400

            return Results.Ok(user.Secret);
        });

        app.Run();
    }
}
  1. ๋น„๋ฐ€ํ‚ค๋ฅผ ์ œ์ถœํ•˜์ง€ ์•Š์„ ๋•Œ

์ฝ”๋“œ์˜ ์˜๋„ ๋Œ€๋กœ, 400 ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

            // credential ๋ถˆ๋งŒ์กฑ 
            if (user == null)
            {
                return Results.BadRequest(null); // 400
            }
  1. ๋น„๋ฐ€ํ‚ค๋ฅผ ์ œ์ถœํ–ˆ์„ ๋•Œ,

์œ„์˜ ์ฝ”๋“œ๋Š” ๋ฌด์ฒ™ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.
์—”๋“œํฌ์ธํŠธ๊ฐ€ ๋น„๋ฐ€ํ‚ค๋ฅผ ํ™•์ธํ•˜๊ณ , ํ™•์ธ๋˜๋ฉด ๋ณดํ˜ธ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ธ์ฆ ํ‹ฐ์ผ“ ๋ฐฉ์‹

๊ทธ๋Ÿฌ๋‚˜, ํด๋ผ์ด์–ธํŠธ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์—ด๋žŒํ•  ๋•Œ๋งˆ๋‹ค, ๋น„๋ฐ€ํ‚ค๋ฅผ ์ œ์ถœํ•ด์•ผ ํ•˜๋Š” ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
๋น„๋ฐ€ํ‚ค๊ฐ€ ์ž์ฃผ ์ œ์ถœ๋  ์ˆ˜๋ก ๋ณด์•ˆ ์œ„ํ—˜๋„ ์˜ฌ๋ผ๊ฐ€๊ธฐ ๋•Œ๋ฌธ์—, ์ตœ์ดˆ๋กœ ํ•œ ๋ฒˆ๋งŒ ๋น„๋ฐ€ํ‚ค๋ฅผ ์ œ๊ณตํ•˜๋ฉด, ์ผ์ • ์‹œ๊ฐ„ ์ด๋‚ด์—๋Š” ๋‹ค์‹œ ์ œ์ถœํ•˜๋Š” ์ผ์ด ์—†๊ฒŒ ๋งŒ๋“ค์–ด ๋ณด์•ˆ ์œ„ํ—˜์„ ๋‚ฎ์ถœ ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด, ์„œ๋ฒ„๋Š” ๋น„๋ฐ€ํ‚ค๊ฐ€ ์ตœ์ดˆ๋กœ ๊ฒ€์ฆ๋˜๋ฉด, ์„œ๋ฒ„๋งŒ์ด ์•Œ ์ˆ˜ ์žˆ๋Š” ์ธ์ฆ ํ‹ฐ์ผ“์„ ๋ฐœํ–‰ํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ๋Š” ๊ทธ ๋‹ค์Œ ์š”์ฒญ ์‹œ๋งˆ๋‹ค, ๋น„๋ฐ€ํ‚ค ๋Œ€์‹ ์— ์ธ์ฆ ํ‹ฐ์ผ“์„ ์„œ๋ฒ„์— ์ œ์ถœํ•˜๋„๋ก ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์— ํฌํ•จ๋œ ์ธ์ฆ ํ‹ฐ์ผ“์„ ํ™•์ธํ•˜๋Š” ๊ณผ์ •์„ ์ธ์ฆ(Authentication)์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ธ์ฆ ํ‹ฐ์ผ“ ๋ฐœ๊ธ‰์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ, ManualAuth.Run ๋ฉ”์„œ๋“œ์˜ app.Run(); ์ฝ”๋“œ ๋ฐ”๋กœ ์œ„์— ์‚ฝ์ž…๋‹ˆ๋‹ค.

        const string COOKIE_KEY = "starwars";

        // ๋ณดํ˜ธํ•  ๋ฐ์ดํ„ฐ2
        app.MapGet("/secret", (HttpContext http) =>
        {
            var cookieValue = http.Request.Cookies[COOKIE_KEY];

            // ์ธ์ฆ ํ‹ฐ์ผ“ ์—†์Œ
            if(cookieValue == null)  return Results.Unauthorized(); // 401
            
            var user = s_userRepo.FirstOrDefault(u => u.Name == cookieValue);

            // ์‹คํšจ๋˜๊ฑฐ๋‚˜, ์œ„๋„/๋„์šฉ๋œ ์ธ์ฆ ํ‹ฐ์ผ“ 
            if(user == null)
            {
                http.Response.Cookies.Delete(COOKIE_KEY);
                return Results.BadRequest();
            }

            return Results.Ok(user.Secret);            
        });

        app.MapGet("/login", ([FromHeader]string credential, HttpContext http) =>
        {
            var user = s_userRepo.FirstOrDefault(x => x.Name == credential);

            if (user == null)  return Results.BadRequest();

            // ์ธ์ฆ ํ‹ฐ์ผ“ ๋ฐœ๊ธ‰
            http.Response.Cookies.Append(COOKIE_KEY, user.Name);
            return Results.Ok($"Welcome, {user.Name}");
        });

        app.MapGet("/logout", (HttpContext http) =>
        {
            if (http.Request.Cookies.ContainsKey(COOKIE_KEY))
            {
                http.Response.Cookies.Delete(COOKIE_KEY);
                return Results.Ok("Good bye~~");
            }
            return Results.BadRequest();
        });

์ฐธ๊ณ 
401 Unauthorized ๋Š” ์ด๋ฆ„๊ณผ ๋‹ฌ๋ฆฌ Unauthenticated ์˜ ์˜๋ฏธ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
401 Unauthorized - HTTP | MDN (mozilla.org)

์œ„ ์ฝ”๋“œ๋Š” ์ธ์ฆ ํ‹ฐ์ผ“์„ ์ฟ ํ‚ค์— ์ €์žฅํ•˜๋Š”๋ฐ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์•„๋„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๋กœ๊ทธ์ธ

์ฟ ํ‚ค๋„ ํด๋ผ์ด์–ธํŠธ(Thunder Client)๊ฐ€ ์ž˜ ๋ฐ›์•„์„œ ๋ณด๊ด€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๋น„๋ฐ€ ๋ฐ์ดํ„ฐ ์š”์ฒญ

์ธ์ฆ ํ‹ฐ์ผ“ ์•”ํ˜ธํ™”

ํ˜„์žฌ ์ธ์ฆ ํ‹ฐ์ผ“์€ ํ‰๋ฌธ์ด๋ผ ๋ณด์•ˆ์„ฑ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์•”ํ˜ธํ™”ํ•˜์—ฌ ๋ณด์•ˆ์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค.

์•”ํ˜ธํ™”๋Š” Asp.Net Core ์—์„œ ์ œ๊ณตํ•˜๋Š” IDataProtector ๊ฐ์ฒด๋ฅผ ์„œ๋น„์Šค ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋กํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

builder.Services.AddSingleton<IDataProtector>( _ => 
   DataProtectionProvider.Create("ManualAuth").CreateProtector("auth ticket"));

์ด ๊ฐ์ฒด๋ฅผ ์ธ์ฆ ํ‹ฐ์ผ“์˜ ๋ฐœ๊ธ‰๊ณผ ๊ฒ€์ฆ์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

        app.MapGet("/login", ([FromHeader]string credential, HttpContext http, 
             [FromServices]IDataProtector protector) =>
        {
            var user = s_userRepo.FirstOrDefault(x => x.Name == credential);

            if (user == null)
            {
                return Results.BadRequest();
            }

            // ์ธ์ฆ ํ‹ฐ์ผ“ ๋ฐœ๊ธ‰
            //http.Response.Cookies.Append(COOKIE_KEY, user.Name);

            // ์•”ํ˜ธํ™”๋œ ํ‹ฐ์ผ“ ๋ฐœ๊ธ‰
            var ticket = protector.Protect(user.Name);

            // ํ‹ฐ์ผ“์„ ์„œ๋ฒ„๊ฐ€ ๊ด€๋ฆฌ
            http.Response.Cookies.Append(COOKIE_KEY, ticket);

            // ํ‹ฐ์ผ“์„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ด€๋ฆฌ (JWT์˜ ๊ด€๋ฆฌ ๋ฐฉ์‹)
            //return Results.Ok(ticket);
            // or
            //http.Response.Headers.Append("access-token", ticket);

            return Results.Ok($"Welcome, {user.Name}");
        });

์ฐธ๊ณ 
์ธ์ฆ ํ‹ฐ์ผ“์„ ์ฟ ํ‚ค์— ๋„ฃ์–ด ์‘๋‹ตํ•˜๋ฉด, ํ‹ฐ์ผ“์˜ ๊ด€๋ฆฌ ์ฃผ์ฒด๋Š” ์„œ๋ฒ„๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
๋ฌผ๋ก  ์‚ฌ์šฉ์ž๊ฐ€ ๋ธŒ๋ผ์šฐ์ €์˜ ์ฟ ํ‚ค๋ฅผ ์ง€์šธ ์ˆ˜๋„ ์žˆ๊ธฐ๋Š” ํ•˜์ง€๋งŒ, ๊ทธ ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•˜๊ณค ์ฟ ํ‚ค์— ๋ณด๊ด€๋œ ํ‹ฐ์ผ“์€ ํ•ญ์ƒ ์„œ๋ฒ„๋กœ ์ „๋‹ฌ๋˜๋ฉฐ, ์„œ๋ฒ„๋Š” ์ด๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์ง€์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด์— ๋ฐ˜ํ•ด, ํ‹ฐ์ผ“์„ ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต ํ•ด๋”๋‚˜ ๋ฐ”๋””์— ๋„ฃ์œผ๋ฉด, ์ด ํ‹ฐ์ผ“์˜ ๊ด€๋ฆฌ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์š”์ฒญ์— ์ด ํ‹ฐ์ผ“์„ ๋„ฃ์„ ์ง€ ๋ง์ง€, ๋„ฃ๋Š” ๊ฒฝ์šฐ ํ—ค๋”์— ๋„ฃ์„์ง€ ๋ฐ”๋””์— ๋„ฃ์„ ์ง€๋ฅผ ๊ฒฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

        // ๋ณดํ˜ธํ•  ๋ฐ์ดํ„ฐ2
        app.MapGet("/secret", (HttpContext http, [FromServices] IDataProtector protector) =>
        {
            var cookieValue = http.Request.Cookies[COOKIE_KEY];

            // ์ธ์ฆ ์ˆ˜๋‹จ ์—†์Œ
            if(cookieValue == null)
            {
                return Results.Unauthorized(); // 401
            }

            cookieValue = protector.Unprotect(cookieValue);
            var user = s_userRepo.FirstOrDefault(u => u.Name == cookieValue);

            // ์œ„์กฐ๋˜๊ฑฐ๋‚˜, ๋„์šฉ๋œ ์ฟ ํ‚ค 
            if(user == null)
            {
                http.Response.Cookies.Delete(COOKIE_KEY);
                return Results.BadRequest();
            }            

            return Results.Ok(user.Secret);            
        });

๋กœ๊ทธ์ธ์œผ๋กœ ์ธ์ฆ ํ‹ฐ์ผ“์ด ์•”ํ˜ธํ™”๋˜์–ด ์žˆ๋Š” ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

ํ‹ฐ์ผ“์˜ ๋‚ด์šฉ์€ ์•”ํ˜ธํ™”๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์˜ค๋กœ์ง€ ์„œ๋ฒ„(์˜ ๋ฐ์ดํ„ฐ ํ”„๋กœํ…ํ„ฐ)๋งŒ์ด ๊ทธ ๋‚ด์šฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ : IDataProtector ์ธ์Šคํ„ด์Šค๋Š” ์•”ํ˜ธํ™”/๋ณตํ˜ธํ™”๊ฐ€ ์ธ์Šคํ„ด์Šค ๋ณ„๋กœ ๋…๋ฆฝ์ ์ด๋ผ, ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๊ฐ€ ์•”ํ˜ธํ™”ํ•œ ๋‚ด์šฉ์„ ๋ณตํ˜ธํ™”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ธ์ฆ ๋ฏธ๋“ค์›จ์–ด

ํ˜„์žฌ์˜ ๊ตฌํ˜„์€ ์ธ์ฆ์ด ์—”๋“œ ํฌ์ธํŠธ(/secret)์— ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ, ๋ณดํ˜ธ๊ฐ€ ํ•„์š”ํ•œ ์—”๋“œ ํฌ์ธํŠธ๊ฐ€ ๋Š˜์–ด๋‚œ๋‹ค๋ฉด, ์ธ์ฆ ํ–‰์œ„๊ฐ€ ์—ฌ๋Ÿฌ ์—”๋“œํฌ์ธํŠธ๋กœ ๋ถ„์‚ฐ๋˜์–ด ๊ด€๋ฆฌ๊ฐ€ ์‰ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, ์ธ์ฆ์„ ํ•œ ๊ณณ์œผ๋กœ ๋ชจ์„ ํ•„์š”๊ฐ€ ์žˆ๋Š”๋ฐ, Asp.Net Core ๋Š” ์ด๋ฅผ ์œ„ํ•ด ๋ฏธ๋“ค์›จ์–ด์™€ ClaimsPrincipal ๊ฐ์ฒด๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

์šฐ์„ , ์ฟ ํ‚ค์— ํฌํ•จ๋œ ์ธ์ฆ ํ‹ฐ์ผ“์„ ๋‹ค๋ฃจ๋Š” ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

class CookieAuthenticator
{
    private readonly IDataProtector _protector;

    public CookieAuthenticator(IDataProtector protector)
    {
        _protector = protector;
    }

    public void Authenticate(ref HttpContext http, string authType, List<User> userRepo)
    {
        var cookieValue = http.Request.Cookies[authType];

        if(cookieValue == null)
        {
            return ;
        }

        cookieValue = _protector.Unprotect(cookieValue);
        var user = userRepo.FirstOrDefault(u => u.Name == cookieValue);

       // HttpContext.User ์„ค์ •
        if (user != null)
        {
            var nameClaim = new Claim(nameof(user.Name), user.Name);
            var claimIdenty = new ClaimsIdentity([nameClaim], authType);
            var claimPrincipal = new ClaimsPrincipal(claimIdenty);
            http.User = claimPrincipal;
        }
    }
}

์ด ์„œ๋น„์Šค๋ฅผ ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋กํ•˜๊ณ , ์ด ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

        // ์ฟ ํ‚ค ์ธ์ฆ ์„œ๋น„์Šค
        builder.Services.AddSingleton<CookieAuthenticator>();

        var app = builder.Build();

        // ์ธ์ฆ ๋ฏธ๋“ค์›จ์–ด
        app.Use((http, next) =>
        {
            var authenticator = http.RequestServices.GetRequiredService<CookieAuthenticator>();
            authenticator.Authenticate(ref http, COOKIE_KEY, s_userRepo);
            return next();
        });

์ธ์ฆ์ด ์™„๋ฃŒ๋˜๋ฉด, HttpContext.User ์— Name ํด๋ž˜์ž„์ด ์žˆ๋Š” CliamsPrincipal ๊ฐ์ฒด๊ฐ€ ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค.
์—”๋“œ ํฌ์ธํŠธ๋Š” ์ด ๊ฐ์ฒด๋ฅผ ๊ฒ€์‚ฌํ•˜์—ฌ, ์‚ฌ์šฉ์ž๋ฅผ ์•Œ์•„ ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

        // ๋ณดํ˜ธํ•  ๋ฐ์ดํ„ฐ2
        app.MapGet("/secret", (HttpContext http) =>
        {
            var userName = http.User.FindFirstValue(nameof(User.Name));

            var user = s_userRepo.FirstOrDefault(u => u.Name == userName);

            // ์œ„์กฐ๋˜๊ฑฐ๋‚˜, ๋„์šฉ๋œ ์ฟ ํ‚ค 
            if(user == null)
            {
                http.Response.Cookies.Delete(COOKIE_KEY);
                return Results.BadRequest();
            }            

            return Results.Ok(user.Secret);            
        });

์ž˜ ๋™์ž‘ํ•˜๋‹ˆ, ๋™์ž‘ ํ™•์ธ์€ ์ƒ๋žตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ธ์ฆ ์ธํ”„๋ผ

์ธ์ฆ ์„œ๋น„์Šค์™€ ์ธ์ฆ ๋ฏธ๋“ค์›จ์–ด์˜ ์ฝ”๋“œ๋ฅผ ์ž˜ ๋ณด์‹œ๋ฉด, Asp.Net Core ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ธ์ฆ ๊ด€๋ จ ์ธํ”„๋ผ์ธ IAuthenticationService ์™€ AuthenticationMiddleware ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๊ณผ์ •๊ณผ ๋™์ผํ•จ์„ ์•Œ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

        // ์ฟ ํ‚ค ์ธ์ฆ ์„œ๋น„์Šค
        builder.Services.AddAuthentication("cookie")
            .AddCookie("cookie");
        var app = builder.Build();

        // ์ธ์ฆ ๋ฏธ๋“ค์›จ์–ด
        app.UseAuthentication();

์œ„ ์ธํ”„๋ผ์˜ ๋‚ด๋ถ€ ๊ตฌ์กฐ๋Š” ์ง์ ‘ ๊ตฌํ˜„ํ•œ ๊ฒƒ๋ณด๋‹ค ๋ณด๋‹ค ์ •๊ตํ•˜๊ณ  ์ข€๋” ๊ตฌ์กฐ์ ์ด๋‹ค๋Š” ์ฐจ์ด๋งŒ ์žˆ์„ ๋ฟ ๊ทธ ์›๋ฆฌ๋Š” ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ๊ธ€, ์ธ๊ฐ€ ๊ตฌํ˜„

7๊ฐœ์˜ ์ข‹์•„์š”

์ •๋ฆฌ์•ˆํ•˜์‹ ๋‹ค๋‹ˆ ๊ฒฐ๊ตญ ํ•˜์‹œ๋Š”๊ตฐ์š” ใ…Ž!

4๊ฐœ์˜ ์ข‹์•„์š”

์–‘์งˆ์˜ ๊ธ€ ๋„ˆ๋ฌด ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค :+1: :+1: :+1: :+1:

3๊ฐœ์˜ ์ข‹์•„์š”

์ธ์ฆ/์ธ๊ฐ€ 3

์ธ๊ฐ€์˜ ๊ณผ์ •์— ๋Œ€ํ•ด ์•Œ์•„ ๋ด…๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ๋ฐ, ์ด์ „ ๊ธ€์˜ ์˜ˆ์ œ๋Š” ์ธ๊ฐ€๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ์— ์•ฝ๊ฐ„ ๋ถ€์กฑํ•œ ๋ฉด์ด ์žˆ์–ด, ์ˆ˜์ •ํ•˜๋Š” ๊ฒŒ ์ข‹์„ ๋“ฏํ•ฉ๋‹ˆ๋‹ค.

์šฐ์„ , ์‚ฌ์šฉ์ž ๊ฐ์ฒด๋ฅผ ๋‹ค์‹œ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

class User(string name, string secret, int credentialHash, string skill)
{
    public string Name => name;
    public int CredentialHash => credentialHash;
    public string Secret { get; set; } = secret;
    public string Skill => skill;
}

์‚ฌ์šฉ์ž ์ €์žฅ์†Œ๋„ ์—…๋ฐ์ดํŠธ ํ•ฉ๋‹ˆ๋‹ค.

    static readonly List<User> s_userRepo =
    [
        new User("Luke", "Darth Vader is your father", "1234".GetHashCode(), "Jedi"),
        new User("Leia", "Luke is your brother", "5678".GetHashCode(), "Jedi"),
        new User("Han", "", "9123".GetHashCode(), "Pilot"),
    ];

๋กœ๊ธด ์—”๋“œ ํฌ์ธํŠธ๋„ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ์ฝ”๋“œ๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

        app.MapGet("/login", ([FromHeader]string credential, HttpContext http, [FromServices]IDataProtector protector) =>
        {
            if(string.IsNullOrWhiteSpace(credential))
            {
                return Results.BadRequest();
            }

            var credentialHash = credential.GetHashCode();

            var user = s_userRepo.FirstOrDefault(x => x.CredentialHash == credentialHash);

            if (user == null)
            {
                return Results.BadRequest();
            }

            // ์•”ํ˜ธํ™”๋œ ํ‹ฐ์ผ“ ๋ฐœ๊ธ‰
            var ticket = protector.Protect(user.Name);

            // ํ‹ฐ์ผ“์„ ์„œ๋ฒ„๊ฐ€ ๊ด€๋ฆฌ
            http.Response.Cookies.Append(COOKIE_KEY, ticket);

            // ํ‹ฐ์ผ“์„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ด€๋ฆฌ (JWT์˜ ๊ด€๋ฆฌ ๋ฐฉ์‹)
            //return Results.Ok(ticket);
            // or
            //http.Response.Headers.Append("access-token", ticket);
            
            return Results.Ok($"Welcome, {user.Name}");
        });

๊ทธ๋ฆฌ๊ณ , ์ธ์ฆ ์„œ๋น„์Šค์—, ํด๋ ˆ์ž„์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

    public void Authenticate(ref HttpContext http, string authType, List<User> userRepo)
    {
        var cookieValue = http.Request.Cookies[authType];

        if(cookieValue == null)
        {
            return ;
        }

        cookieValue = _protector.Unprotect(cookieValue);
        var user = userRepo.FirstOrDefault(u => u.Name == cookieValue);

        // ์‚ฌ์šฉ์ž ํ™•์ธ
        if (user != null)
        {
            var nameClaim = new Claim(nameof(user.Name), user.Name);
            var skillClaim = new Claim(nameof(user.Skill),user.Skill); // ์Šคํ‚ฌ ์ถ”๊ฐ€
            var claimIdenty = new ClaimsIdentity([nameClaim, skillClaim], authType);
            var claimPrincipal = new ClaimsPrincipal(claimIdenty);
            http.User = claimPrincipal;
        }
    }

๋งˆ์ง€๋ง‰์œผ๋กœ secret ์—”๋“œ ํฌ์ธํŠธ์—๋„ ์ž๊ฒฉ์„ ๊ฒ€์ฆํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค.

        // ๋ณดํ˜ธํ•  ๋ฐ์ดํ„ฐ2
        app.MapGet("/secret", (HttpContext http) =>
        {
            var userName = http.User.FindFirstValue(nameof(User.Name));

            // ์ธ์ฆ๋˜์ง€ ์•Š์€ ์š”์ฒญ
            if (userName == null)
            {
                http.Response.StatusCode = 401;
                return "";
            }

            var skill = http.User.FindFirstValue(nameof(User.Skill));

            // ๊ถŒํ•œ ์—†๋Š” ์š”์ฒญ
            if (skill != "Jedi")
            {
                http.Response.StatusCode = 403;
                return "";
            }

            var user = s_userRepo.FirstOrDefault(u => u.Name == userName);

            // ์œ„์กฐ/๋„์šฉ๋œ ์ฟ ํ‚ค 
            if (user == null)
            {
                http.Response.StatusCode = 400;
                http.Response.Cookies.Delete(COOKIE_KEY);

                return "";
            }

            return s_userRepo.FirstOrDefault(u => u.Name == userName)?.Secret;   
            
        });

์ธ๊ฐ€

์ธ๊ฐ€๋Š” ๋ณดํ˜ธ๋œ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ ‘๊ทผ ์ž๊ฒฉ์ด ์žˆ๋Š” ์ง€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ธ๊ฐ€๋ฅผ ์œ„ํ•ด์„œ๋Š” ์š”์ฒญ์„ ๋ณด๋‚ธ ์‚ฌ๋žŒ์˜ ์ •๋ณด๋ฅผ ์•Œ์•„์•ผ ํ•˜๋Š”๋ฐ, ๋ชจ๋ฅด๋Š” ๊ฒฝ์šฐ ์ž๊ฒฉ ์œ ๋ฌด๋ฅผ ๋”ฐ์งˆ ํ•„์š”๋„ ์—†์Šต๋‹ˆ๋‹ค.

            var userName = http.User.FindFirstValue(nameof(User.Name));

            // ์ธ์ฆ๋˜์ง€ ์•Š์€ ์š”์ฒญ
            if (userName == null)
            {
                http.Response.StatusCode = 401;
                return "";
            }

์š”์ฒญ์ด ์ธ์ฆ๋˜์—ˆ์œผ๋ฉด, ์ž๊ฒฉ ์š”๊ฑด์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.

            var skill = http.User.FindFirstValue(nameof(User.Skill));

            // ๊ถŒํ•œ ์—†๋Š” ์š”์ฒญ
            if (skill != "Jedi")
            {
                http.Response.StatusCode = 403;
                return "";
            }

์ธ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด

๊ทธ๋Ÿฌ๋‚˜, ํ˜„์žฌ์˜ ์—”๋“œ ํฌ์ธํŠธ๋Š” ์ธ๊ฐ€๋ฅผ ์ง์ ‘ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ๋ณดํ˜ธ๋œ ์—”๋“œ ํฌ์ธํŠธ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ๋ผ๋ฉด, ์ธ๊ฐ€ ์ฝ”๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ณณ์— ๋ถ„์‚ฐ๋˜์–ด ๊ด€๋ฆฌ๊ฐ€ ์‰ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฏธ๋“ค์›จ์–ด๋กœ ์ง‘์ค‘์‹œํ‚ต๋‹ˆ๋‹ค.

์ธ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด์˜ ์ฑ…์ž„์€ ์ธ๊ฐ€๋œ ์š”์ฒญ๋งŒ ์—”๋“œ ํฌ์ธํŠธ๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ์ธ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด ์ฝ”๋“œ๋ฅผ ์ธ์ฆ ๋ฏธ๋“ค์›จ์–ด ๋‹ค์Œ์— ๋„ฃ์Šต๋‹ˆ๋‹ค.
์ธ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด๋Š” ์ธ์ฆ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์„ค์ •ํ•œ HttpContext.User ์˜ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ธฐ์—, ์ด ์ˆœ์„œ๋Š” ๋ฐ˜๋“œ์‹œ ์ง€์ผœ์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

        // ์ธ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด
        app.Use((http, next) =>
        {
            var path = http.Request.Path;  
            if (path.StartsWithSegments("/secret") is false)
                return next();

            var userName = http.User.FindFirstValue(nameof(User.Name));

            // ์ธ์ฆ๋˜์ง€ ์•Š์€ ์š”์ฒญ
            if (userName == null)
            {
                http.Response.StatusCode = 401;
                return Task.CompletedTask;
            }

            var skill = http.User.FindFirstValue(nameof(User.Skill));

            // ๊ถŒํ•œ ์—†๋Š” ์š”์ฒญ
            if (skill != "Jedi")
            {
                http.Response.StatusCode = 403;
                return Task.CompletedTask;
            }

            var user = s_userRepo.FirstOrDefault(u => u.Name == userName);

            // ์œ„์กฐ/๋„์šฉ๋œ ์ฟ ํ‚ค 
            if (user == null)
            {
                http.Response.StatusCode = 400;
                http.Response.Cookies.Delete(COOKIE_KEY);

                return Task.CompletedTask; 
            }

            return next();
        });

์ด์ œ secret ์—”๋“œ ํฌ์ธํŠธ๋Š” ์ธ๊ฐ€๋œ ์š”์ฒญ๋งŒ์„ ๋ฐ›๋Š” ๊ฒƒ์ด ๋ณด์žฅ๋˜๊ธฐ, ์ž์‹ ์˜ ์ž„๋ฌด์—๋งŒ ์ถฉ์‹คํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

        // ๋ณดํ˜ธํ•  ๋ฐ์ดํ„ฐ2
        app.MapGet("/secret", (HttpContext http) =>
        {
            var userName = http.User.FindFirstValue(nameof(User.Name));
            return s_userRepo.FirstOrDefault(u => u.Name == userName)?.Secret;                    
        });

์ธ๊ฐ€ ์„œ๋น„์Šค

ํ˜„์žฌ์˜ ์ธ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด๋Š” โ€œ/secretโ€ ์—”๋“œ ํฌ์ธํŠธ์— ๋Œ€ํ•œ ์ธ๊ฐ€ ๋งŒ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
๋ณดํ˜ธ๋˜๋Š” ์—”๋“œ ํฌ์ธํŠธ๊ฐ€ ๋Š˜์–ด๋‚˜๊ฑฐ๋‚˜, ์ธ๊ฐ€ ๋ฐฉ์‹์ด ์ถ”๊ฐ€๋˜๋Š” ๊ฒฝ์šฐ, ๊ด€๋ จ ๋ฏธ๋“ค์›จ์–ด๋“ค์ด ๋Š˜์–ด๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
์ด ๊ฒฝ์šฐ, ๋ชจ๋“  ์š”์ฒญ์˜ ์ฒ˜๋ฆฌ ๊ฒฝ๋กœ(์š”์ฒญ ํŒŒ์ดํ”„ ๋ผ์ธ)๊ฐ€ ๋Š˜์–ด๋‚˜์„œ ์„œ๋ฒ„์˜ ์„ฑ๋Šฅ์— ์ข‹์ง€ ์•Š๊ณ , ์ฝ”๋“œ ๊ด€๋ฆฌ๋„ ์‰ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ํ๋‹จ์„ ๋ง‰๊ธฐ ์œ„ํ•ด, ์ธ๊ฐ€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ณ„๋„์˜ ์„œ๋น„์Šค๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

class CookieAuthorizer
{
    // ์‚ฌ์ดํŠธ ์ „์ฒด ๋ณดํ˜ธ ์„ค์ •
    public bool IsGlobal { get; set; } = false;

    // key: path,
    readonly Dictionary<string, List<Func<ClaimsPrincipal, int?>>> _requirements = [];

    public CookieAuthorizer()
    {
        _requirements["/secret"] =
        [
            (p) =>
            {
                var userName = p.FindFirstValue(nameof(User.Name));

                // ์ธ์ฆ๋˜์ง€ ์•Š์€ ์š”์ฒญ
                if (userName == null)
                {
                    return 401;
                }
                return null;
            },
            (p) =>
            {
                var skill = p.FindFirstValue(nameof(User.Skill));

                if (skill == "Jedi")
                    return null;

                // ๊ถŒํ•œ ์—†๋Š” ์š”์ฒญ
                return 403;
            },
        ];
    }

    // ์ธ๊ฐ€ ์„ฑ๊ณต: null, ์‹คํŒจ: ์—๋Ÿฌ ์ฝ”๋“œ
    public int? Authorize(HttpContext http, string path)
    {
        if (_requirements.ContainsKey(path) is false)
            return null;

        var filter = _requirements[path].FirstOrDefault(r => r.Invoke(http.User).HasValue);

        return filter?.Invoke(http.User);
    }
}

์ด๋ฅผ ์„œ๋น„์Šค ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

        // ์ฟ ํ‚ค ์ธ๊ฐ€ ์„œ๋น„์Šค
        builder.Services.AddScoped<CookieAuthorizer>();

์ธ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์ด ์„œ๋น„์Šค์— ์˜์กดํ•˜๋„๋ก ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

        // ์ธ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด
        app.Use((http, next) =>
        {
            var path = http.Request.Path;
            var authorizationService = http.RequestServices.GetRequiredService<CookieAuthorizer>();

            var failCode = authorizationService.Authorize(http, path);

            if(failCode.HasValue)
            {
                http.Response.StatusCode = failCode.Value;
                return Task.CompletedTask;
            }
       
            // ์‚ฌ์ดํŠธ ์ „์ฒด๋ฅผ ๋ณดํ˜ธํ•œ๋‹ค๋ฉด
            if (authorizationService.IsGlobal)
            {
                var userName = http.User.FindFirstValue(nameof(User.Name));
                var user = s_userRepo.FirstOrDefault(u => u.Name == userName);

                // ์œ„์กฐ/๋„์šฉ๋œ ํ‹ฐ์ผ“
                if (user == null)
                {
                    http.Response.StatusCode = 400;
                    http.Response.Cookies.Delete(COOKIE_KEY);

                    return Task.CompletedTask;
                }
            }

            return next();
        });

์ธ๊ฐ€์˜ ์„ค์ •

์‚ฌ์ดํŠธ ์ œ์ž‘์ž๋Š” ๋ณดํ˜ธ๊ฐ€ ํ•„์š”ํ•œ ์—”๋“œ ํฌ์ธํŠธ์™€ ์š”๊ฑด์„ ์ธ๊ฐ€ ์„œ๋น„์Šค์˜ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ง€์ •ํ•˜๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

    public CookieAuthorizer()
    {
        _requirements["/secret"] =
        [
            (p) =>
            {
                var userName = p.FindFirstValue(nameof(User.Name));

                // ์ธ์ฆ๋˜์ง€ ์•Š์€ ์š”์ฒญ
                if (userName == null)
                {
                    return 401;
                }
                return null;
            },
            (p) =>
            {
                var skill = p.FindFirstValue(nameof(User.Skill));

                if (skill == "Jedi")
                    return null;

                // ๊ถŒํ•œ ์—†๋Š” ์š”์ฒญ
                return 403;
            },
        ];
    }

์ธ๊ฐ€ ์ธํ”„๋ผ

์œ„ ์ฝ”๋“œ์˜ ๊ตฌ์กฐ๋Š” Asp.Net Core์˜ ์ธ๊ฐ€ ์ธํ”„๋ผ ์‚ฌ์šฉ๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.
์ธํ”„๋ผ๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ์‹์ด ๋™์ผํ•˜๊ณ ,
image

๋ณดํ˜ธ๋  ์—”๋“œ ํฌ์ธํŠธ๋ฅผ ๋ณ„๋„๋กœ ์ง€์ •ํ•œ๋‹ค๋Š” ์ ์—๋„ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
๋‹ค๋งŒ, ์ธํ”„๋ผ๋Š” Attribute ๋ฅผ ํ†ตํ•ด ์ง€์ •ํ•œ๋‹ค๋Š” ์ฐจ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทผ๋ณธ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ ์ œ๊ณต๊ณผ ๋ฐ์ดํ„ฐ ๋ณดํ˜ธ๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ์ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

SPA (Single Page Application)

์œ„์˜ ๋ฐฉ์‹์€ ์‚ฌ์‹ค ์ „ํ†ต์ ์ธ Http ์„ธ์…˜์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์„ค๊ณ„๋œ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.
๋‹ท๋„ท์„ ๊ธฐ์ค€์œผ๋กœ ๋งํ•˜๋ฉด, Asp.Net Core MVC, Asp.Net Core Web App, Asp.Net Core Wep Api ์—์„œ๋งŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•œ ๋ฐฉ์‹์œผ๋กœ, ๋ชจ๋“  ๋ฉ”์‹œ์ง€๊ฐ€ ์š”์ฒญ ํŒŒ์ดํ”„ ๋ผ์ธ(๋ฏธ๋“ค์›จ์–ด ์ง‘ํ•ฉ)๋ฅผ ํ†ต๊ณผํ•˜๋Š” ๊ฒƒ์„ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜, ๋ธ”๋ ˆ์ด์ € ์„œ๋ฒ„๋Š” Asp.Net Core ์•ฑ์ด๊ธฐ๋Š” ํ•˜์ง€๋งŒ, ํŽ˜์ด์ง€ ์ ‘์†๋งŒ ํŒŒ์ดํ”„ ๋ผ์ธ์„ ํ†ต๊ณผํ•˜๊ณ , ๊ทธ ์ดํ›„๋ถ€ํ„ฐ๋Š” ์›น์†Œ์ผ“์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์š”์ฒญ ํŒŒ์ดํ”„ ๋ผ์ธ์„ ํ†ตํ•œ ์ธ์ฆ/์ธ๊ฐ€๊ฐ€ ์—„๋ฐ€ํ•˜๊ฒŒ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ„ํ—˜ํ•œ ์˜ˆ๋กœ, ํ‹ฐ์ผ“์˜ ์œ ํšจ๊ธฐ๊ฐ„์ด ๋งŒ๋ฃŒ๋˜์—ˆ์ง€๋งŒ, ์›น์†Œ์ผ“ ํ†ต์‹ ์€ ๊ณ„์† ์œ ์ง€๋˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.
๋ธ”๋ ˆ์ด์ € ์„œ๋ฒ„๋Š” ์ด ๋ฌธ์ œ๋ฅผ ์ผ์ • ์‹œ๊ฐ„ ๋งˆ๋‹ค, ํ‹ฐ์ผ“์„ ์žฌ๊ฒ€์ฆํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. (8.0 ์€ ์•„์ง ์ž์„ธํžˆ ์•ˆ๋ด์„œ ๊ผญ ๊ทธ๋ ‡๋‹ค๊ณ  ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.)

์ฐธ๊ณ ๋กœ, ๋‹ท๋„ท์˜ ๋‹ค๋ฅธ SPA ์•ฑ์ธ ๋ธ”๋ ˆ์ด์ € ์™€์ฆ˜ ์•ฑ์˜ ๊ฒฝ์šฐ, ํด๋ผ์ด์–ธํŠธ ์•ฑ์ด๊ธฐ ๋•Œ๋ฌธ์—, ์ธ์ฆ/์ธ๊ฐ€์˜ ์†Œ๋น„์ž์ด์ง€ ์ƒ์‚ฐ์ž๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์ฆ‰ ์„œ๋ฒ„๋กœ ๋ถ€ํ„ฐ ํ‹ฐ์ผ“์„ ๋ฐ›๋Š” ์ž…์žฅ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ๋ธŒ๋ผ์šฐ์ € ๋‚ด๋ถ€์—์„œ ๋™์ž‘ํ•˜๊ธฐ์—, ํ‹ฐ์ผ“์ด ์ฟ ํ‚ค๋กœ ์‘๋‹ต๋œ ๊ฒฝ์šฐ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
๋ฐ”๋””๋กœ ์‘๋‹ต๋œ ๊ฒฝ์šฐ์—๋„, ๋ธŒ๋ผ์šฐ์ €์˜ ๋กœ์ปฌ/์„ธ์…˜ ์ €์žฅ์†Œ์— ์ €์žฅํ•ด๋†“๊ณ  ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

WPF, ์œˆํผ, ๋งˆ์šฐ์ด ๋“ฑ, ๋‹ค๋ฅธ ํ˜•ํƒœ๋กœ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„, HttpClient ๊ฐ์ฒด๊ฐ€ ๋ธŒ๋ผ์šฐ์ €์˜ ์ธํ”„๋ผ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ํฐ ๋ฌธ์ œ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

๋‹ค๋งŒ, ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์€ ํด๋ผ์ด์–ธํŠธ์™€ API ๋ชจ๋‘๋ฅผ ์ž‘์„ฑํ•  ๋•Œ, ์ธ์ฆ/์ธ๊ฐ€๋ฅผ ํด๋ผ์ด์–ธํŠธ์—์„œ ์ฒ˜๋ฆฌํ•˜๊ณ , API๋Š” ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š๋Š” ๊ตฌ์กฐ๋กœ ๋งŒ๋“ค๋ฉด ์•ˆ๋œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฐ ๊ตฌ์กฐ๋Š” ์„œ๋ฒ„ ์ฝ”๋“œ์™€ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋ฅผ ํ˜ผ๋™ํ•ด์„œ ์ƒ๊ธด ๋ฌธ์ œ๋กœ, ๋‹ท๋„ท์˜ ์™€์ฆ˜ ๊ด€๋ จ ๋ฌธ์„œ์—์„œ๋„ ์ˆ˜์‹œ๋กœ ์ฃผ์˜ํ•˜๋ผ๋Š” ๋‹น๋ถ€ํ•˜๊ณ  ์žˆ์œผ๋‹ˆ, ์ž˜ ๊ธฐ์–ตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

3๊ฐœ์˜ ์ข‹์•„์š”

๊ทผ๋ฐ์ด๋ฏธ์ง€๋Š”์ €๋งŒ๊นจ์ง€๋‚˜์š”?

1๊ฐœ์˜ ์ข‹์•„์š”

์ „ ์•ˆ๊นจ์ง€๋„ค์šค ใ…Žใ…Ž