데우스랠리 / 2025.06 ~
데우스랠리 코드젠 아키텍처
참고 자료 · 데우스랠리 데모 영상 보기 ↗
TL;DR
데우스랠리에서 디자이너가 GUI로 편집한 모션을 웹/iOS/Android 핸드오프 코드로 내보내려면, 노드마다 따로 저장된 모션을 코드젠이 읽을 수 있는 하나의 타임라인으로 묶어줘야 했어요. 편집할 때는 노드별로 데이터를 다루는 게 자연스럽지만, 코드를 만들 때는 루트에서 이어지는 전체 노드의 관계와 실행 순서까지 필요했기 때문이에요.
이 차이를 연결하는 변환 계층을 두고 코드젠 직전에만 타임라인 데이터를 만들도록 했어요. 편집 데이터 구조를 코드젠의 입력 형식에 맞춰 바꾸지 않고도 기존 코드컴포넌트 코드젠을 재사용할 수 있게 했어요.
문제 정의 Problem
데우스랠리의 원본 데이터는 각 노드가 자신의 motion과 transition 정보를 갖고 있는 구조라서, 에디터에서 노드를 선택해 값을 바꾸는 흐름에는 잘 맞았어요. 코드젠 쪽에서는 그 데이터로 전체 타임라인을 읽어낼 수 있어야 했는데, 노드마다 흩어진 값을 그대로 넘겨서는 기존 코드젠이 기대하는 형태가 되지 않았어요.
코드를 생성하려면 루트부터 자식 노드들이 어떤 순서와 관계로 움직이는지 살펴야 하고, 개별 노드의 값도 그 흐름에 맞춰 해석해야 했어요. 그렇다고 코드젠에 맞춰 원본 데이터를 바꾸면 노드 단위로 편집하기 좋았던 구조까지 바뀔 수 있어서, 편집 데이터는 유지하면서 전체 타임라인을 만들어줄 방법이 필요했어요.
접근 방식 Approach
루트 노드에서 시작해 자식 관계를 따라가면서 각 노드의 motion과 transition 정보를 모으고, 그 안의 motion value와 easing, 기본 delay와 duration을 코드젠 함수가 읽을 수 있는 형태로 정규화했어요.
다만 zIndex는 한 노드의 값이 형제 노드들과의 관계에도 영향을 주기 때문에, 해당 노드의 값만 옮기는 속성 매핑과는 별도의 규칙으로 다뤘어요. 특정 시점에 zIndex를 가진 노드가 있다면, 그 노드를 기준으로 형제 노드들의 관계와 zIndex 값을 함께 계산하도록 했어요.
핵심 결정 Decision
단일 노드의 모션만 코드로 만든다면 프리뷰용 타임라인 데이터를 그대로 직렬화하는 방법도 가능했을 거예요. 다만 데우스랠리에는 전체 노드 관계를 포함한 코드젠이 필요했기 때문에, 루트부터 타임라인을 다시 구성하고 그 결과를 기존 코드젠 함수에 넘길 수 있는 DST로 만드는 쪽을 선택했어요.
DST는 AST처럼 코드젠에 필요한 정보를 담는 중간 구조로, 에디터가 쓰는 원본 데이터는 그대로 두고 코드를 생성하기 직전에만 이 형태로 변환하도록 했어요.
그만큼 변환 로직이 복잡해지는 건 감수해야 했어요. 특히 zIndex처럼 다른 노드까지 함께 계산하는 규칙을 따로 관리해야 했지만, 그 계산을 변환 계층에서 맡으면 편집하기 좋은 구조를 유지하면서도 기존 코드젠이 기대하는 입력을 만들어줄 수 있었어요.
해결 결과 Result
변환한 DST를 기존 코드컴포넌트 코드젠에 연결하면서, 디자이너가 GUI에서 편집한 모션을 웹/iOS/Android 핸드오프 코드로 이어갈 수 있게 됐어요. 에디터는 노드 중심으로 데이터를 다루고 코드젠은 전체 타임라인을 읽도록 나눠, 편집 구조를 유지한 채 기존 코드젠을 데우스랠리에서도 재사용했어요.
배운 점 Learning
코드젠을 만들 때는 출력 문자열을 어떻게 만들지도 중요하지만, 그보다 먼저 출력 함수가 읽을 수 있는 형태로 데이터를 준비해야 한다는 걸 배웠어요. 에디터와 코드젠이 같은 모션을 다뤄도 필요한 구조는 달랐고, 한쪽을 다른 쪽에 억지로 맞추기보다 각각의 구조를 유지한 채 변환하는 역할을 분명히 두는 게 이 작업에는 더 잘 맞았어요.
이 작업을 다시 한다면 Next
다시 비슷한 구조를 만든다면 DST 명세와 예외 조건의 동작을 문서나 테스트로 먼저 정리해두고 시작하고 싶어요. zIndex처럼 다른 노드의 값까지 함께 계산해야 하는 속성은 구현하면서 규칙을 정하다 보면 코드 여러 곳에 흩어지기 쉬운데, 어떤 관계를 살펴야 하고 어떤 값까지 함께 계산해야 하는지를 미리 적어두면 변환 로직을 더 일관되게 만들 수 있을 것 같아요.