나는 포트폴리오를 깜깜한 어둠에 숨겼다. Google Gemini가 토치를 만드는 데 도와줬다.
Source: Dev.to
이것은 Google Gemini와 함께 만든 글쓰기 챌린지 제출물입니다.
Google Gemini로 만든 것
포트폴리오는 엔지니어로서 당신이 누구인지 보여주기 위한 것입니다. 하지만 어느 순간부터 우리는 모두 똑같은 것을 만들기 시작했습니다: 깔끔한 헤더, 튀는 CSS 그리드의 프로젝트 카드, 그리고 거대한 “Contact Me” 버튼. 엔지니어의 작업을 발견하는 가장 좋은 부분은 단순히 읽는 것이 아니라 발견 행위 자체라는 것을 깨달았습니다.
그래서 저는 제 전체 이력서를 완전한 어둠 속에 뛰어들게 했습니다.
저는 Interactive Torch Portfolio를 만들었습니다 – 화면이 완전히 검은 실험적인 모바일‑우선 단일 페이지 애플리케이션(SPA)입니다. 제 소개, 기술, 프로젝트를 읽거나 보는唯一한 방법은 가상이고 깜박이는 “손전등”을 화면에 물리적으로 끌어다 어둠 속에 빛의 구멍을 만드는 것입니다.
React, Next.js, 혹은 거대한 라이브러리를 사용하지 않기로 했습니다. HTML, CSS, 그리고 순수 DOM 조작만으로 순수하게 만들고 싶었습니다. 움직이는 손전등의 물리 계산과 복잡한 HTML5 Canvas 블렌드 모드를 처리하는 것은 큰 골칫거리가 될 수 있었지만, Google Gemini가 제 수학적 페어 프로그래머로 등장하면서 상황이 달라졌습니다.
Demo
Google Cloud Run 배포(경량 nginx:alpine 이미지로 컨테이너화됨)에서 포트폴리오를 실시간으로 체험할 수 있습니다. 별도의 설정이 필요하지 않으며, 링크를 열고 토치를 끌어다 사용하기만 하면 됩니다.
내가 배운 것
고급 캔버스 블렌드 모드 (기술적 깊이)
HTML5 Canvas API, 특히 globalCompositeOperation에 대한 이해를 깊게 했습니다. 목표는 전체 화면을 어둡게 만들고 마우스가 움직인 위치에 투명한 구멍을 “뚫어내는” 것이었습니다. Gemini 덕분에 브라우저 프레임 레이트에 영향을 주지 않으면서 이 로직을 구현할 수 있었습니다:
// Fill the screen with darkness
ctx.fillStyle = '#050505';
ctx.globalCompositeOperation = 'source-over';
ctx.fillRect(0, 0, width, height);
// "Cut out" the darkness using the glowing gradient
ctx.globalCompositeOperation = 'destination-out';
ctx.fillStyle = gradient; // radial gradient for soft edges
ctx.beginPath();
ctx.arc(startX, startY, maxRadius, 0, Math.PI * 2);
ctx.fill();
플래시라이트 빔에 destination-out을, 주변 불빛에 screen/lighter를 단일 <canvas> 요소에 겹쳐 사용하는 방법을 마스터한 것은 정말 보람 있었습니다.
물리 메커니즘 번역
일반적인 커스텀 커서는 가벼운 느낌입니다. 나는 내 토치를 무겁게 느끼게 만들고 싶었습니다. Gemini와 작업하면서 시각적 물리를 실행 가능한 프롬프트로 표현하는 방법을 배웠습니다. “마우스 이동 속도에 따라 무거운 진자처럼 토치를 기울이게 해라”는 로직을 설명했더니, Gemini가 Math.cos와 Math.sin 회전 행렬을 생성해 SVG 토치를 축을 중심으로 현실감 있게 흔들어 주었습니다.
바닐라 성능의 힘
requestAnimationFrame과 Canvas 컨텍스트만을 순수하게 사용하고 virtual‑DOM diffing을 배제함으로써, 애플리케이션은 즉시 로드되고 수백 개의 애니메이션 수학 기반 화염 입자를 렌더링하면서도 buttery‑smooth 60 FPS를 유지합니다.
Google Gemini 피드백
아주 잘 작동한 점
Gemini가 긴 설계 토론 동안 컨텍스트를 유지하는 능력은 타의 추종을 불허합니다. 현대식 손전등에서 중세식 나무 토치로 전환할 때, 저는 Gemini에게 “손전등 요소를 불꽃이 튀는 나무 토치로 바꾸되, 노이즈 오버레이와 앞서 논의한 물리 효과는 그대로 유지해 주세요.”라고 간단히 요청했습니다. Gemini는 기존 z‑index 레이어를 존중하면서 새로운 SVG 좌표를 생성했습니다. 마찰, 중력, 진자 스윙 같은 개념을 JavaScript 수학으로 변환해 주어 MDN 문서를 뒤져보는 시간을 몇 시간 절약할 수 있었습니다.
문제가 있었던 점
모바일 터치 이벤트에 최적화하도록 Gemini에 명시적으로 요청해야 했습니다. 토치 효과는 처음에 데스크톱 mousemove에서는 작동했지만 touchmove/touchstart에서는 동작하지 않아 스크롤이 불안정했습니다. Gemini는 결국 올바른 코드를 제공했지만( { passive: true } 추가), 문제를 먼저 인식해야 했습니다. 또한 숨겨진 콘텐츠 그리드 레이아웃에 대해 즉시 JavaScript 뷰포트 계산을 사용하기보다 순수 CSS Flexbox 솔루션으로 유도해야 할 때가 있었습니다.
