개발 노트/React Native

[React Native] 통합 앱에서 일반 기기와 태블릿 화면을 함께 최적화하는 기준

pposooj 2026. 5. 19. 15:51

React Native 앱을 만들 때 처음에는 일반 스마트폰 세로 화면만 보고 레이아웃을 잡기 쉽습니다. 저도 화면을 정리할 때 가장 먼저 떠올리는 기준은 보통 휴대폰 세로 화면이었습니다. 하지만 통합 앱처럼 여러 프로파일을 하나의 코드베이스에서 운영하면 화면 조건이 생각보다 훨씬 복잡해집니다.

일반 휴대폰 세로 화면뿐 아니라 일반 휴대폰 가로, 태블릿 세로, 태블릿 가로, Fold나 대화면 기기까지 함께 고려해야 하기 때문입니다. 처음에는 단순히 너비를 꽉 채우면 될 것처럼 보이지만, 실제로 정리해보면 화면 최적화는 그렇게 단순하지 않습니다.

화면 최적화는 단순히 width: '100%'를 넣는 문제가 아닙니다. 화면 크기에 따라 콘텐츠 최대 너비를 제한할지, 버튼을 한 줄로 둘지 줄바꿈할지, 리스트와 상세 화면을 나눠 보여줄지, safe area와 키보드 영역을 어떻게 처리할지 정해야 합니다.

이 글에서는 React Native 통합 앱에서 일반 기기와 태블릿 화면을 함께 최적화하는 기준을 정리해보겠습니다. 기존 화면을 크게 바꾸지 않으면서 반응형 기준을 추가할 때 놓치기 쉬운 부분을 중심으로 살펴보겠습니다.

이 글에서 다룰 문제

반응형 기준이 없으면 다음 문제가 자주 생길 수 있습니다.

  • 태블릿에서 콘텐츠가 화면 전체로 늘어나 읽기 어려워진다.
  • 가로 모드에서 버튼과 검색 영역이 겹친다.
  • 작은 화면에서 액션 버튼이 잘리거나 터치하기 어려워진다.
  • safe area를 고려하지 않아 상단이나 하단 영역이 가려진다.
  • 큰 글자 설정에서 카드나 버튼 텍스트가 깨진다.
  • 특정 프로파일만 확인해서 다른 프로파일 화면 회귀를 놓친다.
  • 광고 영역, 검색 키보드, 지도 화면처럼 예외가 많은 화면이 뒤늦게 깨진다.

단일 앱이라면 화면 몇 개를 직접 확인하는 방식으로도 어느 정도 버틸 수 있습니다. 하지만 프로파일이 많아지면 공통 Screen wrapperresponsive hook을 기준으로 잡고, 대표 프로파일 회귀 테스트를 함께 가져가는 편이 더 안전할 것 같습니다.

화면 최적화의 기본 기준

React Native에서 화면 최적화를 설계할 때는 최소한 아래 기준을 나눠보는 것이 좋습니다. 처음에는 화면 너비만 보면 될 것 같지만, 실제로는 방향, 글자 크기, 안전 영역까지 같이 봐야 하는 경우가 많습니다.

기준 설명 예시
화면 너비 compact, medium, expanded 같은 크기 분류 360, 600, 840dp 기준
방향 세로/가로 모드 portrait, landscape
콘텐츠 최대 너비 태블릿에서 본문이 너무 넓어지지 않게 제한 maxWidth: 720
레이아웃 방식 단일 컬럼 또는 split-pane 리스트+상세 동시 표시
액션 배치 버튼 한 줄 또는 줄바꿈 작은 화면에서는 wrap
safe area 노치, 상태바, 하단 제스처 영역 padding inset
font scale 큰 글자 설정 대응 버튼 높이와 줄바꿈

이 중에서 fontScale과 가로 모드는 특히 놓치기 쉬운 부분 입니다. 세로 화면에서 예쁘게 보이는 카드나 버튼도 가로 모드와 큰 글자 설정이 겹치면 금방 깨질 수 있습니다.

responsive metrics를 먼저 만들기

화면마다 직접 Dimensions.get('window').width를 비교하면 기준이 화면 곳곳에 흩어집니다. 처음에는 빠르게 처리할 수 있지만, 나중에 기준을 바꾸려고 하면 어디를 수정해야 하는지 찾기 어려워질 수 있습니다.

그래서 공통 responsive metrics를 만드는 방식이 좋습니다. 

export type WindowSizeClass = 'compact' | 'medium' | 'expanded';
export type Orientation = 'portrait' | 'landscape';

export type ResponsiveMetrics = {
  width: number;
  height: number;
  safeWidth: number;
  orientation: Orientation;
  sizeClass: WindowSizeClass;
  contentMaxWidth: number;
  shouldUseSplitPane: boolean;
  shouldWrapActions: boolean;
};

export function getWindowSizeClass(width: number): WindowSizeClass {
  if (width >= 840) return 'expanded';
  if (width >= 600) return 'medium';
  return 'compact';
}

