Framer Code Component 기반 디자인 QA 프로세스

마지막 수정일 · 2024. 10. 14.

TL;DR

동적 레이아웃(Masonry)은 시안으로 만들 수 있는 케이스가 아니어서 Figma 기반 QA가 구조적으로 작동하지 않았다. 그래서 순서를 뒤집었다.

  • 기존: 디자이너가 시안 → 개발자가 구현 → 디자이너가 결과물 스크린샷으로 QA
  • 변경: 프론트가 Framer Code Component로 동작하는 컴포넌트를 먼저 제작 → 디자이너가 그 위에서 시안 작업 → 실제로 움직이는 UI + 실제 API 데이터로 QA

결과적으로 QA 커뮤니케이션 사이클이 약 40% 단축됐고, props·variant·spacing이 디자인 시스템 기준으로 통일됐다.

배경이 되는 Masonry 구현은 가상화 기반 Masonry 레이아웃 직접 구현에 정리해뒀다.



문제상황

Figma + Storybook 조합으로 일하고 있었는데, 홈 화면 Masonry가 붙으면서 이 구조가 깨졌다.

Figma로는 Masonry를 못 그린다

Figma의 Auto Layout은 고정된 열 구조다. Masonry처럼 아이템 높이에 따라 배치가 결정되는 레이아웃은 표현이 안 되고, 다중 column을 만들려면 결국 손으로 하나씩 배치하는 반복작업이 된다. 그래서 시안은 Masonry 대신 Grid 기반으로 근사해서 그려졌다.

문제는 이게 단순한 근사가 아니라는 점이었다. 우리가 풀려던 문제 자체가 "높이가 제각각인 아이템을 어떻게 배치할 것인가" 였는데, 시안은 그 문제가 존재하지 않는 상태를 그리고 있었다. 검증해야 할 지점이 시안에서 사라진 것이다.

Dummy Data로는 검증이 안 된다

두 번째는 데이터였다. 시안에 들어가는 이미지는 디자이너가 고른 몇 장이라 비율이 고르게 예쁘다. 그런데 실제 피드에 들어오는 건 인스타그램/유튜브에서 긁어온 콘텐츠라서 비율 분포가 훨씬 험하다. 세로로 아주 긴 9:16 비디오가 연속으로 들어오는 케이스 같은 게 실사용에서는 흔한데, 시안에는 없었다.

데이터 다양성 부족으로 실제 사례 기반 테스트가 불가능했다.


여기에 팀 상황이 겹쳤다. 웹/앱 개발자마다 스타일과 인터랙션 구현 방식이 달라서, 같은 시안을 줘도 결과가 달랐다. 디자이너는 각각을 스크린샷과 빌드로 확인하고 코멘트를 남겼고, QA 시간이 과도하게 늘어났다.



해결방안 — 순서를 뒤집기

정리하면 문제는 "QA를 대충 한다"가 아니라 "디자이너가 실제 동작을 볼 방법이 없다" 였다. 사람 문제가 아니라 협업 구조 문제였다.

그래서 Framer를 도입하고 만드는 순서를 바꿨다.

Framer를 고른 이유는 프로토타이핑 툴이라서가 아니라 Code Component를 쓸 수 있어서였다. 실제 React 코드가 캔버스 위에서 그대로 돌아간다.

  • 실제 Masonry 레이아웃을 구현 그대로 올릴 수 있다
  • Code Component 기반이라 props로 구조를 열어둘 수 있다
  • 실제 API를 붙여서 다양한 데이터로 QA할 수 있다

프론트가 먼저 만든다

프론트엔드가 구현에 들어가기 전에, 동작하는 컴포넌트를 Framer Code Component로 먼저 만들었다.

tsx
import * as React from "react"
import { Frame, addPropertyControls, ControlType } from "framer"

export default function Masonry(props) {
    const { columnCount, gap, items, background } = props

    const columns = React.useMemo(() => {
        const cols = Array.from({ length: columnCount }, () => [])
        const heights = Array.from({ length: columnCount }, () => 0)

        items.forEach((item, index) => {
            const ratio = item.aspectRatio || 1
            const height = 100 / ratio // width 고정 시 높이 계산

            const minIndex = heights.indexOf(Math.min(...heights))
            cols[minIndex].push({ ...item, height })
            heights[minIndex] += height + gap
        })

        return cols
    }, [items, columnCount, gap])

    const columnWidth = `calc(${100 / columnCount}% - ${gap}px)`
    // ...생략
}


