반응형 레이아웃 만들기 — Next.js + Mantine 실전 예제

웹 서비스의 사용자는 데스크톱, 태블릿, 모바일 등 다양한 화면 크기에서 페이지를 사용합니다.
따라서 하나의 화면이 다양한 디바이스에서 자연스럽게 동작하도록 만드는 반응형 설계는 필수입니다.

이번 글에서는 자산앱 프로젝트의 포트폴리오 상세 화면을 예시로,
Mantine UI + Next.js 기반에서 반응형 레이아웃을 어떻게 구성했는지 실제 화면의 캡처와 코드를 중심으로 정리해봤습니다.


🔍 이번 글에서 다룰 내용

  • 왜 반응형 레이아웃이 중요한가?
  • Mantine UI의 반응형 도구(hiddenFrom, visibleFrom, Grid.Col span) 실제 활용
  • 모바일/태블릿/데스크톱에서 UI가 어떻게 달라지는지 설계 방식
  • PortfolioDetail 화면에서 사용한 반응형 패턴 실전 예제
  • CSS 미디어쿼리를 직접 쓰지 않고도 반응형을 자연스럽게 구성하는 팁

1. 반응형이 필요한 이유

포트폴리오 관리 앱과 같은 데이터 중심 UI는 PC에서는 충분한 공간을 통해 많은 요소를 보여줄 수 있지만,
모바일에서는 단일 컬럼 UI로 단순화되어야 가독성과 조작성이 확보됩니다.

즉, 같은 데이터라도 화면에 따라 다르게 배치하는 것이 사용자 경험을 좌우합니다.

Mantine은 다음과 같은 기능으로 반응형을 쉽게 지원합니다:

기능설명
hiddenFrom, visibleFrom특정 해상도 구간에서 DOM 자체를 숨김/표시
Grid.Col span={{ base, md }}구간별 컬럼 너비 지정
group wrap="wrap"작은 화면에서 요소가 자동으로 다음 줄로 내려감
px={{ base, md }}해상도마다 패딩/마진 값을 다르게

2. 실제 구현: PortfolioDetail 화면 반응형 구조

아래는 실제 포트폴리오 상세 화면의 레이아웃 코드 일부입니다.

이 화면은 다음과 같은 특징을 갖습니다.

✔ 모바일

  • Dashboard를 가장 위에 배치
  • 1컬럼 UI
  • 버튼 문구 축소(아이콘 위주)

✔ 데스크톱

데스크톱 화면 예시
  • Dashboard를 왼쪽 고정
  • 오른쪽 영역에서 Tabs 렌더링
  • 좌우 넓은 여백 활용

3. 헤더 영역의 반응형 처리

👉 핵심 전략

  • 작은 화면에서는 버튼 라벨 숨기기
  • 버튼 그룹은 자동 줄바꿈으로 UI 붕괴 방지
<Group justify="space-between" align="center" wrap="wrap" gap="md">
  <Group gap="sm" align="center">
    <Tooltip label="메인화면으로">
      <ActionIcon size="xl" variant="subtle">
        <IconArrowLeft size={28} />
      </ActionIcon>
    </Tooltip>

    <Title order={1} style={{ minWidth: 0, wordBreak: 'break-word' }}>
      {portfolioName}
    </Title>
  </Group>

  <Group gap="xs" wrap="wrap">
    <Button size="sm" variant="light" leftSection={<IconEdit size={16} />}>
      <Text hiddenFrom="sm">수정</Text>
      <Text visibleFrom="sm">포트폴리오 수정</Text>
    </Button>

    <Button size="sm" variant="outline" color="red" leftSection={<IconTrash size={16} />}>
      <Text hiddenFrom="sm">삭제</Text>
      <Text visibleFrom="sm">포트폴리오 삭제</Text>
    </Button>
  </Group>
</Group>

4. Dashboard + Tabs 메인 레이아웃

Mantine Grid를 이용해 아래와 같이 구성했습니다:

  • 모바일: Dashboard → Tabs 순서 (1컬럼)
  • 데스크톱: 5:7 비율의 2컬럼
<Grid mb="xl" gutter={{ base: 'sm', sm: 'md', lg: 'lg' }}>
  <Grid.Col span={{ base: 12, md: 5 }}>
    <DashboardCard />
  </Grid.Col>

  <Grid.Col span={{ base: 12, md: 7 }}>
    <Tabs />
  </Grid.Col>
</Grid>

💡 포인트

  • span={{ base: 12, md: 5 }} → 제일 유용한 반응형 패턴
  • gutter도 화면 크기별로 다르게 지정하여 시각적 간격 최적화

5. Dashboard 내부 반응형 구조

Dashboard는 모바일에서 가로 정렬,
데스크톱에서는 세로 정렬로 바뀝니다.

<Box hiddenFrom="md">
  <Group align="flex-start" gap="md" wrap="nowrap">
    <Stack style={{ flex: 1 }}>
      {/* 요약 정보들 */}
    </Stack>

    <DonutChart size={160} />
  </Group>
</Box>

<Box visibleFrom="md">
  <DonutChart size={250} />
</Box>

💡 디자인 팁

  • 모바일에서는 차트를 줄이고 정보 중심 UI로
  • 데스크톱에서는 차트 크기를 넉넉하게

6. 모바일 버튼 UX: 텍스트 숨김 패턴

Mantine은 아래 두 줄로 모바일/데스크톱 전환을 매우 쉽게 만듭니다.

<Text hiddenFrom="sm">추가</Text>
<Text visibleFrom="sm">자산 추가</Text>

아이콘 + 짧은 라벨 조합은 대부분의 모바일 UI에서 좋은 UX를 제공합니다.


7. 반응형 설계 실전 팁 정리

✔ 모바일 우선 설계가 훨씬 단순해진다

복잡한 데스크톱 UI를 먼저 만들면 모바일 대응이 어렵습니다.

✔ hiddenFrom/visibleFrom으로 DOM 자체를 분리하라

CSS 조작보다 유지보수성이 높고, 성능에도 불리하지 않습니다.

✔ Grid는 복잡한 화면에서 반드시 사용

레이아웃 무너짐 없이 안정적으로 구성됩니다.

✔ Group + wrap은 모바일 UI의 무적 조합

버튼이 줄바꿈되며 레이아웃이 깨지지 않음.


📚 참고 (References)

댓글 남기기