[TIL/Nest] 2025/05/08

์›๋ฏผ๊ด€ยท2025๋…„ 5์›” 8์ผ

[TIL]

๋ชฉ๋ก ๋ณด๊ธฐ
177/201
post-thumbnail

NestJS + Google OAuth + Session ์ค‘๊ฐ„ ์ •๋ฆฌ ๐Ÿคฎ

์ด ๊ธ€์€ ๋ถ€์ ์ ˆํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋งค์šฐ ๋†’์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ ์ •๋ง ์ž์‹ ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ ˆ๋Œ€๋กœ ๋ฏฟ์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

0. Overview โœ๏ธ

์•„,,, ๊ณ ๋ฏผ์ด ์ •๋ง ๋งŽ์•˜๋˜ ์ฃผ์ œ๊ณ  ์—ฌ์ „ํžˆ ์™„๋ฒฝํ•˜๊ฒŒ ํ•ด๊ฒฐ๋˜์ง€๋Š” ์•Š์•˜์Šต๋‹ˆ๋‹ค๋งŒ, ์™„๋ฒฝ์ด๋ผ๋Š” ๊ฑด ์—†์ฃ . ๊ณ„์† ๋ฐœ์ „ํ•ด ๋‚˜๊ฐ€๋Š” ๊ฒƒ์ด์ง€์š”. ์„ธ์…˜ ๋ฐฉ์‹์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ณผ์ •์—์„œ ์ œ๊ฐ€ ๊ฒช๊ณ  ์žˆ๋Š” ๋ฌธ์ œ๋“ค์„ ๊ณต์œ ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

์šฐ์„ ์€ ๊ตฌ์ฒด์ ์ธ ๋…ผ์˜์— ์•ž์„œ ์ •๋ฆฌ๋ณธ์„ ๊ณต์œ ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ์ œ์‹œ๋œ ๋ชฉ์ฐจ๋Š” ์ด๋ฏธ์ง€์˜ ์ˆœ์„œ์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋‚˜ ์ž์‹ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„๋Š” ์„œ๋ž์ด๊ณ , ํšŒ์› DB๋Š” ์•”๊ธฐ ๋…ธํŠธ์ด๋ฉฐ, ์„ธ์…˜ DB๋Š” ์ปจ๋‹ ํŽ˜์ดํผ์ฃ . ๊ทธ๊ฒŒ ๋ญ”๋ฐ.

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

๋‹คํ–‰ํžˆ ๊ฐ๋…๊ด€์ด ์ข€ ๋„๋„ํ•ฉ๋‹ˆ๋‹ค. ํฌ์ŠคํŠธ์ž‡์— ๋ณด๋‹ˆ 39ํŽ˜์ด์ง€์— ์˜ˆ์ƒ ๋ฌธ์ œ์— ๋Œ€ํ•œ ๊ฐœ๋…์ด ์žˆ๋‹ค๊ณ  ํ•˜๋„ค์š”. ๊ทธ ํŽ˜์ด์ง€๋ฅผ ํ†ตํ•ด ์•”๊ธฐ ๋…ธํŠธ๋ฅผ ์ฝ์–ด ๊ธฐ์–ต์„ ๋ณต์›ํ•˜๊ณ  ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ƒ…๋‹ˆ๋‹ค.

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

1. Click Google Button โœ๏ธ

๋ฌธ๋“ ๋กœ๊ทธ์ธ์ด ํ•˜๊ณ  ์‹ถ์–ด์กŒ์Šต๋‹ˆ๋‹ค. ํ•˜ํ•„์ด๋ฉด ๊ตฌ๊ธ€๋กœ ํ•˜๊ณ  ์‹ถ์–ด์กŒ์Šต๋‹ˆ๋‹ค. ํšŒ์›๊ฐ€์ž…์€ ๋˜์–ด ์žˆ๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