export function getResponsiveMetrics(params: {
  width: number;
  height: number;
  fontScale: number;
}): ResponsiveMetrics {
  const {width, height, fontScale} = params;
  const orientation = width > height ? 'landscape' : 'portrait';
  const sizeClass = getWindowSizeClass(width);
  const contentMaxWidth = sizeClass === 'expanded' ? 960 : 720;
  const safeWidth = Math.min(width, contentMaxWidth);

  return {
    width,
    height,
    safeWidth,
    orientation,
    sizeClass,
    contentMaxWidth,
    shouldUseSplitPane: sizeClass === 'expanded' && orientation === 'landscape',
    shouldWrapActions: safeWidth < 360 || fontScale >= 1.3,
  };
}

이렇게 metrics를 만들면 화면 컴포넌트는 숫자 비교를 직접 하지 않아도 됩니다. 대신 shouldUseSplitPane, shouldWrapActions처럼 의미 있는 값으로 레이아웃을 바꿀 수 있습니다.

나중에 기준을 바꾸더라도 한 곳에서 수정할 수 있어 유지보수가 쉬워집니다. 처음에는 공통 함수를 만드는 일이 조금 번거롭게 느껴질 수 있지만, 화면이 늘어날수록 기준을 모아두는 쪽이 훨씬 편했습니다.

Screen wrapper로 공통 기준 적용하기

프로파일별 화면이 많다면 모든 화면에서 같은 규칙을 반복하지 않는 것이 좋습니다. 공통 Screen wrapper를 두고 최대 너비, safe area, 가로/세로 기준을 한 번에 적용하면 화면 회귀를 줄일 수 있습니다.

import React from 'react';
import {PixelRatio, useWindowDimensions, View} from 'react-native';

export function ResponsiveScreen({children}: {children: React.ReactNode}) {
  const {width, height} = useWindowDimensions();
  const fontScale = PixelRatio.getFontScale();
  const metrics = getResponsiveMetrics({width, height, fontScale});

  return (
    <View
      testID="responsive-screen"
      style={{
        flex: 1,
        alignItems: 'center',
        paddingHorizontal: metrics.sizeClass === 'compact' ? 16 : 24,
      }}
    >
      <View style={{width: '100%', maxWidth: metrics.contentMaxWidth}}>
        {children}
      </View>
    </View>
  );
}

여기서 핵심은 태블릿이라고 해서 모든 화면을 무조건 넓게 쓰지 않는 것입니다. 본문형 화면은 최대 너비를 제한하는 편이 읽기 쉽습니다. 반대로 지도나 대시보드처럼 넓은 화면이 유리한 화면은 별도 기준을 둘 수 있습니다.

처음에는 태블릿 화면을 넓게 쓰는 것이 좋아 보일 수 있지만 실제로 본문형 화면을 전체 너비로 늘려보면 시선 이동이 커져서 오히려 읽기 어려워지는 경우가 있습니다.

가로 모드와 태블릿은 같은 문제가 아니다

가로 모드와 태블릿은 비슷해 보이지만 다른 문제입니다. 일반 스마트폰 가로 모드는 높이가 낮아져 세로 공간이 부족해집니다. 반면 태블릿 세로 모드는 너비는 넓지만 여전히 단일 컬럼이 더 자연스러울 수 있습니다.

화면 상태 주요 문제 권장 기준
휴대폰 세로 좁은 너비 단일 컬럼, 액션 wrap
휴대폰 가로 낮은 높이 상단 영역 축소, 스크롤 보장
태블릿 세로 넓은 너비 maxWidth 제한, 여백 균형
태블릿 가로 넓은 너비와 높이 split-pane 검토
Fold 펼침 중간/확장 경계 breakpoint와 실제 캡처 확인
큰 글자 설정 텍스트 넘침 버튼 높이, 줄바꿈 허용

처음에는 width >= 600이면 무조건 태블릿 레이아웃으로 바꾸고 싶을 수 있습니다. 하지만 태블릿 세로 화면에서 split-pane을 강제로 적용하면 오히려 화면이 복잡해질 수 있습니다. 너비와 방향을 함께 보는 기준이 필요합니다.

프로파일별 회귀 테스트가 필요한 이유

통합 앱에서는 같은 Screen wrapper를 쓰더라도 프로파일마다 첫 화면과 주요 기능이 다릅니다. 지도 앱은 지도나 목록이 중요하고, 파일 데이터 앱은 리스트와 상세 화면이 중요합니다. 유틸리티 앱은 설정이나 단일 기능 화면이 더 중요할 수 있습니다.

그래서 화면 최적화 테스트는 단일 대표 화면만 확인하면 부족하고, 공통 responsive hook을 수정했다면 각 계열의 대표 프로파일을 최소한 하나씩은 확인하는 편이 좋습니다.

프로파일 계열 우선 확인 화면
tour-regional 홈, 지도, 상세, 설정
tour-utility 검색, 지도, 필터, 외부 링크
filedata 리스트, 지도 marker, 상세 액션
climbing 코스/지도, 날씨, 상세 정보
nongsaro 카테고리, 목록, 상세, 검색
utility 단일 기능 화면, 설정
hybrid WebView 영역, 외부 링크, safe area

