프로젝트/레트로 테트리스

Claude Code로 테트리스 만들기 3부 - 반응형 레이아웃 구현

ksc-dev 2026. 4. 20. 20:30

1. 배경
3부는 모바일에서도 잘 보이도록 반응형 레이아웃을 구현한 과정이다.
 
2. 핵심 문제
테트리스 보드는 10×20 고정 비율이라 CSS vw/vh 단위만으로는 화면에 맞추기 어렵다. 높이 기준으로 맞추면 가로로 삐져나오고, 가로 기준으로 맞추면 세로로 삐져나온다.
 
3. 해결 방법 — JS로 동적 셀 크기 계산

const CELL_SIZE = computed(() => {
  const byHeight = Math.floor((windowHeight.value * 0.75) / BOARD_ROWS)
  const byWidth = Math.floor((windowWidth.value * 0.62) / BOARD_COLS)
  return Math.max(16, Math.min(byHeight, byWidth))
})

 
높이 기준과 너비 기준을 둘 다 계산하고 작은 값을 선택해서 항상 화면 안에 들어오게 했다.
 
4. CSS 변수로 값 전달
- js

const boardStyle = computed(() => ({
  '--cell-size': `${CELL_SIZE.value}px`
}))
- css
.board-cell {
  width: var(--cell-size);
  height: var(--cell-size);
}

JS에서 계산한 값을 CSS 변수로 전달해서 보드 전체 크기가 자동으로 바뀌게 했다.
 
5. 배운 개념 — computed 순수성
처음에 computed 안에서 windowHeight.value에 계산 결과를 덮어써서 버그가 생겼다. computed는 읽기만 해야 하고 반응형 값을 수정하면 안 된다.

// ❌ 잘못된 방법
windowHeight.value = Math.floor(...) 

// ✅ 올바른 방법
const byHeight = Math.floor(...)

 
6. CSS 미디어 쿼리 — 캐스케이드 순서

/* 기본 (데스크탑) */
.right-panel {
  flex-direction: column;
}

/* 모바일 — 파일 맨 아래에 위치해야 함 */
@media (max-width: 599px) {
  .game-layout {
    flex-direction: column;
  }
  .right-panel {
    flex-direction: row;
  }
}

CSS는 나중에 쓴 규칙이 이긴다. @media 블록이 기본 스타일보다 위에 있으면 모바일 스타일이 항상 무시된다.
 
7. 마무리
이번 파트에서 CSS 캐스케이드 순서는 이해가 됐다. computed 순수성과 CSS 변수 전달 방식은 아직 완전히 이해하지 못했다. 다음 프로젝트에서 직접 써보면서 익혀야 할 것 같다.