κ°μ
λ―Έμ | κΈ°κ° | Repository | PR & Review | github page |
---|---|---|---|---|
μν 리뷰 1λ¨κ³ | 23-03-17 - 23-03-27 |
Repo | PR & Review | π¬ μν 리뷰 |
π λ―Έμ νκ³
μν 리뷰μ 2λ¨κ³ λ―Έμ λͺ©νλ λ€μκ³Ό κ°λ€.
- μν μμΈμ 보 μ‘°ν
- APIμμ μ 곡νλ νλͺ©μ νμ©νμ¬ μμΈ μ 보λ₯Ό 보μ¬μ£Όλ λͺ¨λ¬ μ°½μ ꡬννλ€.
- ν€λ³΄λμ ESC ν€λ₯Ό λλ₯΄λ©΄ λͺ¨λ¬ μ°½μ λ«μ μ μλ λ± μ¬μ©μ±μ κ³ λ €νλ€.
- λ³μ 맀기기
- μ¬μ©μλ μνμ λν΄ λ³μ μ μ€ μ μμΌλ©° μλ‘κ³ μΉ¨νλλΌλ μ¬μ©μκ° λ¨κΈ΄ λ³μ μ μ μ§λμ΄μΌ νλ€.
- λ³μ μ 5κ°λ‘ ꡬμ±λμ΄ μμΌλ©° ν κ°λΉ 2μ μ΄λ©° 1μ λ¨μλ κ³ λ €νμ§ μλλ€.
- UI⁄UX κ°μ νκΈ°
- μν λͺ©λ‘κ³Ό μν μμΈ μ λ³΄κ° λ¨λ λͺ¨λ¬μ°½μ λν λ°μν λ μ΄μμμ ꡬμ±νλ€.
- μν λͺ©λ‘μμ λ 보기 λ²νΌμ λλ μ λ νμ΄μ§νλ λ°©μμμ 무ν μ€ν¬λ‘€ λ°©μμΌλ‘ λ³κ²½νλ€.
μ΄μ€ κΈ°μ΅μ λ¨λ ꡬνμ λν΄ κΈλ‘ λ¨κΈ°κ³ μ νλ€.
πΊ λͺ¨λ¬ μ°½
λͺ¨λ¬ μ°½μ ꡬννκΈ° μν΄ position: fixed;
css μμ±μ μ¬μ©νμλ€. μ΄λ μ λ² λ―Έμ
μΈ μ μ¬ λ λ¨Ήμ§μ κ°μ λ°©λ²μ΄μλ€. λλ¬Έμ λͺ¨λ¬ μ°½μ ꡬννλ κ²μ μ΄λ ΅μ§ μμλ€. cssλ₯Ό μ¬μ©νμ¬ λͺ¨λ¬ μ°½μ λ§λλ κ²λΏ μλλΌ html νκ·Έλ₯Ό μ¬μ©νμ¬ λͺ¨λ¬ μ°½μ μ‘°κΈ λ μ½κ² λ§λ€ μ μλ€λ κ²μ λ€λ₯Έ ν¬λ£¨λ€μ PRμμ μκ² λμλ€. ν΄λΉ νκ·Έλ dialog
νκ·Έμ΄λ€. μ²μ 보λ νκ·Έμ΄κΈ° λλ¬Έμ MDNμμ μ΄λ₯Ό μ°Ύμ보μλ€.
κΈ°λ³Έμ μΌλ‘ dialog
νκ·Έμ open
μμ±μ νμ©νμ¬ λͺ¨λ¬ μ°½μ μ΄κ³ λ«μ μ μλ€. μ¬λ λ°©λ²μ HTMLDialogElement
μ μΈμ€ν΄μ€ λ©μλμΈ showModal
λ₯Ό μ¬μ©νλ€. λ«λ λ°©λ²μ λμ± μ λ°νλ€. ESC
λ₯Ό ν€λ₯Ό λλ₯΄λ©΄ μλμΌλ‘ λ«νλ€. μ΄λ₯Ό dialog
νκ·Έ μμ΄ κ΅¬ννλ €λ©΄ μλ°μ€ν¬λ¦½νΈκ° νμνλ€. νμ§λ§ dialog
νκ·Έλ κΈ°λ³Έμ μΌλ‘ ESC
ν€μ λν λ°μμ μ 곡νλ νΈλ¦¬ν κ² κ°λ€λ λλμ΄ λ λ€. λͺ¨λ¬ μ°½μ λ«λ λ λ€λ₯Έ λ°©λ²μ λͺ¨λ¬ μ°½ λ΄μμ form
νκ·Έλ₯Ό μ΄μ©ν λ νΈλ¦¬νκ² μ μ©ν μ μλ€. form
νκ·Έμ method
μμ±μ dialog
λ‘ μ§μ νκ³ submit
λ²νΌμ λ§λλ©΄ λλ€. μ΄λ dialog
μ returnValue
μμ±μ fromλ₯Ό μ μΆν λ μ¬μ©ν buttonμ value
λ‘ μ€μ λλ€.
μ΄μ κ°μ dialog
λ₯Ό μ¬μ©νλ©΄ λ³΄λ€ νΈλ¦¬νκ² λͺ¨λ¬ μ°½μ λ§λ€ μ μμ κ² κ°λ€. λν μμΌλ‘ 리μ‘νΈλ₯Ό λ€λ£¨κ² λ ν
λ°, dialog
νκ·Έλ₯Ό μ¬μ©νμ¬ λͺ¨λ¬ μ°½ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ§μ λ§λ€ μ μμ κ²λ§ κ°μ λλμ΄ λ λ€. λ¨, μμ§ dialog
νκ·Έλ IE λΈλΌμ°μ μμλ μ§μμ νμ§ μμΌλ―λ‘ μ΄ μ μ μ μν΄μΌ νλ€.
π½ λ³μ μ μ₯νκΈ°
λ³μ μ λ‘컬μ€ν 리μ§μ μ μ₯μ΄ λμ΄μΌ νλ€. λλ¬Έμ λ€μκ³Ό κ°μ κ°μ²΄λ₯Ό λ§λ€μ΄ λ³μ μ μ μ₯νκ³ λΆλ¬μ€λλ° νμ©νμλ€.
const handleLocalStorage = {
getAllMovieStar: (): { -readonly [k in keyof ArrayLike<number>]: number } => {
return JSON.parse(localStorage.getItem('movieStar') as string) || {};
},
getMovieStar: (movieId: number) => {
return handleLocalStorage.getAllMovieStar()[movieId] || 0;
},
setMovieStar: (movieId: number, starCount: number) => {
const movieStar = handleLocalStorage.getAllMovieStar();
movieStar[movieId] = starCount;
localStorage.setItem('movieStar', JSON.stringify(movieStar));
},
};
export default handleLocalStorage;
μ²μμ Map
κ°μ²΄λ₯Ό λ‘컬μ€ν 리μ§μ μ μ₯μ νλ €κ³ νλ€. μ€λ³΅λ ν€λ₯Ό κ°μ§μ§ μκ³ μμ±μ μΆκ°, μ κ±°, μμ νκΈ° νΈλ¦¬νκΈ° λλ¬Έμ΄λ€. νμ§λ§ Map
κ°μ²΄μ JSON.stringify
λ©μλλ₯Ό μ¬μ©νκ² λλ©΄ λΉ κ°μ²΄κ° λ°νλλ€. μ΄ λλ¬Έμ Map
κ°μ²΄λ₯Ό νμ©νμ§ λͺ»νμλ€. μ΄μ μ΄ μμ¬μ λ€. νμ
λ κ°κ²°νκ² Map<number, number>
λ‘ ν μ μμκΈ° λλ¬Έμ΄λ€.
Map
κ°μ²΄λ₯Ό νμ©νμ§ λͺ»ν μμ¬μμ λ€λ‘νκ³ κ·Έλ€μμΌλ‘ μ΄λ»κ² λ‘컬μ€ν 리μ§μ μν μμ΄λμ λ³μ μ μ μ₯ν μ μμμ§ κ³ λ―Όμ νμλ€. κ²°κ΅ number μΈλ±μ€ μκ·Έλμ²μ νμ
μ μ¬μ©νκΈ°λ‘ νμλ€. κ·Έ μ΄μ λ μ΄λ€ μν μμ΄λκ° μ¬μ§ λͺ¨λ₯΄κΈ° λλ¬Έμ(λμ μΈ λ°μ΄ν°μ΄κΈ° λλ¬Έμ) μΈλ±μ€ μκ·Έλμ²κ° μ μ νκΈ° λλ¬Έμ΄λ€.
μΆκ°μ μΌλ‘ ν€κ° numberμΈ μΈλ±μ€ μκ·Έλμ²λ₯Ό λ€λ£° λ, Array, νν, ArrayLikeμ κ°μ νμ
μ μ¬μ©νλ©΄ λλ€. μ κ·Όμ μ΄μ μ λλ€λ©΄ ArrayLike
κ° κ°μ₯ μ¬λ°λ₯Έ νμ
μ΄ λλ€. λ¨, ArrayLike
μ readonly
μμ±μ΄λ―λ‘ μμ λ‘κ² μμ±μ μΆκ°, μ κ±°, μμ νκΈ° μν΄μ readonly
μμ±μ μ κ±°ν΄μΌ νλ€.
λ¨Όμ λ€μμ λͺ¨λ μνμ λ³μ μ κ°μ Έμ€λ λ©μλμ΄λ€.
const handleLocalStorage = {
getAllMovieStar: (): { -readonly [k in keyof ArrayLike<number>]: number } => {
return JSON.parse(localStorage.getItem('movieStar') as string) || {};
},
};
νμ
μ 보면 λκ° μ μ ? μ΄μ?νλ€.. λ΄κ° μκ°νμ¬ λ§λ νμ
μΈλ° ArrayLike
μ ν€λ μ¬μ©λκ³ μμ§λ§ κ°μ μ¬μ©λκ³ μμ§ μλ€. λκ° μ΄μ€νμ§λ§, νμ
μ€ν¬λ¦½νΈλ₯Ό λ°°μ°κ³ μλ κ³Όμ μμ μ¬λ¬ κ³ λ―Όμ νλ€λ κ²μ μμλ₯Ό λκ³ μΆλ€. readonly
μμ±μ μ κ±°νκΈ° μν΄ λ§€νλ νμ
μμ -readonly
λ₯Ό μμ±νμλ€.
λ€μμ νΉμ μνμ λ³μ μ κ°μ Έμ€κ³ , μ μ₯νλ λ©μλμ΄λ€.
const handleLocalStorage = {
getMovieStar: (movieId: number) => {
return handleLocalStorage.getAllMovieStar()[movieId] || 0;
},
setMovieStar: (movieId: number, starCount: number) => {
const movieStar = handleLocalStorage.getAllMovieStar();
movieStar[movieId] = starCount;
localStorage.setItem('movieStar', JSON.stringify(movieStar));
},
};
μ λ κ°μ λ©μλλ ν¬κ² μ΄λ €μ΄ κ² μλ€.
μ 체μ μΌλ‘ λ΄€μ λ νμ
μ λ°λ‘ μ μΈνλ κ²μ΄ μ’μ κ² κ°λ€λ μκ°μ νμλ€. λν λ©μλλ₯Ό μ μν λ νμ΄ν ν¨μκ° μλλΌ ν¨μ μ μΈμμΌλ‘ μμ±νμ¬ λ©μλ λ΄λΆμμ κ°μ²΄μ μ κ·Όν λ this
ν€μλλ₯Ό μ¬μ©ν μ μλλ‘ νλ©΄ μ’μ κ² κ°μ λ€μκ³Ό κ°μ΄ 리ν©ν°λ§μ νμλ€.
type LocalStorageMovieStar = {
-readonly [k in keyof ArrayLike<number>]: number;
};
const handleLocalStorage = {
getAllMovieStar: function (): LocalStorageMovieStar {
return JSON.parse(localStorage.getItem('movieStar') as string) || {};
},
getMovieStar: function (movieId: number) {
return this.getAllMovieStar()[movieId] || 0;
},
setMovieStar: function (movieId: number, starCount: number) {
const movieStar = this.getAllMovieStar();
movieStar[movieId] = starCount;
localStorage.setItem('movieStar', JSON.stringify(movieStar));
},
};
export default handleLocalStorage;
βοΈ λ³μ μ λ§μ°μ€ μ¬λ¦¬κΈ°
λ³μ μ 맀기기 μ , λ€μκ³Ό κ°μ΄ λ³μ μμ λ§μ°μ€λ₯Ό μ¬λ¦¬λ©΄ ν΄λ¦μ νμ§ μμλ λ§μ°μ€λ₯Ό μ¬λ¦° λ³μ κΉμ§ λͺ¨λ λ³λ€μ λ°°κ²½μ΄ μ±μμ§λ κ²μ ꡬννκ³ μΆμλ€.
μ²μμ λ³ νλνλμ μ΄λ²€νΈλ₯Ό μΆκ°νμλ€. κ·Έ μ΄νμ λ‘μ§μ λ€μκ³Ό κ°λ€.
- λ³μ data-set μ΄νΈλ¦¬λ·°νΈ κ°μ λ°λΌ λ³μ΄ μλ‘κ² κ·Έλ €μ§λ€.
- λ³μ΄ μλ‘κ² κ·Έλ €μ§κΈ° λλ¬Έμ μ΄λ²€νΈκ° μ¬λΌμ§κΈ° λλ¬Έμ λ€μ μ΄λ²€νΈλ₯Ό μΆκ°νλ€.
κ·Έλ€μ κ³Όμ λ§ λ΄λ λΉν¨μ¨μ μ΄λΌκ³ λκ»΄μ§μ§ μλκ°? λ§μ°μ€λ₯Ό μμ§μΌ λλ§λ€ κ³μν΄μ μλ‘μ΄ μ΄λ²€νΈλ₯Ό μΆκ°ν΄μ€μΌ νλ€. λ‘μ§λ 볡μ‘ν΄μ§λΏλλ¬ μλλ μμνλ λ°λ‘ λμνμ§ μμλ€.
μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ μ΄λ²€νΈ μμμ μ¬μ©νμλ€.
λ³ μμ΄μ½μ λ¬Άλ 컨ν μ΄λλ₯Ό λ§λ€κ³ μ΄λ²€νΈλ₯Ό μΆκ°νμλ€. μΆκ°ν μ΄λ²€νΈλ λ€μκ³Ό κ°λ€.
$votedStarContainer.addEventListener(
'mousemove',
this.hoverStarIcon.bind(this)
);
$votedStarContainer.addEventListener(
'mouseleave',
this.leaveStarIcon.bind(this)
);
$votedStarContainer.addEventListener('click', this.toggleVoteStar.bind(this));
λ§μ§λ§ μ΄λ²€νΈλ ν΄λ¦νλ μ΄λ²€νΈμ΄λ€. λλ¨Έμ§ λ μ΄λ²€νΈκ° λ³ μμ΄μ½μ λ¬Άλ 컨ν μ΄λ μμμ λ§μ°μ€κ° μμ§μ΄κ±°λ λ λκ° λ μ€νλλ μ΄λ²€νΈμ΄λ€.
μ’λ μμΈν μ΄ν΄λ³΄μ. λ¨Όμ mousemove
μ΄λ²€νΈμ λν μ½λ°±ν¨μμ΄λ€.
class VoteMovie {
// ...
hoverStarIcon(event: Event) {
const star = event.target as HTMLImageElement;
if (!star.matches('.vote-star')) return;
const hoverStarCount = Number(star.dataset.starCount) as Score;
this.insertStar(hoverStarCount);
}
}
vote-star
λ₯Ό ν΄λμ€λ‘ κ°μ§λ λ
Έλμ data-starCount
μ΄νΈλ¦¬λ·°νΈ κ°μ λ°νμΌλ‘ insertStar
λ©μλκ° μ€νλλ€.
κ·Έλ€μμ mouseleave
μ΄λ²€νΈμ λν μ½λ°±ν¨μμ΄λ€.
class VoteMovie {
// ...
leaveStarIcon() {
this.insertStar(this.score);
}
}
νμ¬μ μ μ this.score
λ₯Ό λ°νμΌλ‘ insertStar
λ©μλκ° μ€νλλ€. insertStar
λ©μλλ λ€μκ³Ό κ°λ€.
class VoteMovie {
// ...
insertStar(hoverStarCount: number) {
const $voteStarContainer = this._node.querySelector<HTMLDivElement>(
'.voted-star-container'
);
if (!$voteStarContainer) return;
const starHTML = this.createStarNodes(hoverStarCount);
$voteStarContainer.innerHTML = '';
$voteStarContainer.insertAdjacentHTML('beforeend', starHTML);
}
}
innerHTML
νλ‘νΌν°λ₯Ό μ¬μ©νμ¬ λ³μ 컨ν
μ΄λ λ΄λΆμ λ
Έλλ₯Ό μ κ±°νκ³ insertAdjacentHTML
λ©μλλ₯Ό μ¬μ©νμ¬ μλ‘μ΄ λ³μ μ λ£λλ€. μμ κ°μ κ³Όμ μ΄ λ³μ 컨ν
μ΄λ λ΄λΆμμ λ§μ°μ€κ° μμ§μ΄κ±°λ λ°μΌλ‘ λ²μ΄λ λ μ€νλλ€. λ¬Όλ‘ μμ κ°μ κ³Όμ λ λ§μ°μ€κ° μμ§μΌ λλ§λ€ κ³μ μ€νλκΈ° λλ¬Έμ innerHTML
, insertAdjacentHTML
κ° κ³μ μ€νλλ€. μ΄λ ν¨μ¨μ μ΄λΌκ³ ν μ μλ λΆλΆμ΄λ€.
π μν 리뷰μ λν μ 체μ μΈ νκ³
λ 벨1μ λ§μ§λ§ λ―Έμ μ΄ λλ¬λ€. μ΄μ μλ ꡬ쑰μ λν΄ λ§μ μ κ²½μ μΌλ€λ©΄ μ΄λ² λ―Έμ μμλ μ¬μ©μμκ² μΉμ ν μλΉμ€λ₯Ό μ 곡νλ κ²μ λ³΄λ€ λ μ κ²½μ μΌλ€.
1λ¨κ³μμλ λ 보기 λ²νΌμ΄ μμλ€λ©΄, 2λ¨κ³μμλ λ 보기 λ²νΌμ΄ μλλΌ λ¬΄ν μ€ν¬λ‘€λ‘ μνλ₯Ό μΆκ° λ‘λνμλ€. λν λ³μ μμ λ§μ°μ€λ₯Ό μ¬λ¦ΌμΌλ‘μ¨ λ°μνλ μ΄λ²€νΈ, λ°μν λμμΈ λ±λ±... μ΄λ¬ν κΈ°λ₯λ€μ ν΅ν΄ UXμ λν΄ κ³ λ―Όνλ μκ°μ κ°μ‘λ€.
API ν΅μ μ ν΅ν΄ μν μ 보λ₯Ό κ°μ Έμ μλΉμ€μ λ§λ λλ©μΈμ λ§λλ κ³Όμ μμ μ€μ λ‘ λκ΅°κ°μ ν΅μ νλ κ³Όμ λ κ²½ννμλ€. ν΄λΉ κ³Όμ μμ λΆλ¬μ¨ μν μ 보λ₯Ό κ·Έλλ‘ μ°λ κ²μ΄ μλλΌ μ 보λ₯Ό μ¬κ°κ³΅νλ μ΄μ λ κΉ¨λ«κ² λμλ€. μ§§κ² λ§νλ©΄ 'μ΄λ€ λ°μ΄ν°κ° λ€μ΄μλ λ΄ μλΉμ€μμ μ¬μ©νλ λ°μ΄ν°(μλ°ν λ§νλ©΄ κ°μ²΄μ μμ±)λ νμ λμΌνλ€!'μ΄λ€.
API ν΅μ μ΄ μ€ν¨ νμ λ, μ΄μ λν μ€λ₯ λ©μμ§λ ν¨κ» ꡬννμλ€. νμ§λ§ μ¬κΈ°μ μμ¬μ΄ μ μ ν΄λΌμ΄μΈνΈ μλ¬, μλ² μλ¬μ λν κ°κ°μ μ€λ₯ λ©μμ§κ° μλλΌ λͺ¨λ μ€λ₯λ₯Ό νλλ‘ μ·¨κΈνλ€λ κ²μ΄λ€. λ€μ λμ΄μΌ μκ°ν΄ 보면 μ‘°κΈ λ λΆμ§λ°νλ€λ©΄ μΆ©λΆν κ³ λ €νμ λ§ν κ²μ΄λ€. λ°μ±νμπ
μ§κΈκΉμ§ μ€μΌλ ν€ UIμ λν΄ μ§κΈκΉμ§ μκ°ν΄ λ³Έ μ μ΄ μμλ€. μ νλΈμ 첫 λ‘λ©μ΄ μ€μΌλ ν€ UIλΌλ κ²λ λͺ°λκ³ μ΄λ νλμ κΈ°λ₯μ΄λΌλ κ²λ λͺ°λλ€. μ§κΈκΉμ§ λ‘λ©μ΄λΌκ³ νλ©΄ 무νν λμκ°λ λκ·ΈλΌλ―Έλ°μ μκ°μ΄ λμ§ μλλ€. μμ§ μλ²½ν νλ‘ νΈ κ°λ°μκ° λλ €λ©΄ λ©μλ€.
λ΄κ° νΈνκ² κ°λ°νλ νκ²½μ μ€μνλ€. νμ§λ§ λ΄κ° λ§λ μλΉμ€λ₯Ό μ΄μ©νλ μ¬μ©μλ€μ νΈμμ±μ μ°μ μ μΌλ‘ μκ°νλ λ§μΈλλ₯Ό ν€μ°μ.
π μν μ
- νμ μ λν΄ λλ¦ κ³ λ―Όμ νμλ€.
- μΉ μ»΄ν¬λνΈκ° μλλΌ classλ‘ λ§λ€κΈ° μν΄ κ³ λ―Όνμλ€.
- eslint μ€μ μ μ€μ€λ‘ ν΄λ³΄μλ€.
π μμ¬μ΄ μ
- ꡬνμ νλ€ λ³΄λ MVC ν¨ν΄μ λͺ¨μ΅μ 보μΈλ€.
- λ°μν UIλ₯Ό κΉλνκ² νμ§ λͺ»νλ€.
- anyλ₯Ό μ¬μ©ν λΆλΆμ λ―Έμ² λ¦¬ν©ν°λ§ λ λ°κ²¬νμ§ λͺ»νλ€.
- λκΈ°, λΉλκΈ°μ λν νμ΅μ΄ νμνλ€.
Intersection Observer API
λ₯Ό κ°μ Έλ€ μ°κΈ°λ§ νλ€. λ¬΄μ¨ μ리μΈμ§μ λν νμ΅μ΄ λΆμ‘±νλ€.
π μμΌλ‘μ κ°μ€
- ꡬνλ μ€μνμ§λ§ κ°λ λΆν° μ μ§κ³ λμ΄κ°μ.
- νμ΅λͺ©νκ° νμ μ€μν¨μ μμ§ λ§μ.
'π μ°μνν ν¬μ½μ€ > Level1' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
λ 벨1 - μΈν°λ·° (0) | 2023.04.14 |
---|---|
λ 벨1 μν 리뷰 - step1 (2) | 2023.04.14 |
λ 벨1 μ μ¬ λ λ¨Ήμ§ - step2 (0) | 2023.04.14 |
λ 벨1 μ μ¬ λ λ¨Ήμ§ - step1 (0) | 2023.04.14 |
λ 벨1 νμ΄μ λ‘λ - step2 (0) | 2023.04.13 |