플러터로 사용자가 보는 화면을 작업한다면 누구나 사이즈를 어떻게 주지? 라는 고민을 해봤을 것이다.
위젯사이즈는 어떻게 줘야 할까, 얼마만큼 줘야 할까? 기기별로 나눠야 한다면 수많은 기기들이 가진 해상도 사이의 구분은 어떻게 할까 등등... 을 고민하기전에 먼저 화면과 관련된 용어와 개념에 대해 알아보자.
Pixel
픽셀은 디지털 이미지와 디스플레이 장치에서 사용되는 개념으로, 이미지를 구성하는 가장 작은 단위를 의미한다. 픽셀은 "picture element"의 줄임말이며, 말 그대로 화면에 표시되는 모든 그래픽 요소의 구성 요소이다.
픽셀은 정사각형 또는 직사각형의 형태를 가지며, 각 픽셀은 특정한 색상과 밝기 값을 나타낸다. 컴퓨터 화면이나 디지털 이미지에서 픽셀은 그리드 형태로 배열되어 있으며, 수많은 픽셀이 모여 하나의 이미지를 형성한다.
화면 해상도는 픽셀의 수로 표시되며, 가로 방향과 세로 방향의 픽셀 수를 나타내는 두 가지 숫자로 표현된다. 예를 들어, "1920x1080" 해상도는 가로 방향으로 1920개의 픽셀과 세로 방향으로 1080개의 픽셀을 가지는 화면을 의미한다.
논리적 픽셀
모바일(안드로이드, iOS)에서는 다양한 기기의 해상도에 대응하기 위해서 물리적인 해상도를 직접 사용하지 않고 논리적인 단위를 사용한다. 안드로이드에서는 dp, iOS에서는 포인트라고 부른다.
물리적인 해상도를 사용하지 않고 논리적 픽셀을 사용하는 이유는 다양한 화면 크기와 해상도를 가진 디바이스에서 일관된 사용자 경험을 제공하기 위해서 다양한 디바이스의 화면 밀도나 해상도에 독립적으로 작업할 수 있게 하기 위함이다.
물리적인 해상도를 사용하기 보다 논리적 픽셀을 사용하면 일관성 있는 UI를 구성할 수 있게 된다.
물론 모든 화면에서 똑같은 크기로 보인다는 아니고, 비슷한 UI를 그려준다로 보면 된다.
DP (Density-independent Pixel)
dp는 안드로이드에서 사용하는 논리적 픽셀의 단위이다.
1dp는 160dpi를 갖는 화면에서 하나의 픽셀과 대응한다. 160dpi는 1인치당 160개의 픽셀을 가지고 있다는 뜻이다.
안드로이드의 밀도 기준이 160dpi인데, 처음 나온 안드로이드 스마트폰의 화면 사이즈라서 그렇다고 한다.
예를들어 100dp만큼 어떤 위젯을 그려줘 하면 해상도에따라 실제 그려지는 픽셀의 갯수는 다르겠지만 '비슷'하게 그려진다.
스마트폰의 해상도에 따라서 1dp가 그리는 픽셀의 수가 달라진다.
DPI
해상도에 대해 찾다보면 자주 보이는 단위로 dpi가 있는데 dots per inch로, 1인치에 얼마나 많은 점들이 있는지를 나타낸다.
PPI (Pixel per inch) 라는 단위도 있는데, 인쇄쪽과 관련이 없다면 둘은 같다고 생각해도 된다.
참고 : https://minamond.tistory.com/134
DPI? PPI? 헷갈리는 이미지 해상도 개념 정리!
안녕하세요 여러분! 아몬드입니다😀 오늘은 엣시에서 프린터블(printable) 상품을 판매하는 분들이라면 한 번쯤 들어보셨을! DPI 와 PPI 라는 개념에 대해 설명해드리려고 합니다 :) 사실 이건 엣시
minamond.tistory.com
논리적 해상도와 물리적 해상도에 관련된 조금 더 자세한 이야기는 아래 링크에서 참고하면 좋다.
https://remain.co.kr/page/designsystem/resolution-kinds.php
리메인커리어 | 리메인
remain.co.kr
플러터에서는 어떻게 처리하고 있을까?
플러터도 안드로이드나 iOS처럼 논리적 픽셀을 사용한다. 위젯의 사이즈에 적어주는 숫자는 다 논리적 픽셀 단위라고 생각하면 된다.
내부적으로 실제 픽셀과 논리적 픽셀 간의 변환을 처리하고 있는데 이 과정에서 devicePixelRatio 값을 사용하여 실제 픽셀과 논리적 픽셀 사이의 비율을 계산한다.
devicePixelRatio란?
The number of device pixels for each logical pixel. This number might not
be a power of two. Indeed, it might not even be an integer. For example,
the Nexus 6 has a device pixel ratio of 3.5.
devicePixelRatio의 주석을 보면, 1개의 논리적 픽셀이 가지고있는 물리적인 픽셀의 갯수라고 생각하면 된다.
갤럭시 S22 Ultra를 기준으로 실제로 들어오는 값을 확인을 해보자.
모델명 | 디스플레이 크기 | 해상도 |
S22 | 6.1 in (155 mm) | 2340×1080 |
S22+ | 6.6 in (168 mm) | 2340×1080 |
S22 Ultra | 6.8 in (173 mm) | 3088×1440 |
S22 Ultra의 경우 화면의 해상도는 가로 1440 픽셀, 세로 3088 픽셀이다.
S22 ultra에서 미디어쿼리로 사이즈를 가져오면 아래처럼 나온다.
final device = MediaQuery.of(context);
final size = device.size; // Size(360.0, 724.0)
final devicePixelRatio = device.devicePixelRatio; // devicePixelRatio : 4.0
화면의 Size는 미디어 쿼리를 통 해서 가져올 수 있고 이 값은 플러터가 렌더링 되는 사이즈의 값이다. 물리적인 해상도 크기가 아니다.
일반적으로 플러터에서 위젯의 높이나 가로길이를 double로 주게 되는데 이 값은 위에서 얘기했듯이 Logical Pixel 값이므로
화면을 꽉 차게 그릴려면 Size가 360 * 724 인 화면에서는
SizedBox(
width: 360,
height: 724,
)
로 값을 주면 된다.
안드로이드에서 dp는 변경이 가능하다
안드로이드의 경우 최소 너비가 dp라는 단위로 설정되어 있는데, OS의 '설정'에서 변경이 가능하다.
S22 ultra에서 기본 설정된 최소 너비는 360인데 이걸 720으로 바꾸게 되면 MediaQuery값이 아래와 같이 변경된다.
I/flutter (23230): size : Size(720.0, 1496.0)
I/flutter (23230): devicePixelRatio : 2.0
다음글
위젯이 왜.. 다르게 보이지? 2.이미지와 devicePixelRatio
기타 참고 링크
안드로이드에서 이미지를 처리하는 방법
https://developer.android.com/training/multiscreen/screendensities?hl=ko#TaskProvideAltBmp
모바일 화면 해상도 통계
https://gs.statcounter.com/screen-resolution-stats/mobile/worldwide
Mobile Screen Resolution Stats Worldwide | Statcounter Global Stats
This graph shows the stats of mobile screen resolutions worldwide based on over 5 billion monthly page views.
gs.statcounter.com