๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Frontend Dev/๐Ÿฅ ์ฝ”๋“œ์Šคํ…Œ์ด์ธ  FE ๋ถ€ํŠธ์บ ํ”„

[Main Project 3์ฃผ์ฐจ] 9.11 ~ 9.17 | ๊ธฐ๋Šฅ ๊ตฌํ˜„ (ํŒ€์ฐพ๊ธฐ/ํŒ€์›์ฐพ๊ธฐ ๊ฒŒ์‹œํŒ CRUD, ๋Œ“๊ธ€, ๊ฒ€์ƒ‰/ํ•„ํ„ฐ)

๋ฐ˜์‘ํ˜•

[Main Project 3์ฃผ์ฐจ]  9.11 ~ 9.17
๊ธฐ๋Šฅ ๊ตฌํ˜„ (ํŒ€์ฐพ๊ธฐ/ํŒ€์›์ฐพ๊ธฐ ๊ฒŒ์‹œํŒ CRUD, ๋Œ“๊ธ€, ๊ฒ€์ƒ‰/ํ•„ํ„ฐ) 

๐Ÿ’ฌ ํ”„๋กœ์ ํŠธ๊ฐ€ ๋๋‚œ ํ›„์— ๋ฐ์ผ๋ฆฌ๋กœ ์ •๋ฆฌํ–ˆ๋˜ ๊ธฐ๋ก์„ ๋ณด๋ฉฐ ํ”„๋กœ์ ํŠธ ์ „์ฒด ๊ณผ์ •์„ ์ •๋ฆฌํ•˜์—ฌ 4์ฃผ์ฐจ๋กœ ๋‚˜๋ˆ„์–ด ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ”— 1์ฃผ์ฐจ

๐Ÿ”— 2์ฃผ์ฐจ

3์ฃผ์ฐจ: ํ˜„์žฌ๊ธ€

๐Ÿ”— 4์ฃผ์ฐจ

๐Ÿ”— ๋ฐ๋ชจ๋ฐ์ด & ํ”„๋กœ์ ํŠธ ์ „์ฒด ํšŒ๊ณ 

 

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป Github Repository https://github.com/sw2377/smoothie
๐Ÿš€ SUMMARY

 9.11 MON 
- ํŒ€์ฐพ๊ธฐ/ํŒ€์›์ฐพ๊ธฐ ๊ฒŒ์‹œํŒ CRUD API Call ํ…Œ์ŠคํŠธ ์™„๋ฃŒ

 9.12 TUE 
- front-end 2์ฐจ merge

 9.13 WED 
1. ์ „๋‚  merge ํ›„ ๋ฐœ์ƒํ–ˆ๋˜ authInstance ๊ด€๋ จ ์—๋Ÿฌ ํ•ด๊ฒฐ
2. ๋Œ“๊ธ€ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ์ค‘!
3. ํ”„๋ก ํŠธ์—”๋“œ ์ž„์‹œ ๋ฐฐํฌ (S3)


 9.14 THU 
1. ๐Ÿง™๐Ÿป 3์ฐจ ๋ฉ˜ํ† ๋ง ์„ธ์…˜
2. ์„œ๋ฒ„: ํƒ„๋ ฅ์ „ ์ฃผ์†Œ IP ์ ์šฉ


 9.15 FRY 
1. ํŒ€์ฐพ๊ธฐ/ํŒ€์›์ฐพ๊ธฐ ๊ฒŒ์‹œํŒ ์ˆ˜์ •์ž‘์—…
2. ๋Œ“๊ธ€ ์ผ€์ด์Šค๋ณ„ CSS ์ž‘์—…


 9.16 ~ 17 SAT, SUN 
โžก๏ธ ํ”„๋กœ์ ํŠธ ๋งˆ๊ฐ์ผ์ด ์ฝ”์•ž์ด๋ผ ๋งˆ๋ฌด๋ฆฌ ์ž‘์—… ์ง„์ž…
1. ํŒ€์ฐพ๊ธฐ/ํŒ€์›์ฐพ๊ธฐ ๊ฒŒ์‹œํŒ ๋ฐ ๋Œ“๊ธ€ ๊ธฐ๋Šฅ ๊ตฌํ˜„
2. ๊ฒŒ์‹œํŒ ๊ฒ€์ƒ‰/ํ•„ํ„ฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„
3. ๊ธฐ์ˆ ์Šคํƒ ์•„์ด์ฝ˜ ์ถ”๊ฐ€

 

๐Ÿ“™ 3์ฃผ์ฐจ ํšŒ๊ณ 

๐Ÿ“– ๋ชฉ์ฐจ

๋”๋ฏธ๋ฐ์ดํ„ฐ → ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ ๊ธฐ๋Šฅ ๊ตฌํ˜„

๋Œ“๊ธ€๋กœ ํŒ€์› ์ˆ˜๋ฝํ•˜๊ณ  ์•Œ๋ฆผ ๋ณด๋‚ด๊ธฐ
 
โ—พ๏ธ ๋Œ“๊ธ€ ์ผ€์ด์Šค๋ณ„ CSS ์ž‘์—…

  โ—พ๏ธ ๋Œ“๊ธ€ ์ˆ˜๋ฝํ•˜๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ์•Œ๋žŒ ๊ตฌํ˜„

AWS S3 ํ”„๋ก ํŠธ ๋ฐฐํฌ

๐Ÿง™๐Ÿป 3์ฐจ ๋ฉ˜ํ† ๋ง ์„ธ์…˜

์—๋Ÿฌ ํŒŒํ‹ฐ์˜ ์‹œ์ž‘

๋งˆ๋ฌด๋ฆฌ ์ž‘์—…์„ ํ•˜๊ณ  ์‹ถ์—ˆ์ง€๋งŒ…

