[๐Ÿš— ํšŒ๊ณ ] ๊ฐœ๋ฐœ ์™„์„ฑ๋„๋ฅผ ๋†’์ธ๋‹ค๋Š” ๊ฒƒ์— ๋Œ€ํ•˜์—ฌ

devAndersonยท2023๋…„ 8์›” 25์ผ
4

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
100/105

๐Ÿ’ก ์‰ฌ์šด ๊ฐœ๋ฐœ์€ ์—†๋‹ค. ๋‹จ์ง€ ๋†“์น˜๊ณ  ์žˆ์„ ๋ฟ์ด๋‹ค

๋ฉด์ ‘์„ ๋‹ค๋‹ˆ๋‹ค ๋ณด๋ฉด ์ƒ๋‹นํžˆ ๋งŽ์€ ๋ถ„๋“ค์ด pdf๋กœ ๋œ ์ด๋ ฅ์„œ์— ์•„์ดํŒจ๋“œ๋กœ ๋ฉ”๋ชจ๋ฅผ ํ•˜์‹œ๋ฉด์„œ ์ง„ํ–‰ํ•˜์…จ๋˜๊ฑธ๋กœ ๊ธฐ์–ตํ•œ๋‹ค.

์ตœ๊ทผ ์ด๋ ฅ์„œ๋ฅผ ํ™ˆํŽ˜์ด์ง€๋กœ ์ง์ ‘ ๊พธ๋ฉฐ ๋ฐฐํฌ๋ฅผ ํ•˜๋ ค๋Š” ๋„์ค‘์— ์œ„์˜ ๊ธฐ์–ต๋“ค์ด ๋– ์˜ฌ๋ผ์„œ
(๊ทธ๋ฆฌ๊ณ  ๋งˆ์นจ ์‰ฝ๊ณ  ์žฌ๋ฐŒ์„ ๊ฒƒ ๊ฐ™์•„์„œ)
๋ฉ”๋ชจํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณด๋ฉด ์ข‹๊ฒ ๋‹ค๋Š” ๋งˆ์Œ์„ ๋จน๊ณ  ๊ฐœ๋ฐœ์„ ์ฐฉ์ˆ˜ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

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

๊ฐœ์ธ์ ์œผ๋กœ ๋งŽ์€ ์šฐ์—ฌ๊ณก์ ˆ์„ ๊ฒช์€ ํ† ์ด ํ”„๋กœ์ ํŠธ์ด๊ณ , ๊นจ๋‹ซ๋Š” ์ ์ด ์žˆ์–ด ์ด๋ฅผ ๊ธฐ๋ก์œผ๋กœ ๋‚จ๊ธฐ๋ ค๊ณ  ํ•œ๋‹ค.

์•„์ง๋„ ๋งŽ์€ ๋ถ€๋ถ„ ๊ฐœ์„ ์ค‘์ด์ง€๋งŒ ๊ถ๊ธˆํ•˜์‹  ๋ถ„๋“ค์€ "์•ค๋”์†์”จ์˜ ๋ ˆ์ฅฌ๋ฉ” ํŽ˜์ด์ง€" ๋‚˜ "๋ ˆ์ฅฌ๋ฉ” ์†Œ์Šค์ฝ”๋“œ" ๋ฅผ ์ฐธ์กฐํ•ด์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก ๋“œ๋กœ์ž‰ ์ž์ฒด๋Š” ์‚ฌ์‹ค ์—„์ฒญ๋‚˜๊ฒŒ ๊ฐ„๋‹จํ•˜๋‹ค

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

์บ”๋ฒ„์Šค์—์„œ 2d ๊ทธ๋ž˜ํ”ฝ ๋””์ž์ธ์„ ๊ทธ๋ฆฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์บ”๋ฒ„์Šค element์—์„œ getContext('2d') ๋ฅผ ํ†ตํ•ด ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์ปจํ…์ŠคํŠธ ์ธ์Šคํ„ด์Šค ๋‚ด์˜ ๋ฉ”์„œ๋“œ๋“ค์„ ์ ์ ˆ์ด ํ™œ์šฉํ•˜๋ฉด ๊ฐ€๋Šฅํ•˜๋‹ค.

const context = canvas.getContext('2d');

context.beginPath = ๋“œ๋กœ์ž‰์˜ ์‹œ์ž‘์„ ์•Œ๋ฆฌ๋Š” ํ•จ์ˆ˜
context.moveTo(x,y) = ๋“œ๋กœ์ž‰์˜ ์‹œ์ž‘ ์ขŒํ‘œ๋ฅผ ์„ค์ •ํ•˜๋Š” ํ•จ์ˆ˜
context.lineTo(x,y) = ํŠน์ • ์ขŒํ‘œ๊นŒ์ง€ ๋“œ๋กœ์ž‰ ๊ฒฝ๋กœ๋ฅผ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜
context.stroke = ๋งŒ๋“ค์–ด์ง„ ๋“œ๋กœ์ž‰ ๊ฒฝ๋กœ์— ์‹ค์ œ ํ”ฝ์…€์„ ์ ์šฉ์‹œ์ผœ ์บ”๋ฒ„์Šค์— ๋‚˜ํƒ€๋‚ด๊ฒŒ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜.

์ฆ‰ ์บ”๋ฒ„์Šค์— ๋ผ์ธ ํ•˜๋‚˜๋ฅผ ๊ทธ๋ฆฌ๋ ค๋ฉด beginPath => moveTo => lineTo => stroke ์ˆœ์œผ๋กœ ์ง„ํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ ๋‚ด์šฉ์€ ์บ”๋ฒ„์Šค element ๋‚ด์— ํ”ฝ์…€๋กœ ๋‚จ์•„์žˆ๊ฒŒ ๋œ๋‹ค.

๋งŒ์•ฝ ์บ”๋ฒ„์Šค ๋‚ด์— ์ง€์ •๋œ pixel๊ฐ’๋“ค์„ ์ดˆ๊ธฐํ™”ํ•˜๊ณ ์‹ถ๋‹ค๋ฉด context.clearRect ๋ฅผ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค. ๋„ค์ด๋ฐ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋“ฏ์ด ํ˜ธ์ถœ์„ ํ•˜๋ฉด ์ธ์ž๋กœ ์ „๋‹ฌ๋˜๋Š” ์˜์—ญ๋งŒํผ์˜ ํ”ฝ์…€์„ ์‚ญ์ œํ•œ๋‹ค.

