드림코딩의 브라우저 101 강의 section 중 하나인 Carrot game을 이틀간에 걸쳐 완성했고, 오늘 솔루션 영상을 봤다.
솔루션 영상을 보면서 내가 작성한 코드와 엘리가 작성한 코드를 비교해 보고, 리팩토링 과정을 거쳤다. 이 과정에서 내가 고쳐야 할 부분과 느낀점들에 대해 정리하고자 한다.
리팩토링을 하기 전 작성했던 코드를 보면, class를 추가하고, 당근과 벌레를 추가하고, counter를 수정하는 등 여러가지 동작들이 함께 작성되어 있다. 이런 코드는 기능이 잘 작동한다고 해도 가독성이 좋지 않아 코드가 무엇을 의미하는지 직관적으로 알기 힘들다. 또한 프로젝트의 규모가 커질 경우 유지, 보수에도 어려움이 있어 지양해야하는 코드 작성이다.
const startBtn = document.querySelector('.startBtn');
const counter = document.querySelector('.counter');
startBtn.addEventListener('click', (e) => {
if (startBtn.classList.contains('active') === false) {
startBtn.classList.add('active');
startBtn.innerHTML = `<i class="fa-solid fa-stop"></i>`;
addItem('carrot__img', CARROT_COUNT, '/carrot/img/carrot.png');
addItem('bug__img', BUG_COUNT, '/carrot/img/bug.png');
startTimer();
const carrotEl = document.querySelectorAll('.carrot__img');
counter.textContent = carrotEl.length;
console.log(carrotEl);
} else {
modalStop();
startBtn.classList.remove('active');
}
});
때문에, 함수 단위로 코드를 작성하고, 하나의 함수에는 한가지 동작을 수행하도록 작성하는 것을 지향해야 한다.
위의 코드를 함수 단위로 작성하게 되면, 가독성이 좋아져 코드를 직관적으로 이해할 수 있으며, 함수마다 어떤 동작을 수행하는지 알 수 있어, 코드 수정 시 더욱 편하게 할 수 있다. 처음부터 적응이 쉽지 않겠지만 항상 함수 단위로 작성해야 한다는 것을 기억하도록 하자.
const startBtn = document.querySelector('.startBtn');
let started = false;
startBtn.addEventListener('click', (e) => {
if (started) {
stopGame();
} else {
startGame();
}
});
function startGame() {
started = true;
initGame(); // counter, bug, carrot 생성
showTimerAndScore(); // timer, counter 다시 보이게
startTimer(); // timer 시작
startBtn.innerHTML = `<i class="fa-solid fa-stop"></i>`;
}
function stopGame() {
started = false;
stopTimer(); // timer stop
hideStartBtn(); // startBtn 숨기기
showModaleAndText('Replay ❓');
}
내가 만든 Timer는 stop 버튼을 누르면 1초가 지나가고 멈추는 현상이 발생했다.
let timer = undefined;
function startTimer() {
let reaminingTimeSec = GAME_DURATION_SEC;
updateTimerText(reaminingTimeSec);
timer = setInterval(() => {
if (reaminingTimeSec <= 0) {
clearInterval(timer);
finishGame(false);
return; // 이 부분을 놓치지 말자.
}
updateTimerText(--reaminingTimeSec);
// if (!modal.classList.contains('hidden')) {
// clearInterval(timer);
// seconde = 10;
// }
}, 1000);
}
당근과 벌레 이미지에 마우스를 올리면 이미지가 커지는 transform: scale(1.1)을 적용하고 싶었으나 적용되지 않았다. 이유는 이미지를 랜덤하게 배치할 때 transform: translate() 속성을 사용해서 배치했기 때문! item.style.transform 이런 식으로 스타일을 주면 inline CSS로 적용되기 때문에 최우선으로 적용이 된다. 때문에 CSS 파일에서 아무리 transform을 줘도 적용이 되지 않았던 것. 그래서 left, top 속성을 이용해서 배치를 하고 transform을 적용하였다.
for (let i = 0; i < count; i++) {
const item = document.createElement('img');
item.setAttribute('class', className);
item.setAttribute('src', imgPath);
const x = Math.random() * (bottomRect.width - CARROT_SIZE);
const y = Math.random() * (bottomRect.height - CARROT_SIZE);
item.style.left = `${x}px`;
item.style.top = `${y}px`;
// item.style.transform = `translate(${x}px, ${y}px)`
bottomContainer.appendChild(item);
}
기능은 모두 구현해서 기분은 좋았으나, 솔루션 영상을 보고난 뒤에는 내 코드가 너무 쓰레기 같아서 조금 실망했다. 하지만 다음부터는 제대로 짜면 되는거 아닌가!!? 라는 마인드를 가져본다.
아마 1번의 리팩토링 과정을 더 거칠텐데 그때도 제대로 배우고 포스팅하도록 하겠다.