개발2026-02-22

React에서 부모 Flex 방향을 자식에게 전달하는 방법 | data-attribute 패턴

Flexbox의 flex-direction에 따라 자식 노드의 fill 사이징 CSS가 달라지는 문제를, HTML data-attribute로 해결한 실전 사례를 코드와 함께 정리합니다.

React에서 부모 Flex 방향을 자식에게 전달하는 방법 | data-attribute 패턴

웹 에디터에서 Framer 스타일의 사이징 시스템을 구현하면서, 같은 fill 모드라도 부모의 flex-direction에 따라 적용해야 하는 CSS가 완전히 달라지는 문제를 만났다. 이 글에서는 문제의 원인을 분석하고, data-attribute를 활용해 해결한 과정을 코드와 함께 정리한다.

문제 상황: fill 사이징과 Flexbox 축의 관계

fill 사이징이란

fill은 부모의 남은 공간을 채운다는 의미의 사이징 모드다. Framer, Figma 같은 디자인 도구에서 흔히 볼 수 있는 개념으로, CSS에서는 Flexbox의 속성을 조합해 구현해야 한다.

문제는 이걸 CSS로 변환하려면 flex: 1alignSelf: "stretch"어느 쪽을 써야 하는지가 부모의 flex-direction에 따라 달라진다는 점이다.

Flexbox의 main axis와 cross axis

Flexbox에는 main axis(정렬 방향)와 cross axis(교차 방향)라는 두 개의 축이 있다. flex-direction이 바뀌면 두 축의 역할이 뒤바뀐다.

codeColumn Stack (세로 배치):
  main axis  = height (세로)
  cross axis = width  (가로)

Row Stack (가로 배치):
  main axis  = width  (가로)
  cross axis = height (세로)

fill을 CSS로 변환할 때의 규칙은 다음과 같다.

  • main axis에서의 fillflex: 1 — 남은 공간을 비율로 채움
  • cross axis에서의 fillalignSelf: "stretch" — 교차 방향으로 늘림

이를 표로 정리하면 다음과 같다.

사이징 모드 Column Stack (세로) Row Stack (가로)
widthMode: "fill" alignSelf: "stretch" (cross) flex: 1 (main)
heightMode: "fill" flex: 1 (main) alignSelf: "stretch" (cross)

같은 widthMode: "fill"이라도 부모가 column이면 alignSelf: "stretch", rowflex: 1이 된다. 자식 노드가 자기 스타일을 결정하려면 부모의 direction을 반드시 알아야 한다.

해결: data-attribute로 부모 방향을 DOM에 노출

React prop 전달이 불가능한 구조적 이유

일반적인 React 패턴이라면 부모가 자식에게 direction을 prop으로 내려주면 된다. 하지만 이 에디터에서는 적합하지 않았다.

크기를 결정하는 resolveSizeStyle 유틸리티 함수는 React 컴포넌트 트리 바깥에서 독립적으로 동작한다. 노드 데이터와 DOM 정보만으로 스타일을 계산하는 구조이기 때문에, React의 prop 체인에 접근할 수 없다.

Stack 컴포넌트에 data-stack-direction 추가

Stack 컴포넌트가 렌더링할 때 data-stack-direction 속성을 DOM 요소에 남기도록 했다.

tsx// Stack.tsx — 부모 컴포넌트
export default function StackComponent({ node, children }: NodeComponentProps<StackNode>) {
  const direction = node.props.direction ?? "column";

  return (
    <div
      data-component-id={node.id}
      data-stack-direction={direction}  // ← 자식이 읽을  있도록 노출
      style={{ ...cssProps, flexDirection: direction }}
    >
      {children}
    </div>
  );
}

핵심은 data-stack-direction={direction} 한 줄이다. 이 속성은 브라우저 렌더링에 영향을 주지 않지만, 다른 코드에서 부모의 방향 정보를 읽을 수 있게 한다.

자식의 크기 계산 함수에서 부모 방향 읽기

자식의 CSS를 결정하는 resolveSizeStyle에서 부모 DOM 요소의 data-stack-direction을 읽는다.

tsx// resolveSizeStyle.ts — 자식의 크기 계산
const parentEl = document.querySelector(`[data-component-id="${parentNode.id}"]`);
const parentDir = parentEl?.getAttribute("data-stack-direction") as "row" | "column" ?? "column";

// 부모 방향(main/cross axis)에 따라 fill → CSS 변환 분기
if (widthMode === "fill") {
  if (parentDir === "row") {
    style.flex = 1;              // main axis → flex로 남은 공간 채움
  } else {
    style.alignSelf = "stretch"; // cross axis → stretch로 교차 방향 늘림
  }
}

querySelector로 부모 요소를 찾고, getAttribute로 문자열 하나를 읽는 것만으로 축 판별이 끝난다.

getComputedStyle 대신 data-attribute를 선택한 이유

getComputedStyle(parentEl).flexDirection으로도 같은 값을 얻을 수 있다. 그럼에도 data-attribute를 선택한 이유는 두 가지다.

1. 성능: 레이아웃 재계산 없이 값 읽기

getComputedStyle()은 호출 시 브라우저가 레이아웃 재계산(reflow)을 트리거할 수 있는 무거운 API다. 반면 getAttribute()는 DOM 요소에 저장된 문자열을 단순히 읽는 연산으로, 비교할 수 없을 만큼 가볍다.

2. 명시성: 코드 의도가 드러나는 네이밍

data-stack-direction이라는 이름에서 "이 요소는 Stack이고, 방향 정보를 자식에게 제공한다"는 설계 의도가 명확히 드러난다. getComputedStyle로 스타일 값을 우회적으로 읽는 방식보다 코드를 읽는 사람에게 의도를 전달하기 쉽다.

정리: data-attribute 패턴이 유효한 조건

data-attribute를 통해 부모 상태를 자식에서 조회하는 이 패턴은 만능이 아니다. 다음 조건에서 유효하다.

  • React prop 체인 밖에서 부모 정보에 접근해야 할 때
  • 부모의 특정 속성이 자식의 렌더링 로직을 결정할 때
  • getComputedStyle() 대신 가볍고 명시적인 값 전달이 필요할 때

반대로, 모든 로직이 React 컴포넌트 안에서 완결된다면 prop 전달이나 Context API가 더 적절하다. data-attribute는 DOM을 통해 부모 상태를 조회해야 하는 특수한 상황에서 유용한 패턴이다.


Flexbox flex-direction main axis / cross axis data-attribute fill 사이징 getComputedStyle 대안 flex:1 vs alignSelf:stretch