앱을 iPhone 6 / 6 Plus에 맞추는 작업을 하던 중에 PPI에 혼란이 와서 직접 계산해 봤습니다.

우선 오리지널 iPhone의 물리적 스크린 크기는 가로 1.94 인치(4.93cm), 세로 2.91 인치(7.4cm)입니다.1 해상도(resolution)는 320x480이므로 PPI는 약 163입니다. (위 수치로 계산하면 165가 되는데 대부분 163으로 표시해서 이를 기준으로 합니다.) PPI가 163라는 것은 64x64 픽셀의 이미지가 물리적으로 0.4인치 x 0.4인치 = 1cm x 1cm 정도의 크기가 된다는 것을 의미합니다. (64/163=0.39in=1cm)

iPhone 4로 넘어오면서 물리적인 크기는 유지하면서 해상도를 두배(640x960)로 만들었습니다. 따라서 PPI는 약 326(계산으로는 330)이 되었습니다. iPhone 4에서 1cm x 1cm로 이미지를 표현하려면 128x128 픽셀이 필요합니다. (1/2.54*326=128) 하지만 프로그래밍시에는 scale factor를 도입해서(UIScreen의 scale 속성) 논리적인 좌표는 오리지널 iPhone과 동일하게 64x64를 갖도록 해서 iPhone 4를 지원하기 위해 별도의 작업이 필요없도록 했습니다. (대신 hairline을 표현하기가 까다로워 졌습니다.)

iPhone 5에서는 해상도가 640x1152(논리적 해상도 320x568)로 켜졌지만, 물리적 크기도 1.94 인치 x 3.49 인치로 늘어서 PPI는 iPhone 4와 동일하게 326입니다.

이제 iPhone 6를 보겠습니다. iPhone 6의 물리적 스크린 크기는 가로 2.3 인치(5.8cm), 세로 4.1 인치(10.4cm)이고, 해상도는 750x1334(논리적 해상도 375x667)입니다.2 PPI를 계산해보면 326으로 iPhone 4, iPhone 5와 동일합니다. 즉, iPhone 4, iPhone 5에서와 동일한 논리적 픽셀 값을 사용하면 사용자에게 같은 크기로 보인다는 얘기입니다. 대신 스크린 크기가 커졌으므로 더 많은 1cm x 1cm 이미지를 표시할 수 있겠죠.

그런데 여기서 하나 새로운 개념이 추가됩니다. 디스플레이 확대/축소(Display Zoome)에서 확대됨(Zoomed)를 설정하면 이미지, 글씨등이 크게 표시됩니다. 기술적으로는 논리적 해상도로 375x667 대신 320x568을 기준으로 작업함을 의미합니다. 이 상태에서 iPhone 4와 동일하게 64x64 픽셀로 이미지를 위치시키면 물리적 크기가 1.17cm x 1.17cm가 됩니다.

마지막으로 iPhone 6 Plus는 가로 2.7 인치(6.8cm), 세로 4.8 인치(12.2cm), 해상도 1080x1920을 갖습니다. PPI는 400이 되겠네요. 그런데 iPhone 6 Plus는 특이하게 414x736의 논리적 해상도를 갖습니다. (scale factor는 3으로 1242x2208 캔버스에 그려집니다.) 실 해상도와 정수로 대응하지 않습니다. 왜 이렇게 했을까요?

만약 논리적 해상도를 360x640으로 했다면, iPhone 4에 맞춰 64x64로 작업한 이미지는 1.2cmx1.2cm로 표시됩니다. 반면 414x736인 경우 1.05cmx1.05cm로 나머지 기종에서 기대하는 크기와 비슷합니다. (어짜피 물리적 해상도와 다른데 정확히 맞추지 않은 이유는 모르겠습니다.)

마지막으로 iPhone 6 Plus에서 확대됨을 선택하면 iPhone 6의 논리적 해상도인 375x667로 동작합니다. 이 경우 64x64로 작업한 이미지(scale factor는 3x이므로 192x192 픽셀의 이미지가 필요)는 1.16cm x 1.16cm로 iPhone 6의 확대됨 모드와 비슷한 크기로 표시됩니다.

요약하면 코드 작성시 같은 픽셀 크기로 작업하면 iPhone 종류와 상관없이 같은 물리적 크기로 표시됩니다. 다만 한 화면에서 표시되는 양만 달라집니다. iPhone 6 / 6 Plus의 확대됨 모드에서는 약 16%~17%가 더 크게 표시됩니다.


  1. http://www.theverge.com/2012/4/9/2937265/the-4-inch-iphone-5
  2. http://stackoverflow.com/questions/25756087/detecting-iphone-6-6-screen-sizes-in-point-values

개발을 하다보면 몇몇 설정 파일을 수정한 채로 개발을 하는 경우가 있습니다. 예를 들면 서버 주소를 개발용 서버로 변경해서 작업을 할 수 있겠죠. 만약 개발용 서버가 명확히 정해져 있다면, 디버그 모드와 출시 모드를 구분하는 식으로 고정된 설정 파일을 만들 수 있겠지만, 개발용 서버가 개발자 개인 컴퓨터인 경우는 이것도 쉽지 않습니다.

이런 용도로 변경된 파일들은 당연히 주 저장소에 올라가면 안 되겠죠. (하지만 이 파일 자체는 주 저장소에 포함되어야 하기에 .gitignore를 쓸 수는 없습니다) 저 같이 ‘git commit -a’을 실행하는데 익숙한 사람은 매번 커밋시 이 파일이 포함되지 않도록 신경써주는것이 꽤 큰 비용입니다.

다행히 git는 이를 위한 해결책이 있습니다. 다음 명령을 실행하면 해당 파일에 대한 변경을 무시합니다.

git update-index --assume-unchanged <file>

다시 변경된 내역을 표시하려면 다음 명령을 실행합니다.

git update-index --no-assume-unchanged <file>

변경이 무시되고 있는 파일 목록은 다음 명령으로 확인할 수 있습니다.

git ls-files -v | grep '^h'

참고

Nginx 로그 분석을 위해 시간별로 나누고 싶었습니다. 스크립트를 짜도 오래 걸리는 일은 아니겠지만, 쉘에서 하는 방법을 한번 찾아봤습니다.

Nginx 로그는 다음과 같은 형태를 가집니다.

xx.xx.xx.xx - - [25/Sep/2014:06:54:29 +0000] "GET /blahblah HTTP/1.1" 200 130 "-" "User-Agent"

다음 명령은 공백으로 나눠진 토큰 중 4번째, 즉 시간을 표시합니다.

awk '{ print $4 }' access.log
awk '{ print substr($4,2) }' access.log # 앞의 [ 제거

여기에 split 함수를 써서 날짜와 시간을 얻을 수 있습니다.

awk '{ split(substr($4,2),array,"[/:]"); print array[1], array[4] }' access.log

필요한 정보를 알았으니 각 줄을 적절한 파일에 쓰도록 하면 됩니다.

awk '{ split(substr($4,2),array,"[/:]"); print > (array[1] "-" array[4] ".log") }' access.log

갱신:

좀 더 큰 데이터에 해보니 too many open files 에러가 발생합니다. awk가 좀 오래된 도구다 보니 열린 파일 수 제한이 낮은 듯 합니다. (MacOSX 기준으로 채 20개를 넘지 못하네요.)

이 경우 파일을 계속 닫아주면 됩니다. 대신 ‘»‘를 써줘야 정상적으로 추출됩니다.

awk '{ split(substr($4,2),array,"[/:]"); fn = array[1] "-" array[4] ".log"; print >> fn; close(fn) }' access.log

참고