제작
느낀점
- 무척 단순한 페이지지만 프론트를 아무것도 모르는 사람이 프롬프트를 입력해서 웹페이지가 나오는 건 내게도 충격이었다.
- 그럼에도 불구하고, 언어의 구조/설계를 모르는 입장에서 다소 아쉬운 결과물이 나오긴 했다. 바이브 코딩이 대세라지만, 어떻게 사용하는지 어떤 흐름을 가지고 어떻게 만드는지 골격은 알고 만들어야겠다.
- 이거 잘못하면 저작권 침해.....
- 웹이지만, 현재 진행하는 그래픽스 과제와 코드 흐름이 꽤 비슷하다는 인상을 받았다.
- 뭐에서 공통점을 느꼈는가? -> 이벤트 기반 프로그래밍
- 유저의 클릭, 키보드 입력, 시스템이 보내는 신호(event)에 의해 프로그램의 흐름이 변동됨
- event loop: 프로그램이 무슨일이 일어났나~ 하면서 계속 확인하는 심장부
- event queue: 동시다발적으로 발생하는 이벤트(클릭, 마우스 이동 등)를 발생 순서대로 줄을 세워두는 대기열
- event handler/callback: 특정 이벤트가 발생했을 때 이렇게 행동하세요. 라는 함수들
- ai 가 알려주는 MLX와 JS의 비교
| 개념 | JavaScript (High-level) | MLX / C (Low-level) |
|---|
| 추상화 (Abstraction) | 브라우저 엔진이 이벤트 루프와 큐를 내부적으로 관리하여 개발자는 로직에만 집중 가능 | 개발자가 직접 mlx_loop를 실행하고 각 상황에 맞는 Hook 함수를 설계하고 연결해야 함 |
| 메모리 (Memory) | 가비지 컬렉터(GC)가 더 이상 사용되지 않는 변수를 자동으로 정리하여 메모리 누수 방지 | mlx_new_image 등으로 할당한 메모리는 반드시 mlx_destroy_image 등을 통해 직접 해제해야 함 |
| 렌더링 (Rendering) | ctx.fillRect나 ctx.arc와 같이 이미 구현된 고수준 API를 호출하여 손쉽게 그래픽 구현 | 이미지 버퍼의 시작 주소를 얻어와 각 픽셀의 메모리 주소(int pointer)에 직접 색상 값을 써넣어야 함 |
개선점
- TV를 연결해서 활용할 예정인데, 하나씩 뽑히는 떡 타일이 너무 작은 건 아닐까..
- 화면 분할을 좌우로 했는데, 핸드폰에서는 겹치는 부분이 일부 있음
- 복주머니와 뽑힌 떡 숫자를 정중앙에 가장 돋보이게 배치하고, history는 화면 하단에 가로로 최대 20개 배치하는 게 더 적절할 것 같다.
- 20번째 떡을 뽑은 순간 새로운 창(modal=안내창)이 뜨면서 이전까지 뽑은 떡이 가려진다는 단점
streams란?

🛠 stack
- Languages: Vanilla JavaScript(ES6+), HTML5, CSS3
- Web APIs: Canvas API (Real-time Physics), Web Audio API (Sound Synthesis)
- Styling: Modern CSS (Flexbox, CSS Variables, Keyframe Animations)
이번 생에 front는 처음이라..(?)
분명히 꾸글 모임으로 용어를 여러 번 들었는데, 듣기만 한 공부는 흘러가버렸구나..
1. Vanilla JavaScript
- vinilla: SW에서 아무런 수정이나 추가 기능이 없는 순정 상태. jQuery, React, Vue, Angular와 같은 외부 도구를 전혀 사용하지 않고 브라우저가 기본으로 제공하는 기능만 사용하는 방식
2. HTML5 (Semantic Markup)
- 웹 표준을 준수하여 구조화된 문서 설계
- semantic: 의미론적인, "header"와 같은 태그를 사용하여 구조를 더 정확히 설계
- 효과음을 위해 사용한 AudioContext나 시각효과를 위한 "canvas" 태그가 HTML5의 핵심 기능.
-> 멀티미디어 및 웹 앱플랫폼
- WHATWG
3. CSS3
- Cascading Style Sheets Level 3
- 특성: Modern CSS (Flexbox/Grid)
- flexbox도입으로 정렬을 직관적으로 함
-> cf) 선(1차원)의 배치에 강함. Grid는 면(2차원) 배치에 강함.
html? css? js?

