๊ฐ์ธ์ ์ผ๋ก๋ ๋ฏธ์ ์ํ์ ํตํด ์ฑ์ฅํ ๊ณผ์ ์ ๊ธฐ๋กํ๊ณ ,
๋๊ตฐ๊ฐ์๊ฒ๋ ์ด ๊ธ์ด ๋์์ด ๋์์ผ๋ฉด ํ๋ ๋ง์์ ๋๋ค :)
๐ ๏ธ 1์ฃผ ์ฐจ ๊ฒฐ๊ณผ๋ฌผ
1์ฃผ ์ฐจ ๋ฏธ์ : ์ซ์ ๊ฒ์ ์ผ๊ตฌ PR
๐ฎ 1์ฃผ ์ฐจ ๋ฏธ์ ๋ฉ์ผ ๋ด์ฉ
1๏ธโฃ ๊ฐ๋ฒผ์ด ๋ฏธ์ ..?
1์ฃผ ์ฐจ ๋ฏธ์ ์ธ '์ซ์ ์ผ๊ตฌ ๊ฒ์'์ ๋ณด๊ณ ๋ฐ๊ฐ์ ๋ค. ์ง๋ ๊ธฐ์๋ค์์ ์์ฃผ ๋์๋ ๋ฏธ์ ์ด์๊ธฐ ๋๋ฌธ์ด๋ค. (ํ์๋ 6๊ธฐ์ ์ง์ํ๊ณ ) ์ง๋ 5๊ธฐ์์๋ 2์ฃผ ์ฐจ ๋ฏธ์ ์ด์๋๋ฐ ์ด๋ฒ์ 1์ฃผ ์ฐจ์ ๋ฐฐ์ ๋ผ์ ์ค์? ํ๋ค. ์๋ง ์ง๋ ๊ธฐ์ 1์ฃผ ์ฐจ '์จ๋ณด๋ฉ' ๋ฏธ์ ์ด ๊ธฐ๋ฅ ๊ตฌํ๋ณด๋ค๋ ์๊ณ ๋ฆฌ์ฆ ๋ฌธ์ ํ์ด์ ๊ฐ๊น์์ ๊ทธ๋ฐ ๊ฒ ์๋๊น? ํ๋ ์ถ์ธก์ ํด๋ณด์๋ค.
์ฒซ ๋ฉ์ผ ๋ด์ฉ์ ์ํ๋ฉด, ๊ฐ๋ฐ ํ๊ฒฝ ์ธํ ๊ณผ Git ๋ฑ ๋ฏธ์ ์ธ์๋ ์ถ๊ฐ๋ก ์ตํ์ผ ํ๋ ๋ถ๋ถ๋ค์ด ์์ด '๊ฐ๋ฒผ์ด ๋ฏธ์ '์ผ๋ก ์ค๋นํ๋ค๊ณ ํ๋ค. ์ ๋ง ๊ฐ๋ฒผ์ธ์ง ๋ชจ๋ฅด๊ฒ ์ง๋ง, ์ฝ ์ผ์ฃผ์ผ์ด๋ผ๋ ์๊ฐ์ด ์ฃผ์ด์ง ๋งํผ ํ๋ํ๋ ๊ผผ๊ผผํ๊ฒ ํด ๋ณด์!
2๏ธโฃ ์ ๊ฒฝ ์จ์ผ ํ๋ ๊ฒ๋ค
๋ฏธ์ ์ ์ ์ถํ์ง ์์ผ๋ฉด ๋ค์ ํ๋ฆฌ์ฝ์ค ๋จ๊ณ์ ์ต์ข ์ฝ๋ฉ ํ ์คํธ์ ์ฐธ์ฌํ ์ ์์ผ๋ 100% ์๋ฒฝํ๊ฒ ๊ตฌํํ์ง ๋ชปํ๋๋ผ๋ ๊ธฐ๊ฐ ๋ด์ ์ ์ถํ๋ ๊ฒ์ด ์ค์ํ๊ฒ ๋ค. ๋๋ถ์ด, ๊ณผ์ ๋ฅผ ์ ์ถํ ๋ ๋ฏธ์ ์ ์งํํ๋ฉด์ ๋๋ ์ ์ ์๊ฐ๋ฌธ์ผ๋ก ์์ฑํ๊ณ , ์ด๋ ํ์ตํ '๊ณผ์ '์ ์ ๋๋ฌ๋ด ๋ฌ๋ผ๋ ๋ด์ฉ์ด ์์๋ค. ๋ฏธ์ ์ ํ์ด๋ด๋ ๋์ ๋ธ๋ก๊น ์ ์ผ๋ํ๊ณ ๊ทธ๋๊ทธ๋ ๊ธฐ๋ก์ ์ํด๋์ด์ผ๊ฒ ๋ค๊ณ ์๊ฐํ๋ค.
โ๏ธ ํ๋ฆฌ์ฝ์ค ์งํ ๋ฐฉ์
1๏ธโฃ ๋ฏธ์ ์งํ
ํ๋ฆฌ์ฝ์ค 1์ฃผ ์ฐจ ๋ฏธ์ ์ ์ ์ฅ์์์ ์์ ์ ๊นํ์ fork ํ clone ํ์ฌ ์งํํ๋ค. ์์๋ถํฐ git์ ๋ํ ๊ธฐ์ด์ ์ธ ์ดํด๋ฅผ ํ์๋ก ํ๋ค. ๋ฐ๋ผ์ git ์ ๋๋ ์์ ์์ฌ๋ก ๋ค๋ฃฐ ์ ์๋๋ก ๋ฏธ๋ฆฌ ์ต์ํด์ง๋ค๋ฉด ๋ฏธ์ ์งํ ๋์ ์ด์ด์๋ ์ค์๋ฅผ ๋ฐฉ์งํ ์ ์๊ฒ ๋ค. (๋ฌผ๋ก ์ฐํ ์ฝ ์ธก์์ ์ ๊ณตํ ์ด ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํด๋ ์ถฉ๋ถํ๋ค.) ๋๋ ์ด๋ ์ ๋ git์ ๋ํด์๋ ์ต์ํด์ง ํฐ๋ผ, ์ต๋ํ ๊น๋ํ๊ณ ์ง๊ด์ ์ผ๋ก ์ปค๋ฐํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๋ค.
2๏ธโฃ ๋ฏธ์ ๊ตฌ์ฑ
๋งค์ฃผ ๋ฏธ์ ์ (1) ๊ธฐ๋ฅ ์๊ตฌ ์ฌํญ, (2) ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ ์ฌํญ, (3) ๊ณผ์ ์งํ ์๊ตฌ ์ฌํญ ์ธ ๊ฐ์ง๋ก ๊ตฌ์ฑ๋์ด ์๋ค. ๋ฐ๋ผ์ ๋จ์ํ ๊ธฐ๋ฅ ๊ตฌํ๋ฟ๋ง ์๋๋ผ ์ ํ๋ก ์๊ตฌํ๋ ์ฌํญ๋ค์ ๊ผผ๊ผผํ ํ์ธํ์ฌ ์งํํ๋ ๊ฒ์ด ์ค์ํ๊ฒ ๋ค. ์ค์ ๋ก ํ๋ฆฌ์ฝ์ค ์ปค๋ฎค๋ํฐ์์ ์ด๋ฌํ ์๊ตฌ์ฌํญ๋ค์ ๊ผผ๊ผผํ๊ฒ ํ์ธํ์ง ์๊ณ ์ง๋ฌธ์ ํ๋ ์ฌ๋๋ค์ด ๋ง์์ ๋๋๋ค. ๊ฒ๋ค๊ฐ ์๊ตฌ์ฌํญ์ ์งํค์ง ์์์ ํ ์คํธ ํต๊ณผ๋ ๋ฌผ๋ก ์ ์ถ ์ ์ค๋ฅ๊ฐ ๋ฌ๋ ์ฌ๋๋ค๋ ์์๋ค. ๊ทธ๋ฌ๋ ์ด๋ฐ ๊ฒ๋ค์ ๊ฐ์๊ฐ ์์์ ๊ผผ๊ผผํ๊ฒ ์ฑ๊ธฐ์๊ธธ!
3๏ธโฃ ๋ฏธ์ ๋ง๊ฐ ๋ฐ ๊ธฐ์ค
๋ฏธ์ ์งํ ๊ฐ๋ฅ ๊ธฐ๊ฐ์ ์ฝ ์ผ์ฃผ์ผ, ๊ทธ๋ฆฌ๊ณ ๋ฏธ์ ์ ์ถ ๊ฐ๋ฅ ๊ธฐ๊ฐ์ ๋ฐ๋์ ์ ๋์ ์๊ฐ์ด ์ฃผ์ด์ง๋ค. ์ผ๋จ ๋ณธ์ธ Github์ commit์ ํด๋๊ณ , ๋ฏธ์ ์ ์ถ ๊ฐ๋ฅ ๊ธฐ๊ฐ ๋์ push & PR์ ํ๋ฉด ๋๊ฒ ๋ค. (๋ฌผ๋ก ๋ฏธ์ ์ ์ถ ๊ธฐ๊ฐ์ด ์๋๋๋ผ๋ push๋ ํด๋ ๋๋ค๊ณ ํ๋ค.) ๋ฌผ๋ก , ๋ง๊ฐ์ผ ์ดํ ์ถ๊ฐ push๋ ํ์ฉํ์ง ์๋๋ค. ๋ฌผ๋ก ๋ฆฌํฉํ ๋ง์ ์์ ์์ฌ๊ฒ ์ง๋ง, ๊ทธ๋ณด๋ค 1์ฃผ ์ฐจ ๋ฏธ์ ์ ๋ณต์ตํ๊ณ ๋ค์ ๋ฏธ์ ์ ํ๋๋ผ ์ ์ ์ด ์์ ๊ฒ ๊ฐ๋ค.
๐คผโ๏ธ ํ๋ฆฌ์ฝ์ค ์ปค๋ฎค๋ํฐ
1๏ธโฃ ํ๋ฆฌ์ฝ์ค ์ปค๋ฎค๋ํฐ๋?
ํ๋ฆฌ์ฝ์ค์์๋ 4์ฒ ์ฌ ๋ช ์ ๋ฌํ๋ ์ฐ์ํํ ํฌ์ฝ์ค ์ง์์๋ค์ด ํจ๊ป ์ปค๋ฎค๋ํฐ ๋ด์์ ํ์ตํ๊ณ ์ฑ์ฅํ ์ ์๋ค. ๋์ค์ฝ๋ ์ปค๋ฎค๋ํฐ์์ ๊ถ์ฅํ๋ ํ๋์ ์๋ก ๋ฆฌ๋ทฐํ๊ธฐ(์ฝ๋ ๋ฆฌ๋ทฐ), ํ ๋ก ํ๊ธฐ, ํจ๊ป ๋๋๊ธฐ(์ ๋ณด ๊ณต์ ), ๋ค์ ๋์๋ณด๊ธฐ(ํ๊ณ )์ด๋ฉฐ ์ด ํ๋์ด ์๋๋๋ผ๋ ํจ๊ป ํ์ตํ๊ณ ์ฑ์ฅํ ์ ์๋ ์คํฐ๋ ๊ฐ์ค ๋ฑ ๋ฌด์์ด๋ ๊ฐ๋ฅํ๋ค๊ณ ํ๋ค.
2๏ธโฃ ์ฐธ๊ณ ํ ์ฌํญ
๋จ, ๊ฐ์ ์ค์ค๋ก ํ์ตํ ๊ธฐํ๋ฅผ ์ํด ์์ง ๋ง๊ฐ๋์ง ์์ ๋ฏธ์ ์ ๊ด๋ จ๋ ์ง๋ฌธ๊ณผ ๋ต๋ณ์ ๋ง๊ฐ์ผ ์ดํ๋ก ๊ณต์ ํ๋ ๊ฒ ์๋ฌต์ ์์น์ด๋ค. ๋ฌผ๋ก ์ปค๋ฎค๋ํฐ ํ๋ ๊ธฐ๋ก์ ์ต์ข ํฉ๊ฒฉ์ ์ ํ ์ํฅ์ ๋ฏธ์น์ง ์๋๋ค๊ณ ์ฐํ ์ฝ ์ธก์์ ์ ํ์ค๋ช ํ ๋ฑ์ ํตํด ๊ณต์์ ์ผ๋ก ์ด์ผ๊ธฐํ๋ค. ์ฌ์ง์ด ๋์ค์ฝ๋ ์ฑ๋์ ๋ค์ด์ค์ง ์์๋ ๋๋ค.
3๏ธโฃ ์ปค๋ฎค๋ํฐ์ ์ฒซ์ธ์
๋์ค์ฝ๋์ ์ ์ํ๋๋ฐ ํ๋ฆฌ์ฝ์ค ์์ ์ ๋ถํฐ ์ปค๋ฎค๋ํฐ ํ๋์ด ์์ฒญ ํ๋ฐํด์ ๋๋๋ค. ๋ค๋ค ์ด์ ์ด ๋๋จํ๋ค๊ณ ๋๊ผ์ง๋ง, ๋ฏธ์ ์ ์ค์ค๋ก ํ๋๋ฐ์ ์ด์ง ๋ ธ์ด์ฆ๊ฐ ๋๋ ๋ฉด๋ ์์ง ์์ ์ ์ ํ๊ฒ ํ์ฉํ๊ณ ์ ํ๋ค. ํจ๊ป ๋ฆฌ๋ทฐํ๊ณ ํ ๋ก ํ๋ ๊ฒ๋ ํ๋ฆฌ์ฝ์ค์์ ๋๋ฆด ์ ์๋ ํํ์ด๊ธฐ ๋๋ฌธ.
๐ค ๋ฏธ์ ์ ์์,
1๏ธโฃ ๊ธฐ๋ฅ ๋ชฉ๋ก ๋ง๋ค๊ธฐ
๋ฏธ์ ์ ๊ธฐ๋ฅ ์๊ตฌ ์ฌํญ, ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ ์ฌํญ, ๊ณผ์ ์งํ ์๊ตฌ ์ฌํญ ์ธ ๊ฐ์ง๋ก ๊ตฌ์ฑ๋์ด ์๋ค. ํนํ ์ฃผ๋ชฉํด์ผ ํ ์ ์ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ ์ ๊ธฐ๋ฅ ๋ชฉ๋ก์ ๋ง๋ ๋ค๋ ๊ฒ. ๊ธฐ๋ฅ ๊ตฌํ ์ ๋ชฉ๋ก์ ๋ง๋ค์ด์ ธ ์๋ ๊ฒ์ด ์๋๋ผ, ์ง์ ๋ง๋ค์ด์ผ ํ๋ ๊ฒ ํฌ์ธํธ๋ค.
2๏ธโฃ ์ ์ถ ์ ํ ์คํธ ํ์
๊ธฐ๋ฅ ๊ตฌํ์ ๋ชจ๋ ์ ์์ ์ผ๋ก ํ๋๋ผ๋ ์๊ตฌ ์ฌํญ์ ๋ช ์๋ ์ถ๋ ฅ๊ฐ ํ์์ ์งํค์ง ์์ ๊ฒฝ์ฐ 0์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ค. ๊ธฐ๋ฅ ๊ตฌํ์ ์๋ฃํ ๋ค ํ ์คํธ๋ฅผ ์คํํ์ ๋ ํ ์คํธ๊ฐ ์คํจํ ๊ฒฝ์ฐ 0์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ฏ๋ก, ๋ฐ๋์ ํ์ธ ํ ์ ์ถํ๋ค. ํ์๋ Node ํ๊ฒฝ์์ ํ๋ก๊ทธ๋จ์ด ์ ๋์๊ฐ๋์ง ํ์ธํ๊ณ , ํ ์คํธ ํต๊ณผ๊น์ง ํ์ธํ๋ฉฐ ์์ ํ๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ต์ข ์ ์ถ ํ ์คํธ์์ ์์์น ๋ชปํ ์๋ฌ๊ฐ ๋ ์ ์์ผ๋ ๋ฏธ๋ฆฌ๋ฏธ๋ฆฌ ํ์ธํ์.
3๏ธโฃ Node ๋ฒ์ ํ์ธ ํ์
ํ ์คํธ ํจํค์ง ์ค์น๋ฅผ ์ํด Node.js ๋ฒ์ 18.17.1 ์ด์์ด ํ์ํ๋ค. ๋ณธ์ธ ๋ก์ปฌ์ Node ๋ฒ์ ์ด ๋ช์ธ์ง ๊ผญ ํ์ธ ํ ๋ฏธ์ ์ ์งํํ์. ์ฐธ๊ณ ๋ก Node ๋ฒ์ ํ์ธ์ 'node --version'์ผ๋ก ํ์ธ ๊ฐ๋ฅํ๋ฉฐ, ์ ๋ฐ์ดํธ๋ Node.js ๊ณต์ ์ฌ์ดํธ๋ฅผ ์ฐธ๊ณ ํ๊ฑฐ๋, ์๋์ ๊ฐ์ด 'nvm install'๋ก ํน์ Node ๋ฒ์ ์ ์ค์นํ ์ ์๋ค.
โพ๏ธ ๊ธฐ๋ฅ ์๊ตฌ ์ฌํญ
1๏ธโฃ ์ซ์ ์ผ๊ตฌ ๊ฒ์ ์ค๋ช
๋ฏธ์ ์ ๋ํ ์์ธํ ๋ด์ฉ์ ์ฐํ ์ฝ ํ๋ฆฌ์ฝ์ค ๋ ํฌ์ ์์ผ๋ ์ฐธ๊ณ ํ๊ธธ ๋ฐ๋ผ๋ฉฐ, ๊ฐ๋จํ ๊ฒ์ ์ค๋ช ์ ํ์๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก 1๋ถํฐ 9๊น์ง ์๋ก ๋ค๋ฅธ ์๋ก ์ด๋ฃจ์ด์ง 3์๋ฆฌ์ ์๋ฅผ ๋งํ๋ ๊ฒ์์ด๋ค.
๊ฐ์ ์๊ฐ ๊ฐ์ ์๋ฆฌ์ ์์ผ๋ฉด ์คํธ๋ผ์ดํฌ, ๋ค๋ฅธ ์๋ฆฌ์ ์์ผ๋ฉด ๋ณผ, ๊ฐ์ ์๊ฐ ์ ํ ์์ผ๋ฉด ๋ซ์ฑ์ด๋ ํํธ๋ฅผ ์ป๊ณ , ๊ทธ ํํธ๋ฅผ ์ด์ฉํด์ ๋จผ์ ์๋๋ฐฉ(์ปดํจํฐ)์ ์๋ฅผ ๋ง์ถ๋ฉด ์น๋ฆฌํ๋ค. ์ฆ, ์ ์ํ ์ซ์์ ๋ฐ๋ผ ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋๋ก ํ๋ ๊ฒ์ด ํต์ฌ ๊ณจ์์ธ ๋ฏํ๋ค.
2๏ธโฃ ์ซ์ ์ผ๊ตฌ ๊ฒ์ ์์
์) ์๋๋ฐฉ(์ปดํจํฐ)์ ์๊ฐ 425์ผ ๋
123์ ์ ์ํ ๊ฒฝ์ฐ → 1 ์คํธ๋ผ์ดํฌ
456์ ์ ์ํ ๊ฒฝ์ฐ → 1 ๋ณผ 1 ์คํธ๋ผ์ดํฌ
789๋ฅผ ์ ์ํ ๊ฒฝ์ฐ → ๋ซ์ฑ
์ ์ซ์ ์ผ๊ตฌ ๊ฒ์์์ ์๋๋ฐฉ์ ์ญํ ์ ์ปดํจํฐ๊ฐ ํ๋ค. ์ปดํจํฐ๋ 1์์ 9๊น์ง ์๋ก ๋ค๋ฅธ ์์์ ์ 3๊ฐ๋ฅผ ์ ํํ๋ค. ๊ฒ์ ํ๋ ์ด์ด๋ ์ปดํจํฐ๊ฐ ์๊ฐํ๊ณ ์๋ ์๋ก ๋ค๋ฅธ 3๊ฐ์ ์ซ์๋ฅผ ์ ๋ ฅํ๊ณ , ์ปดํจํฐ๋ ์ ๋ ฅํ ์ซ์์ ๋ํ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ค.
์ด ๊ฐ์ ๊ณผ์ ์ ๋ฐ๋ณตํด ์ปดํจํฐ๊ฐ ์ ํํ 3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ๋ฉด ๊ฒ์์ด ์ข ๋ฃ๋๋ค. ๋ฐ๋ผ์ ์ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ฉด์ → ์ปดํจํฐ๊ฐ ์์ฑํ๋ 3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ๊ฑฐ๋ / ๋งํ์ง ์์์ ๋์ ๋ฐ๋ผ ์ ์ ํ ๊ฒฐ๊ณผ๊ฐ ํํํํ ์ ๋์ค๋๋ก ํด์ผ ํ๋ค.
๊ฒ์์ ์ข ๋ฃํ ํ ๊ฒ์์ ๋ค์ ์์ํ๊ฑฐ๋ ์์ ํ ์ข ๋ฃํ ์ ์๋ค. ์ฌ์ฉ์๊ฐ ์๋ชป๋ ๊ฐ์ ์ ๋ ฅํ ๊ฒฝ์ฐ throw๋ฌธ์ ์ฌ์ฉํด ์์ธ๋ฅผ ๋ฐ์์ํจ ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ข ๋ฃ๋์ด์ผ ํ๋ค. ๋ง์ฝ ์ฌ์ฉ์๊ฐ ์์๋๋ ๊ฐ ์ธ์ ๊ฐ์ ์ ๋ ฅํ์ ๊ฒฝ์ฐ ๊ผผ๊ผผํ๊ฒ ์์ธ์ฒ๋ฆฌ๊น์ง ๊ผญ ํด์ฃผ์ด์ผ๊ฒ ๋ค.
๐จ ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ ์ฌํญ - ์คํ ํ๊ฒฝ
โ Node.js 18.17.1 ๋ฒ์ ์์ ์คํ ๊ฐ๋ฅํด์ผ ํ๋ค.
๐ Node ๋ฒ์ ์ฒดํฌ ํ์
โ ํ๋ก๊ทธ๋จ ์คํ์ ์์์ ์ App.js์ play ๋ฉ์๋๋ค.
๐ play()๋ก ํ๋ก๊ทธ๋จ ์คํ์ด ๊ฐ๋ฅํ๋ ์ด๋ฅผ ์ถ๊ฐํ์.
โ package.json์ ๋ณ๊ฒฝํ ์ ์๊ณ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(jQuery, Lodash ๋ฑ)๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค. ์์ Vanilla JS๋ก๋ง ๊ตฌํํ๋ค.
๐ ํ์ง๋ง ํ์๋ ESLint์ Prettier๋ฅผ ์ฌ์ฉํ๊ณ , ๋ณ๊ฒฝ๋ package.json ๋ด์ญ์ ๊ตณ์ด push ํ์ง ์์๋ค.
โ JavaScript ์ฝ๋ ์ปจ๋ฒค์ ์ ์งํค๋ฉด์ ํ๋ก๊ทธ๋๋ฐํ๋ค.
๐ ์๋์์ ์์ธํ๊ฒ ์ด์ผ๊ธฐํ๊ฒ ์ง๋ง, Airbnb ์ฝ๋ ์ปจ๋ฒค์ ์ ํ๋ํ๋ ๋ณด๊ณ ๋ฐ๋ฅด๊ธฐ์๋ ๋๋ฌด ๋ฒ๊ฑฐ๋ก์ ๊ธฐ์ ESLint์ Prettier๋ฅผ ์ค์ ํด์ ์ปจ๋ฒค์ ์ ๋ง์ถ์๋ค.
โ ํ๋ก๊ทธ๋จ ์ข ๋ฃ ์ process.exit()๋ฅผ ํธ์ถํ์ง ์๋๋ค.
๐ ๋ณดํต ํ๋ก๊ทธ๋จ์ ์ข ๋ฃํ ๋ Console.Close()๋ process.exit()๋ฅผ ์ฌ์ฉํ๊ณ ๋ ํ์ง๋ง, ์ฌ๊ธฐ์๋ ๋ฉ์๋๋ฅผ ํธ์ถํ์ง ์๋๋ค. ํ์๋ ๊ทธ๋ฅ '๊ฒ์ ์ข ๋ฃ' ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ค. (์ฐธ๊ณ : Node.js์์ ์ข ๋ฃํ๋ ๋ฐฉ๋ฒ)
โ ํ๋ก๊ทธ๋จ ๊ตฌํ์ด ์๋ฃ๋๋ฉด ApplicationTest์ ๋ชจ๋ ํ ์คํธ๊ฐ ์ฑ๊ณตํด์ผ ํ๋ค. ํ ์คํธ๊ฐ ์คํจํ ๊ฒฝ์ฐ 0์ ์ฒ๋ฆฌํ๋ค.
๐ ์์์ ๋งํ ๊ฒ์ฒ๋ผ ๋ ๊ฐ์ง ํ ์คํธ๋ฅผ ๋ชจ๋ ํต๊ณผํด์ผ ํ๋ค.
โ ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ ์ฌํญ์์ ๋ฌ๋ฆฌ ๋ช ์ํ์ง ์๋ ํ ํ์ผ, ํจํค์ง ์ด๋ฆ์ ์์ ํ๊ฑฐ๋ ์ด๋ํ์ง ์๋๋ค.
๐ ๋ํดํธ๋ก ์๋ ํ์ผ, ์ฝ๋, ํด๋๋ ๊ตณ์ด ๊ฑด๋ค์ง ์์๋ค.
๐จ ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ ์ฌํญ - ๋ผ์ด๋ธ๋ฌ๋ฆฌ
โ @woowacourse/mission-utils์ Random ๋ฐ Console API๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํํด์ผ ํ๋ค.
โ Random ๊ฐ ์ถ์ถ์ Random.pickNumberInRange()๋ฅผ ํ์ฉํ๋ค.
โ ์ฌ์ฉ์์ ๊ฐ์ ์ ๋ ฅ๋ฐ๊ณ ์ถ๋ ฅํ๊ธฐ ์ํด์๋ Console.readLineAsync, Console.print๋ฅผ ํ์ฉํ๋ค.
๐ ๊ตณ์ด ๋ฐ๋ก ๋ง๋ค์ง ์๊ณ ์ฐํ ์ฝ์์ ์ ๊ณตํ๋ utils๋ค์ ์ฌ์ฉํด ์ ๋ ฅ ๋ฐ ์ถ๋ ฅ์ ํ๋ฉด ๋๋ค.
๐ ๋ฏธ์ ์ ํตํด ๋ฐฐ์ด ์
1๏ธโฃ ๊ธฐ๋ฅ ๋ช ์ธ์
์๊ฐ์ด ์กฐ๊ธ ๊ฑธ๋ฆฌ๋๋ผ๋ ๊ธฐ๋ฅ ๊ตฌํ ํ๋ก์ฐ๋ฅผ ํ ์คํธ์ ํ๋ก์ฐ ์ฐจํธ๋ฅผ ํตํด ์ ๋ฆฌํ๋ ํด์ผ ํ๋ ๊ฒ๋ค์ด ๋ช ํํ๊ฒ ๋ณด์๋ค. ํนํ ์ฒซ ๋ฒ์งธ ๋ฏธ์ ์ธ ๋งํผ ์ต์ํ์ง ์์ ํฐ๋ผ ์ด๋ฐ์ ๋ ๋ง์ด ๊ณ ๋ฏผํด ๋ณด์์ผ ํ๋ค๊ณ ์๊ฐํ๋ค.
๋ํ, ๊ธฐ๋ฅ ๋ช
์ธ์๋ ๊ผผ๊ผผํ๊ฒ ์์ฑํ๋ฉด ํ ์๋ก (๋์๊ฒ) ์ข๋ค๊ณ ์๊ฐํ๋ค. ํจ์๋ช
, ๋ณ์๋ช
๊น์ง ๋ชจ๋ ์ ํด๋๋ฉด ํจ์ฌ ๋น ๋ฅธ ์ฝ๋ฉ์ด ๊ฐ๋ฅํ๋ค. (๋ฌผ๋ก ์ด๊ฒ๋ ์ ์ฐจ ์ต์ํด์ง๋ฉด ์ด๋ ๊ฒ๊น์ง ํด๋์ค๋ช
, ๋ฉ์๋๋ช
๊น์ง ์ ์ํ๋ฉฐ ์์ธํ๊ฒ ์์ฑํ์ง ์์๋ ๋๋ค.) ๋ช
์ธ์๋ฅผ ์์ฑํ๋ฉฐ ์ ์ฒด์ ์ธ ๋ก์ง ๊ตฌ์์ ํ ์ ์์ผ๋ ์ฝ๋๋ฅผ ๋ค ์จ๋๊ณ ๋ก์ง์ ์์ ํ๊ฑฐ๋ ํท๊ฐ๋ฆฌ๋ ์ผ์ ๋ฐฉ์งํ ์ ์์๋ค.
๊ธฐ๋ฅ ๋ช ์ธ์๋ฅผ ์์ฑํ๋ค ๋ณด๋ ํ๋ก์ฐ๊ฐ ์ฑ ์ ๋ชฉ์ฐจ์ฒ๋ผ ์ ์ฒด์ ์ธ ๊ทธ๋ฆผ์ด ๊ทธ๋ ค์ง๋๋ก ์์ฑํ๋ ๊ฒ์ด ์ข๋ค๊ณ ์๊ฐํ๋ค. ๋ฌผ๋ก ์ฝ๋๋ ๋ง์ฐฌ๊ฐ์ง. ์ฝ๋๋ฅผ ๋ณด๋ฉด ํ๋ก๊ทธ๋จ์ด ๊ทธ๋ ค์ง๋๋ก ์์ฑํด์ผ๊ฒ ๋ค๊ณ ๋ ์๊ฐํ๋ค.
๋ฌผ๋ก ์ค๊ฐ์ ํธ๋ฌ๋ธ์ํ
์ ํ๊ฑฐ๋ ๋ฆฌํฉํ ๋ง์ ํ๋ฉด์ ๋ก์ง์ ๋ณ๊ฒฝํ๋๋ผ, ์ผ๋จ ์ฝ๋ ์์ → ๊ธฐ๋ฅ ๋ช
์ธ์ ์์ ์ผ๋ก ๊ฑฐ๊พธ๋ก ํ๊ธฐ๋ ํ์ง๋ง, ์ด์จ๋ ๊ธฐ๋ฅ ๋ช
์ธ ์์ฑ์ ๋ฏธ์
์ ๋ง์ฃผํ๋ ๋ง๋งํจ์ ๋์ด์ค ์ ์์ ๊ฒ์ด๋ผ ์๊ฐํ๋ค.
2๏ธโฃ ํจ์ ์ด๋ฆ ์ง๊ธฐ
ํจ์ ํ๋๋ ํ ๊ฐ์ง ์ผ๋ง ํด์ผ ํ๋ ํจ์ ๋ช ์ ๋๊ฐ ๋ด๋ ์ง๊ด์ ์ผ๋ก ์ง๋ ๊ฒ์ด ์ข๋ค. ์๋ฅผ ๋ค์ด, checkPermission()๋ ์น์ธ ์ฌ๋ถ๋ฅผ ํ์ธํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ๋์๋ง ํด์ผ ํ๋ค. ์น์ธ์ฌ๋ถ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ฉ์์ง๋ฅผ ๋์ฐ๋ ๋์์ ์ด ํจ์์ ๋ค์ด๊ฐ์ง ์๋ ๊ฒ ์ข๋ค. (์ฐธ๊ณ : function ํจ์์ด๋ฆ ์ง๊ธฐ (2) - javascript 0604)
ํจ์ ์ด๋ฆ | ์๋ฏธ | ์์ |
show... | ๋ฌด์ธ๊ฐ๋ฅผ ๋ณด์ฌ์ฃผ๋ ํจ์ | showMessage() |
get... | ๊ฐ์ ๋ฐํํ๋ ํจ์ | getAge() |
calc... | ๊ฐ์ ๋ฐํํ๋ ํจ์ | calcSum() |
create... | ๋ฌด์ธ๊ฐ๋ฅผ ์์ฑํ๋ ํจ์ | createForm() |
check... | ๋ฌด์ธ๊ฐ๋ฅผ ํ์ธํ๊ณ ๋ถ๋ฆฐ๊ฐ์ ๋ฐํํ๋ ํจ์ | checkPermission() |
3๏ธโฃ Eslint์ Prettier ์ค์
Airbnb ์คํ์ผ ๊ฐ์ด๋๋ฅผ ๋ณด๋ฉด์ ์ฝ๋ฉํ๊ธฐ์๋ ๋๋ฌด ๋นํจ์จ์ ์ด๋ผ๊ณ ์๊ฐํ๋ค. ์ปจ๋ฒค์ ํ๋ํ๋ ์ด๋ป๊ฒ ๋ค ์ ๊ฒฝ ์จ์ ํ๋ ์ถ์ด ESLint์ Prettier๋ฅผ ์ง์ ์ค์ ํด ๋ณด๊ธฐ๋ก ํ๋ค. ํ์ ํ๋ก์ ํธ ํ ๋๋ ๋๊ตฐ๊ฐ๊ฐ ํด์คฌ๋๋ฐ, ์ด๋ฒ์ ์ฒ์์ผ๋ก ํด๋ดค๊ณ ๋์์ด ๋ง์ด ๋์๋ค. ์ค์ ์ ๋งค์ฐ ๋์์ด ๋ ๋ธ๋ก๊ทธ ๊ธ์ ์ฒจ๋ถํ๋ค.
ํจํค์ง ํ์ผ์ ์์ ํ์ง ๋ง๋ผ๋ ์๊ตฌ์ฌํญ์ด ์์์ง๋ง, ๊ฑฑ์ ๋๋ค๋ฉด ์ฐ์ ์ฝ๋๋ฅผ ์์ฑํ ๋๋ ๋ก์ปฌ ํ๊ฒฝ์์๋ง ESLint์ Prettier๋ฅผ ์ค์น ๋ฐ ์ค์ ํด ๋๊ณ , ์ปค๋ฐ๊ณผ ํธ์๋ฅผ ํ์ง ์์ผ๋ฉด ๋๋ค. (ํ์ง๋ง ํ๋ฆฌ์ฝ์ค 1์ฃผ ์ฐจ ๊ณตํต ํผ๋๋ฐฑ์์ ๊ฐ๋ฅํ๋ฉด ESlint์ Prettier๋ฅผ ์ด์ฉํด ๋์ฑ ์์ฐ์ ์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ์๋ผ๊ณ ๊ธฐ์ฌ๋ ๊ฒ์ ๋ณด๋ ์ ๊ทน์ ์ผ๋ก ์ฌ์ฉํด๋ ์ข๊ฒ ๋ค.)
4๏ธโฃ ํจ์ vs. ํด๋์ค
ํจ์๋ง ์์ฑํ๊ธฐ๋ณด๋ค ์๋์ ๊ฐ์ด ํด๋์ค์ ํํ๋ก ๋ง๋ค์ด ์ํ์ ๋ฉ์๋๋ฅผ ํด๋์ค ๋ด์ ์บก์ํํ๊ณ ์ ํ๋ค. ํจ์๋ก ์์ฑํด๋ ๋์ง๋ง ์ด๊น์ ํด๋์ค ๊ฐ๋ ์ ๋ ์ต์ํด์ง๊ณ ์ถ๊ธฐ๋ ํ๊ณ , ์ถํ ํจ์ ๋ด์ ๊ฐ์ ๋ณ๊ฒฝํ๊ฑฐ๋ ๊ด๋ฆฌํ๋ ๋ฐ์ ํ์ํ ์ํ๋ ์ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ ์ถ์ ํ๊ธฐ ์ด๋ ค์ธ ์ ์๊ธฐ ๋๋ฌธ์ด์๋ค.
// Generator.js
class Generator {
constructor() {
this.computerNumber = this.generateRandomNumber();
}
generateNewCorrectNumber() {
this.computerNumber = this.generateRandomNumber();
}
generateRandomNumber() {
// ... ์๋ต
}
export default Generator;
ํด๋์ค๋ก ๋ํ๋์ ๋ ๋ ๋ง์ ์ฝ๋์ ๊ตฌ์กฐ๊ฐ ํ์ํ ์ ์์ด ์ฒ์์๋ ์กฐ๊ธ ๋ณต์กํ๊ฒ ๋๊ปด์ง ์ ์์ง๋ง, ์ด์จ๋ ๊ฐ์ ์ํ์ ๋ฉ์๋๋ฅผ ํด๋์ค ๋ด์ ์บก์ํํ ์ ์์ ๋ฟ๋ง ์๋๋ผ, ์ธ์คํด์ค๋ฅผ ์ฌ๋ฌ ๋ฒ ์์ฑํด์ ์ถํ ์ถ์ ์ ์ ์ฉํ๊ธฐ๋ ํ๋ค.
5๏ธโฃ ๋น๋๊ธฐ๋ก ์ฌ์ฉ์์ ์ ๋ ฅ ์ฒ๋ฆฌ
async & await๋ก ์ฌ์ฉ์์ ์ ๋ ฅ์ ๋ฐ์ ์ด์ ๋ ์ฌ์ฉ์๊ฐ ์ ๋ ฅ์ ์๋ฃํ ๋๊น์ง ๋ค๋ฅธ ์์ ์ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
// BaseballGame.js
async startGame() {
await this.getUserInput();
}
async getUserInput() {
const input = await Console.readLineAsync(LOG_MESSAGE.INPUT_NUMBER);
this.handleUserInputDuringGame(input);
}
// ... ์๋ต
handleUserInputDuringGame(input) {
if (!isValidGameInputDuringGame(input)) {
throwError(ERROR_MESSAGE.INCORRECT_VALUE);
}
์ ๋ก์ง์ ์ค๋ช
ํ์๋ฉด, ์ผ๋จ ๊ฒ์์ด ์์ํ๊ณ ์ฌ์ฉ์๋ก๋ถํฐ ์
๋ ฅ์ ๋ฐ์ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ํํ๋ค. ์ด๋ await๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ๋ก ์
๋ ฅ์ ๋ฐ๋๋ก ํ์ผ๋ฉฐ, ์ ํจ์ฑ ๊ฒ์ฌ ํจ์๋ฅผ ํธ์ถํ์ฌ ์
๋ ฅ๋ ์ซ์์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ค. ์ ํจํ ์ซ์๊ฐ ์๋ ๊ฒฝ์ฐ, ํด๋น ํจ์์์ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค.
await๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ๋ก ์
๋ ฅ์ ๋ฐ๋๋ก ํ ์ด์ ๋ ์
๋ ฅ์ ๊ธฐ๋ค๋ ค์ผ ํ๋ ๋์ ํ๋ก๊ทธ๋จ์ด ๋ธ๋กํน๋์ง ์๋๋ก ํ๊ธฐ ์ํจ์ด์๋ค. ๋น๋๊ธฐ์ ์ธ ์ฒ๋ฆฌ๋ฅผ ํตํด ์ฌ์ฉ์๊ฐ ์
๋ ฅ์ ์๋ฃํ ๋๊น์ง ๋ค๋ฅธ ์์
์ ์ํํ ์ ์์ผ๋ฉฐ, ์
๋ ฅ ๋๊ธฐ ์๊ฐ ๋์ ๋ค๋ฅธ ์ฝ๋ ๋ํ ์คํ๋ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ์์์ ์ํธ์์ฉ์ ์๊ฐ์ด ๋ถ๊ท์นํ๊ฒ ๋ฐ์ํ๊ธฐ์, ์ฌ์ฉ์์ ์ ๋ ฅ์ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ํ๋ก๊ทธ๋จ์ด ๋ธ๋กํน๋๋ฉด ์ฌ์ฉ์ฑ์ด ์ ํ๋ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฐ๋ผ์ await๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์ ์ ๋ ฅ์ ๊ธฐ๋ค๋ฆฌ๋ฉฐ, ์ด๋ฒคํธ ๋ฃจํ์์ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌ๋ ์ ์๋๋ก ํ๋ค.
6๏ธโฃ throw Error๋ฌธ๊ณผ throw new Error๋ฌธ์ ์ฐจ์ด
๊ฒฐ๋ก ๋ถํฐ ๋งํ์๋ฉด, ๋ ๊ฐ๊ฐ ํฐ ์ฐจ์ด๋ ์์ผ๋, new Error๋ฌธ์ด ๊ธฐ์ ์ ์ผ๋ก ๋ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ํ๋ค. throw Error๋ฌธ์ JavaScript์์ ๊ตฌ์์ธ ๋ฐฉ์์ผ๋ก ์์ธ๋ฅผ ๋ฐ์์ํค๋ ๋ฐฉ๋ฒ์ด๋ฉฐ, Error ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ ๋ด์ฅ๋ Error ์์ฑ์๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ด๋ค. (์ฐธ๊ณ : JavaScript ‘throw new Error’ vs ‘throw Error’ vs ‘throw something’)
๋ฐ๋ฉด, throw new Error ๋ฌธ์ ๋ ํ๋์ ์ธ ๋ฐฉ์์ผ๋ก ์์ธ๋ฅผ ๋ฐ์์ํค๋ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ํ๋ค. ์ด ๋ฐฉ์์ ์์ธ ๊ฐ์ฒด๋ฅผ ๋ช
์์ ์ผ๋ก ์์ฑํ๋ ๊ฒ์ผ๋ก, ์์ธ ๊ฐ์ฒด์ ๋ ๋ง์ ์ ๋ณด๋ ์ปค์คํ
์์ฑ์ ์ถ๊ฐํ๊ฑฐ๋ ๋ค๋ฅธ ํํ์ ์๋ฌ ๊ฐ์ฒด๋ฅผ ๋ง๋ค ์ ์๋ค. (์ฐธ๊ณ : Differences Between “throw” and “throw new Error” in Javascript / NodeJS)
7๏ธโฃ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ๋ช ๊ณผ ํด๋๋ช ์ปจ๋ฒค์
์ปจ๋ฒค์ ์ ์ต๊ด์ ์ผ๋ก ์๋ คํ์ง ์์ผ๋ฉด ๋์ค์ ์ ์ฉํ๋ ค ํ ๋ ํท๊ฐ๋ฆฐ๋ค. ๊ทธ๋ฌ๋ ์ด๋ฒ ๊ธฐํ์ ํ์คํ๊ฒ ์ง๊ณ ๋์ด ๊ฐ์. (์ฐธ๊ณ : google.github.io, 30secondsofcode.org)
ํ์ผ๋ช ์ camelCase๋ฅผ ์ฌ์ฉํ๋ค. (e.g. myJavaScriptFile.js) ๋ค๋ง, ํด๋์ค ์ด๋ฆ์ ๊ฒฝ์ฐ PascalCase๋ฅผ ์ฌ์ฉํ๋ค. ํด๋์ค ์ ์๊ฐ ํฌํจ๋ ํ์ผ๋ช ์ญ์ PascalCase๋ก ์์ฑํ๋ค. (e.g. Generator.js) ๊ทธ๋ฆฌ๊ณ ํด๋๋ช ์ kebab-case๋ฅผ ์ฌ์ฉํ๋ค. (e.g. my-javascript-folder) ๋ค๋ง, ์ด๋ค ํ์ผ ์์คํ (์: NTFS, git, macOS์ ๊ธฐ๋ณธ ์ค์ )์ ๋์๋ฌธ์๋ฅผ ๋ฌด์ํ๋ฏ๋ก, ํ์ผ ๋ฐ ํด๋๋ช ์ด ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ์ง ์๋ ํ๊ฒฝ์์๋ kebab-case๋ snake_case ์ค ์ด๋ค ๊ฒ์ ์ฌ์ฉํด๋ ์๊ด์๋ค.
8๏ธโฃ require? import?
์ด๋ฒ ๋ฏธ์ ์ ํ๋ฉด์ ์ธ๋ถ ๋ชจ๋์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ถ๋ฌ์ฌ ๋ require๊ณผ import ๋ ์ค ์ด๋ค ๊ฒ์ ์จ์ผ ํ๋์ง ๊ณ ๋ฏผํ๋ค. ๋ ๋ค ๋น์ทํ ๊ฑฐ ์๋๊ฐ? ์๊ฐํ๊ธฐ ๋๋ฌธ.
์๊ณ ๋ณด๋ (์ฐธ๊ณ : ์๋ฐ์คํฌ๋ฆฝํธ CommonJS ๋ชจ๋ ๋ด๋ณด๋ด๊ธฐ/๋ถ๋ฌ์ค๊ธฐ) require๋ Node.js์์ ์์ ๋ถํฐ ์ฌ์ฉ๋๊ณ ์๋ CommonJS์ ํค์๋์ด๊ณ , import๋ ES6(ES2015)์์ ์๋กญ๊ฒ ๋์ ๋์ด ํ์ฌ ์๋ฐ์คํฌ๋ฆฝํธ ์ํ๊ณ์์ ํ์ค์ด ๋์ด๊ฐ๊ณ ์๋ ํค์๋๋ผ๊ณ ํ๋ค. ๋ ๊ฐ์ ํค์๋ ๋ชจ๋ ํ๋์ ํ์ผ์์ ๋ค๋ฅธ ํ์ผ์ ์ฝ๋๋ฅผ ๋ถ๋ฌ์จ๋ค๋ ๋์ผํ ๋ชฉ์ ์ ๊ฐ์ง๊ณ ์์ง๋ง, ๋น์ทํ ๋ฏ ์ฝ๊ฐ์ฉ ๋ค๋ฅธ ๋ฌธ๋ฒ์ ๊ฐ์ง๊ณ ์๋ค. ๊ทธ๋์ ํ์๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ ํ์ค์ด ๋์ด๊ฐ๊ณ ์๋ค๋ import๋ฌธ์ ์ฌ์ฉํ๋ค.
// Node.js์์ ์์ ๋ถํฐ ์ฌ์ฉ๋๊ณ ์๋ CommonJS์ ํค์๋
const express = require("express");
const app = express();
// ES6(ES2015)์์ ์๋กญ๊ฒ ๋์
๋์ด ํ์ฌ ์๋ฐ์คํฌ๋ฆฝํธ ์ํ๊ณ์์ ํ์ค์ด ๋์ด๊ฐ๊ณ ์๋ ํค์๋
import express from "express";
const app = express();
๐ฉ๐ป๐ง ํธ๋ฌ๋ธ ์ํ
์ผ๋ฐ์ ์ธ ์๋ฌ๋ ๋ฐ๋ก ๋ค๋ฅธ ๊ธ๋ก ๋ฐํํ๊ณ ,
๋ณธ ๋ฏธ์ ์์ ๋ง์ฃผํ ์ ์๋ ๋ช ๊ฐ๋ง ๊ธฐ์ ํฉ๋๋ค.
1๏ธโฃ App.js ๋ชจ๋์ ์ฐพ์ ์ ์๋ค๋
์์ ์๋ฌ ๋ฉ์์ง๋ฅผ ์ ์ฝ์ด๋ณด๋ฉด 'App.js ๋ชจ๋์ ์ฐพ์ ์ ์๋ค'๋ ๋ด์ฉ์ด๊ธฐ์, ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ํด๊ฒฐ์ ์๋ํ๋ค. ์ฒซ ๋ฒ์งธ๋ Node ํ๊ฒฝ์์ ๊ฒ์ ์คํ ์ 'node App.js' ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํ๋ ์์น๊ฐ ๋ฃจํธ๊ฐ ์๋๋ผ '/src'์์ ํด๋ณด๋ ๊ฒ์ด๋ค.
๋ํ, ์์์ ๊ธฐ์ ํ ๊ฒ์ฒ๋ผ const & require๋ฌธ์ ๋ชจ๋ import & export ๋ฌธ์ผ๋ก ์์ ํ๋ค. (๋ฌผ๋ก ํจ์์ ํด๋์ค์ ๋ง๊ฒ ์ฌ์ฉํ๋ ๊ฒ๋ ์ค์) ์ฌ์ค ๋ชจ๋์ ์ฐพ์ ์ ์๋ ์์ธ์ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์๊ฒ ์ง๋ง ์ฐ์ ์์ ๊ฐ์ด ํด๊ฒฐ์ ํ๋ค.
2๏ธโฃ ํ ์คํธ ํต๊ณผ๊ฐ ์๋๋ค๋
Node ํ๊ฒฝ์์๋ ๊ฒ์ ์คํ๊ณผ ๋ชจ๋ ๊ธฐ๋ฅ์ด ์ ๊ตฌํ๋์๋๋ฐ, 'npm test'๋ฅผ ํ์ ๋์ ํ ์คํธ๋ ํต๊ณผํ์ง ๋ชปํ๊ณ ์์๋ค. ๊ธฐ๊ป ๋ค ๊ตฌํํ๋๋ฐ ํ ์คํธ ํ์ธ์กฐ์ฐจ ๋ชปํ๋ ๊ต์ฅํ ๋ง๋งํ๋ค. ํ์ง๋ง ๋ด ์ฝ๋์ ๋ฌธ์ ๊ฒ ๊ฑฐ๋ ํด์ ํ ์คํธ ์ฝ๋์ ํจ๊ป ์๋ฒฝ ๋ด๋ด ๋ถ์ก๊ณ ์์๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค์๋ ์์นจ, ๊ฐ์ฌํ๊ฒ๋ ๊ต์ฅํ ํํธ๊ฐ ๋๋ ๋ธ๋ก๊ทธ์์ ๋ณธ ๋ด์ฉ์ ๊ธฐ๋ฐ์ผ๋ก ์ฝ๋๋ฅผ ๋ค์ ์ดํด๋ณด์๋ค.
์ด๊ฒ ์ฌ๊ฑธ! ๋น๋๊ธฐ๊ฐ ๋ฌธ์ ์๋ค. async๋ฅผ ๋ถ์ธ ํจ์๋ฅผ ํธ์ถํ๊ณ , await๋ฅผ ๋ถ์ด์ง ์์๊ธฐ ๋๋ฌธ์ด์๋ค. await๋ฅผ ๋ถ์ด์ง ์์ผ๋ฉด play ํจ์๋ ์๋ฌ๋ฅผ ๋ฑ๋ ํจ์๋ง ์คํ์์ผ ๋๊ณ ๋๋๊ธฐ ๋๋ฌธ์ด๋ค. async & await๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๊ฒ์ ์คํ์ ๋ด๋นํ๋ ๋ฉ์๋ ๋ด๋ถ์์ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๊ฑฐ๋ await ๊ฐ๋ฅํ ๋น๋๊ธฐ ์์ ์ ์ํํด์ผ ํ๋ค. ๊ทธ๋ฌ๋ฉด ๊ฒ์ ์คํ ๋ฉ์๋ ๋จ๊ณ(์ฌ์ฉ์๊ฐ ์ซ์๋ฅผ ์ ๋ ฅ์ ์๋ฃํ๋ ๋ฑ)๊ฐ ์๋ฃ๋ ๋๊น์ง App ํด๋์ค์ play ๋ฉ์๋๊ฐ ๊ธฐ๋ค๋ฆด ์ ์๋ค.
์ฝ๋๋ ์๋์ ๊ฐ์ด ์ฌ์ฉ์์ ์ ๋ ฅ์ ๊ธฐ๋ค๋ฆฌ๋ ๋ชจ๋ ๊ณณ์ async & await๋ฅผ ๋ถ์ฌ ์ฃผ์๋ค.
// App.js
import BaseballGame from './BaseballGame.js';
import { Console } from '@woowacourse/mission-utils';
import { LOG_MESSAGE } from './constants.js';
import { printMessage } from './utils.js'
class App {
constructor() {
this.game = new BaseballGame();
}
async play() {
printMessage(LOG_MESSAGE.START_GAME);
await this.game.startGame(); // ์์ ๋ ๊ฒ์ ์์ ๋ฉ์๋ ํธ์ถ
}
}
const app = new App();
app.play();
export default App;
App.js ๋ฟ๋ง ์๋๋ผ ์๋ BaseballGame.js์์๋ ๊ฒ์ ์คํ ๋ฉ์๋ startGame์ ๋น๋๊ธฐ ๋ฒ์ ์ผ๋ก ์์ ํ๋ค. ์๋ฅผ ๋ค์ด, Console.readLine๋ฅผ Promise๋ก ๋ํ ํ๊ฑฐ๋ ์ ์ ํ ๋ฐฉ์์ผ๋ก ๋น๋๊ธฐ ์ฒ๋ฆฌํ๋ฉฐ, ์ด๋ await์ ํจ๊ป ์๋ํด์ผ ํ๋ค๋ ๊ฒ. ๊ทธ๋ฌ๋ ๊ฒ์ ์คํ ์ ์ฌ์ฉ์์ ์ ๋ ฅ์ ๋ค๋ฃจ๋ ๋ชจ๋ ๊ณณ์ ์ดํด๋ณด๋ ๊ฒ์ด ์ข๊ฒ ๋ค.
// BaseballGame.js
// ... ์๋ต
class BaseballGame {
constructor() {
this.computer = new Generator();
}
async startGame() {
await this.getUserInput();
} // ์์ ๋ ๊ฒ์ ์์ ๋ฉ์๋
async getUserInput() {
const input = await Console.readLineAsync(LOG_MESSAGE.INPUT_NUMBER);
this.handleUserInputDuringGame(input);
} // ์์ ๋ ์ฌ์ฉ์ ์
๋ ฅ ๋ฉ์๋
async recommendRestart() {
await printMessage(LOG_MESSAGE.CORRECT_END);
const input = await Console.readLineAsync(`${LOG_MESSAGE.RESTART_INPUT}\n`);
this.handleUserInputEndGame(input);
} // ์์ ๋ ๊ฒ์ ์ฌ์์ ์
๋ ฅ ๋ฉ์๋
handleUserInputDuringGame(input) {
// ... ์๋ต
}
async handleUserInputEndGame(input) {
const isValidGameInputEndGame = [GAME_SELECT.RESTART, GAME_SELECT.END];
// ... ์๋ต
}
restartGame() {
this.computer.generateNewCorrectNumber();
this.startGame();
}
}
export default BaseballGame;
์ ์ฝ๋ ํ๋จ์ ๊ฒ์ ์ข ๋ฃ ์ ๋ ฅ์ ๋ด๋นํ๋ handleUserInputEndGame ๋ฉ์๋ ๋ด์์๋ ๋น๋๊ธฐ ์์ ์ ๊ธฐ๋ค๋ฆด ํ์๊ฐ ์์ผ๋ฏ๋ก await๋ฅผ ์ฌ์ฉํ์ง ์์๋ ๋๋ค. ์ด ๋ฉ์๋๋ ๋๊ธฐ์ ์ธ ์์ ์ ์ํํ๊ธฐ์, ์ ๋ ฅ๊ฐ์ ๊ฒ์ฌํ๊ณ ์ฒ๋ฆฌํ๋ ๋ถ๋ถ์์ ์ถ๊ฐ์ ์ธ ๋น๋๊ธฐ ์์ ์ด ํ์ํ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
3๏ธโฃ ํ ์คํธ ํต๊ณผ๋ฅผ ์ํด์ ๊ณต๋ฐฑ ํ๋๋ ์ค์
์ผ์ถ ๊ธฐ๋ฅ ๊ตฌํ์ ๋ค ๋๋ ๊ฒ ๊ฐ๋ค๊ณ ์๊ฐํด ํ ์คํธ๋ฅผ ๋๋ ค ๋ณด์๋๋ฐ, ์์ ๊ฐ์ด ์ถ๋ ฅ ๊ฐ์ด ๋ค๋ฅด๊ฒ ๋์จ๋ค๋ ์๋ฌ ๋ฉ์์ง๋ฅผ ๋ณด์๋ค. ๋ฉ์์ง๋ฅผ ์์ธํ ๋ณด๋ '1 ๋ณผ 1 ์คํธ๋ผ์ดํฌ'๊ฐ ๋์์ผ ํ๋๋ฐ ๊ทธ๋ ์ง ์์์ ์๋ฌ๊ฐ ๋๋ ๊ฒ ๊ฐ์๋ค.
์ด์ด์๊ฒ๋ n๋ณผ n์คํธ๋ผ์ดํฌ๋ผ๋ ํํธ๋ฅผ ์ถ๋ ฅํ ๋ ๋ณผ๊ณผ ์คํธ๋ผ์ดํฌ ์ฌ์ด์ ๊ณต๋ฐฑ์ด ์์ด์ ์๊ธฐ๋ ๋ฌธ์ ์๋ค. ์๋์ ๊ฐ์ด ๋ณผ ๊ฐ์ ๋ฆฌํฐ๋ด ๋ฐ๋ก ๋ค์ ๊ณต๋ฐฑ์ ์ถ๊ฐํด ์ฃผ์๋ค.
const convertNumberToString = (strikeNumber, ballNumber) => {
let hintMessage = '';
if (ballNumber > 0) {
hintMessage += `${ballNumber}${HINT_MESSAGE.BALL} `; // ๊ณต๋ฐฑ ์ถ๊ฐ
}
if (strikeNumber > 0) {
hintMessage += `${strikeNumber}${HINT_MESSAGE.STRIKE}`;
}
if (hintMessage.length === 0) {
hintMessage += HINT_MESSAGE.NOTING;
}
return hintMessage;
};
4๏ธโฃ ํ ์คํธ๋ ํต๊ณผ๋๋๋ฐ..
์์ ๊ฐ์ด ํ ์คํธ ํต๊ณผ๋ ๋์๊ณ , Node ํ๊ฒฝ์์ ์ ์๋๋๋ ๊ฒ๋ ํ์ธํ๋ค. ๊ทธ๋ฐ๋ฐ ํ๋จ์ ๋ ธ๋์ ๊ธ์๋ก "Jest did not exit one second after the test run has completed."๋ผ๋ ๋ฉ์์ง๊ฐ ๋ด๋ค. ๋ฌด์จ ์๋ฏธ์ธ๊ฐ ์ฐพ์๋ณด๋ ์๋์ ๊ฐ๋ค๊ณ ํ๋ค.
Jest์ ์ด๋ฌํ ์๋ฌ๋ ์ฃผ๋ก ๋น๋๊ธฐ ์์ ์ด ์๋ฃ๋์ง ์์ ํ ์คํธ๊ฐ ์ข ๋ฃ๋์ง ์์์ ๋ ๋ฐ์ํ๋ค๊ณ ํ๋ค. ๊ทธ๋์ ์๋ฌ ๋ฉ์์ง ์๋ ค์ฃผ๋ฏ, ์ ์ํ๋ ๋ฐฉ๋ฒ ์ค ํ๋์ธ '--detectOpenHandles' ์ต์ ์ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ์์ ์ด ์๋ฃ๋์ง ์์ ํธ๋ค(Handles)์ ์๋ณํ๊ณ ํด๊ฒฐํด๋ ๋๋ค. ์๋์ ๊ฐ์ด package.json์ ์ต์ ์ ์ถ๊ฐํ๋ฉด ๋ ์ด์ ๋ ธ๋์ ๋ฉ์์ง๊ฐ ๋จ์ง ์๋๋ค. (ํ์ง๋ง ์ด ๋ฉ์์ง๊ฐ ์๋ค๊ณ ํ ์คํธ ํต๊ณผ๊ฐ ๋์ง ์๋ ๊ฑด ์๋๋ ๊ฑฑ์ ๋ง์.)
"scripts": {
"test": "jest --detectOpenHandles"
}
๐งน ๋ฆฌํฉํ ๋ง
1๏ธโฃ ์ถ๋ ฅ ๋ฉ์์ง๋ค์ constants๋ก ๋๊ฒฐ
์ถ๋ ฅ ๋ฉ์์ง๋ค์ ์คํ์๊ฐ ์๊ธธ ๊ฐ๋ฅ์ฑ์ด ๋๊ณ , (ํ ์คํธ ํต๊ณผ๋ฅผ ์ํด์๋ผ๋ฉด ๋๋์ฑ) ์ดํ ๋ณ๊ฒฝ๋์ด์๋ ์๋๋ค. ๋ฐ๋ผ์ ์ผ๋ช '๋๊ฒฐ' ์์ผ๋์์ผ ํ๋ค. Object.freeze()๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ด์ฅ ๊ฐ์ฒด์ ๋ฉ์๋ ์ค ํ๋๋ก, ๊ฐ์ฒด์ ์์ฑ์ ๋ณ๊ฒฝ ๋๋ ์์ ํ ์ ์๋๋ก ๋ง๋๋ ๋ถ๋ณ์ฑ์ ๋ถ์ฌํ๋ค. ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด์ ์์ฑ์ ๋๊ฒฐํ๊ณ , ๋์ค์ ์ด ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ๋ ค๋ ์๋๊ฐ ์คํจํ๋๋ก ํ๊ธฐ์ ์๋์ ๊ฐ์ด ์ ์ฉํ๋ค.
const LOG_MESSAGE = Object.freeze({
START_GAME: '์ซ์ ์ผ๊ตฌ ๊ฒ์์ ์์ํฉ๋๋ค.',
INPUT_NUMBER: '์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์ : ',
CORRECT_END: '3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ์
จ์ต๋๋ค! ๊ฒ์ ์ข
๋ฃ',
END_GAME: '๊ฒ์ ์ข
๋ฃ',
RESTART_INPUT: '๊ฒ์์ ์๋ก ์์ํ๋ ค๋ฉด 1, ์ข
๋ฃํ๋ ค๋ฉด 2๋ฅผ ์
๋ ฅํ์ธ์.',
});
// ... ์ดํ๋ ์๋ต
2๏ธโฃ ์ค๋ณต๋ ์ซ์๊ฐ ์๋์ง ํ์ธํ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ
๊ฒ์ ํ๋ฆ ์, ์ปดํจํฐ๊ฐ ๋๋ค ํ 3์๋ฆฌ ์ซ์๋ฅผ ์์ฑํด์ผ ํ๋๋ฐ ์ด๋ ์ค์ํ ์กฐ๊ฑด์ด '์ค๋ณต์ด ์์ด์ผ ํ๋ค๋ ๊ฒ'์ด์๋ค. ์ด๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ์ฒ์์๋ ๋ฐฐ์ด์ ํ๋ ๋ง๋ค์ด, includes()๋ฅผ ์ฌ์ฉํด ์ด๋ฏธ ์ซ์๊ฐ ๋ฐฐ์ด์ ๋ค์ด์๋์ง (์ค๋ณต๋ ์ซ์๊ฐ ์๋์ง) ํ์ธํ๊ณ , ์๋ค๋ฉด ํด๋น ์ซ์๋ฅผ push()๋ก ๋ฃ์ด์ฃผ์๋ค.
๊ทธ๋ฌ๋ค ๋ด์ฅ ํจ์ ์ค, set()์ ๋ฐ๊ฒฌํ๊ณ ๋ฆฌํฉํ ๋ง ํ๋ค. Set์ ๊ฐ์ฅ ํฐ ํน์ง์ '์ค๋ณต๋ ์์๋ฅผ ํ์ฉํ์ง ์๋๋ค๋ ๊ฒ'์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ํ์ฉํ๋ฉด ๋์๋ค. array์ ์์๋ฅผ push()ํ๋ ๊ฒ์ฒ๋ผ, set()์ add()๋ฅผ ํ์ฉํด ๊ฐ์ ์ถ๊ฐํ ์ ์๊ณ ์ค๋ณต์ ํ์ฉํ์ง ์๋๋ค. ๊ทธ๋ฆฌ๊ณ array์ ์์ ์กด์ฌ ์ฌ๋ถ๋ฅผ ํ์ธํ๋ includes()์ฒ๋ผ, set()์ has()๋ก ํ์ธํ ์ ์๋ค.
์๋์ ๊ฐ์ด set & add๋ฅผ ์ฌ์ฉํด ์์ ํ๋ ์ฝ๋๊ฐ ํจ์ฌ ๊น๋ํด์ก๋ค.
// ์์ ์ : includes & push ์ฌ์ฉ
generateRandomNumber() {
const computerArray = [];
while (computerArray.length < 3) {
const newComputerNumber = Random.pickNumberInRange(1, 9);
if (!computerArray.includes(newComputerNumber)) {
computerArray.push(newComputerNumber);
}
}
return computerArray.join('');
}
// ์์ ํ : set & add ์ฌ์ฉ
generateRandomNumber() {
const generatedNumber = new Set();
while (generatedNumber.size < 3) {
const newComputerNumber = generateNumberInRange(1, 9);
generatedNumber.add(newComputerNumber);
}
return Array.from(generatedNumber).join('');
}
}
3๏ธโฃ ์ด๋ฆ์ ์ง๊ด์ ์ผ๋ก
๋ฉ์๋๋ช , ํ์ผ๋ช , ํด๋์ค๋ช ์ ์ ์ฒด์ ์ผ๋ก ์ดํด๋ณด๋ฉฐ ์๋์ ๊ฐ์ด ๋๊ตฌ๋ ์์๋ณผ ์ ์๊ฒ ์์ ํ๋ค. ๋ฌผ๋ก ์ฃผ์์ ์ฌ์ฉํด ๊ฐ ๋ฉ์๋์ ํด๋์ค๊ฐ ์ด๋ค ์ญํ ์ ํ๋์ง ์จ๋ ๋์์ง ์์ง๋ง, ์ฌ์ค ๊ฐ์ฅ ์ข์ ๊ฑด ์ด๋ฆ ์์ฒด์์ ๋ฌด์จ ์ญํ ์ ํ๋์ง ์ ์ ์๋๋ก ํ๋ ๊ฒ์ด๋ค.
// 1. ๊ฒ์ ์งํ์ค ์
๋ ฅ ๊ฐ์ด ์ ํจํ์ง ํ๋จํ๋ ๋ฉ์๋ ์ด๋ฆ ์์
// ๋ณดํต boolean์ returnํ๋ ํจ์๋ is ~ ์ด๋ฐ ์์ผ๋ก ์ฐ๊ธฐ ๋๋ฌธ
checkValidNumberDuringGame → isValidGameInput
// 2. ์
๋ ฅ ๊ฐ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ ํ์ผ ์ด๋ฆ ์์
// ๋์ฌ๋ ์ข์ง๋ง '์ญํ '์ ๋ถ๋ช
ํ ๋๋ฌ๋ด๋ฉด ๋ ์ข๋ค.
checkValid.js → validator.js
// 3. ์ปดํจํฐ๊ฐ ๋๋คํ ์ซ์๋ฅผ ์์ฑํ๋ ํด๋์ค ์ด๋ฆ ์์
// ์ปดํจํฐ ๋ผ๊ณ ์ด๋ฆ๋ง ์จ๋๋ ๊ฒ๋ณด๋ค ์ปดํจํฐ๊ฐ ํ๋ '์ญํ '์ ๋ถ๋ช
ํ ๋๋ฌ๋ด๋ฉด ๋ ์ข๋ค.
Computer.js → Generator.js
๊ทธ๋ฆฌ๊ณ ์ฑ <ThoughtWorks Anthology>์ ๋์ค๋ ๊ฐ์ฒด ์งํฅ ์ํ ์ฒด์กฐ ์์น์์๋ ์ด๋ฆ์ ๋ฌด์์ ์ค์ด๊ธฐ๋ณด๋ค ๊ฐ๋ตํ๊ณ ๋ ๋ช ํํ๊ฒ ํ๋ผ๊ณ ๋งํ๋ค. "๋๊ตฌ๋ ์ค์ ํด๋์ค, ๋ฉ์๋, ๋๋ ๋ณ์์ ์ด๋ฆ์ ์ค์ด๋ ค๋ ์ ํน์ ๊ณง์ ๋น ์ง๊ณค ํ๋ค. ๊ทธ๋ฐ ์ ํน์ ๋ฟ๋ฆฌ์ณ๋ผ. ์ถ์ฝ์ ํผ๋์ ์ผ๊ธฐํ๋ฉฐ, ๋ ํฐ ๋ฌธ์ ๋ฅผ ์จ๊ธฐ๋ ๊ฒฝํฅ์ด ์๋ค. ํด๋์ค์ ๋ฉ์๋ ์ด๋ฆ์ ํ ๋ ๋จ์ด๋ก ์ ์งํ๋ ค๊ณ ๋ ธ๋ ฅํ๊ณ ๋ฌธ๋งฅ์ ์ค๋ณตํ๋ ์ด๋ฆ์ ์์ ํ์."
4๏ธโฃ ๋น์ฆ๋์ค ๋ก์ง์ด ์๋ ํจ์๋ค์ utils.js์ ๋ถ๋ฆฌ
ํํ ํ๋ก๊ทธ๋๋ฐ์ ํ๋ฉด์ '๋น์ฆ๋์ค ๋ก์ง', '๋๋ฉ์ธ ๋ก์ง'์ ๋ํด ์ด์ผ๊ธฐํ๋ค. ๋ค์ด๋ ๋ดค์ง๋ง ํด๋น ๊ฐ๋ ์ ์ ๋ชฐ๋ผ์ ๊ณต๋ถํด ๋ณด๊ณ (์ฐธ๊ณ : ๋น์ฆ๋์ค ๋ก์ง, ๋๋ฉ์ธ ๋ก์ง์ด ๋๋์ฒด ๋ญ์ง?) ์ด๋ฒ ๋ฏธ์ ์ฝ๋์๋ ์ ์ฉํ๋ค. ์๋์ ๊ฐ์ด utils.js๋ผ๋ ํ์ผ์ ๋ฐ๋ก ๋ง๋ค์ด export ํ๊ณ , ํด๋น ํจ์๊ฐ ์ฌ์ฉ๋๋ ๊ณณ์ import ํ๋ค.
// utils.js
// ์ฌ์ฉ์์๊ฒ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ ํจ์
const printMessage = (message) => Console.print(message);
// ์ปดํจํฐ๊ฐ ๋๋คํ ์ซ์๋ฅผ ์์ฑํ๋ ํจ์
const generateNumberInRange = (min, max) => Random.pickNumberInRange(min, max);
// ์๋ฌ๋ฅผ ์ถ๋ ฅํ๋ ํจ์
const throwError = (message, condition = true) => {
if (condition) throw new Error(message);
};
// ... ์๋ต
export { printMessage, generateNumberInRange, throwError };
์ฐธ๊ณ ํ ๊ธ์ ๋ฐ๋ฅด๋ฉด, ๋๋ฉ์ธ ๋ก์ง์ ํ์ค ๋ฌธ์ ์ ๋ํ ์์ฌ๊ฒฐ์ ์ ํ๋ ์ฝ๋์ด๋ฉฐ, ๋๋จธ์ง ์ฝ๋๋ ๊ทธ ๊ฒฐ์ ์ ์ํ ์ ๋ ฅ๊ฐ์ ๋ง๋ค์ด์ฃผ๊ฑฐ๋, ๊ทธ ๊ฒฐ์ ์ ๊ฒฐ๊ณผ๋ฌผ์ ํด์ํ๊ณ ๋ณด์ฌ์ฃผ๊ณ ์ ํํ๋ ์ฝ๋๋ผ๊ณ ํ๋ค. ์ด๋ฐ ๊ธฐ์ค์ ์ธ์์ ์ฐ๋ฆฌ๊ฐ ๋๋ฉ์ธ ๋ก์ง๊ณผ ์๋ ๊ฒ์ ๋๋๋ ์ด์ ๋ ๋ช ํํ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ๋ฅผ ์ํด์๋ค.
๋๋ฉ์ธ ๋ก์ง๊ณผ ์๋ ๊ฒ์ ์ ๋๋๊ณ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ๋ฉด, ๊ฐ๋ฐ์๊ฐ ๋ก์ง์ ์ดํดํ๊ธฐ ์ฌ์์ง๋ค. ์ด๋ฐ ์ด์ ๋ก ํด๋ฆฐ ์ํคํ ์ฒ์์๋ ๋ค๋ฅธ ๊ณ์ธต๋ค์ ๋๋ฉ์ธ ๋ก์ง์๊ฒ ์ ๋ ฅ์ ์ ๋ฌํ๊ณ , ๋ณํ๋ฅผ ์ธ๋ถ๋ก ์ ๋ฌํ๋ ์ญํ ์ ํ๋๋ก ๋ช ํํ๊ฒ ๋ถ๋ฆฌํ๋ค๊ณ ํ๋ค. ์์ผ๋ก์ ๋ฏธ์ ์์๋ ๊ด์ฌ์ฌ ๋ถ๋ฆฌ์ ๋ ์ ๊ฒฝ ์ฐ๋ฉด์ ์ฝ๋ฉํด์ผ๊ฒ ๋ค๊ณ ์๊ฐํ๋ค.
5๏ธโฃ else๋ณด๋ค early return
์ฐํ ์ฝ ํด๋ฆฐ์ฝ๋ ์ฒดํฌ๋ฆฌ์คํธ์ ๋ฐ๋ฅด๋ฉด, else ์์ฝ์ด ์ฌ์ฉ์ ์ง์ํ๋ค๊ณ ํ๋ค. ๋ฌผ๋ก ์ด๋ฒ ๋ฏธ์ ์์๋ ์ด ์์น์ ์ค์ํ๋ผ๊ณ ๋ฐ๋ก ๋ง์ ํ์ง ์์์ง๋ง ํด๋ฆฐ์ฝ๋๋ฅผ ์ผ๋ํ๋ฉฐ ์ฝ๋๋ฅผ ์ง๋ ค๊ณ ํ๋ค. ์์นญํด ๋ณด๋ ์ง๋ ๊ธฐ์์์๋ else๋ฅผ ํฌํจํ else if, switch๋ฌธ๋ ์ง์ํ๋ฉด ์ข๋ค๋ ๋ง์ด ์์ด์ ๋๋๋ก์ด๋ฉด early return์ ํ๊ณ ์ ํ๋ค. (๋ฌผ๋ก ์ด ๋ถ๋ถ์ ์ฌ๋๋ง๋ค ๊ฐ๋ก ์๋ฐ์ด ์์ ์ ์๊ณ , ํ๋ง๋ค ํ์ฌ๋ง๋ค ๋ค๋ฅผ ์ ์์ผ๋ ์ฐธ๊ณ ๋ง ํ์.)
// ์์ ์
async handleUserInputEndGame(input) {
const isValidGameInputEndGame = [GAME_SELECT.RESTART, GAME_SELECT.END];
if (!isValidGameInputEndGame.includes(input)) {
throwError(ERROR_MESSAGE.INCORRECT_VALUE);
}
switch (input) { // switch๋ฌธ ์ฌ์ฉ
case GAME_SELECT.RESTART:
this.restartGame();
break;
case GAME_SELECT.END:
printMessage(LOG_MESSAGE.END_GAME);
break;
}
}
// ์์ ํ
async handleUserInputEndGame(input) {
const isValidGameInputEndGame = [GAME_SELECT.RESTART, GAME_SELECT.END];
if (!isValidGameInputEndGame.includes(input)) {
throwError(ERROR_MESSAGE.INCORRECT_VALUE);
return; // early return
}
if (input === GAME_SELECT.RESTART) {
this.restartGame();
return; // early return
}
if (input === GAME_SELECT.END) {
printMessage(LOG_MESSAGE.END_GAME);
}
}
โ๏ธ 1์ฃผ ์ฐจ ์๊ฐ
1๏ธโฃ ๋ง์ค์ ์์ด ๊ฐ์
์ฐ์ํํ ํฌ์ฝ์ค๋ฅผ ์ง์ํ ์ด์ ๋ ์ค์ค๋ก๋ฅผ ๋ง์ค์ผ ์ ์์ด ๋ถ๋ชํ๊ณ ์ฑ์ฅํ ์๋ฐ์ ์๋ ํ๊ฒฝ์ ๋๊ณ ์ถ๊ธฐ ๋๋ฌธ์ด์๋ค. ๋คํํ ํ๋ฆฌ์ฝ์ค๋ฅผ ํตํด ๋ง์ค์๊ณผ๋ ๋ฉ์ด์ง๊ณ ์๋ ๊ฒ ๊ฐ๋ค. ์ด์ ์๋ ์ ๊ทน์ ์ผ๋ก ์๋ํ์ง ์์๋ ์ฝ๋ ์ปจ๋ฒค์ , ํด๋ฆฐ ์ฝ๋ฉ, ๊ด์ฌ์ฌ ๋ถ๋ฆฌ, ํ ์คํธ ์ฝ๋ ๋ฑ์ ๋ง์ค์ ์์ด ์ฐพ์๋ณด๊ณ ์ฝ๋์ ๋ น์ฌ๋ด๊ณ ์ ํ๋ค. ์ด๋ฌํ ์๋๋ค์ ๊ธฐ๋ฐ์ผ๋ก ์์ผ๋ก์ ๋ฏธ์ ์ ๋ ์์ ๊ฐ ์๊ฒ ๋์ ํ ์ ์์ ๊ฒ ๊ฐ๋ค.
2๏ธโฃ ๋ฌ๋ฏธ๋ ๋ฌธ์ ํด๊ฒฐ
๊ฐ๋ฐ์๋ ๋ง์ ๋ฌธ์ ๋ฅผ ๋ง๋ ์๋ก ์ฑ์ฅํ๋ค๊ณ ๋ฏฟ๋๋ค. ํ์ง๋ง ๋ฏฟ๋ ๊ฒ๊ณผ๋ ๋ค๋ฅด๊ฒ ์ค์ฒํ๋ ๊ฒ์ ์ด๋ ต๊ณ , ์ฆ๊ฒ๊ฒ ํ๋ ๊ฒ์ ๋๋์ฑ ์ด๋ ค์ด ๊ฒ ๊ฐ๋ค. ์ด๋ฒ ๋ฏธ์ ์ํ์ ํ๋ฉด์ ์์ํ์ง ๋ชปํ ์๋ฌ๋ค์ ๋ง์ฃผํ๋ฉฐ ๋๋ฌด๋ ๊ณ ๋์์ง๋ง, ํด๊ฒฐํ ๋ค ์ฑ์ทจ๊ฐ์ ์ด๋ฃจ ๋งํ ์ ์์๋ค. ์ญ์ ํ๋ก๊ทธ๋๋ฐ์ ๋ฌ๋ฏธ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ์ด๋ผ๋ ๋ง์ ๋ค์ ํ๋ฒ ์ค๊ฐํ๋ค. ์์ผ๋ก๋ ์๋ฌ๋ฅผ ๋ง๋๋ฉด ์คํ๋ ค ์ฑ์ฅ์ ๊ธฐํ๋ผ ์๊ฐํ๊ณ ์ ๋๊ฒ ๋ฐ๊ฒจ์ฃผ์ด์ผ๊ฒ ๋ค.
3๏ธโฃ ‘๊ทธ๋ ๊ตฌ๋’๋ ํ์ด
๊ทธ๋์ ๊ฐ๋ฐ์ ๊ฐ์๋ ์ฑ ์ผ๋ก ํ์ตํ ๋๋ ‘๊ทธ๋ ๊ตฌ๋’ ํ๊ณ ๋๊ฒผ๋ ๊ฒ๋ค์ด ๋น๋ก์ ํ์ด(?)์ด ๋์ด ๋์์๋ค. ์ด๋ฒ ๋ฏธ์ ์ ํ๋ฉด์ ์ฌ์ํ ์ค์๊ฐ ์๋ฌ์ ์์ธ์ด ๋๊ฑฐ๋, ๊ธฐ๋ณธ์ ์ธ ๊ฐ๋ ์ ํ์คํ๊ฒ ์์ง ๋ชปํด ์ค์ค๋ก ๋๋๋ ์ ์ด ์๋ค. ํ์ง๋ง ์ด๋ฅผ ์ฑ์ฅ์ ๊ณ๊ธฐ๋ก ์ผ์ ๋ค์ ๊ณต๋ถํ๋ฉด์ ๋ถ์กฑํ ๊ฒ์ ์ฑ์ธ ์ ์์๋ค. ์์ผ๋ก๋ ์ฌ์ํ ๊ฐ๋ ์ด๋ผ๋ ํ์ด์ด ๋์ง ์๋๋ก ๋ฐ๋์ ์์ ์ฝ๋๋ฅผ ์จ๋ณด๊ฑฐ๋ ์๊ฒ๋ผ๋ ๋ง๋๋ ์ฐ์ต์ ํ๋ฉฐ, ํ์คํ ๋ด ๊ฒ์ผ๋ก ๋ง๋ค์ด์ผ๊ฒ ๋ค.
๋๊ธ