ํšŒ์›๊ฐ€์ž… ๋•Œ์™€ ๋™์ผํ•œ ํ”„๋กœ์„ธ์Šค(๊ตฌ๊ธ€ ํ”„๋กœ์„ธ์Šค)๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ๊ธ€๋กœ ๋กœ๊ทธ์ธ์„ ํ•˜๊ฒ ๋‹ค๋Š” ๋ง์€, ๊ตฌ๊ธ€ ์„œ๋น„์Šค๋ฅผ ํ•œ ๋ฒˆ์€ ๊ฑฐ์ณ์•ผ ํ•œ๋‹ค๋Š” ๋ง๊ณผ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํšŒ์›๊ฐ€์ž… ํ”„๋กœ์„ธ์Šค์—์„œ๋Š” ์œ ์ € ์ •๋ณด๊ฐ€ ์—†์—ˆ๊ธฐ์—, /phone ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•œ ๋’ค verification ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์ณ์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ๋Š” ์ด๋ฏธ ํšŒ์›๊ฐ€์ž…์ด ์™„๋ฃŒ๋œ ์œ ์ €์ž„์„ ์ „์ œํ•˜๊ธฐ ๋•Œ๋ฌธ์—, Database์—์„œ ํ•ด๋‹น ์œ ์ €๋ฅผ ์ฐพ๋Š” ๋กœ์ง์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

2. Find user in the user database โœ๏ธ

์•„ ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ ํƒˆ๋ชจ๊ฐ€ ์ง„ํ–‰๋˜๋Š”๋ฐ์š”, ์ €์˜ ์ตœ์ข…์ ์ธ ๋ชฉํ‘œ๋Š” ๊ตฌ๊ธ€ ์œ ์ € ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ์•„๋‹ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์—„๋ฐ€ํžˆ ๋”ฐ์ง€๋ฉด '๊ตฌ๊ธ€์„ ํ†ตํ•ด ๊ฐ€์ž…ํ•œ ์šฐ๋ฆฌ ์œ ์ €'์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ตฌ๊ธ€์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ณ ์œ ํ•œ accountId๋ฅผ, ์ตœ์ข… ์œ ์ € ํ…Œ์ด๋ธ”์˜ ์™ธ๋ž˜ํ‚ค๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ •์„์— ๊ฐ€๊นŒ์šฐ๋‚˜, ๊ฐœ๋–ก๊ฐ™์€ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ๋•Œ๋ฌธ์— ์–ด๋ ค์›€์ด ์žˆ์—ˆ๊ณ , ์—ฌ๊ธฐ์„œ ๋งŽ์€ ์‹œ๊ฐ„์„ ์ง€์ฒดํ•  ์ˆ˜๋Š” ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹คํ–‰ํžˆ ๋‘ ํ…Œ์ด๋ธ”์ด ๊ณตํ†ต์ ์œผ๋กœ email ๊ฐ’์„ ๊ฐ–๊ณ  ์žˆ์—ˆ๊ธฐ์— email๋กœ ์ ‘๊ทผํ•ด์„œ ์ตœ์ข… ์œ ์ € ์ •๋ณด๋ฅผ ๊บผ๋‚ด์™”์Šต๋‹ˆ๋‹ค. ๊ทธ ์ •๋ณด๊ฐ€ ์ฝ”๋“œ ์ƒ์˜ viaGoogleUser์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

์ข‹์€ ๊ธฐํš์€ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ ์€ ๊ธฐํš์ด๋ผ๋Š” ์ ์„ ๋‹ค์‹œ๊ธˆ ์ƒ๊ฐํ•ด ๋ณด๋ฉฐ, ์ด์–ด์„œ ๋‚ด์šฉ์„ ๊ณต์œ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

3. Create session โœ๏ธ

์„ธ์…˜์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”, ๊ธฐ์ดˆ์ ์ธ ์„ค์ • ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•˜๊ฒŒ๋งŒ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

app.use()์—๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ, ์„œ๋ฒ„๋กœ์˜ ์š”์ฒญ๊ณผ ์‘๋‹ต์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด cookie์™€ session, ๊ทธ๋ฆฌ๊ณ  passport๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค๊ณ  ๋ช…์‹œํ•œ ๊ฒƒ์œผ๋กœ ์œ„ ์ฝ”๋“œ๋ฅผ ํ•ด์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