๐Ÿ“ 3์ฃผ์ฐจ, ์ž‘์—…ํ•˜๋ฉฐ ๋‚˜๋Š” ๋ฌด์—‡์„ ๋ฐฐ์› ์„๊นŒ? (What I Learned)

  1. react-quill ์‚ฌ์šฉํ•˜๊ธฐ

 

๋”๋ฏธ๋ฐ์ดํ„ฐ → ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ ๊ธฐ๋Šฅ ๊ตฌํ˜„

 ๋‚ด๊ฐ€ ๋‹ด๋‹นํ–ˆ๋˜ ๋‘ ๊ฐœ์˜ ๊ฒŒ์‹œํŒ์„ ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋กœ๋งŒ ์ž‘์—…ํ•˜๋‹ค๊ฐ€, API Call์„ ํ†ตํ•ด ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ์ž‘์—…์„ ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ํฌ์ŠคํŠธ๋งจ๊ณผ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋ฒˆ๊ฐˆ์•„ ๊ฐ€๋ฉฐ HTTP ์š”์ฒญ๊ณผ ํ…Œ์ŠคํŠธ๋ฅผ ๋ฐ˜๋ณตํ–ˆ๊ณ , ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ๋ฅผ ์ œ์™ธํ•œ ์ž‘์„ฑ๊ณผ ์ˆ˜์ •, ์‚ญ์ œ, ๋Œ“๊ธ€์€ ๋ชจ๋‘ ๋กœ๊ทธ์ธ์ด ๋œ ์ƒํƒœ์—์„œ ์ด๋ฃจ์–ด์ ธ์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ…Œ์ŠคํŠธ ๊ณ„์ •์„ ๋งŒ๋“ค์–ด ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ์‹ค์ œ๋กœ ๋‚ด๊ฐ€ ์ž‘์—…ํ•  ํŽ˜์ด์ง€์—์„œ๋Š” ๊ฒŒ์‹œ๋ฌผ์„ ์‚ญ์ œํ•˜๋Š” ํ–‰์œ„๋Š” ํ•  ์ˆ˜ ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— (์‚ญ์ œ๋Š” ๋‹ค๋ฅธ ํ”„๋ก ํŠธ ํŒ€์›๋ถ„์ด ์ž‘์—…ํ•˜๋Š” ๋งˆ์ดํŽ˜์ด์ง€์—์„œ๋งŒ ๊ฐ€๋Šฅํ–ˆ๋‹ค) ์‚ญ์ œ ๊ธฐ๋Šฅ์€ ๋™์ž‘์„ ํ•˜๋Š”์ง€๋งŒ ํ™•์ธํ–ˆ๋‹ค.

 ์ฒ˜์Œ ์‚ฌ์šฉํ•ด๋ณด๋Š” Redux Toolkit์˜ createAsyncThunk์™€ auth๋ฅผ ๋‹ด๋‹นํ•œ ํŒ€์›๋ถ„๊ป˜์„œ ๋งŒ๋“  Axios Instance๋ฅผ ์‚ฌ์šฉํ•ด ๋น„๋™๊ธฐ ๋กœ์ง์„ ์ž‘์„ฑํ–ˆ๋‹ค. ์‚ฌ์‹ค ์ด๋ฒˆ์— ์ž‘์„ฑํ•œ Redux Toolkit ์ฝ”๋“œ๋Š” ๊ฐ•์˜๋ฅผ ์„  ์ˆ˜๊ฐ• ํ›„์— ๊ฐ•์˜์™€ ์ตœ๋Œ€ํ•œ ๋น„์Šทํ•œ ํ˜•ํƒœ๋กœ ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•œ๊ฑฐ๋ผ, ๋‹ค์‹œ ์ž‘์„ฑํ•ด๋ณด๋ผ๊ณ  ํ•˜๋ฉด ์•„๋งˆ ๋˜ ์ฐธ๊ณ ์ฝ”๋“œ๋ฅผ ์—ด์‹ฌํžˆ ํŒŒํ—ค์ณ๋ด์•ผํ•  ๊ฒƒ ๊ฐ™๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ thunk์™€ slice๋ฅผ ๋”ฐ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ, slice์˜ extraReducers์—์„œ pending, fulfilled, rejected ์‹œ์— ์–ด๋–ค ํ–‰๋™์„ ํ•˜๋ผ๊ณ  ๋งค๋ฒˆ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š”๊ฒŒ ๋งž๋Š” ๋ฐฉ๋ฒ•์ธ์ง€ ์˜๋ฌธ์ด ๋“ค์—ˆ๋‹ค. Redux Toolkit์—์„œ ์–ด๋– ํ•œ ๋ฐฉ์‹์œผ๋กœ data๋ฅผ fetchํ•˜๋Š”์ง€ ๋” ์ฐพ์•„๋ณผ ํ•„์š”์„ฑ์ด ์žˆ๋‹ค๊ณ  ๋Š๊ผˆ๋‹ค.

projectsThunks.ts, projectsSlice.ts

 

๋Œ“๊ธ€๋กœ ํŒ€์› ์ˆ˜๋ฝํ•˜๊ณ  ์•Œ๋ฆผ ๋ณด๋‚ด๊ธฐ

 ํŒ€์›์ฐพ๊ธฐ ๊ฒŒ์‹œํŒ์—๋Š” ๋Œ“๊ธ€๊ธฐ๋Šฅ์ด ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋Œ“๊ธ€ ๊ธฐ๋Šฅ๋„ ๊ตฌํ˜„์„ ํ•ด์•ผ ํ–ˆ๋‹ค. ๊ธฐํš ํšŒ์˜์—์„œ ํ”„๋กœ์ ํŠธ ์นธ๋ฐ˜์„ ํ†ตํ•ด ํ”„๋กœ์ ํŠธ๋ฅผ ๊ด€๋ฆฌ(ํŒ€์› ์ˆ˜๋ฝ ๋“ฑ์„ ํฌํ•จ)ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์—†์• ๋Š” ๋Œ€์‹  ๋Œ“๊ธ€์œผ๋กœ ๋Œ€์ฒดํ•˜์ž๊ณ  ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋Œ“๊ธ€ ๊ธฐ๋Šฅ ๋˜ํ•œ ํ•„์ˆ˜์˜€๋Š”๋ฐ, ๊ฐ„๋‹จํ•  ์ค„ ์•Œ์•˜๋˜ ๋Œ“๊ธ€๋„ ์ƒ๊ฐ๋ณด๋‹ค ํ•  ์ผ์ด ๋งŽ์•˜๋‹ค.

 

