728x90
싱글톤(Singleton) 패턴 이란?
싱글톤 패턴은 하나의 클래스에 대해 단 하나의 인스턴스만 존재하도록 보장하는 디자인 패턴.
즉, 객체가 여러 개 생성되지 않도록 막고, 어디서든 같은 객체를 공유 하는 것.
싱글톤을 사용하는 이유?
1. 객체를 하나만 유지해야 하는 경우
어떤 객체는 하나만 존재해야 의미가 있는 경우.
예:
- 게임 루프 (GameLoop): 게임이 한 번만 실행되어야 함.
- 설정 관리 (SettingsManager): 모든 곳에서 같은 설정을 유지해야 함.
- 데이터베이스 연결 (DatabaseConnection): 하나의 연결을 공유해야 함.
- 로그 시스템 (Logger): 여러 개의 로거를 만들면 로그가 분산될 수 있음.
싱글톤을 사용하면 이런 객체를 중복 생성하지 않고 하나의 인스턴스만 사용 가능.
게임 루프와 캔버스 예제를 통한 싱글톤 이해하기.
singleTonHT.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Game Loop Test</title>
</head>
<body>
<!-- 게임을 표시할 캔버스 -->
<canvas id="gameCanvas" width="500" height="500"></canvas>
<script type="module">
import { GameLoop } from "./singleTon.js";
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
// 싱글톤 인스턴스 생성
const game1 = GameLoop.Instance(canvas, ctx);
game1.start();
// 새로운 객체를 만들어도 기존 인스턴스가 반환되는지 확인
const game2 = GameLoop.Instance(canvas, ctx);
if (game1 == game2) {
console.log("game1 == game2 true이면 싱글톤이 정상 동작하는 것 :", game1 === game2); // true이면 싱글톤이 정상 동작하는 것!
}
</script>
</body>
</html>
singleTon.js
// 싱글톤 패턴을 적용한 게임 루프 클래스
export class GameLoop {
constructor(canvas, ctx) {
console.log("🚀 GameLoop 생성자 호출됨!");
// 기존 인스턴스가 있으면 반환 (싱글톤 패턴)
if (GameLoop.instance) {
console.log("⚠️ 이미 생성된 인스턴스를 반환합니다.");
return GameLoop.instance;
}
// 캔버스와 컨텍스트 저장
this.canvas = canvas;
this.ctx = ctx;
this.x = 100; // 원의 초기 위치
this.speed = 2; // 이동 속도
this.isRunning = false; // 게임 루프 실행 여부
this.lastFrameTime = performance.now(); // 마지막 프레임 시간 저장
GameLoop.instance = this; // 현재 인스턴스를 저장
console.log("✅ 새로운 GameLoop 인스턴스가 생성되었습니다.");
}
// 싱글톤 인스턴스를 반환하는 정적 메서드
static Instance(canvas, ctx) {
if (!GameLoop.instance) {
console.log("🎯 새로운 인스턴스를 생성합니다.");
GameLoop.instance = new GameLoop(canvas, ctx);
} else {
console.log("🔄 기존 인스턴스를 반환합니다.");
}
return GameLoop.instance;
}
// 게임 루프 시작
start() {
if (this.isRunning) {
console.log("⚠️ 이미 게임 루프가 실행 중입니다!");
return;
}
console.log("▶️ 게임 루프 시작!");
this.isRunning = true;
this.loop(); // 루프 실행
}
// 게임 루프 (반복 실행)
loop() {
if (!this.isRunning) return; // 실행 중이 아니면 중단
console.log("🎬 새 프레임 실행 중...");
this.backgroundRender(); // 캔버스 지우기
this.drawCircle(); // 원 그리기
this.lastFrameTime = performance.now(); // 현재 프레임 시간 저장
requestAnimationFrame(() => this.loop()); // 다음 프레임 요청
}
// 캔버스를 지우는 함수
backgroundRender() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
// 원을 그리는 함수 (애니메이션 효과 포함)
drawCircle() {
this.ctx.beginPath();
this.ctx.arc(this.x, 100, 30, 0, Math.PI * 2); // 원을 그림
this.ctx.fillStyle = "blue"; // 원 색상 지정
this.ctx.fill();
this.ctx.closePath();
// 원을 이동시킴
this.x += this.speed;
// 캔버스 경계를 벗어나면 방향을 바꿈
if (this.x > this.canvas.width || this.x < 0) {
console.log("🔄 // 캔버스 경계를 벗어나면 방향을 바꿈!");
this.speed *= -1;
}
}
}
시연영상
(게임 객체를 각각 생성하여 일치하는경우 콘솔창에서 로그로 확인이 가능함)
'JavaScript' 카테고리의 다른 글
[JavaScript] Debounce와 Throttle: 차이점과 활용 방법 (0) | 2025.03.10 |
---|---|
[JavaScript] 로컬 이미지 업로드 및 이미지 확대하여 모달창에 띄우기 (0) | 2025.02.12 |
[JavaScript] 다중 Progress Bar와 전체 진행률 구현하기 (2) - 일시중지 및 삭제버튼 추가 (0) | 2025.02.05 |
[JavaScript]TensorFlow.js로 고양이 이미지 판별 앱 만들기 (0) | 2025.02.04 |
[JavaScript] 사용자 입력 기반 다중 Progress Bar와 전체 진행률 구현하기 (0) | 2025.01.22 |