React Native에서 화면 크기(너비, 높이)를 구할 때 사용하는 가장 기초적인 도구인 Dimensions API에 대해 알아보자.
import { Dimensions } from 'react-native';
// 'window'나 'screen' 중 하나를 선택해서 가져온다.
const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;
console.log(`너비: ${windowWidth}, 높이: ${windowHeight}`);
Dimensions.get()을 쓸 때 인자로 'window'와 'screen' 중 하나를 넣어야 하는데, iOS에서도 기술적으로는 screen이 약간 더 크지만(상태바 영역 포함), 실용적으로는 거의 동일한 값이 나오기 때문에 큰 차이가 없다.
window (추천)
현재 나의 앱이 실제로 사용할 수 있는 영역의 크기다.
screen
Dimensions.get('window')는 아주 편리해 보이지만, 치명적인 단점이 하나 있다.
바로 이 값은 한 번 가져오면 변하지 않는 상수로 박제된다는 것이다.
다음과 같은 문제 상황을 보자.
import React, { useState, useEffect } from 'react';
import { View, Text, Dimensions } from 'react-native';
const DimensionsExample = () => {
// 초기값 설정
const [windowDimensions, setWindowDimensions] = useState(Dimensions.get('window'));
useEffect(() => {
// 1. 화면 크기가 변할 때(회전, 폴더블폰 펼침) 실행될 함수
const onChange = ({ window }) => {
setWindowDimensions(window);
};
// 2. 리스너 등록
const subscription = Dimensions.addEventListener('change', onChange);
// 3. 청소 (Cleanup)
return () => subscription.remove();
}, []);
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>너비: {windowDimensions.width}</Text>
<Text>높이: {windowDimensions.height}</Text>
</View>
);
};
useWindowDimensionsReact Native 팀도 Dimensions API 쓰는 게 귀찮다는 걸 알고, Hook을 만들어줬다.
import React from 'react';
import { View, Text, useWindowDimensions } from 'react-native';
const BestPracticeExample = () => {
// 그냥 이거 한 줄이면 끝이다. 회전하면 알아서 값이 바뀜.
const { width, height } = useWindowDimensions();
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>너비: {width}</Text>
<Text>높이: {height}</Text>
{/* 화면이 넓으면 가로 배치, 좁으면 세로 배치 같은 반응형 UI 가능 */}
<View style={{ flexDirection: width > 500 ? 'row' : 'column' }}>
{/* ... */}
</View>
</View>
);
};
Dimensions와 함께 자주 쓰이는 API인데, 아래와 같이 dp와 실제 물리 픽셀 간의 변환이 필요할 때 사용한다.
import { PixelRatio } from 'react-native';
// 디바이스의 픽셀 밀도 (1x, 2x, 3x 등)
const pixelDensity = PixelRatio.get();
// dp를 실제 픽셀로 변환 (이미지 최적화할 때 필수)
const dpToPixel = PixelRatio.getPixelSizeForLayoutSize(100); // 100dp -> ?px
// 물리 픽셀을 dp로 변환
const pixelToDp = PixelRatio.roundToNearestPixel(2.7); // 2.66666 -> 3
import { Dimensions } from 'react-native';
const { width: SCREEN_WIDTH } = Dimensions.get('window');
// 디자인 기준 너비 (피그마 디자인이 375px 기준이라고 가정)
const BASE_WIDTH = 375;
// 비율로 크기 계산
export const scale = (size: number) => (SCREEN_WIDTH / BASE_WIDTH) * size;
// 폰트는 너무 크게/작게 되지 않도록 제한
export const moderateScale = (size: number, factor = 0.5) =>
size + (scale(size) - size) * factor;
// 사용 예시
<Text style={{ fontSize: moderateScale(16) }}>
모든 폰에서 적절한 크기로 보임
</Text>
import { useWindowDimensions } from 'react-native';
const ResponsiveLayout = () => {
const { width } = useWindowDimensions();
// 화면 크기에 따른 레이아웃 분기
const isTablet = width >= 768;
const columns = isTablet ? 3 : 1;
return (
<View style={{
flexDirection: isTablet ? 'row' : 'column',
gap: 16
}}>
{/* 태블릿에서는 3단 그리드, 폰에서는 1단 리스트 */}
</View>
);
};
onLayout 이벤트 사용KeyboardAvoidingView 또는 react-native-keyboard-controller 사용react-native-size-matters 라이브러리 추천