feat: 07-Stopwatch 과제 (이윤지)#29
Open
le2yunji wants to merge 2 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📝 과제 요약
💡 설계 및 고민한 부분
스톱워치의 동작 원리를 생각해봤습니다.
경과 시간 = 현재 시각 - 누른 시간 + 이전에 누적된 시간이 식을 이용해서 구현할 수 있을 거라고 판단했습니다.
필요한 상태를 생각했습니다.
위 식에 들어가는
현재 시각,누른 시간,누적된 시간, 그리고작동 여부를 상태로 만들었습니다.경과된 시간의 연속적인 흐름을 화면에 어떻게 표현할지 고민했습니다.
처음에는
setInterval을 사용해 일정 주기마다 현재 시각을 갱신하는 방식으로 구현했습니다.이 방식은 동작 자체는 가능했지만, 실제 화면에서 밀리초 단위의 변화가 매끄럽게 보이지 않는 문제가 있었습니다.
또한
setInterval은 지정한 시간 간격마다 정확하게 실행되는 것이 아니라 브라우저 상황에 따라 지연될 수 있다는 점도 알게 되었습니다.그래서 AI의 도움을 받아
requestAnimationFrame과performance.now()를 사용하는 방식으로 개선했습니다.requestAnimationFrame은 브라우저의 화면 갱신 타이밍에 맞춰 콜백을 실행하기 때문에, 스톱워치처럼 화면에 시간이 계속 갱신되어야 하는 UI에 더 적합하다고 판단했습니다.또한 기존에는
Date.now()를 사용했지만, 스톱워치에서는 실제 날짜나 시각보다 “얼마나 시간이 지났는지”가 중요하므로performance.now()를 사용하는 것이 더 자연스럽다고 이해했습니다.Start를 누르면 현재 시각을
startTime으로 저장하고, Stop을 누르면현재 시각 - 시작 시각을 기존 누적 시간에 더해elapsedTime에 저장하도록 했습니다.이렇게 하면 스톱워치를 멈췄다가 다시 시작해도 이전에 측정한 시간이 유지되고, 새로 흐른 시간만 이어서 누적됩니다.
📖 학습한 내용 및 어려웠던 점 (선택)
Date.now()나performance.now()처럼 호출할 때마다 값이 달라지는 함수를 직접 실행하면 안 된다는 것을 알게 되었습니다.처음에는 컴포넌트 본문에서 현재 시각을 바로 구해
displayTime을 계산하려고 했지만, 렌더링 중에 변하는 값을 직접 호출하면 React의 순수성 규칙에 맞지 않는다는 오류가 발생했습니다.따라서 현재 시각은 이벤트 핸들러,
useEffect,setInterval,requestAnimationFrame같은 렌더링 외부 흐름에서 구하고, 그 값을 상태로 저장해 화면에 반영해야 한다는 점을 배웠습니다.requestAnimationFrame은 한 번만 실행되는 함수이며, 반복 실행하려면 콜백 내부에서 다시 자기 자신을 예약해야 한다는 것을 알게 되었습니다.위 코드에서
update함수가 실행될 때마다 다시requestAnimationFrame(update)를 호출하기 때문에 시간이 계속 갱신됩니다.즉,
useEffect가 계속 반복 실행되는 것이 아니라,requestAnimationFrame안의update함수가 자기 자신을 계속 다시 예약하는 구조입니다.useEffect는 타이머 루프를 시작하고 정리하는 역할을 하고,requestAnimationFrame(update)는 실행 중에 화면 시간을 계속 갱신하는 반복 루프 역할을 한다는 점을 이해했습니다.isRunning이true가 되면useEffect에서 animation frame 루프를 시작하고,isRunning이false가 되거나 컴포넌트가 언마운트되면 cleanup 함수에서cancelAnimationFrame을 호출해 기존 루프를 정리합니다.이를 통해 타이머가 멈춘 뒤에도 불필요하게 화면 갱신이 계속 예약되는 문제를 방지할 수 있었습니다.
최종적으로 화면에 표시할 시간은 아래 기준으로 계산했습니다.
실행 중일 때는 기존 누적 시간에 현재 실행 구간에서 흐른 시간을 더하고, 정지 중일 때는 확정된 누적 시간만 보여주도록 처리했습니다.
❓ 질문 사항 (선택)
📸 스크린샷 (선택)
2026-06-26.5.20.11.mov