react

react로 그림판을 만든 뒤 후기 [0]

weaklion 2025. 12. 10. 17:17

react와 konva를 이용해서 그림판을 만들었습니다.

konva는 js를 이용해서 canvas를 2d로 제어할 수 있는 라이브러리입니다. 

원래는 HTML의 자체 canvas API를 쓸까 했는데 그러면 하나의 기능을 만드는데 너무 긴 시간이 소비될 것 같아서 안 했습니다.

하지만 그냥 canvas API를 쓸 걸 그랬습니다.

 

이번엔 ai와 적극적으로 소통해서 만들었습니다. 

ai를 이용해서 고작 이 딴 거나 만들었냐? 고 하면 딱히 할 말은 없는데, 

이번 프로젝트에서 중요한 건 ai에 의존하는 게 아니라, ai를 통한 코드 퀄리티를 높이는 거라, 우선 코드를 입력한 뒤

그 코드를 리팩터링 할 때 ai를 쓰는 방향으로 진행했습니다.

그러니까 좀 봐주세요. ai로 코드 찍는 건 양심에 가책이 있어서 안 했습니다.

 

지금 그림판에 구현되어 있는 기능은 총 6가지입니다.

그리기, 지우개, 텍스트, 선택, 되돌리기, undo, redo.   

간단해 보이는 기능들이고 실제로 대부분은 만드는데 어렵지 않았습니다. 

konva에 있는 데모들에 다 있었던 기능들이고, 따라만 하면 다 나오는 것들이었죠.

문제는 선택과 지우개였습니다. 둘 다 데모가 나와있기는 하지만 전제가 다릅니다. 

konva의 공식 홈페이지에 있는 demo는 globalCompositeOperation를 destination-out 하는 방법입니다.

canvas API에서도 지울 때 사용하는 방법이지만 이렇게 되면 모형을 선택하거나 이동할 수 없습니다. 그냥 온전한 그림판의 형태만 띄게 되는 거죠.

 

그림판을 만들면서 참고한 프로젝트는 canva draw와 excalidraw입니다.

두 프로젝트의 공통점은 내가 그린 도형(텍스트 포함)을 자유자재로 선택하고 제어할 수 있으며, 문제없이 지울 수도 되어야 합니다. 

그리고 내가 그린 도형에 대한 데이터를 저장할 수 없다면, 추후 리팩토링도 불가능할 거라 판단되어, 도형을 지울 땐 destination-out이 아닌 다른 방법으로 지워야만 합니다.

그게 뭐냐면...

 

프로젝트 구조

그전에 프로젝트를 어떤 구조로 만들었는지 잠깐 복기 형식으로 적도록 하겠습니다.

어차피 이 블로그도 제가 공부한 것들을 복기 형식으로 적는 거라, 딱히 불만은 없는 걸로 하겠습니다.

기본 골자는 FSD(Feature-Sliced Design) 아키텍처입니다. 본래 fsd는 대형 프로젝트에 적합하다고 알려져 있고, 면접에서도 그렇게 대답하지만 공식 레퍼런스에선


FSD는 다음 조건에 해당하면 도입할 수 있습니다:

  • 프런트엔드(웹, 모바일, 데스크톱 등)를 개발하고 있고
  • 라이브러리가 아닌 애플리케이션을 개발하고 있다면

언어, UI 프레임워크, 상태 관리 도구에 대한 제약은 없습니다.
Monorepo 환경에서도 사용 가능하며, 프로젝트 구조를 나눠 점진적으로 적용할 수 있습니다.


라고 나와있네요. 즉, 프런트엔드로 개발하면서, 라이브러리가 아니라면 그냥 써도 된다는 겁니다.

fsd에 관한 자세한 글은 아래를 참조해 주세요

기능 분할 설계(Feature-Sliced Design, FSD)란

 

기능 분할 설계(Feature-Sliced Design, FSD)란

Feature-Sliced Design(FSD)는 프론트엔드 애플리케이션의 구조를 잡는 아키텍처 방법론입니다. FSD는 이름 그대로 기능 단위로 분할하는 것에 초점이 맞춰져 있으며 현재 많은 주목을 받는 아키텍처 중

weaklion1.tistory.com

 

fsd에 관해 좀 더 레퍼런스를 찾다 보면 알겠지만, 명확한 정의는 없습니다. 

명확한 답이 없다는 건 자유롭기도 하지만, 구조를 벗어나기도 쉽다는 뜻입니다.

가령 feature라는 단어의 뜻만 보고 특정한 entity의 crud만 집어넣어야 한다라고 해석할 수도 있는 거죠.

이 부분은 사실 fsd 홈페이지에서도 명확하게 정의가 돼있지 않아 난감했는데, 최근에 정의된 게 있더라고요.


Entity 간 관계

원칙적으로 Slice끼리는 서로 모르면 좋습니다.
하지만 현실적으로 다른 Entity를 포함하거나 상호작용하는 경우가 있습니다.
이때는 로직을 상위 Layer(Feature/Page)로 올려 처리하세요.

만약 한 Entity 데이터에 다른 Entity가 포함된다면,
@x 표기를 사용해 교차 Public API로 연결을 명시적으로 드러내세요.

Layer | Feature-Sliced Design


Entity 간에 관계에서도 다른 entity를 포함하거나 상호작용을 한다면 상위 layer에서 처리하라고 레퍼런스에선 이야기를 하고 있었습니다.

이를 토대로 폴더 구조를 만들었습니다.

 

이렇게 보니 굳이 fsd로 할 필요가 없긴 합니다. 그냥 편한 대로 하면 되겠습니다

그래도 어쨌든 저는 fsd라는 아키텍처에 대해 좀 더 공부하고 싶었고, 좋은 계기가 되긴 했습니다.

 

특이한 점은 entites에 entity가 하나에, features에 canvas와 관련된 기능만 있다는 점입니다.

엥? 아까 네가 말한 거랑 다른데?라고 할 수 있는데 맞습니다.

처음엔 entites에 line과 text, 그리고 eraser 총 3개의 엔티티가 있었습니다.

그리고 3개의 엔티티가 상호작용하는 걸 features에서 관리했는데

ui만 다르고, 내용은 비슷한  컴포넌트를 나눌 필요가 없다고 생각해서 shape라는 엔티티 안에 ui만 따로 해서

관리하는 걸로 결정했습니다.

features에도 마찬가지로 shape와 엔티티의 기능들을 처리하고 있지만

canvas라는 거대한 종이 안에서 처리되는 기능들이기 때문에 이름을 명시적으로 바꿨습니다.

 

좀 더 자세한 건 기능을 알아볼 때 보도록 하겠습니다.

 

나머지는 딱히 특별한 건 없습니다. 다만 widgets이 없는데, 이 자리엔 canvas가 들어가도 무방합니다.

 

다음엔 어떤 방법으로 도형을 지웠는지, 기능에 대해서 알아볼 건데

그건 이다음 글에 적도록 하겠습니다.

 

 

 

 

 

'react' 카테고리의 다른 글

useImperativeHandle는 무엇인가?  (0) 2025.10.16
[react] setState에 관하여.  (0) 2019.03.24
리액트 router의 activeClassname에 관한 팁.  (0) 2019.02.25