4. Serialize session ID โœ๏ธ

serializeUser() ํ•จ์ˆ˜๊ฐ€ ์ „๋‹ฌ๋ฐ›๋Š” user๋Š” viaGoogleUser์ž…๋‹ˆ๋‹ค. ์„ธ์…˜์— ์ตœ์ข… ์œ ์ €์˜ id๋ฅผ ์ €์žฅํ•˜๊ฒ ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

์ดํ›„ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ req.login()์„ ์‹คํ–‰ํ•˜๋ฉด session ID๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

5. Response + session ID โœ๏ธ

๊ฐ„๋‹จํ•˜๊ฒŒ๋งŒ ์ƒ๊ฐํ•ด ๋ณด์ฃ . ์ง€๊ธˆ ์šฐ๋ฆฌ์˜ ๋ชฉ์ ์€, ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ์˜ id๋ฅผ ์„ธ์…˜์— ์ €์žฅํ•œ ๋’ค, ์„ธ์…˜ id๋ฅผ ํด๋ผ์ด์–ธํŠธ๋กœ '์ฟ ํ‚ค์— ๋‹ด์•„' ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ผ๋‹จ ํด๋ผ์ด์–ธํŠธ์— ์ฟ ํ‚ค๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด ๋ด…์‹œ๋‹ค.

์•„ ์•„์ฃผ ํƒˆ์ทจํ•˜๊ณ  ์‹ถ๊ฒŒ ์ž˜ ๋„์ฐฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ธฐํšŒ๊ฐ€ ๋˜๋ฉด ํ•ดํ‚น์„ ๊ณต๋ถ€ํ•ด ๋ณด๊ณ  ์‹ถ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ญ๋‹ˆ๋‹ค.

6. Request protected data โœ๏ธ

overview์—์„œ ์ œ์‹œํ•œ 6๋ฒˆ์— ๋Œ€ํ•œ ํ๋ฆ„์„ ํ™•์ธํ•ด ๋ณด์ฃ .

์„ธ์…˜ id๊ฐ€ ์ฟ ํ‚ค์— ๋‹ด๊ธด ์ƒํƒœ๋กœ ํด๋ผ์ด์–ธํŠธ์— ์™”์œผ๋‹ˆ, protected data์— ๋Œ€ํ•ด ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด, ์„œ๋ฒ„๋กœ ์ฟ ํ‚ค๊ฐ€ ์ „์†ก๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ฟ ํ‚ค์— ๋Œ€ํ•œ validation์„ ๊ฑฐ์นœ ๋’ค ์„ธ์…˜ id๋ฅผ ํ™•์ธํ•˜๊ณ , ์„ธ์…˜ id์— ๋งž๋Š” ์„ธ์…˜ ์œ ์ € ์ •๋ณด๋ฅผ ๋ณต์›ํ•ด์„œ ๋‹ค์‹œ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•ด ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ์„  ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

์œ„ ๋กœ์ง์€ ์•ฑ๋ฐ”์— ์ž‘์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์•ฑ๋ฐ”๊ฐ€ ๋ชจ๋“  ํŽ˜์ด์ง€์— ๊ฑธ์ณ ์žˆ์œผ๋‹ˆ, ์–ด๋–ค ํŽ˜์ด์ง€๋ฅผ ๊ฐ€๋“  ์ง€์†์ ์œผ๋กœ ์„ธ์…˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ์„ ์ด๋ฏธ ํ–ˆ๋Š”๋ฐ ์ง€์†์ ์œผ๋กœ ์‚ฌ์šฉ์ž ์„ธ์…˜ ์ •๋ณด๋ฅผ ์š”์ฒญํ•œ๋‹ค? ์ด๊ฑฐ์•ผ๋ง๋กœ protected data์— ๋Œ€ํ•œ ์š”์ฒญ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ .

7๋ฒˆ ํŒŒํŠธ์—์„œ๋Š” ์„ค๋ช…์ด ์•„๋‹ˆ๋ผ ์„๊ณ ๋Œ€์ฃ„๋ฅผ ํ•˜๋ ค ํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์‹ค NestJS์—์„œ ์„ธ์…˜ ๋ฐฉ์‹์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด Guard์™€ Strategy๋ผ๋Š” ๊ฐœ๋…์„ ์ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋„ˆ๋ฌด ๋งŽ์€ ๊ฒƒ์„ ๊ณ ๋ คํ•˜๊ฒŒ ๋˜๋ฉด, ํ•œ ๋ฐœ์ง๋„ ๋ชป ์›€์ง์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ฆ‰, ํ˜„์žฌ๋กœ์„œ๋Š” validate ๋กœ์ง์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์—ญ์ง๋ ฌํ™”๋กœ ๊ฐ€์‹œ์ฃ .

8. Deserialize session ID โœ๏ธ

์„ธ์…˜ id๋ฅผ ํ†ตํ•ด ์„ธ์…˜์—์„œ ์‹ค์ œ ์ €์žฅ๋œ ์œ ์ €์˜ id๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , ๊ทธ ๊ฐ’์„ ํ†ตํ•ด ์œ ์ € ์ •๋ณด๋ฅผ ๋ณต์›ํ•ด์„œ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

9. Response โœ๏ธ

๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ๋„์ฐฉํ–ˆ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„ค์š”.

Foreign key๋กœ database๋ฅผ mapping ํ•ด์•ผ ํ•˜๋Š”๋ฐ ์ผ๋‹จ email๋กœ viaGoogleUser๋ฅผ ํŒŒ์‹ฑ ํ–ˆ๋‹ค๋Š” ์ , Guard์™€ Strategy๋ฅผ ์ ์šฉํ•˜์ง€ ์•Š์•˜๋‹ค๋Š” ์ , ์„ธ์…˜ ID๋ฅผ ์ œ์™ธํ•˜๊ณ  ํ”„๋ก ํŠธ์—”๋“œ์— ๋‚ด๋ ค์•ผ ํ•  ์ตœ์†Œ data์— ๋Œ€ํ•œ ์ •๋ฆฌ๊ฐ€ ๋๋‚˜์ง€ ์•Š์•˜๋‹ค๋Š” ์ , ์ฟ ํ‚ค๊ฐ’(์„ธ์…˜ ID)๋ฅผ ํ†ตํ•œ UI/UX ์ฒ˜๋ฆฌ๊ฐ€ ์ง„ํ–‰๋˜์ง€ ์•Š์•˜๋‹ค๋Š” ์  ๋“ฑ์˜ ํ•œ๊ณ„๊ฐ€ ๋‚จ์•„์žˆ์Šต๋‹ˆ๋‹ค.

10. Conclusion โœ๏ธ

์•„ ์‰ฝ์ง€ ์•Š์€๋ฐ์š”. ์ˆ˜ํ•™ ์‹ค๋ ฅ์€, ์Žˆ์ˆ˜ํ•™ C ๋ ˆ๋ฒจ ๋ฌธ์ œ๋ฅผ ํ˜ผ์ž ๋™๋™๋Œ€๋ฉด์„œ ํ’€ ๋•Œ ๋А๋Š” ๋ฒ•์ด์ง€์š”. ์˜ค๋Š˜ ๋ญ”๊ฐ€ ์ž˜ ํ’€๋ฆฌ์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค ์„ฑ์žฅํ•˜์…จ์Šต๋‹ˆ๋‹ค. ์ž ๊น ์•ˆ ํ’€๋ฆฌ๋Š” ๊ฑธ๋กœ ์ฃผ๋ˆ… ๋“ค์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ์ž˜ ํ•ด๋‚ผ ๊ฒ๋‹ˆ๋‹ค. (๋ธ”๋กœ๊ทธ๋ฅผ ์šฐ์—ฐํžˆ ๋ณด๊ฒŒ ๋œ ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ)

profile
Write a little every day, without hope, without despair โœ๏ธ

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