์œ„์˜ ๋‚ด์šฉ๋งŒ ๋ด์„œ๋Š” ์ฐธ์œผ๋กœ Easyํ•˜๊ธฐ ๊ทธ์ง€์—†๋Š” ๋‚ด์šฉ์ด๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ๋กœ๋„ ์ธํ„ฐ๋„ท์— ๋ธ”๋กœ๊น…๋˜์–ด์žˆ๋Š” ๋‚ด์šฉ๋“ค์„ ๋ณด๋ฉด ์—ฌ๊ธฐ๊นŒ์ง€์˜ ๋‚ด์šฉ์ด ๋งŽ๋‹ค.

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

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

๐Ÿ’ก ํผ์งํผ์งํ•œ ๋ฌธ์ œ๋“ค์„ ๋‚˜์—ดํ•ด ๋ณด์ž๋ฉด

๐Ÿšจ ERROR 1. ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€๋Š” ๋„ˆ๋ฌด ์ž‘๊ณ , ๋ฐ์ดํ„ฐ ์ €์žฅ์€ ์ตœ์ ํ™”๋ฅผ ํ•„์š”๋กœํ–ˆ๋‹ค.

์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๊ธฐ ์ „๊นŒ์ง€์˜ ๋‚˜์—๊ฒŒ ์–ธ์ œ๋‚˜ ๋กœ์ปฌ ์œ ์ €์—๊ฒŒ ๋ฌด์–ธ๊ฐ€๋ฅผ ์ €์žฅ์‹œํ‚ค๋ ค๋ฉด ๋‹น์—ฐํžˆ ํƒํ•˜๋Š” ์„ ํƒ์ง€๋Š” "๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€" ์˜€์—ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ์ด๋ฒˆ์— ์บ”๋ฒ„์Šค ์ด๋ฏธ์ง€๋ฅผ ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€์— ์ง‘์–ด๋„ฃ์œผ๋ ค๋‹ค๊ฐ€ ์›น์ด ํ„ฐ์ง€๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ–ˆ๋‹ค.

์Šคํ† ๋ฆฌ์ง€ ์šฉ๋Ÿ‰์ด ๋„˜์น  ๊ฒฝ์šฐ ์‰ฝ๊ฒŒ ๋งŒ๋‚˜๊ฒŒ ๋˜๋Š” QuataExceeded ์—๋Ÿฌ์˜ ์˜ˆ์‹œ

์ฒ˜์Œ์—๋Š” ๊ทธ๋ƒฅ ์บ”๋ฒ„์Šค์—์„œ ์ถ”์ถœ๋œ ์ด๋ฏธ์ง€ ๊ฐ์ฒด ๊ทธ ์ž์ฒด๋ฅผ ์ง๋ ฌํ™”ํ•˜์—ฌ ๋„ฃ์—ˆ๋˜ ๊ฒƒ์ด ๋ฌธ์ œ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.
์™œ๋ƒํ•˜๋ฉด ์ด๋ฏธ์ง€ ๊ฐ์ฒด๋ฅผ ์ง๋ ฌํ™”ํ•ด๋„ ์ด๋ฏธ ๊ทธ ํฌ๊ธฐ๊ฐ€ ์ตœ์†Œ 5mb๋ฅผ ๋„˜์–ด๊ฐ€๊ธฐ ๋•Œ๋ฌธ์ด์—ˆ๋‹ค.

๋‹จ์ˆœํ•˜๊ฒŒ ์  ํ•˜๋‚˜๋งŒ ์ฐ์–ด๋„ ์ƒ์„ฑ๋˜๋Š” ์บ”๋ฒ„์Šค ์ด๋ฏธ์ง€๊ฐ€ 2๊ฐœ๋งŒ ๋˜์–ด๋„ ์ด๋ฏธ localStroage๋Š” ์šฉ๋Ÿ‰ ์ดˆ๊ณผ๋ฅผ ์ผ์œผํ‚ค๋ฉฐ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

๊ทธ๋Ÿฐ๋‹ค๊ณ  ๊ฐœ์ธ ๋ฉ”๋ชจ ์‹œ์Šคํ…œ์„ ์œ„ํ•ด์„œ ์„œ๋ฒ„์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์€ ๊ณผํ•œ ํŠธ๋ ˆ์ด๋“œ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.

์„ค๋ น AWS๋กœ ์„œ๋ฒ„๋งŒ๋“ค๊ณ  RDS์—๋‹ค๊ฐ€ ๋ฉ”๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค๊ณ  ํ•ด๋„ ๋ฌธ์ œ๋‹ค. ๊ณผ์—ฐ ์ด๊ฒŒ Production Level์„ ๊ณ ๋ คํ•œ๋‹ค๋ฉด ๋งž๋Š” ๊ตฌํ˜„์ผ๊นŒ

๋‹ต์€ ์ ˆ๋Œ€ ์•„๋‹ˆ๋‹ค์˜€๋‹ค. ํ•œ ์‚ฌ๋žŒ์ด ๋ฉ”๋ชจ๋ฅผ ๋ช‡๋ฒˆ ํš ๊ทธ์€๊ฒƒ๋งŒ์œผ๋กœ๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜๋Š”๊ฒŒ ๋ช‡์‹ญ mb๋ผ๋ฉด ์œ ์ €๊ฐ€ ์ˆ˜๋ฐฑ, ์ˆ˜์ฒœ, ์ˆ˜๋งŒ์ด ๋˜๋Š” ์ˆœ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜๋Š” ๋ฐ์ดํ„ฐ์˜ ์–‘์€ ๊ธฐํ•˜๊ธ‰์ˆ˜์ ์œผ๋กœ ๋Š˜์–ด๋‚  ๊ฒƒ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋‚ด ๋ˆ๋„ DB ์œ ์ง€๋น„๋กœ ๋‚ ์•„๊ฐˆ๊ฒƒ์ด๋‹ค

๋‚˜๋Š” ์–ด๋–ป๊ฒŒ๋“  ๊ฐœ์ธ์˜ ๋ฉ”๋ชจ ๋ฐ์ดํ„ฐ๋Š” ๊ฐœ๋ณ„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์†Œ์ง€ํ•˜๊ณ  ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ค.

๋งˆ์น˜ ์ฟ ํ‚ค์ฒ˜๋Ÿผ, ๊ฐœ๋ณ„์ ์œผ๋กœ๋งŒ ์‹๋ณ„ ๊ฐ€๋Šฅํ•˜๊ณ  ์‚ฌ์šฉ๋  ๋ฐ์ดํ„ฐ๊ฐ€ ๊ตณ์ด ์„œ๋ฒ„์˜ ์„ธ์…˜์ด๋‚˜ DB์— ์ €์žฅ๋˜๋Š” ๊ฒƒ์€ ์˜ณ์ง€ ๋ชปํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.

๊ทธ๋ž˜์„œ ํด๋ผ์ด์–ธํŠธ๋‹จ์—์„œ ์‚ฌ์šฉํ•  ์ €์žฅ์†Œ๋ฅผ ์กฐ๊ธˆ ๋” ์ฐพ์•„๋ณด๋‹ˆ ์›น ์Šคํ† ๋ฆฌ์ง€๋กœ indexedDB๋ผ๋Š” ์กด์žฌ๊ฐ€ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