특정 프로파일 하나만 보고 화면 최적화가 끝났다고 판단하면 다른 계열에서 메뉴나 광고 영역이 깨질 수 있습니다. 이 부분은 실제로 정리하다 보면 놓치기 쉬운 부분이라, 대표 프로파일 기준을 따로 잡아두는 것이 좋습니다.

화면 매트릭스 체크리스트

게시 전이나 PR 검증 전에는 아래 매트릭스를 기준으로 확인하면 좋습니다. 처음부터 모든 조합을 자동화하기 어렵다면, 최소한 스크린샷 캡처 스크립트나 수동 체크 기록을 남겨두는 것부터 시작해볼 수 있습니다.

항목 확인 내용
일반 휴대폰 세로 기본 화면, 버튼, 카드, 스크롤 정상 여부
일반 휴대폰 가로 상단 영역과 액션 버튼이 겹치지 않는지
태블릿 세로 본문 최대 너비와 좌우 여백이 적절한지
태블릿 가로 split-pane 적용 여부와 상세 영역 표시 확인
Fold/대화면 breakpoint 경계에서 레이아웃이 갑자기 깨지지 않는지
큰 글자 버튼, 탭, 카드 텍스트가 잘리지 않는지
Safe area 상태바, 노치, 하단 제스처 영역에 가리지 않는지
키보드/검색 검색창 포커스 시 입력 영역이 가려지지 않는지
광고 영역 광고 placeholder가 콘텐츠를 밀어내거나 겹치지 않는지
성능 큰 화면에서 리스트/지도 렌더링이 과도하게 느려지지 않는지

나중에 같은 화면을 다시 볼 때 비교 기준이 있으면 훨씬 편합니다. 특히 화면 최적화는 한 번에 완성하기보다, 깨지는 케이스를 기록하면서 조금씩 보완하는 쪽이 현실적인 것 같습니다.

자주 하는 실수

1. 태블릿 대응을 단순히 flex: 1이나 width: '100%'로 끝내는 경우가 있습니다. 화면이 넓어졌다고 콘텐츠도 끝없이 넓어지면 읽기 어려워집니다. 본문형 화면은 최대 너비를 제한하는 것이 좋습니다.

2. 가로 모드를 태블릿과 같은 문제로 보는 경우도 있습니다. 휴대폰 가로 모드는 높이가 부족한 경우가 많아, 오히려 상단 영역을 줄이고 스크롤을 보장하는 쪽이 중요합니다.

3. 큰 글자 설정을 확인하지 않는 경우가 있습니다. 디자인상 멀쩡해 보이던 버튼도 fontScale이 커지면 텍스트가 잘릴 수 있습니다. 액션 버튼은 줄바꿈이나 세로 배치 기준을 준비해두는 편이 안전합니다.

4. 한 프로파일만 보고 공통 Screen wrapper를 수정하는 경우도 있습니다. 통합 앱에서는 프로파일마다 첫 화면과 기능이 다르기 때문에 대표 프로파일 테스트가 필요합니다.

추천 적용 순서

화면 최적화 기준을 한 번에 모두 바꾸려고 하면 부담이 큽니다. 아래 순서처럼 공통 기준부터 조금씩 추가해보는 편이 좋습니다.

  1. 공통 responsive metrics 함수를 만든다.
  2. compact, medium, expanded 기준을 정한다.
  3. Screen wrapper에서 maxWidth와 padding 기준을 통일한다.
  4. 가로 모드와 태블릿 가로를 분리해서 처리한다.
  5. 큰 글자 설정에서 액션 버튼이 줄바꿈되도록 한다.
  6. 대표 프로파일별 화면 매트릭스를 만든다.
  7. 스크린샷 캡처나 connected UI 테스트로 회귀를 확인한다.

이 순서대로 진행하면 화면마다 임시 조건문을 넣는 일을 줄일 수 있습니다. 처음에는 조금 느려 보일 수 있지만, 프로파일이 늘어날수록 공통 기준이 있는 쪽이 훨씬 안정적인 것 같습니다.

결론

React Native 통합 앱에서 화면 최적화는 단순한 스타일 수정이 아니라 운영 기준에 가깝습니다. 일반 휴대폰, 태블릿, 가로 모드, 큰 글자, safe area를 함께 고려해야 하고, 프로파일별 대표 화면도 확인해야 합니다.

가장 먼저 할 일은 화면 크기를 의미 있는 metrics로 바꾸는 것입니다. 그다음 Screen wrapper에서 공통 기준을 적용하고, 프로파일별 화면 매트릭스로 회귀를 확인하면 됩니다.

특정 화면 하나만 예쁘게 만드는 것보다 중요한 것은 다른 프로파일 화면이 함께 깨지지 않는 구조를 만드는 것입니다. 통합 앱을 관리한다면 responsive hook, Screen wrapper, 대표 프로파일 테스트를 한 묶음으로 설계해보는 것이 좋겠습니다.

참고 자료

  • React Native useWindowDimensions, PixelRatio 관련 공식 문서
  • React Native safe area 처리 관련 문서
  • Android 대화면 및 태블릿 레이아웃 가이드
  • 프로젝트 내부 화면 최적화 매트릭스와 대표 프로파일 테스트 문서