1. setInterval과 setTimeout
두 메서드는 기본적으로 일정 간격을 두고 실행하도록 만들어주는 스케줄링 메서드 입니다.
setInterval : 지정된 주기로 특정 코드를 실행한다.
func 호출 사이의 지연 간격이 실제 명시 간견보다 짧아짐
func를 실행하는데 소모되는 시간도 지연간격에 포함시키기 때문
let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...)
// 5초 후에 정지
setTime(() => { clearInterval(timerId); alert('정지'); }, 5000);

setTimeout : 지정된 초가 지난 후 특정 코드를 1회 실행한다.
이전 함수의 실행이 종료된 이후에 다음 함수의 호출에 대한 계획이 세워지므로 명시한 지연 시간이 보장된다.
// 1번 방법
setTimeout fn() {
console.log(3)
}
setTimeout(fn, 3000);
// 2번 방법 : 함수를 매개변수 안에 직접 작성
setTimeout(finction(){
constole.log(3)
}, 3000);
// 3번 방법 : 함수에 인수가 필요하다면 시간 뒤에 작성
const tld = function showName(name){
console.log(name);
}
setTimeout(showName, 3000, 'Mike');
clearTimeout(tld);
두 개의 매개변수를 가진다.
첫번째는 일정 시간이 지난 뒤 실행하는 함수이고, 두 번째는 시간이다. 3000은 3초를 의미한다.