โ—พ๏ธ ๋Œ“๊ธ€ ์ผ€์ด์Šค๋ณ„ CSS ์ž‘์—…

๋Œ“๊ธ€ UI ๊ตฌํ˜„์ค‘

 

 ์šฐ์„  ์ฒซ๋ฒˆ์งธ๋กœ, ๋Œ“๊ธ€์˜ contents ์ผ€์ด์Šค๋ณ„๋กœ CSS ์ž‘์—…์ด ์ด๋ฃจ์–ด์ ธ์•ผ ํ–ˆ๋‹ค. ๋Œ“๊ธ€์„ ํ†ตํ•ด ํŒ€์› ์ˆ˜๋ฝ๊ณผ ๊ฑฐ์ ˆ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•œ ‘์ง€์›๋Œ“๊ธ€’๊ณผ ์ผ๋ฐ˜์ ์œผ๋กœ ๋Œ“๊ธ€์„ ์ž‘์„ฑํ•˜๋Š” ‘์ผ๋ฐ˜๋Œ“๊ธ€’๋กœ ๋‚˜๋‰˜์–ด์กŒ๋‹ค.

1. ์ผ๋ฐ˜๋Œ“๊ธ€ โžก๏ธ width 100%
2. ์ง€์›๋Œ“๊ธ€ โžก๏ธ width ์กฐ์ ˆ ํ•„์š”
  1) ์ˆ˜๋ฝ/๊ฑฐ์ ˆ ์ „: ์ˆ˜๋ฝํ•˜๊ธฐ ๊ฑฐ์ ˆํ•˜๊ธฐ ๋ฒ„ํŠผ ๋…ธ์ถœ
  2) ์ˆ˜๋ฝ/๊ฑฐ์ ˆ ํ›„: ์ˆ˜๋ฝ ๋˜๋Š” ๊ฑฐ์ ˆ ๋ฉ˜ํŠธ ๋…ธ์ถœ

 

 ๋˜ํ•œ ๋Œ“๊ธ€ ์ž‘์„ฑ์ž๋งŒ ๋Œ“๊ธ€์„ ์ˆ˜์ •/์‚ญ์ œ๊ฐ€ ๊ฐ€๋Šฅํ–ˆ๊ณ , ์ง€์›๋Œ“๊ธ€์ด ์ˆ˜๋ฝ๋œ ํ›„์—๋Š” ์ž‘์„ฑ์ž๋„ ์ˆ˜์ •/์‚ญ์ œ๊ฐ€ ๋ถˆ๊ฐ€ํ–ˆ๋‹ค. ์ด์— ๋งž์ถฐ ์ผ€์ด์Šค ์ž‘์—…์„ ํ•˜๋Š”๊ฒŒ ๊ฝค ๋ฒˆ๊ฑฐ๋กœ์› ๋‹ค.

 

DetailComments.tsx

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

 

โ—พ๏ธ ๋Œ“๊ธ€ ์ˆ˜๋ฝํ•˜๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ์•Œ๋žŒ ๊ตฌํ˜„

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

 ์ด์™€ ๊ด€๋ จํ•ด์„œ๋„ ๋ฐฑ์—”๋“œ ํŒ€์›๊ณผ ์ด์•ผ๊ธฐ๋ฅผ ๋ช‡ ๋ฒˆ ๋‚˜๋ˆ„์—ˆ์—ˆ๋Š”๋ฐ, ์ฒ˜์Œ์—๋Š” ๋ณต์žกํ–ˆ๋˜ API Call์ด ๋ฉ˜ํ† ๋ง ์„ธ์…˜ ํ›„ ์ •๋ง ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ณ€๊ฒฝ๋˜๊ธฐ๋„ ํ–ˆ์—ˆ๋‹ค.

โœ๏ธ ๋ฐฑ์—”๋“œ ํŒ€์›๊ณผ ํšŒ์˜๋ฅผ ํ•  ๋•Œ ๊ธฐ์–ตํ•ด์•ผ ํ•  ๋ถ€๋ถ„๋“ค์„ ๋ฉ”๋ชจํ•ด๋‘์—ˆ๋‹ค.

# ์•Œ๋žŒ
- alermType : ํŒ€์› ์ˆ˜๋ฝ์— ๋Œ€ํ•œ ๊ฑฐ๋ฉด 0(ACCEPT)
  (๋‹ค๋ฅธ ์•Œ๋žŒ์ด ์žˆ์„ ์ˆ˜๋„ ์žˆ์–ด์„œ ํ™•์žฅ์„ฑ์„ ์œ„ํ•ด ์ถ”๊ฐ€ํ•œ ํƒ€์ž…)
- targetId : ๋Œ“๊ธ€ ์ž‘์„ฑ์ž์˜ ID
- memberId : ๋ฉค๋ฒ„๋ณด๋“œ์˜ ID

- ๋ฉค๋ฒ„๋ณด๋“œ(ํŒ€์›์ฐพ๊ธฐ๊ฒŒ์‹œํŒ) ์ƒ์„ฑํ•  ๋•Œ /projects ๋กœ (post req: accountId ์ž‘์„ฑ์ž์•„์ด๋””, memberBoardId ๊ฒŒ์‹œ๊ธ€์•„์ด๋””)
โ–ถ๏ธŽ ๋ฐฑ์—”๋“œ์—์„œ ์ฒ˜๋ฆฌ๋จ.

