๐ ์คํ๋ฆฐํธ ๋ฏธ์ ์ฃผ์
๋ฏธ์ 4๋ ๊ธฐ์กด ๋ฏธ์ ์์ ์์ ํ ๋ก๊ทธ์ธ, ํ์๊ฐ์ ํ์ด์ง์
์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํด์ ํผ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ๊ตฌํํ๋ ๊ฒ์ด ์ฃผ์ ์๋ค.
๐ ์คํ๋ฆฐํธ ๋ฏธ์ ์งํ ๊ณผ์
๐ฅ๏ธ ์ด์ ์์ ์์
1. name ์์ฑ ์ถ๊ฐ
๋ฏธ์
4๋ฅผ ์งํํ๋ ค๊ณ ๋ณด๋ input
์ด๋ from
ํ๊ทธ์
name
์์ฑ์ด ๋น ์ ธ ์์ด์ ๊ทธ ๋ถ๋ถ์ ์ถ๊ฐํด ์ฃผ์๋ค.
name ์์ฑ์ ํผ ๋ฐ์ดํฐ ์ ์ก ์ key ์ญํ ์ ํ๋ค.
form์ด ์ ์ถ๋ ๋, ๊ฐ input์ name=value ํํ๋ก ์๋ฒ์ ์ ๋ฌ๋จ
2. autocomplete ์์ฑ ์ถ๊ฐ
๋ธ๋ผ์ฐ์ ์ฝ์์ ํ์ธํด๋ณด๋ autocomplete
์์ฑ๊ณผ ๊ด๋ จ๋ ๊ฒฝ๊ณ ๊ฐ ๋ ์
์ ๊ทผ์ฑ์ ์ํด ์์ฑ์ ์ถ๊ฐํด์ฃผ์๋ค.
autocomplete
์์ฑ์ ์ฌ์ฉํ๋ฉด
์ ์ฌ์ง์ฒ๋ผ ๋ธ๋ผ์ฐ์ ์์ ์๋์์ฑ ๊ธฐ๋ฅ์ ์ ๊ณตํด์ค๋ค.
๐๏ธ ํด๋ ๊ตฌ์กฐ
๐ฆ sprintMission
โฃ ๐constant
โ โ ๐regex.js
โฃ ๐css
โ โฃ ๐auth-style.css
โ โฃ ๐common.css
โ โฃ ๐index-style.css
โ โ ๐variables.css
โฃ ๐images
โฃ ๐js
โ โฃ ๐auth.js
โ โ ๐auth-handlers.js
โฃ ๐index.html
โฃ ๐login.html
โฃ ๐signup.html
โ ๐item.html
์ด๋ฒ ๋ฏธ์
๋ถํฐ JSํ์ผ์ ์ถ๊ฐํด์ผ ํด์ js
ํด๋๋ฅผ ๋ง๋ค์๊ณ ,
์ ๊ท์์ ๊ด๋ฆฌํ๊ธฐ ์ํด constant
ํด๋๋ฅผ ๋ณ๋๋ก ๋ง๋ค์๋ค.
โ๏ธ ๊ตฌํ๊ณผ์
๐ ํ์ผ ๋๋๊ธฐ
JS ํ์ผ์ ํฌ๊ฒ ๋ ๊ฐ๋ก ๋๋์๋ค.
auth.js
→ ๊ธฐ๋ฅ ๊ตฌํ ์ฝ๋auth-handler.js
→ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ฐ๊ฒฐ ์ฝ๋
๊ฐ HTML ํ์ผ์๋ auth-handler.js
๋ง ์ฐ๊ฒฐํ๋ค.
์ด๋ ๊ฒ ๋๋๋ฉด DOM ์ ์ด์ ๊ธฐ๋ฅ ๊ตฌํ์ ๋ถ๋ฆฌํ ์ ์๊ณ , ๊ด๋ฆฌํ๊ธฐ๋ ํธ๋ฆฌํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ค.
์ฒ์์๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ฐ๊ฒฐ ์ฝ๋๋ฅผ login.js
, signup.js
๋ก ๋๋ ์์ฑํ๋๋ฐ,
๊ฒฐ๊ตญ ๋ก๊ทธ์ธ๊ณผ ํ์๊ฐ์ ๋ชจ๋ ํผ ๊ฒ์ฆ + ๋น๋ฐ๋ฒํธ ๋ณด์ด๊ธฐ ๊ธฐ๋ฅ์ด ํ์ํ๋ค๋ ์ ์ด ๊ฐ์์
์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ํ๋๋ก ํฉ์ณ auth-handler.js
์์ ๊ด๋ฆฌํ๋๋ก ๋ฐ๊พธ์๋ค.
โ ๏ธ ์๋ฌ ๋ฉ์ธ์ง ์ถ๋ ฅ
ํผ ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ํ์ํ๊ธฐ ์ํด span ํ๊ทธ๋ฅผ htmlํ์ผ์ ๋ฏธ๋ฆฌ ์ถ๊ฐํด๋์๋ค.
<span class="auth-input-errorMsg none"></span>
์ด๋ฉ์ผ์ด๋ ๋๋ค์ input์ ๋ค์ ํ์ ์์๋ก ํด๋น ์๋ฌ spanํ๊ทธ๊ฐ ์์ด์
nextElementSibling
์ผ๋ก ์ ๊ทผํ ์ ์์์ง๋ง
const errorSpan = input.nextElementSibling
๋น๋ฐ๋ฒํธ input์ ๋น๋ฐ๋ฒํธ ๋ณด์ด๊ธฐ ๋ฒํผ ๋๋ฌธ์
divํ๊ทธ๋ก ํ ๋ฒ ๋ ๊ฐ์ธ์ ธ ์์ด์ ์์ฒ๋ผ ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํ๋ค.
์ด๋ป๊ฒ ํ ์ง ๊ณ ๋ฏผํ๋ค๊ฐ closest()
๋ฉ์๋๊ฐ ์๋ค๋ ๊ฒ์ ์๊ฒ๋์๊ณ ,
closest()
๋ฉ์๋๋ฅผ ํ์ฉํด์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์๋ค.
const errorSpan = input.closest('.auth-input-area').querySelector('.auth-input-errorMsg')
closest()
๋ ์ง์ ํ ์ ํ์์ ์ผ์นํ๋ ๊ฐ์ฅ ๊ฐ๊น์ด ์กฐ์ ์์๋ฅผ ์ฐพ์์ฃผ๋ ๋ฉ์๋์ด๋ค.
๋ชจ๋ input์ด .auth-input-area
์ ๊ฐ์ธ์ ธ ์์๊ธฐ ๋๋ฌธ์
์ด๋ฅผ ๊ธฐ์ค์ผ๋ก span ํ๊ทธ๋ฅผ ์ฐพ์ ์ ์์๋ค.
์ ๋ฐฉ์์ผ๋ก span ํ๊ทธ ์ ๊ทผ์ ๋ณ๊ฒฝํด์ฃผ์๋๋
์๋ฌ๋ฉ์ธ์ง๊ฐ ์ํ๋ ์์น์ ์ ๋ํ๋๋ค.
โ ํผ ์ ํจ์ฑ ๊ฒ์ฆ
const handleFormValidation = (e) => {
const { name, value } = e.target
let errorMsg = ''
if (name === 'email') {
errorMsg = isRequired(value, '์ด๋ฉ์ผ์') || validateEmail(value)
} else if (name === 'password') {
errorMsg = isRequired(value, '๋น๋ฐ๋ฒํธ๋ฅผ') || validatePassword(value)
} else if (name === 'confirmPassword') {
errorMsg = isRequired(value, '๋น๋ฐ๋ฒํธ๋ฅผ') || validateConfirmPassword(value)
} else if (name === 'nickname') {
errorMsg = isRequired(value, '๋๋ค์์') || validateNickname(value)
}
errorMsg ? showErrorMsg(e.target, errorMsg) : clearErrorMsg(e.target)
}
์ฒ์์๋ if ~ else if
๋ฌธ์ผ๋ก ์กฐ๊ฑด๋ณ ๊ฒ์ฆ์ ์ฒ๋ฆฌํ์ง๋ง,
์ค๋ณต์ด ๋ง์ ๋ณด์ฌ ๊ฐ์ฒด๋ฅผ ํ์ฉํ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ๋ค.
const validators = {
email: (value) => isRequired(value, '์ด๋ฉ์ผ์') || validateEmail(value),
password: (value) => isRequired(value, '๋น๋ฐ๋ฒํธ๋ฅผ') || validatePassword(value),
confirmPassword: (value) => isRequired(value, '๋น๋ฐ๋ฒํธ๋ฅผ') || validateConfirmPassword(value),
nickname: (value) => isRequired(value, '๋๋ค์์') || validateNickname(value),
}
export const handleInputValidation = (e) => {
const { name, value } = e.target
const errorMsg = validators[name] ? validators[name](value) : ''
errorMsg ? showErrorMsg(e.target, errorMsg) : clearErrorMsg(e.target)
}
||
์ฐ์ฐ์์ ํน์ง(a || b → a๊ฐ true๋ฉด a๋ฅผ ๋ฆฌํด)์ ์ด์ฉํด์ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
์์ ๊ฒ์ฆ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด ํด๋น ๋ฉ์์ง๋ฅผ ๋ฐํํ๊ณ ,
ํต๊ณผํ๋ฉด ๋น ๋ฌธ์์ด์ด ๋ฐํ๋์ด ๋ค์ ๊ฒ์ฆ ํจ์๊ฐ ์คํ๋๋ค.
์ด ๋ฐฉ์์ผ๋ก ๊ฐ๋ ์ฑ์ ๋์ด๊ณ ์ค๋ณต์ ์ค์ผ ์ ์์๋ค.
์ด ๋ฐฉ์์ด ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ผ์ง๋ ์ ๋ชจ๋ฅด๊ฒ ์ง๋ง
if ~ else if๋ฌธ ๋์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด์ ํจ์ถ์ ์ผ๋ก ํํํ ๊ฒ ๊ฐ์
์์ง์ ๋ง์กฑ์ค๋ฌ์ด ๋ฐฉ๋ฒ์ด๋ผ๊ณ ์๊ฐํ๊ณ ์๋ค.
๐จ ์๋ฑํ ์์์ css๊ฐ ์ ์ฉ๋๋ ๋ฌธ์
input ๊ฐ์ด ์ ํจํ๋ฉด auth-input-complete ํด๋์ค๋ฅผ ์ถ๊ฐํ๋๋ก ํ๋๋ฐ,
๋น๋ฐ๋ฒํธ ๋ณด์ด๊ธฐ ๋ฒํผ(.show-password-button
)์๋ ํด๋น ํด๋์ค๊ฐ ์ ์ฉ๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
์์ธ์ clearErrorMsg
ํจ์์ ์ธ์๋ก
input ํ๊ทธ๋ง ์ ๋ฌ๋ ๊ฑฐ๋ผ๋ ์์๊ณผ ๋ฌ๋ฆฌ ๋ฒํผ ์์๋ ํจ๊ป ๋ค์ด์ค๊ณ ์์๋ค.
๊ทธ๋์ handleInputValidation
์์ input ํ๊ทธ๊ฐ ์๋ ๊ฒฝ์ฐ ๋ฐ๋ก ๋ฆฌํดํ๋๋ก ์ฝ๋๋ฅผ ์์ ํ๋ค.
export const handleInputValidation = (e) => {
if (e.target.tagName !== 'INPUT') return
const { name, value } = e.target
const errorMsg = validators[name] ? validators[name](value) : ''
errorMsg ? showErrorMsg(e.target, errorMsg) : clearErrorMsg(e.target)
}
์ด๋ ๊ฒ ์์ ํ๋๋ ๋ฌธ์ ์์ด ์ ๋์ํ๋ค.
๐ ํ์ด์ง ์ด๋ ์ฒ๋ฆฌ
๋ฏธ์ ์๊ตฌ์ฌํญ์์ API ์ฐ๋์ ์์๊ธฐ ๋๋ฌธ์
๊ฒ์ฆ์ด ์๋ฃ๋๋ฉด ๋จ์ํ ๋ค๋ฅธ ํ์ด์ง๋ก ์ด๋ํ๋๋ก ๊ตฌํํ๋ค.
location.replace('/item.html')
์ด๋ location.replace()
๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ํ์ด์ง๋ฅผ ์ด๋์์ผฐ๋ค.
replace()
๋ ํ์คํ ๋ฆฌ์ ํ์ฌ ํ์ด์ง๋ฅผ ๋จ๊ธฐ์ง ์๊ธฐ ๋๋ฌธ์
์ฌ์ฉ์๊ฐ ๋ค๋ก๊ฐ๊ธฐ ๋ฒํผ์ ๋๋ฅด๋๋ผ๋ ๋ก๊ทธ์ธ/ํ์๊ฐ์ ํ์ด์ง๋ก ๋์๊ฐ ์ ์๋ค.
๋ก๊ทธ์ธ์ด๋ ํ์๊ฐ์ ์ ์ฑ๊ณตํ ํ ๋ค๋ก๊ฐ๊ธฐ๋ฅผ ๋๋ ์ ๋
๋ค์ ๋ก๊ทธ์ธ ํ์ด์ง๋ ํ์๊ฐ์ ํ์ด์ง๊ฐ ๋ณด์ด๋ ๊ฒ์
์ด์ํ ๋์์ด๋ผ๊ณ ์๊ฐํด์ replace()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
โ๏ธ ์ฝ๋ ๋ฆฌ๋ทฐ
๐งน ํด๋ฆฐ ์ฝ๋ ๊ด๋ จ ํผ๋๋ฐฑ
์ด๋ฒ ๋ฏธ์ ์์๋ ์ค๋ณต ์ฝ๋๋ฅผ ์ต๋ํ ์ค์ด๊ณ
ํ ํจ์๊ฐ ํ๋์ ์ญํ ๋ง ํ๋๋ก ์์ฑํ๋ ค๊ณ ์ ๊ฒฝ์ ์ผ๋ค.
๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ์ฝ๋ ๋ถ๋ฆฌ๋ฅผ ์ ํ๋์ง ํ์ ์ด ์์ง ์์ ์ง๋ฌธ์ ๋๋ ธ๊ณ ,
๋ฉํ ๋๊ป์ ํ ์ค์์ ์งํํ ํด๋ฆฐ์ฝ๋ ์์์ ์ถ์ฒํด์ฃผ์ จ๋ค.
์์์์๋ ์ค๋ฌด์์ ์ด๋ค ์ฝ๋๋ฅผ ํด๋ฆฐ์ฝ๋๋ผ๊ณ ํ๋์ง
์์ง๋ ๋์ ์ฝ๋๋ฅผ ์ด๋ป๊ฒ ์์ฑํ ์ ์๋์ง ์ฌ๋ก์ ํจ๊ป ๋ค๋ฃจ๊ณ ์์๋ค.
ํนํ ์ฝ๋ ์์ง์ ๋ํ ๊ฐ๋ ์ ๋ค์ ์๊ฐํด๋ณผ ์ ์์ด์ ์์์ด ๋์์ด ๋์๋ ๊ฒ ๊ฐ๋ค.
์ฌ์ค ์์ง ์์ ํ ์ดํดํ์ง๋ ๋ชปํ์ง๋ง,
์๊ฐ์ด ๋ ๋ ๋ค์ ์์์ ๋ณด๋ฉด์ ์ฝ๋ ์์ฑ ๊ธฐ์ค์ ์๊ฐํด ๋ด์ผํ ๊ฒ ๊ฐ๋ค.
โฉ script ํ๊ทธ์ async/defer ๊ด๋ จ ํผ๋๋ฐฑ
์ด๋ฒ ๊ตฌํ์์ ์๋์ ๊ฐ์ด body ๋ซ๋ ํ๊ทธ ๋ฐ๋ก ์์ script ํ๊ทธ๋ฅผ ์ถ๊ฐํ์๋ค.
<body>
...
<script type="module" src="./js/auth-handlers.js"></script>
</body>
์ด๋ ๊ฒ ์์ฑํ ์ด์ ๋ ๋ธ๋ผ์ฐ์ ๊ฐ DOM์ ํ์ฑํ ๋
script ํ๊ทธ๋ฅผ ๋ง๋๋ฉด ํ์ฑ์ ๋ฉ์ถ๋ค๋ ์ ์ด ์๊ฐ๋์
DOM์ด ๋ชจ๋ ๊ทธ๋ ค์ง ํ์ ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋๋๋ก body ํ๊ทธ ํ๋จ์ ์ถ๊ฐํ๋ค.
ํผ๋๋ฐฑ ๋น์ ์ด ๋ฐฉ์์ด ์์ ๋ ๋๋ง ์ฐจ๋จ ๋ฌธ์ ๋ฅผ ์ํด ์์ฃผ ์ฐ๋ ๋ฐฉ์์ด๊ณ ,
ํ์ฌ๋ head์ ์คํฌ๋ฆฝํธ ํ๊ทธ๋ฅผ ๋๊ณ defer ์์ฑ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ํ๋์ ์ธ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ์๋ ค์ฃผ์ จ๋ค.
defer ์์ฑ
- ์คํฌ๋ฆฝํธ๊ฐ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋ค์ด๋ก๋๋๋ค.
- DOM ํ์ฑ์ ๋ฉ์ถ์ง ์๋๋ค.
- ์คํ์ DOM ํ์ฑ์ด ๋๋ ๋ค์ ์ผ์ด๋๋ค.
defer๋ฅผ ์ฐ๋ฉด ๋ ๋๋ง ์ฐจ๋จ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ฉด์๋ DOM์ด ์ค๋น๋ ๋ค์ ์์ ์ ์ผ๋ก ์คํํ ์ ์๋ค.
๋ํ, ์ด๋ฒ ์ฝ๋์์ ์ฌ์ฉํ type="module"
์์ฑ์
๊ธฐ๋ณธ์ ์ผ๋ก defer
์ฒ๋ผ ๋์ํ๋ค๋ ์ฌ์ค๋ ์๋กญ๊ฒ ์๊ฒ ๋์๋ค.
๊ทธ๋์ ๊ตณ์ด body ํ๋จ์ ๋ ํ์ ์๊ณ , head ํ๋จ์ ์์น์์ผ๋ ๋ฌธ์ ๊ฐ ์๋ค.
์ด์ ํจ๊ป ์์ฃผ ๋น๊ต๋๋ ์์ฑ์ธ async๋ ์ง์ด์ฃผ์ จ๋ค.
async ์์ฑ
- ์คํฌ๋ฆฝํธ๊ฐ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋ค์ด๋ก๋๋๋ค.
- ๋ค์ด๋ก๋๊ฐ ๋๋๋ ์ฆ์ ์คํ๋๋ฏ๋ก DOM ํ์ฑ์ด ๋ฉ์ถ ์ ์๋ค.
- ๋ฌธ์ ๋ด ์์๋ฅผ ๋ฐ๋ฅด์ง ์๊ณ , ๊ฐ์ฅ ๋จผ์ ๋ค์ด๋ก๋๋ ์คํฌ๋ฆฝํธ๊ฐ ๋จผ์ ์คํ๋๋ค.
์ด ํน์ฑ ๋๋ฌธ์ async๋ ์ฃผ๋ก ๊ตฌ๊ธ ์ ๋๋ฆฌํฑ์ค(GA)๋ ๊ด๊ณ ์ฒ๋ผ
DOM๊ณผ ๋ณ๊ฐ๋ก ์คํ๋๋ ์ธ๋ถ ์คํฌ๋ฆฝํธ๋ฅผ ์ฐ๊ฒฐํ ๋ ์์ฃผ ์ฌ์ฉ๋๋ค๊ณ ํ๋ค.
๐ ์คํ๋ฆฐํธ ๋ฏธ์ 4 ํ๊ธฐ
์ด๋ฒ ๋ฏธ์ ์ ์ด์ ๋ฏธ์ ๋ณด๋ค ํ์คํ ๋์ด๋๊ฐ ๋๊ฒ ๋๊ปด์ก๋ค.
ํนํ ํจ์ ๋ถ๋ฆฌ๋ ์ค๋ณต ์ ๊ฑฐ, ๋จ์ผ ์ฑ ์ ์์น์ ์ผ๋ง๋ ์ ์งํค๊ณ ์๋์ง์ ๋ํด ๊ณ ๋ฏผ์ด ๋ง์๋ค.
์์ง์ ๊ธฐ์ค์ด ๋ช ํํ์ง ์์ ๊ณ์ ์ฝ๋๋ฅผ ์์ ํ๋ฉฐ ์์ฑํ์ง๋ง,
๊ทธ๋๋ ์ด๋ฐ ๊ณ ๋ฏผ ๊ณผ์ ์์ฒด๊ฐ ์๋ฏธ ์๋ค๊ณ ์๊ฐํ๋ค. ๐ฅน
๋ค์ ๋ฏธ์ ๋ถํฐ๋ ๋ฆฌ์กํธ๋ฅผ ํ์ฉํด ํ์ด์ง๋ฅผ ๊ตฌํํ๋ ๊ฑธ๋ก ์๊ณ ์๋ค.
๋ฆฌ์กํธ๋ ๋ค์ ์ ๊ณต๋ถํด์ ์์ผ๋ก์ ๋ฏธ์ ๋ ์ ์์ํ๊ณ ์ถ๋ค. ๐