indexedDB์— ๋Œ€ํ•œ ์‚ฌ์šฉ๋ฐฉ๋ฒ•์€ ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ indexedDB ํŠœํ† ๋ฆฌ์–ผ ์—์„œ ์ž์„ธํ•˜๊ฒŒ ์„ค๋ช…ํ•ด์ฃผ๊ณ  ์žˆ๋‹ค. ์ด๋ฒˆ์—๋Š” ๊ฐœ์„ ์ ์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ์ฃผ์ œ๋กœ ์ ์„ ๊ฒƒ์ด๊ธฐ์— indexedDB์— ๋Œ€ํ•œ ์‚ฌ์šฉ๋ฐฉ์‹์˜ ๊ธฐ๋ก์€ ์ถ”ํ›„ ๋‚จ๊ธฐ๊ณ  ๋งํฌ๋กœ ๋Œ€์ฒดํ•˜๋ ค ํ•œ๋‹ค.

๊ธฐ๋ณธ์ ์ธ ์ปจ์…‰๋งŒ ๋‹ค์‹œ ์ƒ๊ธฐํ•ด๋ณด์ž๋ฉด

  1. indexedDB๋Š” ํด๋ผ์ด์–ธํŠธ์ธก์—์„œ ์ œ๊ณตํ•˜๋Š” ์Šคํ† ๋ฆฌ์ง€ API์ด๋‹ค.
  2. ์ €์žฅ ๊ณต๊ฐ„์€ ๋ธŒ๋ผ์šฐ์ €๋งˆ๋‹ค ์ฐจ์ด๊ฐ€ ์žˆ์ง€๋งŒ ๋ณดํ†ต HDD์˜ 50% ์ด์ƒ ์ €์žฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  3. ๊ฑฐ์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. (key - value ํ˜•ํƒœ๋กœ ๊ด€๋ฆฌ๋œ๋‹ค)
  4. Transaction์ด๋ผ๋Š” DBํ†ต์‹ ์„ ์œ„ํ•œ ์ธ์Šคํ„ด์Šค์˜ ๋ฉ”์†Œ๋“œ๋“ค์„ ํ™œ์šฉํ•ด ๋น„๋™๊ธฐ์ ์œผ๋กœ CRUD ์ž‘์—…์„ ํ•œ๋‹ค.

์ด ์›น ์Šคํ† ๋ฆฌ์ง€๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์–ผ๋งˆ๋“ ์ง€ ์ž์œ ๋กญ๊ฒŒ ์˜์†์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅ์‹œํ‚ฌ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

(์ปดํ“จํ„ฐ์˜ ์ž”์—ฌ์šฉ๋Ÿ‰์„ ๋„˜๊ธธ ์ˆ˜๋Š” ์—†์ง€๋งŒ, ๊ทธ ์ „๊นŒ์ง€๋ผ๋ฉด ์ €์žฅ ๊ฐ€๋Šฅ! ๊ทธ๋ฆฌ๊ณ  ์ž”์—ฌ ์šฉ๋Ÿ‰๋„ navigator API๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ €์žฅํ•˜๊ธฐ ์ „ ๋ฏธ๋ฆฌ ํ•ธ๋“ค๋ง์ด ๊ฐ€๋Šฅํ•˜๋‹ค.)

๊ทธ๋ž˜์„œ ์ฒ˜์Œ์—๋Š” indexedDB์—๋‹ค๊ฐ€ ์ด๋ฏธ์ง€ ์ธ์Šคํ„ด์Šค ๊ทธ ์ž์ฒด๋ฅผ ์ง‘์–ด๋„ฃ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ์—ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ๊ทธ๊ฒŒ ๊ณผ์—ฐ ๊ดœ์ฐฎ์€ ํ–‰๋™์ผ๊นŒ ํ•˜๋Š” ์˜๋ฌธ์ด ๋‚ด indexedDB ์Šคํ† ๋ฆฌ์ง€๋ฅผ ๋ฐ”๋ผ๋ณด๋ฉด์„œ ๋“ค๊ฒŒ ๋˜์—ˆ๋‹ค.
image

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

๊ฑฐ๊ธฐ๋‹ค๊ฐ€ ์ €์žฅ๋งŒ ํ•˜๊ณ  ๋๋‚  ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ์—ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋งŒ์•ฝ ํš์„ 200๋ฒˆ ๊ทธ์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ, ๋‹ค์‹œ ๋Œ์•„์˜ค๋ฉด ์ด 200๋ฒˆ์— ๋Œ€ํ•œ ๋ชจ๋“  ์ด๋ฏธ์ง€๋ฅผ canvas์— ๊ทธ๋ ค๋‚ด์•ผ ํ•œ๋‹ค. ์ด๋Š” ์—„์ฒญ๋‚œ ๋ฒ„๋ฒ…์ž„์„ ์œ ๋ฐœํ•˜์—ฌ UX์— ๊ทน๋„๋กœ ์•…์˜ํ–ฅ์„ ๋ฏธ์ณค๋‹ค.

๊ทธ๋ž˜์„œ ์ตœ๋Œ€ํ•œ ์ตœ์ ํ™”์˜ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ณด๊ณ ์ž ๊ณ ๋ฏผ์„ ํ•˜๊ฒŒ ๋˜์—ˆ๊ณ , ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฐ๋ก ์„ ์–ป๊ฒŒ ๋˜์—ˆ๋‹ค.

  1. ๊ตณ์ด ์ด๋ฏธ์ง€ ์ธ์Šคํ„ด์Šค๋ฅผ ์ง๋ ฌํ™”ํ•ด์„œ๊ฐ–๊ณ ์žˆ์ง€ ๋ง๊ณ , ์บ”๋ฒ„์Šค์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ dataURL๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๊ฐ–๊ณ  ์žˆ๊ฒŒ ํ•˜์ž
  2. ์ตœ๋Œ€ํ•œ ์บ”๋ฒ„์Šค์—์„œ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ํ•„์š” ๋‚ด์šฉ๋งŒ ์„ ๋ณ„ํ•˜์—ฌ ๊ด€๋ฆฌํ•˜๋Š” ์ตœ์ ํ™” ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜์ž. ๊ทธ๋ž˜์„œ ์ตœ์ข…์ ์œผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์ €์žฅํ•˜๊ณ  ์žˆ์–ด์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๋ฅผ ์ตœ์†Œํ™”์‹œํ‚ค์ž.

