C.W.K.
Stream
Lesson 01 of 04 · published

Flexbox mental model: 한 번에 한 축

~12 min · flexbox, main-axis, cross-axis, flex-direction, flex-wrap

Level 0Markup Novice
0 XP0/34 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Flexbox 는 1 차원이야. 신경 쓰는 축 고르면 Flexbox 가 그 축 따라 모든 걸 행동하게 만들어."

"1 차원" 이 실제로 뭘 뜻해?

Flexbox 가 자식을 한 번에 단일 축 따라 배치 — row 또는 column. 자식이 추가 라인으로 wrap 가능하지만, 개념적으로 너는 항상 "항목의 줄" 을 생각해. Grid 와 비교해 — Grid 는 row 와 column 을 동시에 생각.

이게 mental model 에 중요해: Flexbox 적기 전에 layout 이 근본적으로 row 인지 column 인지 결정. 그걸 깔끔하게 답할 수 있으면 Flexbox 가 맞는 도구. Row 와 column 둘 다 정밀 제어 한 번에 필요하면 Grid 원하는 거.

두 축 (그리고 그 이름이 중요한 이유)

Flexbox 가 방향이 아니라 축으로 정렬 이름 지어:

  • Main 축 — 자식이 흐르는 축. flex-direction 으로 결정.
  • Cross 축 — main 축에 수직.

기본 flex-direction: row → main 은 수평 (LTR 의 left-to-right), cross 는 수직. flex-direction: column 설정 → main 이 수직, cross 가 수평. Property 이름은 안 바뀜; 그 효과적 방향만 바뀜.

이게 justify-content (main 에 작용) 와 align-items (cross 에 작용) 가 row 와 column flex 컨테이너에서 똑같이 작동하는 이유 — 가리키는 축이 자동으로 swap.

flex-direction

  • row — 기본. Main 축 = inline 방향 (LTR: left-to-right).
  • row-reverse — main 축 뒤집힘. 항목이 right-to-left (LTR 에서) 흐름.
  • column — main 축 = block 방향 (top-to-bottom).
  • column-reverse — main 축 뒤집힘. 항목이 bottom-to-top 흐름.

-reverse 변형이 유용한 경우: "최신 먼저" 채팅 리스트 (column-reverse 가 최신을 source 순서 바닥에 유지하지만 시각적으로 위), 또는 명시적 reverse 필요한 RTL 인식 layout.

Wrap: flex-wrap

기본적으로 flex 항목이 컨테이너 overflow 해도 한 줄에 fit 시키려 함. flex-wrap: wrap 이 fit 안 될 때 여러 줄로 wrap 허용:

flex-flow 약자

flex-flow: row wrapflex-directionflex-wrap 을 한 선언에 설정. 둘 다 쓸 때 편리.

Gap: 모던 spacing property

Flex 컨테이너의 gap: 1rem 이 모든 자식 페어 사이에 1rem 공간 넣어. row-gapcolumn-gap 이 두 축 독립적으로 제어. 옛 margin 기반 spacing 패턴 (컨테이너의 음수 margin, 마지막 빼고 모든 자식의 margin) 을 완전히 대체.

Flex spacing 에 gap 써. 개별 element offset 에 margin 예약. gap 이 margin collapse 안 일으키고, 어느 자식이 첫이든 마지막이든 무관하게 작동하고, insert/remove 에도 맞음 유지. CSS 두 줄이 dozen 줄을 대체.

"옛 브라우저는?" — flex 의 gap 이 2021 년 말 이후 출시된 모든 브라우저에서 지원. 2026 년엔 그 질문 안 나옴.

결정 트리: Flexbox 또는 Grid?

  • 버튼 행, navbar 항목, chip — Flexbox. 1 차원. Wrap 허용.
  • 카드 stack, 섹션 가진 사이드바 — Flexbox column.
  • Header 위, main 가운데, footer — Flexbox column, main 은 flex: 1.
  • 각 row 가 특정 column 수 가진 사진 grid — Grid.
  • 특정 위치에 사이드바, main, header, footer 가진 매거진 스타일 layout — Grid (template-areas 와 함께).
  • 남은 공간 공유하는 동등 너비 column — 각자 flex: 1 가진 Flexbox.
  • 특정 너비의 column (예: 240px 사이드바 + 유연한 main) — 둘 다 작동; Grid grid-template-columns: 240px 1fr 이 가장 타이트.

