Navigation

4. 코드로 옮기기

읽은 화면을 코드로 옮길 때 저장소 컴포넌트를 먼저 씁니다. get_design_context가 돌려준 레이어 구조, 절대 좌표, 임시 에셋 URL은 옮기지 않고 의도만 CSS와 컴포넌트로 다시 씁니다.

4.1 새 마크업보다 저장소 컴포넌트를 먼저 씁니다

디자인 파일의 컴포넌트 정리 상태와 무관하게 화면이 저장소의 동작, 상태, 접근성을 물려받습니다.

Figma 레이어가 컴포넌트로 정리돼 있든 아니든, 화면에 보이는 표, 탭, 버튼은 대부분 저장소에 이미 있습니다. 요소마다 아래 차례로 대응물을 찾고, 대응된 요소는 스크린샷의 모양에 맞춰 설정만 합니다.

  1. 저장소의 ui, widget 컴포넌트
  2. 프로젝트가 쓰는 UI 라이브러리 컴포넌트. @mui/material의 Tabs, Pagination, TextField
  3. 둘 다 없을 때만 새 마크업

모양이 조금 다를 때

차이처리
간격, 색처럼 컴포넌트가 여는 값프롭이나 클래스 주입 지점으로 맞춥니다
컴포넌트가 열지 않는 내부 모양컴포넌트를 복제하지 않고 차이를 보고하거나 컴포넌트 쪽 변경을 제안합니다
같은 차이가 여러 화면에서 반복됨컴포넌트에 변형을 추가하자고 제안합니다

get_code_connect_map을 화면 프레임에 한 번 부르면 이미 매핑된 컴포넌트를 싸게 알 수 있고, 응답이 비어 있어도 이 차례는 같습니다. 대응된 요소에는 get_design_context를 부르지 않습니다. 새 마크업을 만들었으면 그 요소와 이유를 보고의 대응표에 적습니다.

get_design_context가 준 div 격자를 표로 씁니다.

<div className="flex flex-col">
	<div className="flex">
		<div className="w-[60px]">번호</div>
		<div className="w-[270px]">상품명</div>
	</div>
	{products.map((product) => (
		<div className="flex" key={product.id}>
			<div className="w-[60px]">{product.id}</div>
			<div className="w-[270px]">{product.name}</div>
		</div>
	))}
</div>

저장소 표 컴포넌트에 컬럼과 행을 넘깁니다.

<UiTable columns={productColumns} rows={responseProductListSuspense.data.items} />

함께 보기

4.2 레이어 구조를 DOM으로 복제하지 않습니다

디자이너가 도형을 쌓은 방식이 래퍼, 절대 좌표, 임의 값 클래스로 코드에 남지 않습니다.

get_design_context 코드는 레이어 트리를 그대로 펼친 결과라, 디자이너가 도형을 쌓은 방식이 DOM에 남습니다. 옮기기 전에 그 묶음이 화면에서 무엇을 하는지 한 문장으로 말하고, 그 뜻을 CSS 선언이나 컴포넌트로 다시 씁니다.

출력에 보이는 것뜻옮기는 법
회전한 선을 감싼 div 여러 겹과 img구분선border, gap
absolute, inset-[…], 좌표쌓은 배치flex, grid 흐름 배치
w-[270px] 같은 임의 값 Tailwind 클래스샘플 크기프로젝트 CSS 클래스로 옮기고 크기는 규칙 2.3를 따릅니다
인라인 svg의 선, 사각형장식 도형border, background
자식 하나만 감싼 래퍼레이어 묶음없앱니다
data-node-id, data-nameFigma 추적용 속성지웁니다

프로젝트가 Tailwind를 쓰지 않으면 출력의 클래스는 한 개도 옮기지 않습니다. Tailwind를 쓰는 프로젝트도 임의 값 클래스는 프로젝트 토큰 클래스로 바꿉니다.

회전한 선과 래퍼, 추적 속성을 그대로 옮깁니다.

<div className="flex gap-[4px] items-center" data-node-id="12:380">
	<p className="font-['Pretendard:SemiBold'] text-[16px]">{product.name}</p>
	<div className="flex h-[10px] items-center justify-center w-0">
		<div className="flex-none rotate-90">
			<div className="h-0 relative w-[10px]">
				<div className="absolute inset-[-1px_0_0_0]">
					<img src={imgLine94} />
				</div>
			</div>
		</div>
	</div>
	<span className="text-[14px]">{product.stock}</span>
</div>

구분선은 border-left 한 줄로 쓰고 래퍼를 걷습니다.

<div className={clsx("pg_products__nameRow")}>
	<p className={clsx("pg_products__name")}>{product.name}</p>
	<span className={clsx("pg_products__stock")}>{product.stock}</span>
</div>
.pg_products__nameRow {
	display: flex;
	gap: var(--app-space-inline);
	align-items: center;
}

.pg_products__stock {
	padding-left: var(--app-space-inline);
	border-left: 1px solid var(--app-color-border);
}

함께 보기

4.3 아이콘과 이미지는 기존 글리프나 내려받은 에셋을 씁니다

만료되는 에셋 URL과 손으로 그린 도형이 코드에 남지 않습니다.

아이콘은 프로젝트 아이콘 세트에서 먼저 찾고, 없으면 Figma 에셋을 내려받아 저장소에 커밋합니다. 스크린샷 URL은 수명이 짧고 get_design_context 에셋 URL은 7일 동안 유효하므로(2026년 9월 관측), 코드에 남기면 배포한 화면에서 그림이 사라집니다.

상황처리
프로젝트 아이콘 세트에 모양이 같은 글리프가 있음그 글리프를 씁니다. 이름만 같고 모양이 다르면 같은 글리프가 아닙니다
같은 글리프가 없음그 노드에 download_assets를 불러 svgAssets 항목을 받아 저장소에 커밋합니다. defaultFormat은 넘기지 않습니다
사진, 상품 이미지처럼 데이터가 주는 그림에셋으로 두지 않고 응답의 URL을 씁니다

아이콘 하나가 필요할 때 get_design_context 대신 download_assets를 부르면 코드 없이 에셋만 옵니다. 모양을 보고 SVG path를 손으로 그리지 않고, 내려받은 SVG의 width, height는 지우지 않습니다.

MCP 에셋 URL을 그대로 코드에 둡니다.

/**
 * 고정 상품 표시 아이콘
 */
export const UiPinIcon = () => {
	return <img src="https://www.figma.com/api/mcp/asset/30e68a16/b2ddc.svg" alt="" />;
};

내려받아 커밋한 에셋을 가져옵니다.

import pinIconUrl from "@/asset/icon/pin.svg";

/**
 * 고정 상품 표시 아이콘
 */
export const UiPinIcon = () => {
	return <img src={pinIconUrl} alt="" />;
};

스크린샷의 모양을 보고 path를 손으로 그립니다.

<svg viewBox="0 0 16 16">
	<path d="M3 4h10l-4 5v4l-2-1V9z" />
</svg>

모양이 같은 기존 글리프를 씁니다.

<UiFilterIcon />