์šฐ์„  1๋ฒˆ์— ๋Œ€ํ•ด์„œ๋Š” canvas์—์„œ ์ž์ฒด์ ์œผ๋กœ ์ž์‹ ์˜ ๋ฐ์ดํ„ฐ๋ฅผ dataURL๋กœ ๋ณ€ํ™˜ํ•ด ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ canvas.toDataURL ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•ด๊ฒฐ๋œ๋‹ค.

dataURL์ด๋ž€ ํŠน์ • ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒŒ์ผ์„ data์ ‘๋‘์‚ฌ๊ฐ€ ๋ถ™๋Š” ์ŠคํŠธ๋ง ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•œ ๊ฐ’์ด๋‹ค.
๊ตฌ์กฐ์ ์œผ๋กœ data:MIMEํƒ€์ž…;์ธ์ฝ”๋”ฉ๋ฐฉ์‹, ๋ณ€ํ™˜์ฒ˜๋ฆฌ๋œ ์ŠคํŠธ๋ง๊ฐ’์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.image

๊ทธ๋ž˜์„œ ๋ฉ”๋ชจ ์ด๋ฏธ์ง€๋ฅผ dataURL๋กœ ๋ณ€ํ™˜ํ•œ ํ›„, ์ด๊ฒƒ์„ indexedDB์— ์ €์žฅํ–ˆ๋‹ค๊ฐ€ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ imageData๋กœ ๋‹ค์‹œ ๋ณ€ํ™˜์‹œ์ผœ ์‚ฌ์šฉํ•˜๋ฉด ๋˜์—ˆ๋‹ค.

image

๊ทธ๋Ÿฐ๋ฐ, ์—ฌ๊ธฐ์„œ 2๋ฒˆ์— ๋Œ€ํ•œ ๋ฌธ์ œ์ ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

์œ ์ €๊ฐ€ ๋‹ค์‹œ ๋“ค์–ด์™”์„ ๋•Œ, ๋กœ์ปฌ์— ์ €์žฅ๋œ ๋ฉ”๋ชจ๋“ค์„ ๊ฐ€์ง€๊ณ  dataURL => imageData๋กœ ๋ณ€ํ™˜์„ ์‹œํ‚ค๋Š” ๊ณผ์ •์—์„œ, ํ•„์—ฐ์ ์œผ๋กœ image ์™€ canvas๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด์—ˆ๋‹ค.

export function converURLToImageData(url: string | null) {
  return new Promise<ImageData | null>((resolve, reject) => {
    if (!url) return reject(null);
    const canvas = document.createElement('canvas'); // 1. ์บ”๋ฒ„์Šค๋งŒ๋“ค๊ณ 
    const context = canvas.getContext('2d');
    const image = new Image(); // 2. ์ด๋ฏธ์ง€๋งŒ๋“ค๊ณ 
    image.src = url;
    image.addEventListener(
      'load',
      () => {
        canvas.width = image.width;
        canvas.height = image.height;
        context.drawImage(image, 0, 0, canvas.width, canvas.height); //  3. ์ด๋ฏธ์ง€ ๊ทธ๋ฆฌ๊ณ 
        resolve(context.getImageData(0, 0, canvas.width, canvas.height)); // 4. imageData๋ฅผ ์ถ”์ถœํ•ด์•ผ ํ•œ๋‹ค.
      },
      false,
    );
    image.addEventListener('error', () => reject(null));
  });
}

์œ„์—๋Š” dataURL์„ image ์ธ์Šคํ„ด์Šค ๋ฐ์ดํ„ฐ๋กœ ๋ณ€ํ™˜์‹œํ‚ค๋Š” ๋กœ์ง์„ ์ถ”์ƒํ™”ํ•œ ํ•จ์ˆ˜์ด๋‹ค.
์œ„์˜ ๋กœ์ง์„ ๋ณด๋ฉด ์ด 4๊ฐ€์ง€์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฑฐ์ณ์„œ ๊ฒฐ๊ณผ์ ์œผ๋กœ ์–ป๊ณ  ์‹ถ์€ ๊ฐ’์„ ๊ฐ€์ง€๊ฒŒ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ถ€ํ•˜ํ…Œ์ŠคํŠธ๋กœ ์ง์ ‘ 200๋ฒˆ์„ ๊ทธ์–ด๋ณธ ๋‹ค์Œ ์ƒˆ๋กœ๊ณ ์นจ์„ ํ•ด์„œ 200๊ฐœ์˜ dataURL์„ imageData๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ผ€์ด์Šค๋ฅผ ์‹œ๋„ํ•ด๋ณธ ๊ฒฐ๊ณผ, dataURL์ด๋ผ ํ• ์ง€๋ผ๋„ ์ƒ๋‹นํ•˜๊ฒŒ ๋ฒ„๋ฒ…์ธ ํ›„ ๋“œ๋กœ์ž‰ ๋ฐ์ดํ„ฐ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜๋Š” ํ˜„์ƒ์„ ๋ชฉ๊ฒฉํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

๊ทธ๋ž˜์„œ dataURL๋กœ ๋ฐ”๊พผ ๊ฒƒ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ทผ๋ณธ์ ์œผ๋กœ indexedDB์— ์ €์žฅ๋˜์–ด ์žˆ๋Š” ๊ฐ’ ์ž์ฒด๊ฐ€ ๋งŽ์•„์„œ๋Š” ์•ˆ๋œ๋‹ค๋Š” ๊ฒฐ๋ก ์ด ๋‚ฌ๋‹ค.

๊ทธ๋Ÿด๋ ค๋ฉด ์ •๊ตํ•˜๊ฒŒ ์บ”๋ฒ„์Šค์—์„œ ์ €์žฅ๋  ์ด๋ฏธ์ง€๋ฅผ ์„ ๋ณ„ํ•˜๊ฑฐ๋‚˜ ์•„์˜ˆ ํ†ตํ•ฉ์‹œํ‚ค๋Š” ์ตœ์ ํ™” ๋กœ์ง์ด ํ•„์š”ํ–ˆ์—ˆ๋‹ค.

ํ˜„์žฌ undo, redo ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ทธ๋ฆด ๋•Œ๋งˆ๋‹ค useRef์˜ current ๋‚ด ๋ฐฐ์—ด์— drawPath ์ด๋ฏธ์ง€๋“ค์„ ์ €์žฅ์ค‘์ด์—ˆ๋‹ค.

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

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