- ์ˆ˜๋ฝ๋ฒ„ํŠผ ํด๋ฆญํ–ˆ์„ ๋•Œ
  - /projects ๋กœ (post req: accountId ๋Œ“๊ธ€์ž‘์„ฑ์ž์•„์ด๋””, memberBoardId ๊ฒŒ์‹œ๊ธ€์•„์ด๋””)
  - /alerms ๋กœ (post req: alermType ์•Œ๋žŒํƒ€์ž…, accountId ๋Œ“๊ธ€์ž‘์„ฑ์ž์•„์ด๋””, memberBoardId ๊ฒŒ์‹œ๊ธ€์•„์ด๋””)
  - /replys/{replyId} ๋กœ (patch req: acceptType)
  โ–ถ๏ธŽ ์ˆ˜๋ฝ/๊ฑฐ์ ˆ ํ™•์ธ ํ›„์—๋Š” ์ˆ˜์ •/์‚ญ์ œ ์•ˆ๋˜๋„๋ก.

โฌ‡๏ธŽ ๋ณ€๊ฒฝ

- ๋Œ“๊ธ€์ˆ˜์ •์€ content๋งŒ ๋ณด๋‚ด๋Š”๊ฑธ๋กœ ๋ณ€๊ฒฝ (acceptType ์ œ์™ธ)
- reply/accept/{replyId} → ์ˆ˜๋ฝ๋ฒ„ํŠผ ํด๋ฆญํ–ˆ์„ ๋•Œ
- ํ”„๋กœ์ ํŠธ ์ˆ˜๋ฝ์€ acceptType 1 ํ”„๋กœ์ ํŠธ ๊ฑฐ์ ˆ์€ acceptType 2

 

 ์ฒ˜์Œ์—๋Š” ๋Œ“๊ธ€์˜ “์ˆ˜๋ฝํ•˜๊ธฐ” ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์„œ๋ฒ„ ์ธก์˜ ๊ฐ ๋‹ค๋ฅธ ์—”๋“œํฌ์ธํŠธ๋กœ 3๋ฒˆ์˜ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐฑ์—”๋“œ ์ชฝ์—์„œ ์„ค๊ณ„๋ฅผ ํ•˜์…จ๊ธธ๋ž˜, ์ด๋ ‡๊ฒŒ 3๋ฒˆ์˜ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š”๊ฒŒ ๊ดœ์ฐฎ์€์ง€, ์‹ค๋ฌด์—์„œ๋„ ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉ์ด ๋˜๋Š”์ง€ ๊ถ๊ธˆํ•ด์„œ ๋ฉ˜ํ† ๋ง ์‹œ๊ฐ„์— ์งˆ๋ฌธ์„ ํ–ˆ์—ˆ๋‹ค. ๋ฐฑ์—”๋“œ ํŒ€์›๋ถ„๋„ ๊ด€๋ จํ•ด์„œ ๋ฐฑ์—”๋“œ ๋ฉ˜ํ† ๋ง ์‹œ๊ฐ„์— ์งˆ๋ฌธ์„ ํ•˜์…จ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. ๋‹ค์Œ๋‚  ํšŒ์˜๋ฅผ ํ•˜๋Š”๋ฐ ์š”์ฒญ์„ ํ•œ ๋ฒˆ์œผ๋กœ ์ค„์ด๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ์ˆ˜์ •ํ•˜๊ณ , ๋‚˜๋จธ์ง€ ๋กœ์ง์€ ๋ฐฑ์—”๋“œ์—์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค๊ณ  ํ•˜์…จ๋‹ค ๐Ÿฅฐ

 ์ด๋ฏธ HTTP ํ†ต์‹ ์ด ์ž˜ ๋˜๋Š” ์ƒํƒœ์—์„œ ์š”์ฒญ ํ•˜๋‚˜๋งŒ ๋ณด๋‚ด๋ฉด ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ˆ˜์›”ํ•˜๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

AWS S3 ํ”„๋ก ํŠธ ๋ฐฐํฌ

 ๋ฐฑ์—”๋“œ์˜ ๋ฐฐํฌ๋ฅผ ๋‹ด๋‹นํ•˜์‹  ํŒ€์›๋ถ„๊ป˜์„œ ์„ธํŒ…ํ•ด๋‘” AWS S3์— ํ”„๋ก ํŠธ์—”๋“œ ์ž„์‹œ ๋ฐฐํฌ๋ฅผ ํ–ˆ๋‹ค. ํ”„๋ฆฌ ํ”„๋กœ์ ํŠธ ๋•Œ๋„ S3๋กœ ํ”„๋ก ํŠธ ๋ฐฐํฌ๋ฅผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ถ€๋ถ„์€ ์–ด๋ ต์ง€ ์•Š๊ฒŒ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด Vercel๋กœ ๋ฐฐํฌ๋ฅผ ํ•ด๋ณด๊ณ  ์‹ถ์—ˆ๋Š”๋ฐ, Vercel๋กœ ๋ฐฐํฌ์‹œ ์„œ๋ฒ„์ธก https ์ด์Šˆ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„์—์„œ๋„ ์„ธํŒ…์„ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค๊ณ ๋„ ํ–ˆ๊ณ , ์ด ์ฆˆ์Œ ๊ณ„์†ํ•ด์„œ ํ”„๋กœ์ ํŠธ์— ์—๋Ÿฌ๊ฐ€ ๋ฐ˜๋ณต๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ง์„ ๊บผ๋‚ผ ์‹œ๊ฐ„์ด ์—†์—ˆ๋‹ค.

 ์—ฌํŠผ S3 ํ”„๋ก ํŠธ ๋ฐฐํฌ๋Š” ์›ํ™œํ•˜๊ฒŒ ์ž˜ ์ง„ํ–‰๋˜์—ˆ๋‹ค.

 

