-
Notifications
You must be signed in to change notification settings - Fork 171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[2단계 - 자동차 경주 구현] 지그(송지은) 미션 제출합니다. #36
Conversation
cypress/integration/racing.spec.js
Outdated
const carsNum = 4; | ||
const tryCount = 5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
carsNum
과 tryCount
는, 각각
clickAfterTypeCar();
와 clickAfterTypeTryCount();
에서 사용하는 상수를 가져온 것입니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요 부분은 제일 상단의 전역부분에서
const DEFAULT_TRY_COUNT = 5
const DEFAULT_CAR_UNITS = 4
와 같은 형태로 명명해두고,
clickAfterTypeTryCount(tryCount = DEFAULT_TRY_COUNT) {...}
와 같은 형태로도 쓰고, 아래에서도 쓰는 건 어떨까요~?
cypress/integration/racing.spec.js
Outdated
clickAfterTypeCar(); | ||
clickAfterTypeTryCount(); | ||
|
||
const tryCount = 5; | ||
cy.wait(tryCount * 2000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spinner 1000ms, arrow 1000ms가 출력되기 때문에 더한 값인 2000만큼 지연이 발생하도록 했습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 부분을 * 2000같은 공식을 밑에서도 써야하니, 위와 같이 전역으로 값을 빼는것이 좋을 것 같습니다!
const SPINNER_SEC = 1000
const ARROW_DISPLAYING_SEC = 1000
const DEFAULT_TRY_COUNT_TIME = DEFAULT_TRY_COUNT * (SPINNER_SEC + ARROW_DISPLAYING_SEC)
...
cy.wait(DEFAULT_TRY_COUNT_TIME)
src/js/index.js
Outdated
this.UIController.printProgress(car, isCarMoved); | ||
}); | ||
return moveEverySecond.bind(this); | ||
}).bind(this)(), 2000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spinner 1000ms, arrow 1000ms가 출력되기 때문에 더한 값인 2000만큼 지연이 발생하도록 했습니다.
콜백 내에서 Racing
객체의 this.cars
를 업데이트해야하기 때문에 어쩔 수 없이 bind(this)
를 사용했는데,
좋지 않은 방식이라면 지적 부탁드립니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
arrow function으로 작성해보려 햇는데 setInterval
안에 moveEverySecond
와 같은 함수의 이름이 있어야 80줄과 같이 return을 할 수 있더라고요 😬 가장 처음에는 2초의 지연 없이 즉시 실행되게 하려면 저렇게 리턴을 해야 한다고 하는데, (아니면 함수 바디의 내용을 함수 선언 이전에 한번 더 작성해서 미리 한 번 호출한다든가..? 근데 이건 좀 중복되고 지저분해 보여서요.) arrow function으로는 어떻게 작성해야 하는지 오래 고민해 보았지만 답을 찾지 못해서 어쩔 수 없이 bind(this)
를 사용했습니다..!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
첫 회차 실행을 위해 함수가 더 무거워진 느낌인데, 첫회 실행을 하고 2000 sec을 주시는게 더 좋아보입니다!
src/js/index.js
Outdated
clearInterval(moveInterval); | ||
this.getWinners(); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clearInterval
후에도 한 번 더 spinner와 arrow가 출력되고 있어, 바로 return해버리게끔 했습니다.
보기에는 정상 작동하는데, 혹시 문제가 있을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋습니다! 👍 👍
보통 위의 bad case에서 return을 하도록 코딩을 작성하면, 하위의 로직을 돌지 않고 해당 scope 밖으로 던져지므로 성능 (엄청 미비하지만...) 상에서도 좋습니다.
이렇게 return으로 bad case를 먼저 선언하고, 메인 로직 (지금과 같은 상황은 아래의 로직들이 되겠죠) 을 짜는게 일반적인 방법입니다! 문제 없어보입니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
유조님께 먼저 작성드린 피드백 내용인데, 참고하시면 좋을 것 같습니다 😄
src/js/models/Car.js
Outdated
return true; | ||
} | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bool값을 받아 해당 턴에 car가 move하면 화살표를 하나 더하고, 아니라면 무시하는 것으로 바꿔보았습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
멤버변수에 isMove
을 하나 선언하고, move
에서 값을 가져오기보다 get isMoving()
을 만들어서 가져오는게 더 낫지 않을까요~? 이렇게 되면 move
함수는 한번에 두 가지 일을 하게 되네요!
함수는 단순히 딱 하나의 일만 해야하는게 좋습니다 👍 추후에 테스트 코드 검증을 위해서라도요!
} | ||
} | ||
|
||
showResult(cars) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
실시간으로 결과를 출력하는 printProgress
와 구분하기 위해 함수 이름을 바꿨습니다.
showResult
안에서는 spinner, arrow와 상관 없는 car들의 이름과 그 컨테이너 객체만 뜨도록 했습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
지그님! 2단계도 수고 많으셨습니다!
전반적으로 코드가 1단계에 비해 깔끔해진 걸 보니 좋네요!! 👍 👍
상세한 코드 리뷰는 코드 라인에 달아놓았습니다! 해당 피드백을 수정해주시면 감사하겠습니다!
그리고 질문주신 내용에 대한 피드백입니다!
setInterval과 달리 requestAnimationFrame 함수가 브라우저 repaint 지점에 함수를 작동시킨다고 하는데, 이게 확실히 더 성능이 좋은 편인가요? 사실 이번에 처음 들어본 기능인데, 실제로도 많이 쓰이는지 궁금합니다!
setInterval과 requestAnimationFrame은 쓰임의 용도가 다른 친구입니다! 물론 동일한 결과를 위해 이용할 수는 있겠지만요.
- setInterval은 브라우저의 API로 브라우저 내부의 카운트를 진행해 콜백을 진행하는 함수입니다.
- requestAnimationFrame은 이름에서 보이는 것 처럼, animation을 javascript로 제어하기 위해 탄생된 친구입니다.
requestAnimationFrame은 repaint가 되기 전에 호출된 함수를 실행하고, 그 후에 repaint를 진행합니다. 이렇게 되는 이유는 애니메이션의 특성 때문입니다. 애니메이션이 가장 부드럽게 보이려면 보고있는 디스플레이의 주사율과 최대한 비슷해야합니다. 최대한 비슷해야 하는 이유는 디스플레이 주사율이란 초당 깜빡이는 횟수를 나타냅니다. 즉 최대한 깜빡이는 시점이 비슷하다면 사용자 입장에서는 최대한 부드러워 보인다는 의미입니다. 지그님이 보고있는 모니터의 주사율이 60hz 라면, (1초에 60번 깜빡인다면) 웹 브라우저는 해당 하드웨어에 반응해 1초에 60번 requsetAnimationFrame을 호출할 것 입니다 (repaint가 되기 전, requestAnimationFrame을 루프에서 실행했다면, 최대한 브라우저의 깜빡임과 화면의 주사율을 갖게 하기 위해) repaint가 되기 전에 호출되어 repaint를 실행한다는 것은, 최대한 브라우저 단위에서 깜빡이는 시점을 비슷하게 가져가려는 노력일 것 입니다.
그래서 게임에서는 이러한 모니터의 주사율과 그래픽 카드의 연산으로 하여 게임이 진행되는 프레임레이트(fps, framerate)를 같게 하기위해서 AMC - FreeSync, NVIDIA - GSYNC 와 같은 기능을 모니터에 탑재하기도 하죠. (모니터에 그래픽카드 연산과 동일하게 맞추는 하드웨어를 넣습니다. 가격은 역시 비싸집니다..) 또 다른 이야기로는 아이폰 X ~ 11까지 디스플레이 주사율이 144여서 많은 부드러움이 있었으나, 12로 오면서 주사율을 60으로 하향해서 많은 욕을 먹곤 했었죠. 그만큼 디스플레이의 주사율은 사용성에 많은 차이를 줍니다.
이 requestAnimationFrame은 비단 위에서 언급한 컴퓨터 비전(computer vision)의 영역도 있지만 웹 브라우저상에서도 해당 콜백을 보관(eventloop 상에서의 requestAnimationFrame queue)했다가 다시 로직으로 돌려보내는(callstack - execute context queue) 행위에도 웹 브라우저의 queue 우선순위 라던가, 다양한 공부할 부분이 존재합니다. 이러한 공부를 진행하면 eventloop의 queue의 우선순위(microtask queue > request animation frame queue > task queue, 브라우저마다 다를 수 있음)를 이용해서 로직의 우선순위를 조정할 수도 있습니다.
딴 길로 많이 빠졌네요.. 결론을 말씀드리면 requestAnimationFrame은 repaint가 진행되기 이전에 작동되며, 많이 쓰이고, 특히 애니메이션 라이브러리 까보면 십중팔구 다 이거씁니다. 그래서 적극적으로 이용하시면 좋습니다. 같이 공부하면 좋을 것들은 EventLoop, Promise 등이 있겠습니다.
moveCars 함수의 moveInterval 함수가 이것저것 깔끔하게 구현하려다보니 조금 방대해졌는데, 더 나은 방법이 있을지 알고 싶습니다.
요 것은 코드 라인에서의 세부 코맨트에 답변을 달아두었습니다!
긴 글 읽어주셔서 감사합니다.
cypress/integration/racing.spec.js
Outdated
const carsNum = 4; | ||
const tryCount = 5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요 부분은 제일 상단의 전역부분에서
const DEFAULT_TRY_COUNT = 5
const DEFAULT_CAR_UNITS = 4
와 같은 형태로 명명해두고,
clickAfterTypeTryCount(tryCount = DEFAULT_TRY_COUNT) {...}
와 같은 형태로도 쓰고, 아래에서도 쓰는 건 어떨까요~?
cypress/integration/racing.spec.js
Outdated
clickAfterTypeCar(); | ||
clickAfterTypeTryCount(); | ||
|
||
const tryCount = 5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요기에도 중복으로 쓰이니 중복으로 쓰이지 않도록 전역으로 관리하도록 합시다! (위와 같은 내용입니다!)
cypress/integration/racing.spec.js
Outdated
clickAfterTypeCar(); | ||
clickAfterTypeTryCount(); | ||
|
||
const tryCount = 5; | ||
cy.wait(tryCount * 2000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 부분을 * 2000같은 공식을 밑에서도 써야하니, 위와 같이 전역으로 값을 빼는것이 좋을 것 같습니다!
const SPINNER_SEC = 1000
const ARROW_DISPLAYING_SEC = 1000
const DEFAULT_TRY_COUNT_TIME = DEFAULT_TRY_COUNT * (SPINNER_SEC + ARROW_DISPLAYING_SEC)
...
cy.wait(DEFAULT_TRY_COUNT_TIME)
cypress/integration/racing.spec.js
Outdated
clickAfterTypeTryCount(); | ||
|
||
const tryCount = 5; | ||
cy.wait(tryCount * 2000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기도 위와 동일합니다!
cypress/integration/racing.spec.js
Outdated
clickAfterTypeCar(); | ||
clickAfterTypeTryCount(); | ||
|
||
const tryCount = 5; | ||
cy.wait(tryCount * 2000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기두 동일합니다!
src/js/index.js
Outdated
clearInterval(moveInterval); | ||
this.getWinners(); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋습니다! 👍 👍
보통 위의 bad case에서 return을 하도록 코딩을 작성하면, 하위의 로직을 돌지 않고 해당 scope 밖으로 던져지므로 성능 (엄청 미비하지만...) 상에서도 좋습니다.
이렇게 return으로 bad case를 먼저 선언하고, 메인 로직 (지금과 같은 상황은 아래의 로직들이 되겠죠) 을 짜는게 일반적인 방법입니다! 문제 없어보입니다!
src/js/index.js
Outdated
clearInterval(moveInterval); | ||
this.getWinners(); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
유조님께 먼저 작성드린 피드백 내용인데, 참고하시면 좋을 것 같습니다 😄
src/js/index.js
Outdated
this.UIController.printProgress(car, isCarMoved); | ||
}); | ||
return moveEverySecond.bind(this); | ||
}).bind(this)(), 2000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/js/models/Car.js
Outdated
return true; | ||
} | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
멤버변수에 isMove
을 하나 선언하고, move
에서 값을 가져오기보다 get isMoving()
을 만들어서 가져오는게 더 낫지 않을까요~? 이렇게 되면 move
함수는 한번에 두 가지 일을 하게 되네요!
함수는 단순히 딱 하나의 일만 해야하는게 좋습니다 👍 추후에 테스트 코드 검증을 위해서라도요!
src/js/racingUI.js
Outdated
@@ -33,19 +36,47 @@ export default class RacingUI { | |||
document.querySelector(className).style.display = ''; | |||
} | |||
|
|||
showProgress(cars) { | |||
toggleElementDisplay(className, show) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
show의 상태를 받기보다, 특정한 상태로 함수를 만드는게 좋겠습니다.
showElement() {...}
hideElement(){...}
형태로요! 이렇게 되면 비즈니스 로직에서 toggleElementDisplay가 어디서 꺼졌고.. 어디서 켜졌는데 true false를 백날 봐야하는 단점이 있어요.. 이렇게보다 hideElement를 검색해서 한번에 보는게 더 낫지 않을까요~?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사실 toggleElementDisplay
의 경우 기존에 있던 hideElement
, showElement
와 다르게 동일한 className을 갖는 복수의 dom에 대한 display를 바꿔주는 거라, 함수 바디에서 for loop을 돌기 때문에 여러 줄의 코드가 중복되어 하나로 묶고자 했던 것이었습니다. 그런데 t/f를 매번 봐야 하는 문제는 있겠네요 😅 말씀주신 대로 수정해보겠습니다!
src/js/models/Car.js
Outdated
get isMoved() { | ||
return this._isMoving; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고쳐보았습니다!
get name() { | ||
return this._name; | ||
} | ||
|
||
getPosition() { | ||
return this.position; | ||
get position() { | ||
return this._position; | ||
} | ||
|
||
getIsWinner() { | ||
return this.isWinner; | ||
get isWinner() { | ||
return this._isWinner; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
다른 멤버변수들에 대해서도 getter로 변경하고, 중복된 이름을 방지하기 위해 변수명에는 언더바를 붙였습니다.
이렇게 써도 괜찮을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋은것 같습니다! 멤버변수에 _를 붙이는 건 많은 팀에서 하는 코딩 컨벤션 중 하나입니다!
src/js/index.js
Outdated
this.cars.forEach(car => car.move()); | ||
} | ||
this.UIController.showProgress(this.cars); | ||
const moveInterval = setInterval((function moveEverySecond() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moveCars = () => {
const moveEverySecond = (interval) => {
if (this.tryCount === 0) {
interval && clearInterval(interval)
this.getWinners();
return;
}
this.tryCount++;
this.cars.forEach(car => {
car.move();
const isCarMoved = car.isMoved;
this.UIController.printProgress(car, isCarMoved);
})
}
moveEverySecond()
const interval = setInterval(() => moveEverySecond(interval), DELAY.TURN_TIME)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이런형태로 짜도 될 것 같네여
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋은 방법인 것 같습니다! 감사합니다
|
수고 많으셨습니다~ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3/9 자동차 경주 셀프 리뷰
😬😎😵
@@ -10,7 +16,7 @@ describe('자동차 경주', () => { | |||
cy.get('.car-name-btn').click(); | |||
} | |||
|
|||
function clickAfterTypeTryCount(tryCount = 5) { | |||
function clickAfterTypeTryCount(tryCount = DEFAULT_TRY_COUNT) { | |||
if (tryCount) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
파라미터에 디폴트 값을 받고 있으니 tryCount
가 존재하는지 확인하는 if문은 없어도 될 것 같아요!
clickAfterTypeCar(); | ||
clickAfterTypeTryCount(); | ||
|
||
for (let i = 0; i < DEFAULT_TRY_COUNT; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let i for
문은 지양하는 게 좋습니다.
[...Array(DEFAULT_TRY_COUNT)].map(() => ...)
으로 바꿔보는 건 어떨까요?
|
||
cy.wait(DEFAULT_TRY_COUNT_TIME); | ||
|
||
cy.get('.restart-btn').click(); | ||
resetUI(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기서 resetUI()
를 호출하면 테스트하는 의미가 사라지지 않을까요? 🤔
}; | ||
|
||
moveEverySecond(); | ||
const moveInterval = setInterval(() => moveEverySecond(moveInterval), DELAY.TURN_TIME); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export const delay = ms =>
new Promise(resolve => {
setTimeout(resolve, ms);
});
와 같은 delay
유틸을 구현해줘도 좋을 것 같습니다!
return b.position - a.position; | ||
}) | ||
|
||
let maxPosition = sortedCars[0].getPosition(); | ||
let maxPosition = sortedCars[0].position; | ||
for (let car of this.cars) { | ||
if (car.getPosition() === maxPosition) { | ||
if (car.position === maxPosition) { | ||
car.wins(); | ||
} | ||
} | ||
|
||
const winners = this.cars.filter(car => car.getIsWinner()).map(car => car.getName()); | ||
const winners = this.cars.filter(car => car.isWinner).map(car => car.name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const maxPosition = Math.max(...this.cars.map((car) => car.position));
return this.cars
.filter((car) => car.position === maxPosition)
.map((car) => car.name);
for (let i = 0; i < allElements.length; i++) { | ||
allElements[i].style.display = ''; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[...Array(allElements.length)].map(() => ...)
for (let i = 0; i < allElements.length; i++) { | ||
allElements[i].style.display = 'none'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[...Array(allElements.length)].map(() => ...)
if (!document.querySelector(className)) { | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
선택자가 없어서 발생하는 에러의 경우 그냥 return하지 말고 throw Error
를 이용하여 개발자 콘솔에 로그를 남기면 디버깅하기 좋습니다 👾
<div class="forward-icon mt-2">⬇️️</div> | ||
`) | ||
} | ||
}, 1000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
매직넘버 대신 상수로 관리해주세요 😮
|
||
setTimeout(() => { | ||
alert('축하합니다 🎉') | ||
}, 2000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
매직넘버 대신 상수로 관리해주세요 222 😮
RacingCar 학습로그함수의 네이밍
class의 getter와 settergetter로 class 멤버 변수 가져오기
class Car {
constructor(name, position) {
this._name = name;
this.position = position;
}
get name() {
return this._name;
}
get position() {
return this._position;
}
} setter 사용은 지양하기class Car {
constructor(name, position) {
// ...
this.position = position;
}
// bad
set position() {
this._position += 1;
}
// good
move() {
this._position += 1;
}
} setInterval과 requestAnimationFramesetInterval
const moveEverySecond = (interval) => {
if (this.tryCount === 0) {
interval && clearInterval(interval)
this.getWinners();
return;
}
this.tryCount--;
this.cars.forEach(car => {
// ...
})
};
moveEverySecond();
const moveInterval = setInterval(() => moveEverySecond(moveInterval), DELAY.TURN_TIME); requestAnimationFrame
링크기타테스트코드 분리
mounting 시점에서의 이벤트 핸들링
DOM 접근 예외처리
for loop 대신 Array 내장 객체 사용하기// bad
for (let i = 0; i < DEFAULT_TRY_COUNT; i++) { ... }
// good
Array.from({ length: DEFAULT_TRY_COUNT }, () => { ... }) |
안녕하세요☺️ 자동차 미션 2단계 리뷰 요청 드립니다!
✅ Todos
📚 어려웠던 점
setInterval
을 이용해서 1초마다 spinner와 진행 상황(arrow)를 번갈아 출력하다 보니, dom을 조작하는 데 있어 어려움이 있었습니다.moveCars
함수의moveInterval
에서, 즉시 실행 함수와clearinterval
을 함께 써야 하는 동시에this
binding까지 해야 해서 까다로운 부분들이 있었습니다.🤔 궁금한 점
setInterval
과 달리requestAnimationFrame
함수가 브라우저 repaint 지점에 함수를 작동시킨다고 하는데, 이게 확실히 더 성능이 좋은 편인가요? 사실 이번에 처음 들어본 기능인데, 실제로도 많이 쓰이는지 궁금합니다!moveCars
함수의moveInterval
함수가 이것저것 깔끔하게 구현하려다보니 조금 방대해졌는데, 더 나은 방법이 있을지 알고 싶습니다.자세한 내용은 코멘트에 달아 놓았습니다.
리뷰 감사드립니다 😆