๊ฐ€์žฅ ํ•ต์‹ฌ์ ์œผ๋กœ ๊ฐ–๊ณ  ์žˆ์–ด์•ผ ํ•˜๋Š” Image๋งŒ ๋ฉ”๋ชจ๋ผ์ด์ง•ํ•˜์—ฌ ๊ณ„์‚ฐํ•ด์•ผ ํ•˜๋Š” ๋‚ด์šฉ๋“ค์„ ์••์ถ•ํ•˜๋ฉด ๋œ๋‹ค๋Š” ๊ฒฐ๋ก ์„ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

  const updateMemorizedImageData = async (newMemoImage: ImageData) => {
    const { width: newImageWidth, height: newIamgeHeight } = newMemoImage;
    const { width: memorizedPrevWidth, height: memorizedPrevHeight } = memoPrevImageSize.current;
    const isPrevMemoBigger = newImageWidth < memorizedPrevWidth || newIamgeHeight < memorizedPrevHeight;
    // ์ด์ „๊นŒ์ง€ ๊ทธ๋ฆฌ๋˜ ์‚ฌ์ด์ฆˆ๋ณด๋‹ค ์ž‘์€ ์‚ฌ์ด์ฆˆ์—์„œ ๊ทธ๋ฆฌ๊ฒŒ ๋  ๊ฒฝ์šฐ
    // drawPathRef์— ๊ธฐ๋ก๋˜๋Š” ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์˜ ๊ธฐ๋ก = ์ตœ๋Œ€์‚ฌ์ด์ฆˆ ์Šค๋ƒ…์ƒท์ด๋ฏ€๋กœ ์ด๊ฒƒ๋งŒ ์ €์žฅํ•˜์—ฌ ์ตœ์ข… ์ €์žฅ ๋ฐ์ดํ„ฐ ์šฉ๋Ÿ‰ ์ตœ์ ํ™”
    // ํ•ด๋‹น ์ตœ์ ํ™”๊ฐ€ ์—†์„ ๊ฒฝ์šฐ, ๋ชจ๋“  ๊ทธ๋ ค์ง„ drawPath์— ๋Œ€ํ•ด์„œ redrawํ•˜๊ฒŒ๋˜๋ฏ€๋กœ ์ˆ˜์ •ํ•œ๋‹ค.
    if (isPrevMemoBigger) {
      const biggerMemoImage = drawPathRef.current[drawPathRef.current.length - 1]; //๋ฐ˜์‘ํ˜• ์ „ ์ตœ๋Œ€ํฌ๊ธฐ ์Šค๋ƒ…์ƒท
      memorizedImageData.current.push(biggerMemoImage);

      // ์ถ”๊ฐ€ ์ตœ์ ํ™”
      // ๊ฐ€๋Šฅ์„ฑ์€ ์ ์ง€๋งŒ, ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์›น์‚ฌ์ดํŠธ์—์„œ ๋ฉ”๋ชจ๊ธฐ๋Šฅ์„ ์“ธ ๋•Œ ํ™”๋ฉด ํฌ๊ธฐ๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ์ค„์˜€๋‹ค ๋Š˜์˜€๋‹ค๋ฅผ ๋ฐ˜๋ณตํ•˜๋ฉฐ ๊ทธ๋ฆด ๊ฒฝ์šฐ
      // memorized๋˜๋Š” ์ผ€์ด์Šค๊ฐ€ ์ ์  ๋Š˜์–ด๋‚˜๊ฒŒ ๋œ๋‹ค => ์ €์žฅํ•  ๋•Œ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
      // ๋”ฐ๋ผ์„œ, ๊ณ„์† ์ง€์†์ ์œผ๋กœ memorized ๋˜๋Š” ์ด๋ฏธ์ง€์˜ ๊ฐฏ์ˆ˜๊ฐ€ ๋Š˜์–ด๋‚˜๊ธฐ ๋ณด๋‹ค, memorized ๋˜์–ด์žˆ๋Š” ๋ฐฐ์—ด์—์„œ ์ตœ๋Œ€ ์‚ฌ์ด์ฆˆ์˜ ์บ”๋ฒ„์Šค๋ฅผ ๋งŒ๋“ค๊ณ , ๋ฉ”๋ชจ๋ฅผ ๋ณ‘ํ•ฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ๋ฉ”๋ชจ๋งŒ ๊ด€๋ฆฌํ•œ๋‹ค.
      // ํ•ด๋‹น ์ž‘์—…์€ ๋ฐ˜์‘ํ˜•์ด ๋ฐœ์ƒํ•˜๋Š” ์ˆœ๊ฐ„์— ํ•ญ์ƒ 3๊ฐœ์˜ ์บ”๋ฒ„์Šค์— ๋Œ€ํ•ด์„œ๋งŒ ๋ฐœ์ƒํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋น„๊ต์  ๋ถ€๋‹ด์ด ์ ๋‹ค.(ํ˜„์žฌ์ด๋ฏธ์ง€, ๊ธฐ์กด ์ด๋ฏธ์ง€, ๋ฉ”๋ชจ๋ผ์ด์ง•๋˜์—ˆ๋˜ ์ตœ๋Œ€์‚ฌ์ด์ฆˆ ์ด๋ฏธ์ง€)
      const { mergedImageData, dataURL } = genMergedImageData([
        newMemoImage,
        biggerMemoImage,
        ...memorizedImageData.current,
      ]);
      memorizedImageData.current = [mergedImageData];
      mergedDataURL.current = dataURL; // ์ตœ์ข…์ ์œผ๋กœ indexedDB์— ์ €์žฅ๋  ์ตœ๋Œ€ํฌ๊ธฐ์˜ ์บ”๋ฒ„์Šค ์ด๋ฏธ์ง€ dataURL
    }
  };

๋งฅ๋ฝ์—†์ด ๊ฒฐ๋ก ์ ์ธ ์ฝ”์–ด์ฝ”๋“œ๋งŒ ์ ํ˜€์žˆ์œผ๋‹ˆ ๋ญ”๊ฐ€ ์‹ถ์ง€๋งŒ, ๊ฒฐ๋ก ์ ์œผ๋กœ ๋งํ•˜๊ณ  ์‹ถ์—ˆ๋˜ ๋‚ด์šฉ์€ ํ•˜๋‚˜๋‹ค.

๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ์ด ๋˜๊ฒŒ ๋œ๋‹ค๋ฉด, ์ด ๋ฐ์ดํ„ฐ์˜ ๊ด€๊ณ„์„ฑ์„ ๋ณด๊ณ  ํ†ต์ผ์„ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์—ฌ์ง€๊ฐ€ ์กด์žฌํ•œ๋‹ค๋ฉด ํ•„ํ„ฐ๋งํ•˜์—ฌ ์ตœ์ ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค. ๋ฌด์ง€์„ฑ์œผ๋กœ ๋‹ค ๋•Œ๋ ค๋„ฃ์ง€ ๋ง๊ณ .

