문제
Snack Game진행시 가끔씩 프레임 드랍이 생겼고 이를 해결해 유저 경험을 향상시키는 목적.
React에서 할 수 있는 것
리액트의 문제라고 하기엔 memo
로 게임 컴포넌트의 렌더링을 제한했고 사용자와 상호작용으로 이벤트가 발생해 상태의 변경이 생겨야 재렌더링이 일어나기에 성능에 큰 영향은 없었다 실제로 useCallback
을 함수에 적용해보기도 했지만 성능 상 이점은 없었다.
리소스 최적화
게임을 하다가 렉이 걸리면 그래픽 옵션을 낮추는것 처럼 스낵 게임도 이런 방식을 적용할 수 있다.
기존 게임에서 사용하던 사과 이미지는 512x512의 커다란 이미지에 용량도 MB
단위로 거대했고 120개의 객체에 초당 60번 그리니 리소스의 문제도 있었던 것 같다.
리소스를 최적화해 성능을 올리는건 좋은데 고려해볼 사항으로는 적절한 리소스의 최적화를 생각해야했다. 아래 사진과 같이 극단적으로 해버리면 오히려 몰입감을 떨어트려 유저 경험을 해칠 수 있다.
그렇다면 사과게임의 몰입도를 해치지 않으면서 적절한 리소스의 크기는 몇일까?
아래는 사과게임의 사과 반지름 계산 공식이다.
const availableWidth = (offsetWidth - BORDER_OFFSET * 2) / COLUMNS;
const availableHeight = (offsetHeight - BORDER_OFFSET * 2) / ROWS;
const appleRadius = Math.floor(
Math.min(availableWidth, availableHeight) * 0.4,
);
자 그러면 항상 최악의 경우를 생각해야 하니 4K UHD 모니터에서 사과게임을 한다고 가정하고
너비와 높이중 작은 값으로 계산되니 4K모니터의 높이 2160에 사과게임이 렌더링 되는 80%는 2160 * 80 / 100 = 1728
즉 ((1728 - 20 * 2) / 10) * 0.4 = 67.2 반지름이니 2를 곱하면 134.4
모든 환경에서 커버리지를 생각하면 125x125 크기가 맞지만 사과게임 페이지 자체의 max-width
를 생각하면이에 절반인 65x65로 충분하다고 판단했다.
결과로 MB
단위의 이미지를 B
단위로 줄일 수 있었고 사과게임의 성능도 많이 개선되었다.
다른최적화 방법은 뭐가 있을까
- 위 문서는
mdn
이 권장하는canvas
최적화에 관한 방법들을 소개하고 있는데 그중offScreenCanvas
를 주목하였다. (부동소수점, 투명도 등 적용은 의미가 없었다.) offScreenCanvas
를 통해 렌더링을 워커로 위임한다면 더 원활한 게임진행을 제공할 수 있다고 생각했다.
offScreenCanvas를 적용 실패와 마주친 문제들
- 메인스레드와 독립
- 문서의 부족
장점이자 단점이 되어버린 이유. 워커에게 메시지로 데이터를 넘겨야했다.
워커에 렌더링을 위임하는 순간 메인스레드에서 canvas를 제어할 수 없다.
이를 해결하기 위해 postMessage를 통해 워커로 렌더링할 데이터를 보내서 해결할 수 있었다. (전송하는 오버해드 존재)
게임이라는 특성 상 유저와 지속적인 인터렉션이 일어나고 메인스레드에서 처리해야 하는일이 많은데 기능을 하나씩 적용할 때 마다 워커와의 상호작용에 있어서 여러가지 사이드 이펙트를 처리해야 했다.
이는 나중에 사과게임의 확장을 고려했을 때 불리함으로 작용한다고 판단했다.
활발하게 논의되고 자체적으로 offScreenCanvas
를 지원하는 three.js
같은 라이브러리는
문서가 많다.
결국 three.js
라이브러리의 코드를 참고하게 되었는데 WebGL
기반이다 보니 큰 인사이트를 얻지는
못 했다.
이렇게 분석하는것 보다는 문서도 많고 offScreenCanvas
를 적용하지 않더라도 canvas api
보다 빠른 성능을 보장하는 WebGL
기반 엔진을 사용하는게 여러가지 측면에서 좋다고 판단했다.
결론
offScreenCanvas
는 현재 구조에서 도입하는데 발생하는 여러가지 사이드 이펙트와 많은 고민이 필요함 → 생산성의 저하 → 확장시 불리함- 문서도 많고 활발한 논의가 이루어지는
WebGL
기반 엔진을 사용하는게 훨씬 유리하고 좋은방법인것 같다. OffscreenCanvas
의 도입이 기술적으로 가능하지만 현재 프로젝트의 요구사항과 목표에 비추어 봤을 때 최적의 선택이 아니라는 결론.