♻️ Refactor: 보드 스티커 렌더링 Konva -> DOM 전환 및 인터랙션 스펙 구현 - #59
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
고생하셨습니다!
시뮬레이터에서 스티커 드래그가 되지 않습니다! 이 버그만 수정해주세요!
추후 konva 가 쓰일 일이 없을 것 같으면 pacakges.json 도 정리 부탁드립니다.
하고 지금 BoardCanvas.tsx 에 모든 상태랑 전이가 몰려있습니다.
다음 PR에서 전이만 한곳에서 reducer로 관리하고 상태별 동작은 분리하면 좋을 것 같아요. 그래야 디버깅이 좀 수월할 듯 싶어요. 전이 테스트도 추가해주시면 좋을 것 같습니다!
그리고 요건 앞으로 상태가 좀 많아질 것 같아 xstate 미리 고려해봐도 좋아보여요
혹시 시뮬레이터에서 어떤 드래그가 안되나요? 선택박스(하늘색박스)는 잘 뜨고 드래그로 이동만 안되나요? 리사이즈는 되고 드래그만 안되는건가요?!? 보드캔버스 부분은 말씀하신대로 reducer로 분리하면 좋을 것 같아요! 다음 pr에서 작업해볼게요! xstate도 고려해보겠습니다! |
2026-08-11.1.34.39.mov이렇게 돼요 왠진 모르겠지만 |
아 보드 저장이 400떠서 그런거였네요... |
🔍 PR 요약
보드 스티커 렌더링을 Konva 캔버스에서 순수 DOM으로 전환하고,
디자이너가 확정한 인터랙션 스펙(2손가락 회전+확대, 제스처 라우팅, 90° 스냅, 뱃지 z-순서, 선택 표시 등)을 새로 구현
인터렉션 스펙 참고
https://claude.ai/code/artifact/8c982d99-e3a1-4bca-b9db-fb930257f90a
이번 pr은 바로 develop에 머지하는게 아니라 이전 작업인 feat/sticker-drag-resize 브랜치에 우선 머지합니다!
🧾 관련 이슈
🧠 의도 및 배경
기존엔 스티커는 konva로 그리고, 제목 뱃지만 Html(react-konva-utils)로 캔버스 위에 얹는 구조였습니다. 이 구조에서 뱃지의 z-index가 konva랑 맞물리지 않는 문제가 있어서 뱃지를 konva로 전환할 예정이었습니다. 그런데 이렇게 계속 konva로 진행하다보니 복잡도가 너무 높아져서 스티커를 전면적으로 dom 리액트 컴포넌트로 전환하는 방향을 고민하게 됐습니다,,
캔버스기능 구현한다고 당연히 캔버스 라이브러리부터 고르다 보니 사전에 깊은 고민을 하지 못했던 부분인데
지금 저희 서비스 보드 기획에 복잡한 기능은 없고 이정도 규모면 앞으로 계속해서 konva 복잡도를 감수하는게 맞나 싶어져서, 검증 삼아 브랜치를 새로 파서 dom으로 전환한 뒤에 전달받은 스펙 기반 인터렉션을 새로 구현했습니다.
Konva가 주는 대량 렌더링 성능 같은 장점도 있긴한데, 보드당 스티커 수십개 수준에서는 의미가 크게 없다고 판단했고, 기능이 더 쌓이기 전에 지금 DOM으로 옮기는 게 낫다고 우선 저는 생각합니다!
이번 PR의 2손가락 회전+확대 제스처 같은 것도 Konva 좌표계 위에서 구현했다면 훨씬 복잡했을 작업인데 꽤 간단히 해결했습니다
확인해보시고 그래도 konva 유지가 낫다 싶으면 말씀해주셔도 됩니다!
참고로 나중에 붙일 드로잉 기능은 이 결정이랑 상관없이 스티커를 konva로 유지하든 말든 어차피 별도의 캔버스 레이어로 가야 해서 문제 없고, 텍스트 삽입도 오히려 더 간단해집니다.
디자이너님이 전달해주신 인터렉션 스펙에서 도트배경 애니메이션은 이번 범위에서는 제외했습니다.
변경사항이 많아 주요 변경사항을 자세히 작성해두었습니다!
🛠️ 주요 변경 사항
변경된 파일이 많아서 지금 작업중/리뷰중이신 것중에 충돌되는것들 있을텐데, 머지 충돌은 다른분들 작업 머지되면 제가 정리한 뒤에 머지하겠습니다!
렌더링/제스처 핵심
BoardCanvas.tsx: Konva 이벤트 대신 Pointer Events를 직접 구독해 제스처 상태 머신을 구현했습니다.Sticker.tsx: Konva Image → DOMStickerBadgeMark.tsx(신규): 뱃지를 별도 컴포넌트로 분리하고, 스티커의 자식이 아니라 같은 보드 레이어의 형제 노드로 렌더링합니다. CSS transform이 자식에 새 stacking context를 만들어서, 자식으로 두면 z-index가 전역으로 비교되지 않는 문제가 있었습니다.SelectBox.tsx: 기존엔 코너 핸들을 드래그해서 리사이즈하는 인터랙티브 컴포넌트였는데, 리사이즈가 2손가락 핀치로 옮겨가면서 순수 시각(비인터랙티브, pointerEvents: none) 컴포넌트로 다시 작성했습니다.순수 계산 함수 (테스트 포함)
board-camera.tsboard-transform.tsgeometry.ts: angleBetween, rotatePoint, clamp 추가.부수 변경
save-sticker-image.ts: Konva Stage가 없어지면서 캡처 방식을 html-to-image의 toCanvas로 교체했습니다.apps/web/app/layout.tsx,apps/mobile/.../AppWebView.tsx: 인터랙션 스펙의 "뷰포트 확대 방지" 항목 — 웹은 viewport meta에 userScalable: false, 안드로이드 웹뷰는 scalesPageToFit={false}. (iOS는 gesturestart 계열 preventDefault로 이미 처리되어 있던 부분에 안드로이드 쪽 빠진 걸 채운 것.)board-api.ts: boardApi.list()도 USE_MOCK사용할 수 있게 변경🚨 트러블슈팅 (선택)
남은 항목 (이번 PR 범위 밖)
📸 스크린샷
아이폰 화면녹화에 터치 보이게 하는법이 없길래 우선 이렇게만...
ScreenRecording_08-10-2026.12-41-42_1.mov