중요한 건 addPropertyControls다. columnCount, gap 같은 값을 Framer 우측 패널의 컨트롤로 노출해두면, 디자이너가 코드를 몰라도 값을 바꿔가며 결과를 즉시 볼 수 있다.

이게 만들어지는 순간 대화의 성격이 바뀌었다.

  • 전: "column 간격이 좀 넓은 것 같아요" → 개발자가 고쳐서 빌드 → 다시 확인 (사이클 1회)
  • 후: 디자이너가 gap 값을 직접 돌려보고 "gap 8이 제일 낫다" 고 확정해서 전달 (사이클 0회)

그리고 이 컴포넌트의 배치 로직은 실제 구현과 같은 그리디 알고리즘이다. 시안이 곧 구현과 같은 레이아웃이 되니까, 디자이너가 시안을 만드는 시간 자체도 줄었다. Figma에서 다중 column을 손으로 배치하던 반복작업이 사라졌기 때문이다.


실제 API를 붙인다

Dummy Data 문제는 Framer의 Fetch로 풀었다. 실제 API 엔드포인트를 붙이고 응답 필드를 컴포넌트에 매핑하면, 운영 데이터 그대로 캔버스 위에서 렌더된다.

이 시점부터 QA의 성격이 달라졌다.

  • 예쁜 더미가 아니라 실제로 들어오는 비율 분포로 레이아웃을 본다
  • 9:16 비디오가 연속으로 들어오는 것 같은 극단 케이스가 자연스럽게 노출된다
  • 데이터를 새로고침하면 매번 다른 조합이 나오므로, 사실상 랜덤 스트레스 테스트가 된다

디자이너가 "이 케이스에서 이상해요"라고 말할 때 그 케이스가 실재하는 데이터가 됐다는 게 제일 컸다. 이전에는 개발자가 "그런 경우가 실제로 있나요?"를 되묻는 데서 사이클이 한 번 더 돌았다.



성과

항목 개선 전 개선 후
QA 커뮤니케이션 사이클 기준 약 40% 단축
동적 레이아웃 검증 시안으로 표현 불가 실제 동작 + 실제 데이터로 검증
props · variant · spacing 구현자마다 상이 디자인 시스템 기준으로 통일
디자이너의 QA 참여 스크린샷 코멘트 값을 직접 조작하며 확정

props·variant·spacing이 통일된 건 부수효과가 아니라 구조적 결과였다. Code Component로 먼저 만들면 컴포넌트의 인터페이스가 디자인 단계에서 이미 확정되기 때문이다. 디자이너가 만지는 컨트롤이 곧 구현의 props라서, 둘이 어긋날 수가 없다.



회고

이 건에서 배운 건 느린 것의 원인을 사람에서 찾지 않는 것이었다.

처음 문제 인식은 "QA가 너무 오래 걸린다"였고, 그 상태로는 "더 꼼꼼히 보자" 같은 결론밖에 안 나온다. 근데 쪼개 보니 원인은 디자이너가 동적 레이아웃의 실제 동작을 볼 수 있는 수단이 아예 없다는 구조적 결핍이었다. 수단이 없는 상태에서 노력을 더 넣어봐야 사이클만 늘어난다.

그리고 이런 종류의 문제는 순서를 바꾸는 것만으로 풀리는 경우가 꽤 있다는 것도 같이 배웠다. 새 도구를 도입했다기보다, 원래 마지막에 하던 일(구현)을 앞으로 당겼을 뿐이다.



한계

  1. Code Component 유지 비용
    Framer용 컴포넌트와 실제 구현이 각각 존재하므로, 구현이 바뀌면 Framer 쪽도 같이 갱신해야 한다. 자동 동기화가 없어서 방치하면 시안과 구현이 다시 벌어진다
  2. 커버 범위
    Masonry처럼 레이아웃이 곧 문제인 컴포넌트에는 효과가 컸지만, 단순한 정적 컴포넌트에는 굳이 Framer를 거칠 이유가 없다. 어디까지를 이 프로세스에 태울지 기준을 명문화하지 못했다
  3. 실제 API 노출
    QA용으로 운영 API를 붙이는 구조라, 인증이 필요한 엔드포인트나 민감한 데이터로는 확장하기 어렵다. 별도의 QA용 샘플 엔드포인트를 두는 편이 맞다