Flexbox 가 안 하는 것 (그리고 왜 OK)

Flexbox 는 항목을 두 축에 동시에 정밀하게 정렬 안 함. 같은 컨테이너의 항목 A 가 row 2, column 3 에 있고 항목 B 가 row 1, column 1 에 있길 원하면, 그건 Grid. Flexbox 가 source 순서로 main 축 따라 항목 배치; cross 축 정렬은 전체 줄에 대한 거지 개별 위치가 아냐.

Flexbox 는 또 Grid 처럼 명시적 row/column "트랙" 가지지 않아. 항목이 overflow 시 wrap, 하지만 "이 항목이 row 3 에 간다" 라고 말할 수 없어. 그걸 원하는 자신을 발견하면 Grid 원하는 거.

피파의 노트

피파의 채팅 패널이 Flexbox column: 가운데에 flex: 1 가진 메시지 리스트 (사용 가능한 height 채우게 자라고, content overflow 시 스크롤), 바닥에 composer (auto height), 위에 header. 자식 셋, 컨테이너 하나, 방향 하나. 대화 사이드바가 대화 행들 가진 Flexbox column. 모든 수평 배치 (action 버튼 행, tag chip, council 의 brain picker) 가 gap 가진 Flexbox row. WebUI 의 거의 모든 UI 표면이 flex 트리 — Grid 는 2 차원 정밀이 제 값 하는 페이지 레벨 layout 몇 개에 예약.

Code

flex-direction 세 컨텍스트·css
/* 기본 flexbox: row */
.nav {
  display: flex;
  gap: 1rem;
  /* main 축: 수평
     cross 축: 수직
     항목이 left-to-right 흐름 */
}

/* Flex column: 수직 stack */
.sidebar {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  /* main 축: 수직
     cross 축: 수평
     항목이 top-to-bottom stack */
}

/* 채팅 메시지용 reverse (source 의 바닥에 최신) */
.chat-history {
  display: flex;
  flex-direction: column-reverse;
  /* Source 순서 항목이 시각적으로 reverse 로 나타남.
     JS 가 새 메시지 append 하지만 위에 보이게 하고 싶을 때 유용. */
}
Wrap + gap·css
/* 카드 행 wrap */
.card-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}
.card-row > .card {
  flex: 1 1 240px;     /* grow, shrink, basis 240px */
  /* 각 카드가 240px 되고 싶지만, 행 채우게 자랄 수 있음.
     카드 4 개가 fit 안 되면, 새 줄로 wrap 하고 각 카드가
     행 너비 채우게 stretch. */
}

/* flex-flow 약자 */
.card-row {
  display: flex;
  flex-flow: row wrap;  /* flex-direction + flex-wrap */
  gap: 1rem;
}

/* row 와 column 분리 제어 가진 gap */
.gallery {
  display: flex;
  flex-flow: row wrap;
  row-gap: 2rem;        /* wrap 됐을 때 row 사이 */
  column-gap: 1rem;     /* 같은 row 의 sibling 사이 */
}
축으로 결정되는 실제 layout·css
/* 코드 안의 mental model: row vs column 결정 */

/* 버튼 그룹 → flex row */
.btn-group {
  display: flex;
  gap: 0.5rem;
}

/* 폼의 수직 stack → flex column */
.form-fields {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Sticky footer 페이지 layout → flex column */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin: 0;
}
main {
  flex: 1;             /* 남은 height 채우게 자람 */
}

/* Wrap 카드 가진 masonry-ish grid → flex row + wrap */
.gallery {
  display: flex;
  flex-flow: row wrap;
  gap: 1rem;
}
.gallery > * {
  flex: 1 1 200px;     /* 모든 카드가 200px 에서 flex */
}

External links

Exercise

Sticky-footer 페이지 layout 만들기: <body> 가 min-height: 100vh 가진 flex column, <main> 이 flex: 1, <header><footer> 가 기본 크기. DevTools 에서 확인 (viewport 리사이즈, main 에 content 추가, footer 행동 확인). 그러고 나서 5 항목 가진 navbar 를 gap: 1rem 가진 flex row 와 margin-right: auto 로 나머지 항목을 오른쪽으로 미는 로고로 변환.
Hint
Flex 컨테이너 안 margin: auto 가 main 축 따라 사용 가능한 공간 소비 — '나머지 오른쪽으로 밀기' 패턴에 완벽. main 의 flex: 1 이 footer 를 sticky 하게 만드는 거.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.