์ด ๋ชจ๋“  ๊ณผ์ •์ด ์ง„ํ–‰๋˜์—ˆ๋˜ ๊ทผ๋ณธ์ ์ธ ๋ฌผ์Œ์€ ์ด๊ฒŒ ์ •๋ง ์ตœ์„ ์ด์•ผ? ๋ผ๋Š” ๊ฒƒ์ด์—ˆ๊ณ , ๋ถ€์กฑํ•˜์ง€๋งŒ ๊ณ„์† ๊ณ ๋ฏผํ•ด๋‚˜๊ฐ€๋‹ค ๋ณด๋‹ˆ ๊ฐœ์„ ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ์ง€๋“ค์ด ์กด์žฌํ–ˆ๋‹ค.

๊ณ ์ง‘์ด๋ผ๋ฉด ๊ณ ์ง‘์ด๊ฒ ์ง€๋งŒ ์ด ๊ณ ์ง‘์„ ํ†ตํ•ด์„œ ๋” ๋‚˜์€ ํผํฌ๋จผ์Šค๋ฅผ ๋„์ถœํ•  ์ˆ˜ ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹์„ ์ž์„ธ๋ผ๊ณ  ์—ฌ๊ธฐ๊ณ  ์žˆ๋‹ค.


๐Ÿ‘ฃ ํ•™์Šตํ•œ ๋‚ด์šฉ
๋กœ์ปฌ ์‚ฌ์šฉ์ž๊ฐ€ ๊ท€์†์ ์œผ๋กœ ๊ฐ–๊ฒŒ ํ•  ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ ๋ฏผํ•œ๋‹ค๋ฉด, transaction์„ ์ด์šฉํ•˜์—ฌ ์•ˆ์ „ํ•˜๊ฒŒ CRUD์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ indexedDB๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ˆ˜๋‹จ์„ ๋ฐฐ์› ๋‹ค.


๐Ÿšจ ERROR 2. ๋งˆ์šฐ์Šค์—์„œ ์ž˜ ๊ทธ๋ ค์ง€๋„ค, ๊ทธ๋Ÿผ ์ด์ œ ๋ชจ๋ฐ”์ผ๋กœ ๊ฐ€๋ณผ๊นŒ... ์‘? ํ„ฐ์น˜๋ž‘ ์™œ ํŽœ์ด ๋‘˜๋‹ค... ์ด๊ฒƒ์€ SRP์œ„๋ฐ˜?

์›น์—์„œ ๋งˆ์šฐ์Šค๋กœ ์ž˜ ๊ทธ๋ ค์ง€๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜๊ณ  ๋‚œ ๋’ค ๋„ˆ๋ฌด ๊ธฐ๋ถ„์ด ์ข‹์•˜๋‹ค.

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

์ด๋ฒคํŠธ ํƒ€์ž…์ด ๋‹ค๋ฅธ๋ฐ(๋งˆ์šฐ์Šค ํด๋ฆญ๊ณผ ํ„ฐ์น˜ ๋“ฑ)
์ด ์ด๋ฒคํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋‹ฌ๋ฆฌ ์ ์šฉ๋˜์•ผ ํ•˜๋Š” ๊ฒƒ๋„ ๋‹น์—ฐํ•œ ์ด์น˜์ผ ๊ฒƒ์ด๋‹ค.

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

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

๊ทธ๋ฆฌ๊ณ  ์ด๋ฒˆ์€ (๋ฌผ๋ก  ์—„์—ฐํžˆ ๋งํ•˜์ž๋ฉด ์ข€ ๋ฒ”์œ„๋Š” ๋‹ค๋ฅด์ง€๋งŒ) SRP์— ๊ด€๋ จํ•œ ๋น„์Šทํ•œ ๊ฒฝํ—˜์ด๋ผ๊ณ  ๋‚˜๋ฆ„ ์ƒ๊ฐ์„ ์ •๋ฆฌํ•ด๋ณธ๋‹ค.

SRP๋ž€ ํ•œ ํด๋ž˜์Šค๊ฐ€ ๊ฐ€์ ธ์•ผ ํ•˜๋Š” ๊ด€์‹ฌ์‚ฌ ํ˜น์€ ์ฑ…์ž„์€ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๊ฐ€ ๋‹ค์–‘ํ•œ ์ผ์„ ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค๋Š” ์›์น™์ด๋‹ค.

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

์ฑ…์ž„์ด ํ•˜๋‚˜๋ผ๋ฉด, ๋ณ€๊ฒฝ ์ด์œ ๋„ ํ•˜๋‚˜์—ฌ์•ผ ํ•œ๋‹ค. ๋” ์ƒ์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค๋ฅธ ๋ถ„์˜ ๋ธ”๋กœ๊น…์„ ์ฐธ์กฐํ•˜๋ฉด ์ข‹๋‹ค.

์ตœ๊ทผ์— ๋‹ค์‹œ ๊ธฐ์ดˆ OOP๋ฅผ ๊ณต๋ถ€ํ•˜๋‹ค๊ฐ€ ๋‚ด๊ฐ€ ์ž‘์„ฑํ–ˆ๋˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ๋Š๋ผ๋Š” ๊ฒƒ์ธ๋ฐ ํ•จ์ˆ˜ ์—ญ์‹œ๋„ ํ•˜๋‚˜์˜ ์ฑ…์ž„์›์น™์— ๋”ฐ๋ผ ๋ถ„๋ฆฌ๋˜์–ด ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ ๋‹ค.

Image

์œ„์˜ ์‚ฌ์ง„์€ ์›น์—์„œ ๋“œ๋กœ์ž‰์„ ์‹œ์ž‘ํ•  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜ startDrawing ์™€, ๋ชจ๋ฐ”์ผ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜ startDrawingForMobile์˜ ๋ชจ์Šต์ด๋‹ค.

์•ˆ์— ์žˆ๋Š” ๋กœ์ง์ด ๋™์ผํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค (checkPointerType์„ ํ˜ธ์ถœํ•˜๋Š”์ง€์˜ ์œ ๋ฌด๋งŒ ๋นผ๋ฉด).

์‹ค์ œ๋กœ, ์ฒ˜์Œ์— ๊ตฌํ˜„ํ•  ๋•Œ์—๋Š” ์• ์ดˆ๋ถ€ํ„ฐ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋„ ๋‘˜๋กœ ๋‚˜๋ˆ ๋†“์ง€๋„ ์•Š์•˜์—ˆ๋‹ค.