index.html
Structure: 브라우저가 읽어 들여 화면에 그릴 모든 객체의 목록을 담고 있다
- 컴포넌트 정의: 게임 제목, 떡의 개수를 표시하는 배지, 복주머니, 결과 창, 히스토리, 그리드 등 HTML 태그로 선언
- 식별자 부여: 자바스크립트가 접근할 수 있도록 각 요소(ex. currentTile, resetBtn)를 부여하여 '동작의 대상'을 명확하게 한다.
- 상태 준비: 게임 종료시 나타날 modal 창과 꽃가루가 터질 canvas 공간을 미리 만들어 둔다.
- 외부 자원 연결: google fonts로부터 폰트를 불러오고, CSS와 JS 파일을 연결하여 하나의 앱으로 묶어 준다.
style.css
Presentation: 정적인 HTML 요소를 예쁘고 생동감 있게 바꾼다
- 테마 및 변수 관리: ':root'를 통해 브랜드 컬러(떡 색깔, 배경색 등)를 변수로 선언하고 유지보수성을 높임
- 레이아웃 설계: Flexbox를 활용해 좌측(조작 영역)과 우측(결과 영역)으로 화면 분할, 모바일 환경에서도 최적화되도록 미디어 쿼리(@media) 적용
- 하지만, 모바일 환경 최적화가 좀 더 필요하다.
- 애니메이션 구현: 토끼의 숨쉬기(breath), 주머니를 누를 때의 쫄깃한 느낌(squeeze), 모달이 나타나는 효과(popIn) 등을 정의, 일종에 손맛 추가
- 사용자 정의 커서: 마우스 커서를 당근 모양으로 바꿈
script.js
Behavior: 사용자의 행동에 따라 데이터가 어떻게 변하고 화면이 어떻게 바뀌어야 하는지를 결정
- 상태 관리(state management): 현재 주머니의 남은 떡의 목록(bag), 진행된 턴 수(turnCount) 등을 변수로 관리
- suffle: 1~30번 타일과 별 타일을 생성하고(generateTiles) 이를 공정하게 섞음
- 이벤트 처리: 사용자가 복주머니를 클릭하면 떡을 뽑는다(performDraw). 그리고 화면에 업데이트 (displayTile)하며 히스토리에 기록을 남김(addToHistory)
- 멀티미디어 제어: AudioContext를 사용하여 동적으로 효과음을 생성, Canvas API를 직접 조작해 물리 연산이 가미된 꽃가루 효과를 렌더링한다.
꽃가루 로직
중력 계산이라니? 갑자기 물리 시간
const ctx = confettiCanvas.getContext('2d');
function updateConfetti() {
ctx.clearRect(0, 0, confettiCanvas.width, confettiCanvas.height);
for (let i = 0; i < particles.length; i++) {
const p = particles[i];
p.x += p.vx;
p.y += p.vy;
p.vy += 0.5;
ctx.fillStyle = p.color;
ctx.fillRect(p.x, p.y, p.size, p.size);
}
if (particles.length > 0) requestAnimationFrame(updateConfetti);
}
p.vy += 0.5;
- 0.5 -> 0.1로 줄이면 중력이 줄어들어서 천천히 떨어짐
- 0.5 -> 1 중력이 늘어나서 빨리 떨어짐. WOW
- 오일러 적분(Euler Integration)을 활용하였다고..
재밌는 프로젝트 하셨네요.
짧은 사이에 괴물이 돼버리신 모습에 놀랐습니다.
익숙한 게임이라 생각했는데 컴플레또(Completto)랑 비슷하네요.
잊고 살았는데 감사합니다.