๐Ÿง™๐Ÿป 3์ฐจ ๋ฉ˜ํ† ๋ง ์„ธ์…˜

 ๋ฉ˜ํ† ๋ง ์„ธ์…˜์˜ ์งˆ๋ฌธ์„ ์ ๊ทน์ ์œผ๋กœ ํ™œ์šฉํ•œ ๋‚˜..

 ์ž‘์—…์„ ํ•˜๋‹ค๋ณด๋‹ˆ API ๋ช…์„ธ์„œ์— ํŽ˜์ด์ง€๋ณ„ ๊ฒŒ์‹œ๊ธ€ ๋ฆฌ์ŠคํŠธ์— ๋Œ€ํ•œ GET ์š”์ฒญ๊ณผ ๊ฒŒ์‹œ๊ธ€ ํ•˜๋‚˜์— ๋Œ€ํ•œ GET ์š”์ฒญ์ด ๋”ฐ๋กœ ์žˆ๋Š” ๊ฒƒ์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค. ๊ฒŒ์‹œ๊ธ€ ์ž์ฒด์— ๋Œ€ํ•œ response๋Š” ๊ฐ™์•˜๊ณ , ํŽ˜์ด์ง€๋ณ„ ๊ฒŒ์‹œ๊ธ€ ๋ฆฌ์ŠคํŠธ์˜ GET ์š”์ฒญ์€ page์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ์ถ”๊ฐ€๋˜์–ด ์žˆ์—ˆ๋‹ค.

 ์ด๋Ÿด ๊ฒฝ์šฐ, ์˜ˆ๋ฅผ ๋“ค์–ด ํŒ€์›์ฐพ๊ธฐ ๊ฒŒ์‹œํŒ์˜ "memberBoardId": 1์˜ ์ƒ์„ธํŽ˜์ด์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค๋ฉด,

 

  1. ํŒ€์›์ฐพ๊ธฐ ๊ฒŒ์‹œ๊ธ€ ๋ฆฌ์ŠคํŠธ response์—์„œ "memberBoardId": 1์„ ์ฐพ์•„ ์ƒ์„ธํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋‚˜์€์ง€

  2. ํŒ€์›์ฐพ๊ธฐ ๊ฒŒ์‹œ๊ธ€ ํ•˜๋‚˜์— ๋‹ค์‹œ ์š”์ฒญ์„ ๋ณด๋‚ด "memberBoardId": 1์˜ data๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•์ด ๋‚˜์€์ง€

 

 ์ž‘์—…์„ ํ•˜๋‹ค๊ฐ€ ๋ฌธ๋“ ๊ถ๊ธˆํ•ด์กŒ๋‹ค. ์ด์ „์— ๋„คํŠธ์›Œํฌ ์š”์ฒญ์€ ๋น„์šฉ์ด ๋น„์‹ธ๋‹ค๋Š” ๋‚ด์šฉ์„ ๋“ค์€ ์ ์ด ์žˆ์–ด ๋‹ค์‹œ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ๊ธฐ์กด์— ๋ฐ›์€ ์‘๋‹ต์—์„œ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๋Š” ๋ฐฉ๋ฒ•์ด ๋” ๋‚ซ์ง€ ์•Š์„๊นŒ? ๋ผ๊ณ  ์ƒ๊ฐ์„ ํ–ˆ๋Š”๋ฐ ์ •์ž‘ ๊ตฌํ˜„์€ ๋‘๋ฒˆ์งธ ๋ฐฉ๋ฒ•์œผ๋กœ ํ–ˆ์—ˆ๋˜ ๋‚˜๋ž€ ์‚ฌ๋žŒ… ๐Ÿซ ๐Ÿซ ๐Ÿซ 

 ์—ฌํŠผ ๊ฒฐ๋ก ์€ ์ƒˆ๋กœ ์š”์ฒญํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋‚ซ๋‹ค๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. (1๋ฒˆ ๋ฐฉ๋ฒ•) ์™œ๋ƒํ•˜๋ฉด ์ƒ์„ธํŽ˜์ด์ง€๋กœ ์ง„์ž…ํ•˜๋Š” ๋™์•ˆ ์ •๋ณด๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž์—๊ฒŒ ํ•ญ์ƒ ์—…๋ฐ์ดํŠธ๋œ ์ •๋ณด๋ฅผ ๋ณด์—ฌ์ค˜์•ผ ํ•œ๋‹ค๋ฉด ๋งค๋ฒˆ ์š”์ฒญ์„ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ฆ‰, ์ค‘์š”ํ•œ๊ฑด ์ˆ˜์‹œ๋กœ ๋ฐ”๋€Œ๋Š” ๋‚ด์šฉ์ธ์ง€, ๊ทธ๋ ‡์ง€ ์•Š์€์ง€๋ฅผ ํŒŒ์•…ํ•˜๋Š”๊ฒŒ ์ค‘์š”ํ•˜๋‹ค.

 

์ด ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹ค์–‘ํ•œ ๋ถ€๋ถ„์„ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์—ˆ๋Š”๋ฐ,

 

• ๋งˆ์ดํŽ˜์ด์ง€์˜ ๋ผ์šฐํŒ…์˜ ๊ฒฝ์šฐ url์„ mypage/5 ๋Œ€์‹  mypage/userid ์ด๋Ÿฐ์‹์œผ๋กœ ์œ ๋‹ˆํฌํ•œ ๊ฐ’์ด ์˜ค๋„๋ก ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•˜๋‹ค.

• ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์‹œ && ๋ณด๋‹ค ์‚ผํ•ญ์—ฐ์‚ฐ์ž๋ฅผ ์„ ํ˜ธ (isLogin ? <Hello /> : <World />)
  → ๋งŒ์•ฝ ์ฝ”๋“œ๋ฅผ ์ž˜๋ชป ์ž‘์„ฑํ–ˆ์„ ๋•Œ isLogin && <Hello /> ์ด๋Ÿฐ ์‹์˜ ์ž‘์„ฑ๋ฒ•์€ ์˜๋„์น˜ ์•Š๊ฒŒ 0์ด ํ™”๋ฉด์— ํ‘œํ˜„๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์ข…์ข… ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค.

• ์ตœ๋Œ€ํ•œ ์ž‘์€ ๋‹จ์œ„๋กœ ์ž‘์„ฑ
  → ๋ญ๋ผ๊ณ  ์„ค๋ช…ํ•ด์•ผ ๋”ฑ ๋งž๋Š” ์šฉ์–ด์ธ์ง€ ๋ชจ๋ฅด๊ฒ ๋Š”๋ฐ, ์˜ˆ๋ฅผ ๋“ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ํ˜•์‹์ด๋‹ค.

<ActionButton buttonType={"submit"}>
  {location.pathname.startsWith("/projectlist/edit") &&
    "์นด๋“œ ์ˆ˜์ •ํ•˜๊ธฐ"}
  {location.pathname.startsWith("/projectlist/new") &&
    "์นด๋“œ ๋“ฑ๋กํ•˜๊ธฐ"}
</ActionButton>

// location.pathname.startsWith("/projectlist/edit") 
// ์œ„ ํ‘œํ˜„ ๋Œ€์‹  ์•„๋ž˜์ฒ˜๋Ÿผ,

{ EDIT_CARD ? "์นด๋“œ ์ˆ˜์ •ํ•˜๊ธฐ" : "์นด๋“œ ๋“ฑ๋กํ•˜๊ธฐ" }
// ์ตœ๋Œ€ํ•œ ์ตœ์†Œ๋กœ ์ค„์ด๋Š” ๊ฒƒ์„ ์ถ”์ฒœ
// ๋ฌผ๋ก  ๋น„๊ต์  ๊ฐ„๋‹จํ•œ ๊ตฌํ˜„์ผ ๋•Œ๋Š” ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€์ง€๋Š” ์•Š์ง€๋งŒ
// ๊ตฌ์กฐ๊ฐ€ ์ข€ ๋ณต์žกํ•ด์ง€๋ฉด ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ด๋Š” ๊ฐœ์ธ์ด ์ž˜ ํŒ๋‹จํ•˜์—ฌ ์ž‘์—…ํ•˜๋ฉด ๋ ๋“ฏ!

 

์—๋Ÿฌ ํŒŒํ‹ฐ์˜ ์‹œ์ž‘

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

 ์ด๋Ÿฐ์ €๋Ÿฐ ์—๋Ÿฌ๊ฐ€ ์žˆ์—ˆ์ง€๋งŒ, ๋‹ค๋ฅธ ํŒ€์›๋“ค์ด ์ž‘์—…ํ•˜๋˜ ์ฝ”๋“œ์—์„œ ๋‚ฌ๋˜ ์—๋Ÿฌ๋ผ ์–ด๋–ค ๋ถ€๋ถ„์ด ์ž˜๋ชป๋˜์—ˆ์„๊นŒ ์ถ”์ธก๋งŒ ํ•  ๋ฟ ๋‚ด๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๊ฐ€ ์—†์—ˆ๋‹ค. ์•ฝ๊ฐ„์˜ ๋ฌด๋ ฅ๊ฐ์„ ๋Š๋ผ๋ฉด์„œ ๋‚ด๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ์ž‘์—…์„ ๋จผ์ € ์ง„ํ–‰ํ•ด์•ผ๋งŒ ํ–ˆ๋‹ค.

 

 

