
왓챠벨 보기
소개
왓챠벨이란?
왓챠벨은 왓챠의 마케팅 이벤트로 영화 관련 스피드 퀴즈를 할 수 있는 서비스 입니다.
맡은 포지션
- 왓챠벨 인트로 애니메이션 구현
- 순수 CSS anmiatoin으로 세부 움직임 제어
- 타임어택바 제작 및 최적화
- useImperativeHandle 를 이용하여 리렌더링 최적화
- 디자인 디테일 체크 및 수정
기술 스택
- next js
- graphQL
- typescript
- jest
인트로 애니메이션 제작기
시작 배경
원래 이미지로 존재했던 인트로 부분이 애니메이션처럼 움직였으면 좋겠다는 생각이 들어 제안을 드렸고 받아들여져 애니메이션 작업에 들어갔다.
작업
- 순수 CSS로 제작했다. 다른 라이브러리도 고려해봤지만 간단한 애니메이션 구현이 목표였기 때문에 주변 소스를 찾아가며 제작했다.
- 가장 노력을 들였던 부분은
종이 쳐지는 것같은
자연스러운 모션이었다. rotate와 translate 값을 계산하고 조절하며 만들었다.
- 물론 반응형 작업이 필요했기 때문에 뾰족한 배경을 바탕으로 모든 요소가 위치할 수 있도록 position 값을 지정하였다.

- 다만 문제는
클릭이 가능하지 않아
보인다는 점이었다.
- 디자이너 선생님과 회의를 거쳐 눌릴 것 같은 사인을 주는 것과, scale 조절을 해주는 방법 중 후자가 더 낫다는 판단을 하였다.
- 오히려 하나의 이스터에그가 된 느낌이라 재밌었다.
.gif?table=block&id=21f5c6ec-9e69-49d1-943a-0e4af4516ef3&cache=v2)
.gif?table=block&id=ef45dd5d-add3-4344-b916-204ad949ebc1&cache=v2)
렌더링 순서 문제
- 하나의 문제가 있다면 최초 로딩 때
사진이 불규칙하게 렌더링
되는 점이었다.
- 종 바디와 검은 종이 별도로 존재했기 때문에 따로 렌더링 됐을 때 보기가 안좋았다.
- 이는 CSR 방식으로 이미지를 불러오고 있기 때문에 생긴 일이라 next에서 제공하는 image 태그를 사용하거나 next config에서 svg를 컴포넌트처럼 불러올 수 있도록 바꿔야 했다.
- 이때 next에서 image 태그를 사용하니 css가 부분적으로 먹히는 걸 발견했다. 찾아보니 next image에서 우선순위를 가지는 스타일이 몇몇 존재해 이에 대한 별도 처리가 필요했다.
- 그래서 차라리 전자의 방법보단 깔끔하게 config를 수정해서 svg를 컴포넌트화 시키는 게 낫다고 판단했다.
- 한 가지 더 고려해야 할 점은 config 설정만 끝냈을 때 svg의 viewport가 생략되는 문제가 있었다. 이는 view-port인데 viewPort라 되어 있어 이를 인지하지 못하고 생략시키기 때문에 발생한다고 이해했다. 그래서 viewport를 무시하지 않는다는 추가 설정을 해주었다.
- 추가로 이미지가 렌더링 되기 전에 도전 버튼이 먼저 렌더링 되어 갑자기 버튼이 위에서 아래로 내려오는 것을 방지하기 위해 min-height로 사용자가 좀 더 편안한 화면을 볼 수 있도록 만들었다.
타임어택 제작 및 최적화
시작 배경
시간 제한이 있는만큼 타임어택바가 필요했고, 타임어택바는 계속 렌더링이 필요한 반면 문제는 사용자가 문제를 선택하기 전까지 렌더링이 필요없기에 최적화 작업이 필요했다.
작업
- 타이머는 use-timer라는 라이브러리를 사용했다. 단순 시간을 계산해줄 뿐만 아니라 문제가 넘어가면서, 버튼을 누르면서 시간을 재시작하거나 멈출 필요가 있어 필요하다고 생각했다.
- 최적화를 위해선
useImperativeHandle
을 사용했다. 타임어택바는 하위 컴포넌트로 존재하고 문제와 다른 기능이 있는 상위 컴포넌트로 존재했기 때문에 prop을 내려주는 방식을 사용하지 않기 위해 사용했다. - props을 내려주면 time이란 상태가 변하니 모든 컴포넌트를 재렌더링 시키기 때문.
- useImperativeHandle은 쉽게 말하면 부모 컴포넌트가 자식 컴포넌트의 요소에 접근해 행위 주체를 부모로 전환할 때 사용한다.
- 따라서 use-timer에서 제공하는 start, pause 등의 함수를 부모 컴포넌트의 상황에 따라 useImperativeHandle로 실행시키면 time이란 상태가 변경돼도 문제가 들어있는 부모 컴포넌트는 재렌더링을 하지 않는다.
.gif?table=block&id=4aa8cd54-971d-4429-ae4b-075855a54c6a&cache=v2)
재밌었던 점
- progress를 나타내는 bar는 charka ui를 썼는데 여기서 bar를 채우는 기준은 %이다. 하지만 time은 interval과 step에 따라 달라지는 frame과 같은 단위이기에 원하는 시간만큼 progress bar가 잘 보이고, 동작하게 하기 위해 다양한 계산을 시도했다.
- 그러다 소수점이 불가피하게 발생했고 소수점이 발생할 때 동작이 이상한 것이 확인되었다.
- 내부코드를 보니 자연수로만 사용할거라 판단했는지 endTime의 기준이
time ≥ endTime
이 아닌time === endTime
이었다. 오직 딱 맞는 경우만 endTime이라 판단하는 게 맞지 않다 생각해서 use timer 깃허브에 이슈로 남겨놓고 계산을 다시 정립해서 문제를 해결하였다.
