[TIL] 타이머 시간동안 최대한 많이 클릭하는 게임! // useState, useRef, 변수

김형준·2022년 1월 26일

Today I Learned...

목록 보기
11/13
post-thumbnail

10초 동안 최대한 많이 클릭하는 게임을 만들어보기로 했다. 최근 드림코딩을 복습하며 간단한 게임들을 만들어 보고 싶었는데, 챌린지해보기 좋은 게임이라고 생각이 들었고, 재밌을 것 같았다.
그렇게 처음 만든 게임의 동작은 다음과 같다.

조금 더 요소를 추가해보고 싶었다. 현재 클릭 횟수를 가리고, 10초 동안 내가 클릭한 횟수를 예상해보는 화면을 하나 더 구성했다. 일치하면 기록으로 인정되고 아니면 기록으로 인정되지 않는다! 너무 재밌어 보인다

프로젝트 구상

첫 화면

<Start버튼>,<최고 기록>

  • <Start버튼>을 눌러 게임을 시작한다!
  • <최고 기록>을 로컬 스토리지에 저장해서 브라우저를 종료하고 다시 시작해도 저장되도록 한다.

두 번째 화면

<10초 타이머>, <+ 버튼>

  • 10초 타이머 -> 매초 렌더링 되어야 하니까 usestate로 하는게 좋을 것 같다.

  • <+ 버튼>을 클릭하면 클릭한 횟수만큼 count변수에 할당

  • 10초가 지나면 자동 화면 전환

세 번째 화면

<예상 클릭 횟수를 입력받는 input>, <제출 button>

  • focus()로 편하게 작성
  • 빈값 제출 확인
  • 엔터키로 제출되게 하기

네 번째 화면

<실제 클릭 횟수>, <예상 클릭횟수> <결과 표시> <다시하기>

  • 예상 클릭 횟수가 실제 클릭 횟수와 일치하면 현재 최고 기록과 비교해서 더 큰 값을 localstorage에 key 'best'의 값으로 갱신
  • <다시하기>버튼으로 첫 화면으로 복귀
  • 복귀하면서 모든 변수 초기화.

타이머를 어떻게 만들지?

start 버튼을 누르면 작동하는 함수이다.

const [time, setTime] = useState(10);
const start = () => {
setTime(10);
let stopWatch = setInterval(() => {
setTime((time) => time - 1);
}, 1000);
setTimeout(() => clearInterval(stopWatch), 11000);
};

time은 현재 남은 시간을 보여줄 변수이다. 실시간으로(1초마다) 변화를 보여줘야 하므로 useState로 만들었다. start 버튼을 누르면 time을 10으로 할당해주고(나중에 다시할때 0에서 시작하는 것 방지) setInterval를 이용해주었다.
setInterval 로 time 값을 1초마다 1씩 줄였다. 그리고 clearInterval로 10초가 지나면 setInterval을 제거해주었다.

useEffect(() => {
if (time === 0) {
setView('expect');
}
});

그리고 useEffect로 time이 0이 되면 다음 화면으로 넘어가게 설계했다.

최종 구현 화면

useRef? useState? 아하!

여기서 기획을 어떻게 할 지에 따라 useRef를 쓰거나 useState를 쓸 수 있었다. 처음에 만든 게임은 그냥 많이 누르면 되는거라서 실시간으로 몇 번이나 눌렀는지 보여주는게 좋을 것 같았다. 실시간 변화? = 실시간 렌더링 = useState사용!
하지만 횟수를 맞추는 게임의 경우 클릭횟수를 보여주지 않아도 된다. 즉 useState로 굳이 실시간으로 렌더링해 줄 필요가 없었다.
useRef를 언제 사용하는가? 변화를 감지하고는 싶은데 실시간으로 렌더링 할 필요는 없을때! 그렇다면 일반 변수랑은 뭐가 다른가? 싶을 수 있다. useRef는 페이지가 다시 마운트되지 않는 이상 값이 유지된다. 즉 useState처럼 값을 유지하지만 렌더링 되지만 않는 것이다. useState를 사용하다보면 의도치않게 페이지가 리렌더링되어 값이 날아가버리거나 전달되지 않는 경우가 많은데, useRef는 그 대안이 될 수 있다.
다음 유튜브를 보고 바로 이해가 갔다!
https://youtu.be/VxqZrL4FLz8

로컬 스토리지 활용

  • 내 최고 기록을 보존하고 싶었다. useRef를 사용한다고 해도 페이지를 새로고침하거나 브라우저를 껐다 키면 최고 기록이 유지되진 않는다. 그렇다고 이런 간단한 오프라인 게임에 서버를 쓰기도 과분하고, 간단히 내 로컬에 값을 저장하고 싶을때! 바로 로컬 스토리지다. 사용법도 정말 간단하다.

    localstoarge.setItem("key","value")로 저장하고 localstorage.getItem("key") 로 손쉽게 호출할 수 있다. 한번 저장하면 굳이 지우지 않는 한 계속 저장되어 있다. (메모리 낭비의 우려가 있다..)

  • 로컬스토리지로 페이지를 껐다 켜도 최고 기록이 남아있다!

    느낀점

    내가 생각한 것을 실물로 구현하는건 정말 재밌다. 내가 개발을 사랑하는 이유가 이것이 아닐까. 그게 무엇이든 구현할 수 있는 날이 올 때까지 열심히 해야겠다!

profile
긍정의 힘을 믿어요

0개의 댓글