๐Ÿง ๋‹น์‹œ์—๋Š” ๊ฐ‘์ž๊ธฐ ์ž˜ ๋˜๋˜ ์ฝ”๋“œ๊ฐ€ merge ํ›„์— ๋˜์ง€ ์•Š๊ณ , ์ด๋Ÿฐ์ €๋Ÿฐ ๋ฌธ์ œ ์ƒํ™ฉ์— ๋ถ€๋”ชํžˆ์ž ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•ด์•ผ ํ• ์ง€ ์„œํˆด๋ €๋‹ค. ์„œ๋ฒ„ ์ชฝ ์ฝ”๋“œ์—์„œ ๋‚œ ์—๋Ÿฌ๋Š” ๋‘˜์งธ์น˜๊ณ , ์ดˆ๋ฐ˜์— ํ”„๋ก ํŠธ ์ชฝ์˜ authInstance ๊ด€๋ จํ•ด์„œ๋„ ๋‚œ ์—๋Ÿฌ๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ, ์ด ๋ถ€๋ถ„์„ ๋‹ค๋ฅธ ํ”„๋ก ํŠธ ํŒ€์›์ด ์ž‘์—…ํ–ˆ๊ณ , ๋‚˜๋Š” axios intersepter(? instance?)๋ฅผ ์‚ฌ์šฉํ•ด๋ณธ์ด ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฌด์—‡์ด ๋ฌธ์ œ์ธ์ง€ ์˜ˆ์ธกํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์› ๋‹ค. ๋‚ด๊ฐ€ ์ž‘์—…ํ•˜๋˜ ๋ถ€๋ถ„์—๋„ ํ•ด๋‹น ์—๋Ÿฌ๊ฐ€ ์˜ํ–ฅ์„ ๋ฏธ์ณค๊ธฐ ๋•Œ๋ฌธ์— ์ฒ˜์Œ์—๋Š” ๋ฌด์—‡์ด ๋ฌธ์ œ์ธ์ง€ ์‚ดํŽด๋ณด๊ธฐ๋Š” ํ–ˆ์—ˆ๋Š”๋ฐ, ์ž˜ ๋˜์ง€ ์•Š์ž ํ•ด์•ผํ•  ๋‹ค๋ฅธ ์ž‘์—…๋„ ๋งŽ์•„์„œ ํ•ด๋‹น ํŒ€์›๋ถ„์ด ํ•ด๊ฒฐ์„ ํ•ด์ฃผ๊ฒ ์ง€, ๋ผ๋Š” ์ƒ๊ฐ์œผ๋กœ ํ•œ ๋ฐœ ๋’ค๋กœ ๋ฌผ๋Ÿฌ๋‚˜์žˆ์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. ์šฐ๋ฆฌ ํ”„๋ก ํŠธ ํŒ€์›๋ถ„๋„ ๋ฌธ์ œ๊ฐ€ ๋ญ”์ง€ ์ฐพ๊ธฐ ํž˜๋“ค์–ดํ•˜๋Š” ๊ฒƒ ๊ฐ™๊ธฐ๋Š” ํ–ˆ์—ˆ๋Š”๋ฐ, ๊ฒฐ๊ตญ์—” ํ•ด๊ฒฐ์„ ํ–ˆ์—ˆ๋‹ค. ๋‹น์‹œ์—” ๋‚ด ์ž‘์—…ํ•˜๋Š”๋ฐ๋„ ๋ฐ”๋น ์„œ ๋‚จ์˜ ์ฝ”๋“œ์—์„œ ๋‚œ ์—๋Ÿฌ๋ฅผ ๋ณผ ์—ฌ์œ ๊ฐ€ ์—†์—ˆ๋Š”๋ฐ, ์ง€๊ธˆ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ๋‚˜์˜ ๊ทธ๋Ÿฐ ๋Œ€์ฒ˜๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉํ–ฅ์ด์—ˆ์„๊นŒ, ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ ๋‹ค. ์—๋Ÿฌ์˜ ์›์ธ์„ ๊ฒ€์ƒ‰ํ•ด์„œ ์ฐพ์•„๋ณด๋Š”๋ฐ ์‹œ๊ฐ„์„ ์กฐ๊ธˆ๋งŒ ๋” ๋“ค์˜€๋”๋ผ๋ฉด, ์กฐ๊ธˆ ๋” ๋งˆ์Œ์˜ ์—ฌ์œ ๋ฅผ ๊ฐ€์กŒ๋”๋ผ๋ฉด, ์ข€ ๋” ํ•จ๊ป˜ ์ƒ๊ฐํ•ด ๋ดค๋”๋ผ๋ฉด ์ด๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. ์„œ๋ฒ„ ์ชฝ ์ฝ”๋“œ์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์˜€๋‹ค. Java๋กœ ์ž‘์„ฑ๋œ ์ฝ”๋“œ๋ฅผ ๋”๋”์šฑ ์ฝ์„ ์ˆ˜๊ฐ€ ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ๋Š” ๋ฌผ๋ก ์ด๊ณ  ํ•ด๊ฒฐ๋ฐฉ์•ˆ๋„ ์˜ˆ์ธกํ•  ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค. ํ•˜์ง€๋งŒ ํŒŒ์ด์ฌ์„ ๊ณต๋ถ€ํ•ด๋ดค๋˜ ๋‹ค๋ฅธ ํ”„๋ก ํŠธ ํŒ€์›๋ถ„์ด ์ด๋Ÿฐ์ €๋Ÿฐ ๋ฐฉํ–ฅ์œผ๋กœ ๋ฌด์—‡์ด ๋ฌธ์ œ์ผ๊นŒ ์˜ˆ์ธกํ•˜๊ณ , ์˜๊ฒฌ์„ ๊ณต์œ ํ•ด์ฃผ๋Š” ๋ชจ์Šต์„ ๋ณด๋ฉด์„œ ๋ช‡๋ช‡ ์ƒ๊ฐ์ด ๋“ค์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. ๋ชจ๋“  ๊ฑธ ๋‹ค ์•Œ ์ˆ˜๋Š” ์—†๊ฒ ์ง€๋งŒ, ์กฐ๊ธˆ๋งŒ ๋” ๋„“๊ฒŒ ๊ณต๋ถ€๋ฅผ ํ•˜๋ฉด ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์— ๋Œ€ํ•ด ์กฐ๊ธˆ ๋” ์œ ์—ฐํ•œ ๋Œ€์ฒ˜๊ฐ€ ๋  ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ๋„ ๋“ค์—ˆ๋‹ค.

 

๋งˆ๋ฌด๋ฆฌ ์ž‘์—…์„ ํ•˜๊ณ  ์‹ถ์—ˆ์ง€๋งŒ…

 3์ฃผ์ฐจ์— ๋“ค์–ด์˜ค๋‹ˆ ๋งˆ์Œ์ด ๊ธ‰ํ•ด์กŒ๋‹ค. ์‹œ๊ฐ„์ด ์–ผ๋งˆ ๋‚จ์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์€๋ฐ, ํ•ด์•ผํ•  ์ผ์ด ๋„ˆ๋ฌด ๋งŽ์•˜๋˜ ๊ฒƒ์ด๋‹ค. ๋‹คํ–‰ํžˆ๋„ ๋งˆ์ง€๋ง‰ ์ฃผ๋ง์— ์„œ๋ฒ„๋ฅผ 12์‹œ ~ 9์‹œ๊นŒ์ง€ ์—ด์–ด์ฃผ๊ธฐ๋กœ ํ•ด์„œ ๊ทธ ์‹œ๊ฐ„๋™์•ˆ์€ ์„œ๋ฒ„ ํ†ต์‹ ์ด ํ•„์š”ํ•œ ์ž‘์—…์„ ๊ณ„์†ํ•ด์„œ ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 ์ฃผ๋ง๋™์•ˆ 2๊ฐœ์˜ ๊ฒŒ์‹œํŒ๊ณผ ๋Œ“๊ธ€์˜ ์ค‘์š”๋„ “์ƒ”์ธ ๊ธฐ๋Šฅ์€ ๋‹ค ๊ตฌํ˜„์„ ๋งˆ์ณค๊ณ , ๊ฒ€์ƒ‰๊ณผ ํ•„ํ„ฐ ๊ธฐ๋Šฅ๋„ ๋งˆ๋ฌด๋ฆฌ๋ฅผ ํ–ˆ๋‹ค. ์™„๋ฒฝํ•˜์ง€๋Š” ์•Š์•˜์ง€๋งŒ, ๊ธฐ๋Šฅ ๊ตฌํ˜„์ด ๋˜๋Š” ๊ฒƒ์— ์˜๋ฏธ๋ฅผ ๋‘์—ˆ๋‹ค.

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

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

 