๊ทธ๋ƒฅ ํ•˜๋‚˜์˜ "StartDrawing"์ด๋ผ๋Š” ๊ฐœ๋…์•„๋ž˜์— ๋ฉ”์„œ๋“œ๋ฅผ ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋งˆ๋ƒฅ ๋ฌถ๊ณ  ๋‚ด๋ถ€์—์„œ ์ผ€์ด์Šค๊ฐ€ ๋ถ„๋ฆฌ๋  ์ƒํ™ฉ์ด ์กด์žฌํ•œ๋‹ค๋ฉด "if....๋ชจ๋ฐ”์ผ์ด๋ฉด" ์ด๋Ÿฐ์‹์œผ๋กœ ๋ถ„๊ธฐ์ฒ˜๋ฆฌ๋ฅผ ํ–ˆ์—ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ๊ทธ๋Ÿฌ๋‹ค๋ณด๋‹ˆ๊นŒ ์ ์  ํ•˜๋‚˜์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ํ•ด์•ผ ํ•˜๋Š” ์ผ์ด ๋งŽ์•„์ ธ๊ฐ€๊ณ , ์ฝ”๋“œ๊ฐ€ ์žฅํ™ฉํ•ด์ง€๋Š” ๊ฒƒ์„ ๋ชฉ๊ฒฉํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

์•„๋ž˜๋Š” ์‹œ์ž‘ ์ดํ›„ ์‹ค์ œ ๋“œ๋กœ์ž‰์„ ์ผ์œผํ‚ค๋Š” onDrawing๊ณผ ๊ด€๋ จํ•˜์—ฌ ๋‘ ํ•ธ๋“ค๋Ÿฌ์˜ ๋กœ์ง์„ ๋ณด์—ฌ์ค€๋‹ค.

  const onDrawing = (e: React.MouseEvent<HTMLCanvasElement, MouseEvent>) => {
    const context = canvasCtxRef.current;
    const x = e.pageX;
    const y = e.pageY;

    if (isCanvasOpen) {
      if (!isDrawing) { // ๋“œ๋กœ์ž‰์ด ์•„๋‹ ๋•Œ, ์ฆ‰ ๊ทธ๋ƒฅ ์บ”๋ฒ„์Šค ์œ„์— ๋งˆ์šฐ์Šค๊ฐ€ ์›€์ง์ด๊ณ ๋งŒ ์žˆ์„ ๋•Œ์˜ ์ผ€์ด์Šค ๋ถ„๋ฆฌ
        context?.beginPath();
        context?.moveTo(x, y);
      } else {
        applymemoContextAttr();
        context?.lineTo(x, y);
        context?.stroke();
      }
    }
  };


  const onDrawingForMobile = (e: React.PointerEvent<HTMLCanvasElement>) => {
    checkPointerType(e.pointerType, () => {
      const context = canvasCtxRef.current;
      const x = e.pageX;
      const y = e.pageY;

      if (isCanvasOpen) { // ๋ชจ๋ฐ”์ผ์—๋Š” ๋งˆ์šฐ์Šค ํฌ์ธํ„ฐ ๊ฐœ๋…์ด ์—†์œผ๋ฏ€๋กœ, ๋ถ„๋ฆฌ๋  ํ•„์š”๊ฐ€ ์—†๋‹ค.
        applymemoContextAttr();
        context?.lineTo(x, y);
        context?.stroke();
      }
    });
  };

๋ถ„๋ช…ํžˆ ์ดˆ๋ฐ˜ ๋ณ€์ˆ˜์„ ์–ธ๊นŒ์ง„ ๊ฐ™์€๋ฐ, ๋ถ„๊ธฐ์ ๋ถ€ํ„ฐ๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค.

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

๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ๋งˆ๋ƒฅ ๋‘ ๋‹ค๋ฅธ ํƒ€์ž…์˜ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ€์ง„ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ•ฉ์ณ์„œ ํ•˜๋‚˜๋กœ ๋ฌถ๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

์ฝ”๋“œ์ƒ์œผ๋กœ๋Š” ๊ทธ๊ฒŒ ๋” ํ•œ์ค„์ด๋ผ๋„ ์ค„์ด๋Š” ์ผ์ผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, ๋‚ด๋ถ€์ ์œผ๋กœ ์ •๋ง ์ง€์ €๋ถ„ํ• ๊ฒƒ์ด๋‹ค.

์ € ๋ถ„๊ธฐ์ ์— ๋Œ€ํ•œ ๋‚ด์šฉ์ด ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•จ๊ณผ ๋™์‹œ์—, ์•„์ง๊นŒ์ง€ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š์•˜๋˜ ์กด์žฌ "checkPointerType" ๊นŒ์ง€ ์ถ”๊ฐ€๋œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ.

 const checkPointerType = (pointerType: 'mouse' | 'touch' | 'pen', callback: Function) => {
    if (pointerType === drawType) {
      callback();
    }
  };

์œ„ ํ•จ์ˆ˜๋Š” ํ˜„์žฌ ์ „์—ญ recoil์—์„œ ๊ด€๋ฆฌ๋˜๋Š” ์ƒํƒœ์™€ ์ธ์ž๋กœ ๋“ค์–ด์˜ค๋Š” ์ด๋ฒคํŠธ ํƒ€์ž…์„ ๋น„๊ตํ•˜์—ฌ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚ฌ์ง€์˜ ์œ ๋ฌด๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด๋‹ค.

์ด ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๊ตฌํ˜„ํ•œ ์ด์œ ๋Š” ํŒœ ๋ฆฌ์ ์…˜(์†๋ฐ”๋‹ฅ์ด ์ ‘์ด‰ ์‹œ ํ„ฐ์น˜๋กœ ์ธ์‹๋˜์–ด ๊ทธ๋ ค์ง€๋Š” ๋ฌธ์ œ์ผ€์ด์Šค) ๋•Œ๋ฌธ์ธ๋ฐ ์ด๊ฒƒ์€ ์ผ๋‹จ ์‚ฌ์กฑ์ด๋‹ˆ ๋„˜์–ด๊ฐ€๊ณ ,

๋‹ค์‹œ๊ธˆ ๋งํ•˜์ง€๋งŒ ์ด ๋ชจ๋“ ๊ฒƒ๋“ค์„ ๋‹ค ๊ณ ๋ คํ•ด์„œ ํ•˜๋‚˜์˜ ํ•จ์ˆ˜์— ํ†ตํ•ฉํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž.

 const onEveryDrawing = (
    e: React.MouseEvent<HTMLCanvasElement, MouseEvent> | React.PointerEvent<HTMLCanvasElement>,
  ) => {
    const context = canvasCtxRef.current;
    const x = e.pageX;
    const y = e.pageY;

    if ((e as React.PointerEvent<HTMLCanvasElement>).pointerType) {
      const pointerType = (e as React.PointerEvent<HTMLCanvasElement>).pointerType;

      if (pointerType === drawType && isCanvasOpen) {
        applymemoContextAttr();
        context?.lineTo(x, y);
        context?.stroke();
      }
    } else if (isCanvasOpen) {
      if (!isDrawing) {
        context?.beginPath();
        context?.moveTo(x, y);
      } else {
        // ๊ทธ๋ฆด ๋•Œ, ํ•ด๋‹น ์ขŒํ‘œ๊นŒ์ง€ ํ”ฝ์…€๊ฒฝ๋กœ๋ฅผ ๋งŒ๋“ค๊ณ (lineTo) ๊ทธ ํ”ฝ์…€์„ ์ฑ„์›Œ๋„ฃ์–ด์„œ ๋ผ์ธ์„ ๋งŒ๋“ ๋‹ค(stroke).
        applymemoContextAttr();
        context?.lineTo(x, y);
        context?.stroke();
      }
    }
  };

