데우스랠리 / 2025.06 ~
데우스랠리 코드젠 아키텍처
TL;DR
데우스랠리 코드젠은 노드별로 흩어져 있는 편집 데이터를 루트 노드 기준의 타임라인 DST로 재구성하고, 기존 코드컴포넌트 코드젠 자산을 데우스랠리로 확장한 작업이에요. DST는 AST처럼 코드젠 함수에 바로 넘길 수 있는 중간 구조예요. 이 DST를 만들면 웹/iOS/Android 핸드오프 코드 생성 흐름에 연결할 수 있었어요.
문제 정의 Problem
데우스랠리의 원본 데이터는 노드마다 자기 모션 정보를 가진 객체들의 모음에 가까웠어요. 하지만 개별 노드의 데이터 조각을 그대로 출력하는 방식으로는 코드젠을 만들 수 없었어요. 전체 모션 흐름을 코드로 만들려면 루트 노드를 기준으로 자식 노드를 순회하면서 각 노드의 motion/transition 정보를 모아 하나의 타임라인 구조로 재구성해야 했어요. 편집 도구의 데이터 모델과 코드젠의 데이터 모델이 달랐기 때문에 그 사이를 이어주는 변환 계층이 필요했어요.
접근 방식 Approach
루트 노드를 기준으로 전체 자식 관계를 순회하고, 각 노드의 motion과 transition 정보를 코드젠용 타임라인 DST로 정규화하는 구조를 잡았어요. 노드마다 흩어져 있던 편집 데이터를 코드젠 함수가 이해할 수 있는 DST로 바꾸는 변환 계층을 따로 두었어요. 코드젠 입력은 개별 노드가 아니라 전체 타임라인 흐름을 필요로 했기 때문에, 루트 노드에서 시작해 자식 관계를 따라가는 관점을 기준으로 잡았어요. zIndex처럼 자기 자신뿐 아니라 sibling 관계까지 바꾸는 프로퍼티는 단순 property 매핑과 분리해서 다뤘어요.
데우스랠리 원본 데이터는 노드마다 모션 정보가 담긴 구조라서, 코드젠 전에 루트 노드 기준으로 전체 흐름을 다시 구성해야 했어요. 각 노드를 순회하면서 랠리 타임라인 구성에 필요한 easing, motion value, default delay, default duration 같은 값을 수집했어요. 수집한 값은 기존 코드컴포넌트 코드젠 함수가 입력으로 받을 수 있는 DST 형태로 정리했어요. zIndex는 자기 자신에게만 적용되는 값이 아니라 sibling 관계에 영향을 주는 값이라 별도 규칙으로 분리했어요.
특정 시점에 zIndex를 가진 노드가 있다면, 그 노드를 기준으로 sibling 간의 관계와 sibling들의 zIndex 값을 함께 계산했어요.
핵심 결정 Decision
노드별 편집 데이터를 루트 기준 타임라인 DST로 재구성하는 계층을 뒀어요. 전체 노드 관계를 담은 코드젠이 필요해서 루트 노드 기준 타임라인 DST를 생성했어요. 단일 노드 기준 코드젠이라면 프리뷰에 들어가는 타임라인 데이터를 그대로 직렬화하는 단순한 구조를 고를 수 있었어요. 하지만 데우스랠리는 전체 노드의 관계를 포함한 코드젠이 필요했기 때문에, 이 변환 계층을 둘 수밖에 없었어요.
그만큼 변환 로직은 복잡해졌어요. 대신 기존 코드컴포넌트 코드젠 로직에 맞는 DST 입력을 만들었고, 데우스랠리 데이터를 웹/iOS/Android 핸드오프 코드 생성 흐름에 연결했어요.
해결 결과 Result
기존 코드컴포넌트 코드젠 자산을 데우스랠리 데이터 구조에서도 사용할 수 있게 확장했어요. 디자이너가 GUI에서 만든 노드별 모션 데이터를 웹/iOS/Android 핸드오프 코드 생성 흐름에 연결할 수 있는 DST로 정리했어요. 코드젠 함수가 기대하는 입력 구조와 편집 도구의 데이터 구조 사이에 명확한 변환 책임을 둘 수 있었어요.
배운 점 Learning
편집 도구의 데이터 모델과 코드젠의 데이터 모델은 다를 수밖에 없고, 그 사이 변환 책임을 명확히 둬야 한다는 걸 배웠어요. 코드젠에서 중요한 건 출력 문자열을 만드는 일만이 아니라, 출력 함수가 다룰 수 있는 중간 구조로 데이터를 정규화하는 일이었어요.
이 작업을 다시 한다면 Next
다음에 비슷한 코드젠 구조를 만든다면 DST 명세와 edge case의 동작 규칙을 더 먼저 정리하고 싶어요. zIndex처럼 sibling 관계까지 바꾸는 프로퍼티는 단순 property 매핑으로 다루기 어려워서, 구현 전에 변환 규칙을 먼저 명세화하는 게 필요하다고 느꼈어요.