๐Ÿ“ 3์ฃผ์ฐจ, ์ž‘์—…ํ•˜๋ฉฐ ๋‚˜๋Š” ๋ฌด์—‡์„ ๋ฐฐ์› ์„๊นŒ? (What I Learned)

1. react-quill ์‚ฌ์šฉํ•˜๊ธฐ

 

GitHub - zenoamaro/react-quill: A Quill component for React.

A Quill component for React. Contribute to zenoamaro/react-quill development by creating an account on GitHub.

github.com

 ์›น ์—๋””ํ„ฐ๋ฅผ ์ข€ ๋” ๋น ๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด react-quill ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. ๊ด€๋ จ๋œ ์ž๋ฃŒ๊ฐ€ ๋งŽ์•„์„œ ๋น ๋ฅด๊ฒŒ ์„ธํŒ…ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋‹ค๋งŒ ์„ธํŒ… ํ›„์— ์›น ์—๋””ํ„ฐ์— ์ž…๋ ฅ๋œ ๋‚ด์šฉ์„ ํ™”๋ฉด์— ์ถœ๋ ฅํ•˜๊ณ ์ž ํ•  ๋•Œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ž…๋ ฅํ•ด์ฃผ์–ด์•ผ ํ–ˆ๋‹ค.

 

<div dangerouslySetInnerHTML={{ __html: content }} />

 → React์—์„œ๋Š” ๋ณด์•ˆ ์ด์Šˆ๊ฐ€ ์žˆ์–ด ๊ธฐ๋ณธ์ ์œผ๋กœ HTML ํƒœ๊ทธ๋ฅผ ์ง์ ‘ ์‚ฝ์ž…ํ•  ์ˆ˜ ์—†๊ฒŒ ์„ค์ •๋˜์–ด ์žˆ๋Š”๋ฐ, ์œ„ํ—˜ํ•˜์ง€๋งŒ dangerouslySetInnerHTML ์ด ์†์„ฑ์„ ์‚ฌ์šฉํ•ด HTML ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ ‡๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ฒŒ ๋˜๋ฉด ๊ณต๊ฒฉ์ž๊ฐ€ ์•…์˜์  ์ฝ”๋“œ๋ฅผ ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰์‹œํ‚ค๋Š” XSS(Cross Site Script) ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•ด์ง€๋Š”๋ฐ, ์ด๋Ÿฐ ๊ฒฝ์šฐ ์ž…๋ ฅ ๊ฐ’์˜ ๋ณด์•ˆ ๊ฒ€์‚ฌ๋ฅผ ํ†ตํ•ด ์œ„ํ—˜์„ฑ์ด ์žˆ์„ ๋ฌธ์ œ๋ฅผ ์˜ˆ๋ฐฉํ•ด์•ผ ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

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

 

 โญ react-quill ์‚ฌ์šฉํ•˜๊ธฐ ์™ธ์—๋„ useParams()์— ํƒ€์ž…์„ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•, createAsyncThunk์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ 2๊ฐœ ์ด์ƒ ๋„˜๊ธฐ๊ธฐ ๋“ฑ ๊ธฐ๋Šฅ ๊ตฌํ˜„์„ ํ•˜๋ฉฐ ๋ชจ๋ฅด๋Š” ๋ถ€๋ถ„์„ ๋งŽ์ด ๋ฐฐ์› ์—ˆ๋Š”๋ฐ, ๋ง‰์ƒ ์ •๋ฆฌ๋ฅผ ํ•˜๋ ค๊ณ  ํ•˜๋‹ˆ ๋‚ด๊ฐ€ ๋ฐฐ์šด๊ฑธ ์•Œ๊ณ  ์‚ฌ์šฉํ•œ๊ฑด์ง€ ํ™•์‹ ์ด ๋“ค์ง€ ์•Š๋Š”๋‹ค. ์ง€๊ธˆ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ๊ฒ€์ƒ‰ํ•ด์„œ ์ฐพ์•˜๋˜ ๋ฐฉ๋ฒ•์„ ์ ์šฉํ–ˆ์„ ๋ฟ, ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ๋˜๋‹ค์‹œ ๋งŒ๋‚œ๋‹ค๋ฉด ๋‹ค์‹œ ๊ฒ€์ƒ‰ํ•˜๊ฒŒ ๋  ๊ฒƒ ๊ฐ™์œผ๋‹ˆ ์—ฌ๋Ÿฌ๋ฒˆ ๋งŒ๋‚˜์„œ ์ต์ˆ™ํ•ด์ง€๋˜์ง€, ๋…ธํŠธ ํ•œ์ผ ์— ์ž˜ ์ •๋ฆฌํ•ด๋‘๋˜์ง€ ํ•ด์•ผ๊ฒ ๋‹ค.

๋ฐ˜์‘ํ˜•