์ €๊ฒŒ ๊ณผ์—ฐ ๋ญ˜ ์–ด๋””๊นŒ์ง€ ํ•˜๋Š” ํ•จ์ˆ˜์ธ์ง€ ๊ตฌ๋ณ„์ด ๊ฐ€๋Š”๊ฐ€

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

(์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋ฒคํŠธ๋ฅผ ํ„ฐ์น˜์ด๋ฒคํŠธ๋กœ ๊ตฌํ˜„ํ•˜๋ คํ–ˆ๋‹ค๋ฉด ํ•ด๋‹น ์ด๋ฒคํŠธ ๊ฐ์ฒด ๋‚ด์—๋Š” pageX๊ฐ€ ์—†๋‹ค. touches ํ”„๋กœํผํ‹ฐ์— ์žˆ๋Š” ๊ฐ’์„ ๊ณ„์‚ฐํ•ด์„œ offsetX๋กœ ๋ณ€ํ™˜ํ–ˆ์–ด์•ผ ํ•œ๋‹ค)

๊ฒŒ๋‹ค๊ฐ€ ์ €๊ฑฐ๋Š” ์•„์ฃผ ๊ฐ„๋‹จํ•œ ๋กœ์ง์ด๋‹ˆ๊นŒ ์ง€๊ธˆ์€ ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์น˜์ง€๋งŒ,

์‹ค์ œ ์„œ๋น„์Šค์—์„œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ•จ์ˆ˜๋ฅผ ํ•˜๋‚˜๋กœ ๋ฌถ์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ํ•จ๋ถ€๋กœ ๋ฌถ๋Š”๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž.

// ์˜ˆ์ƒ๋˜๋Š” ์กฐ๊ฑด๋ฌธ ์ง€์˜ฅ๋„
export function service(){
    if(){
        if(){
            if(){
                if(){
                    if(){}
                }
            }
        }
    }else if(){
        if(){
            if(){

            }
        }else if(){

        }else if(){
            if(){
                
            }
        }
    }
}

์ฝ”๋“œ๊ฐ€ ๋ถ„๋ฆฌ๋˜์–ด ์—ฌ๋Ÿฌ๊ฐœ๊ฐ€ ์ƒ๊ธฐ๊ธด ํ•˜์ง€๋งŒ, ํŠน์ • ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด์„œ ํŠน์ • ์ฑ…์ž„์„ ์ง€๋Š” ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ์„ ์–ธ์ ์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ํŽธ์ด ์ถ”ํ›„ ์œ ์ง€๋ณด์ˆ˜ ๋ฐ ์ฝ”๋“œ ๊ฐ€๋…์„ฑ์— ์žˆ์–ด์„œ ํ›จ์”ฌ ๋„์›€์ด ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

์ฆ‰, ์ด ํ•จ์ˆ˜๊ฐ€ ์–ด๋– ํ•œ "์ฑ…์ž„"์„ ๊ฐ–๊ณ  ๋™์ž‘ํ•˜๋Š” ์ง€์— ๋Œ€ํ•ด์„œ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„์„ ์ง€์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๋ฌผ๋ก  ๋ฐ˜๋ณต๋˜๋Š” ๋กœ์ง์— ๋Œ€ํ•ด์„œ ์˜๋ฏธ์—†์ด ๊ณ„์† ๋™์ผํ•˜๊ฒŒ ๋ฐ˜๋ณต ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ ์—ญ์‹œ ์˜ณ์ง€๋Š” ๋ชปํ•˜๋‹ค.

๊ทธ๋Ÿฌ๋ฏ€๋กœ, ํ•ด๋‹น ๋ฐ˜๋ณต๋˜์–ด ๋ณด์ด๋Š” ๋‚ด์šฉ์ด ๊ณต์šฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์ด๊ฒƒ์ด "์ฑ…์ž„๋ก "์ ์œผ๋กœ ํ•˜๋‚˜์˜ ๋™์ž‘์œผ๋กœ ๋ฌถ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค๋ฉด ์ฑ…์ž„๋‹จ์œ„๋กœ ๋ฌถ์–ด์„œ ํ˜ธ์ถœ์‹œํ‚ค๋Š” ๊ฒƒ๋„ ์ข‹๋‹ค๊ณ  ๋ณธ๋‹ค.


๐Ÿ‘ฃ ํ•™์Šตํ•œ ๋‚ด์šฉ
๋„ˆ๋ฌด ํด๋ฆฐ ์ฝ”๋“œ๋งŒ ๊ณ ์ง‘ํ•˜์—ฌ ํ•จ์ˆ˜๋ฅผ ๋ฌด๋ฆฌํ•˜๊ฒŒ ์ผ๋ฐ˜ํ™”์‹œํ‚ค๋ ค๊ณ  ํ•˜์ง€ ๋ง๊ณ  ์ •ํ™•ํ•œ ์ฑ…์ž„ ์›๋ฆฌ์— ๋”ฐ๋ผ ๊ตฌ๋ถ„ํ•˜์—ฌ ๋กœ์ง์„ ์ž‘์„ฑํ•˜๋Š” ์Šต๊ด€์„ ๋“ค์ด์ž.


๐Ÿ’ก ๊ธ€์„ ์ค„์ด๋ฉฐ

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

ํ•ญ์ƒ ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค๋ณด๋ฉด ๋ˆˆ์•ž์— ์žˆ๋Š” ๊ฒƒ๋งŒ ๋ณด๊ณ  ์ „๋ถ€ ๋‹ค ๊ตฌํ˜„ํ–ˆ๋‹ค๊ณ  ์ฐฉ๊ฐํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ด๋ฒˆ์— ํ† ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ๊ฒฝํ—˜ํ•˜๋ฉด์„œ, ๊ฐ„๋‹จํ•ด ๋ณด์ด๋Š” ๊ธฐ๋Šฅ์ด๋ผ๋„ ์‹ค์ œ๋กœ๋Š” ์„ธ์„ธํ•˜๊ฒŒ ๊ณ ๋ฏผํ•˜๊ณ  ๊ณ ๋ คํ•ด์•ผ๋  ๋ถ€๋ถ„์ด ๋งŽ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๊นจ๋‹ฌ์•˜๋‹ค.

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

profile
์ž๋ผ๋‚˜๋ผ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ƒˆ์‹น!

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