다시말해 setInterval은 주기적으로 지정된 코드를 계속 실행하고, setTimeout은 한 번 실행 후 멈추게 된다.
- setTimeout이 setInterval처럼 주기적으로 실행되도록 만드는 방법
setTimeout(function timeoutTest() {
console.log("timeout");
setTimeout(timeoutTest, 1000);
}, 1000);
참고 : https://velog.io/@uiseop/JS-setTimeout%EA%B3%BC-setInterval-%EC%B0%A8%EC%9D%B4
[JS] setTimeout과 setInterval 차이
setTimeout과 setInterval는 기본적으로 무언가를 일정 간격을 두고 실행하도록 만들어주는 스케줄링 메서드 입니다.두 녀석 다 반환값으로 Timer Identifier를 반환해서 clearTimeout(timerId), clearInterval(timerI
velog.io
https://123okk2.tistory.com/386
[JS] setInterval, setTimeout
자바스크립트에서는 setInterval, setTimeout 함수를 통해 스케줄러를 지원한다. 두 함수의 차이는 아래와 같다. setInterval : 지정된 주기로 특정 코드를 실행한다. setTimeout : 지정된 초가 지난 후 특정
123okk2.tistory.com
https://winterflower.tistory.com/166
[Javascript] setTimeout / setInterval
setTimeout : 일정 시간이 지난 후 함수를 실행 function fn(){ console.log(3) } setTimeout(fn, 3000); setTimeout은 두 개의 매개변수를 갖는다. 첫 번째는 일정 시간이 지난 뒤 실행하는 함수이고, 두 번째는 시간이
winterflower.tistory.com
2. 시간맞추기 게임
스페이스바로 시작/멈춤 조작
7초를 맞추면 초록색이되고 틀리면 빨간색이 된다. 15초가 지나면 0으로 초기화
시도 1
<template>
<div :class="background">
<h1>7초를 맞추세요.</h1>
<label>spacebar로 조작하세요!</label><br/>
<span class="time number">{{ timer }}</span>
</div>
</template>
<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue';
const time = ref(0);
const isRunning = ref(false);
let timerId = null;
const startTimer = () => {
timerId = setInterval(() => {
time.value += 0.1; // 소수점 첫째 자리부터 증가
if (time.value >= 15) {
time.value = 0; // 최대 15까지 증가
}
}, 100); // 0.1초마다 증가
};
const stopTimer = () => {
if (timerId) {
clearInterval(timerId); // 타이머 정지
timerId = null;
setTimeout(() => { // 타이머 멈추기 후 잠시 후 배경색 변경
if (Math.abs(time.value - 7) < 0.1) {
background.value = 'green-background'; // 7초 맞춤
} else {
background.value = 'red-background'; // 7초 못 맞춤
}
}, 100); // 0.1초 후 배경색 변경
}
};
const toggleTimer = () => {
if (isRunning.value) {
stopTimer(); // 멈춤
} else {
startTimer(); // 시작
}
isRunning.value = !isRunning.value; // 상태 반전
};
const background = ref('');
const timer = computed(() => {
return time.value.toFixed(1); // toFixed(n) 소수점 n자리까지 표시
});
const handleSpacebar = (event) => {
if (event.code === 'Space') {
toggleTimer(); // 스페이스바 누를 때 타이머 시작/멈춤
}
};
onMounted(() => {
console.log("onMounted????");
window.addEventListener('keydown', handleSpacebar);
});
// 메모리 누수 및 예기치 않은 동작 방지 및 리소스 정리
onUnmounted(() => {
console.log("onUnmounted!!!!");
window.removeEventListener('keydown', handleSpacebar); // 컴포넌트 해제 시 리스너 제거
});
</script>
<style scoped>
.green-background {
background-color: green; /* 7초 맞췄을 때*/
}
.red-background {
background-color: red; /* 7초 맞추지 못했을 때*/
}
.time.number {
font-size: 100px;
}
</style>
`onUnmounted`를 작성하는 이유는 주로 컴포넌트가 파괴될 때 발생할 수 있는 부작용을 방지하고, 컴포넌트가 더 이상 필요하지 않을 때 리소스를 정리하기 위함입니다.
화면을 이동했을 때, 특히 Vue Router를 사용하여 다른 경로로 전환할 때, 현재 컴포넌트는 파괴되고 새로운 컴포넌트가 렌더링됩니다. 이때 기존 컴포넌트에서 설정한 이벤트 리스너, 타이머, 또는 기타 외부 리소스를 정리하지 않으면 다음과 같은 문제가 발생할 수 있습니다:
- 메모리 누수: 컴포넌트가 파괴된 후에도 이벤트 리스너나 타이머가 제거되지 않으면, 불필요한 메모리 사용이 지속될 수 있습니다.
- 예기치 않은 동작: 컴포넌트가 파괴된 후에도 이벤트 리스너가 작동하면, 스페이스바와 같은 키 입력이 예상치 못한 동작을 유발할 수 있습니다. 이는 새로운 컴포넌트에서 이전 컴포넌트의 리스너가 여전히 활성화되어 있을 때 발생할 수 있습니다.
`onUnmounted`는 이러한 문제를 방지하기 위해 사용됩니다. 컴포넌트가 파괴될 때, `onUnmounted`에서 다음과 같은 작업을 수행할 수 있습니다:
- 이벤트 리스너 제거: 예를 들어, `window.addEventListener('keydown', handleSpacebar)`와 같은 리스너를 추가했다면, 컴포넌트가 파괴되기 전에 `window.removeEventListener('keydown', handleSpacebar)`를 사용하여 리스너를 제거합니다.
- 타이머 중지: `setInterval`이나 `setTimeout`을 사용했다면, 컴포넌트가 파괴될 때 `clearInterval` 또는 `clearTimeout`으로 타이머를 중지합니다.
- 기타 정리 작업: 컴포넌트가 파괴될 때 필요한 다른 정리 작업을 수행합니다.
따라서, `onUnmounted`를 작성하는 것은 화면 전환 후 스페이스바와 같은 입력이 다른 역할을 하도록 하기 위한 직접적인 목적이기보다는, 컴포넌트가 파괴될 때 발생할 수 있는 메모리 누수 및 예기치 않은 동작을 방지하고, 리소스를 적절히 정리하기 위한 필수적인 단계입니다.
새로고침 하니까 onMounted 실행

페이지 옮기면서 onUnmounted 실행됨

참고 : onunmounted : https://ko.vuejs.org/api/composition-api-lifecycle
Vue.js
Vue.js - The Progressive JavaScript Framework
vuejs.org
`timerId`는 타이머를 식별하기 위한 번호 또는 코드입니다. `setInterval`이나 `setTimeout`을 사용하면, 이 함수들은 실행될 때마다 고유한 번호를 반환합니다. `timerId`는 이 번호를 저장하는 역할을 합니다.
### `timerId`가 왜 필요한가요?
- **타이머 중지**: 타이머를 멈추거나 제거하려면, 어떤 타이머인지 알려주는 `timerId`가 필요합니다. 예를 들어, 1초마다 실행되는 타이머를 멈추려면, `clearInterval(timerId)`를 사용해야 합니다.
- **타이머가 작동 중인지 확인**: `timerId`가 값이 있으면, 타이머가 작동 중이라는 의미이고, `null`이면 작동 중이지 않다는 뜻입니다.
### 어떻게 사용되나요?
다음은 타이머를 시작하고 멈추는 간단한 예입니다:
```javascript
let timerId = null;
const startTimer = () => {
if (!timerId) { // 타이머가 작동 중이지 않다면
timerId = setInterval(() => {
console.log('타이머 동작 중');
}, 1000); // 1초마다 실행
}
};
const stopTimer = () => {
if (timerId) { // 타이머가 작동 중이라면
clearInterval(timerId); // 타이머 멈춤
timerId = null; // 타이머가 멈췄음을 표시
}
};
```
### 정리
`timerId`는 타이머가 어떤 것인지 기억하는 번호로, 타이머를 제어하고 중지할 때 필요합니다. 이를 통해 타이머가 작동 중인지 확인하고, 타이머를 정확히 중지할 수 있습니다.
시도 2
backkground를 style까지 안가고 바로 바꾸려고 했는데.... 흠... 변수...가 하나 더 생기는 줄 알았는데 이러나 저러나 있게 되는 변수..
<template>
<div :style="{ backgroundColor: backgroundColor }">
<h1>7초를 맞추세요.</h1>
<label>spacebar로 조작하세요!</label>
<br/>
<span class="time number">{{ timer }}</span>
</div>
</template>
<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue';
// 초기 변수 선언
const time = ref(0);
const isRunning = ref(false);
const backgroundColor = ref('');
let timerId = null; // 타이머의 시간
// 타이머 시작
const startTimer = () => {
timerId = setInterval(() => {
time.value += 0.1; // 소수점 둘째 자리까지 증가
if (time.value >= 15) {
time.value = 0; // 최대 15까지 증가
}
}, 100); // 0.1초마다 증가
};
// 타이머 멈춤
const stopTimer = () => {
if (timerId) {
clearInterval(timerId);
timerId = null;
// 타이머 멈춘 후 배경색 결정
backgroundColor.value = Math.abs(time.value - 7) < 0.1 ? 'green' : 'red';
}
};
// 타이머 시작/멈춤 토글
const toggleTimer = () => {
if (isRunning.value) {
stopTimer();
} else {
startTimer();
}
isRunning.value = !isRunning.value; // 상태 반전
};
// 스페이스바 이벤트 핸들러
const handleSpacebar = (event) => {
if (event.code === 'Space') {
toggleTimer(); // 스페이스바로 타이머 시작/멈춤
}
};
// 컴포넌트가 마운트되면 이벤트 리스너 추가
onMounted(() => {
window.addEventListener('keydown', handleSpacebar);
});
// 컴포넌트가 파괴될 때 이벤트 리스너 제거
onUnmounted(() => {
window.removeEventListener('keydown', handleSpacebar); // 리스너 제거
});
const timer = computed(() => {
return time.value.toFixed(2); // 소수점 둘째 자리까지 표시
});
</script>
<style>
.time.number {
font-size: 100px;
}
</style>
시도 3 변수 줄이기 isRunning과 timeStatus 중 timeStatus만 사용하도록 변경
`isRunning`과 `timeStatus`는 타이머의 상태를 나타내지만, 각기 다른 역할을 수행합니다. 그러나 상황에 따라 둘 중 하나만 사용하여 타이머를 제어할 수 있습니다.
### `isRunning`만 사용하는 경우
`isRunning`은 타이머가 실행 중인지 여부를 부울 값으로 나타냅니다. 이를 기반으로 타이머를 시작하거나 멈추는 동작을 제어할 수 있습니다. `isRunning`만으로도 타이머의 시작/멈춤 상태를 제어할 수 있습니다.
```javascript
const time = ref(0);
const isRunning = ref(false);
let timerId = null;
// 타이머 시작
const startTimer = () => {
timerId = setInterval(() => {
time.value += 0.1; // 소수점 첫째 자리까지 증가
if (time.value >= 15) {
time.value = 0; // 15초가 넘으면 0으로 초기화
}
}, 100);
};
// 타이머 멈춤
const stopTimer = () => {
if (timerId) {
clearInterval(timerId);
timerId = null; // 타이머 정지
}
};
const toggleTimer = () => {
if (isRunning.value) {
stopTimer(); // 멈춤
} else {
startTimer(); // 시작
}
isRunning.value = !isRunning.value; // 실행 상태 반전
};
```
이 경우, `isRunning`을 사용하여 타이머의 상태를 제어하며, 타이머가 실행 중이면 `stopTimer`를, 실행 중이 아니면 `startTimer`를 호출합니다.
### `timeStatus`만 사용하는 경우
`timeStatus`는 타이머의 식별자를 저장하며, 이를 통해 타이머를 제어할 수 있습니다. 이 변수만으로도 타이머의 시작/멈춤을 제어할 수 있습니다.
```javascript
const time = ref(0);
let timeStatus = null; // 타이머 ID
const startTimer = () => {
timeStatus = setInterval(() => {
time.value += 0.1; // 소수점 첫째 자리까지 증가
if (time.value >= 15) {
time.value = 0; // 15초가 넘으면 0으로 초기화
}
}, 100);
};
// 타이머 멈춤
const stopTimer = () => {
if (timeStatus) {
clearInterval(timeStatus); // 타이머 정지
timeStatus = null; // 타이머 ID 초기화
}
};
const toggleTimer = () => {
if (timeStatus) {
stopTimer(); // 멈춤
} else {
startTimer(); // 시작
}
};
```
이 경우, `timeStatus`가 `null`인지 아닌지를 확인하여 타이머의 상태를 제어합니다. `null`이 아니면 타이머가 실행 중이므로 멈추고, `null`이면 타이머를 시작합니다.
### 선택 요인
- **`isRunning`만 사용하는 경우**: 타이머의 상태를 간단하게 나타내고, 타이머 제어를 위한 명확한 부울 값을 제공합니다.
- **`timeStatus`만 사용하는 경우**: 타이머의 식별자에 직접 의존하여 타이머를 제어합니다. 타이머가 작동 중인지 아닌지를 식별자 존재 여부로 구분할 수 있습니다.
상황에 따라 어떤 변수를 사용할지 결정할 수 있습니다. 둘 중 하나만 사용하면 코드를 간소화할 수 있지만, 각 변수의 목적에 따라 코드의 구조와 가독성을 고려하여 선택해야 합니다.
시도 4 timer를 제거하고 time만 사용하기
1. time과 timer의 차이
- time: 타이머의 실제 값을 나타내는 반응형 데이터입니다. 이 값은 ref(0)로 초기화되고, 타이머가 작동할 때 주기적으로 증가합니다. time.value를 조작하여 타이머의 값을 조정할 수 있습니다.
- timer: computed 속성으로, time의 값을 소수점 첫째 자리까지 표시합니다. 이는 사용자에게 타이머의 값을 표시할 때 사용됩니다.
timer를 사용하는 이유
timer는 computed 속성으로, time.value를 소수점 첫째 자리까지 포맷팅하여 반환합니다. 이는 Vue의 반응형 시스템을 활용하여 time.value가 변경될 때마다 UI에 자동으로 업데이트된 값을 표시합니다.
<template>
<div :class="background">
<h1>7초를 맞추세요.</h1>
<label>spacebar로 조작하세요!</label><br/>
<span class="time number">{{ time.value.toFixed(1) }}</span> <!-- 직접 소수점 첫째 자리까지 표시 -->
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const time = ref(0);
let timeStatus = null;
const background = ref('');
const startTimer = () => {
timeStatus = setInterval(() => {
time.value += 0.1; // 소수점 첫째 자리부터 증가
if (time.value >= 15) {
time.value = 0; // 최대 15까지 증가
}
}, 100);
};
const stopTimer = () => {
if (timeStatus) {
clearInterval(timeStatus);
timeStatus = null;
setTimeout(() => { // 0.1초 후 배경색 변경
if (Math.abs(time.value - 7) < 0.1) {
background.value = 'green-background'; // 7초 맞춤
} else {
background.value = 'red-background'; // 7초 못 맞춤
}
}, 100);
}
};
const toggleTimer = () => {
if (timeStatus) {
stopTimer(); // 타이머 멈춤
} else {
startTimer(); // 타이머 시작
}
};
const handleSpacebar = (event) => {
if (event.code === 'Space') {
toggleTimer(); // 스페이스바로 타이머 시작/멈춤
}
};
onMounted(() => {
window.addEventListener('keydown', handleSpacebar);
});
onUnmounted(() => {
window.removeEventListener('keydown', handleSpacebar); // 컴포넌트 해제 시 리스너 제거
});
</script>
<style scoped>
.green-background {
background-color: green;
}
.red-background {
background-color: red;
}
.time.number {
font-size: 100px;
}
</style>
접은글의 코드처럼 <span class="time number">{{ time.value.toFixed(1) }}</span> <!-- 직접 소수점 첫째 자리까지 표시 --> </div> 라고 하려고 했는데 toFixed 함수를 찾을 수 없다는 오류가 났다.
그래서 그냥 computed 쓰기로 함~
`computed` 속성은 Vue.js에서 데이터의 변화를 기반으로 자동으로 계산되는 값입니다. 이를 통해 동일한 로직을 여러 번 실행하지 않고, 의존하는 데이터가 변경될 때만 계산이 이루어지므로 효율적인 코드 작성을 가능하게 합니다.
### `computed` 속성을 사용하여 오류 방지
오류를 방지하기 위해 `computed` 속성을 사용한다는 말은, 다음과 같은 측면에서 발생할 수 있는 문제를 최소화한다는 의미입니다:
1. 재사용 가능한 로직: `computed` 속성은 데이터를 기반으로 특정 로직을 적용하여 계산된 결과를 반환합니다. 동일한 로직을 여러 곳에서 사용할 때, 각기 다른 로직이 있을 경우 발생할 수 있는 오류를 방지할 수 있습니다. `computed`를 사용하면 일관된 로직이 적용됩니다.
2. 의존성 관리: `computed` 속성은 의존하는 데이터가 변경될 때만 계산이 이루어집니다. 이는 불필요한 중복 계산을 피하고, 의존성이 명확하기 때문에 데이터 변화를 기반으로 오류를 줄일 수 있습니다.
3. 코드 간결성 및 가독성: `computed` 속성을 사용하면, 복잡한 로직을 간결하고 읽기 쉽게 작성할 수 있습니다. 여러 곳에서 동일한 로직을 작성할 필요가 없으므로, 코드의 복잡성을 줄이고, 잠재적인 오류를 줄일 수 있습니다.
### `computed`를 통한 오류 방지 예시
`computed`를 사용하여 오류를 방지하는 한 예시로, 타이머의 값을 소수점 첫째 자리까지 포맷팅하여 반환하는 코드를 생각해 볼 수 있습니다:
```vue
<script setup>
import { ref, computed } from 'vue';
const time = ref(0);
// `computed` 속성을 사용하여 값 계산
const formattedTime = computed(() => {
return time.value.toFixed(1); // 소수점 첫째 자리까지 표시
});
</script>
```
여기서 `computed` 속성을 사용하면 다음과 같은 이점이 있습니다:
- 안정성: `time.value.toFixed(1)`을 한 번에 한 곳에서 정의하므로, 포맷팅 과정에서 발생할 수 있는 오류를 줄일 수 있습니다.
- 성능 최적화: `computed` 속성은 의존하는 데이터(`time.value`)가 변경될 때만 계산이 이루어지므로, 불필요한 계산을 줄여 성능을 향상시킵니다.
- 코드 재사용: `computed`를 통해 계산된 값을 여러 곳에서 재사용할 수 있어, 중복 로직으로 인한 오류를 방지할 수 있습니다.
이러한 이점을 통해 `computed` 속성은 복잡한 로직을 간결하고 안정적으로 작성하고, 데이터의 변화에 따라 오류를 최소화하며, 코드의 가독성을 향상시키는 데 도움이 됩니다.
'개인공부' 카테고리의 다른 글
| [vue3] 코드 정렬 권장 순서 (1) | 2024.04.28 |
|---|---|
| [dependency] npm 사용 프로젝트에서 yarn 삭제 (0) | 2024.04.28 |
| [vue3] const time = ref(0); (0) | 2024.04.22 |
| [css]<style scoped> 해당 컴포넌트(파일)에만 css 스타일 적용하게 하는 속성 scoped (1) | 2024.04.21 |
| 문자열 찾기 (1) | 2024.04.15 |