dip
- 몇 가지 도메인 구현 이야기 자료 2015.11.30
- 저수준의 상세한 내용 없이 구현하기 2013.09.11
- 안드로이드 기초 쌓기 - 해상도와 DP 2013.01.15
몇 가지 도메인 구현 이야기 자료
저수준의 상세한 내용 없이 구현하기
최근에 온라인 쇼핑 시스템을 구축하는 프로젝트를 시작했다. 쇼핑 시스템 자체는 솔루션을 약간 커스터마이징해서 사용할 예정이다. 이 시스템의 사용자는 다음의 요구 사항을 갖고 있다.
- 현재 사용중인 ERP 시스템에서 쇼핑 시스템의 판매 정보(매출 등)도 함께 보고 싶음
- 현재 사용중인 ERP 시스템의 재고와 쇼핑 시스템의 재고를 맞추고 싶음
- 이 ERP 시스템은 외부에서 서비스로 제공
여기서, 우리가 저수준 모듈에서 할 수 있는 것이라곤 결과를 보관할 DB 테이블을 정하는 정도이다. 쇼핑 DB에서 데이터를 가져오는 방법도, ERP 서비스 제공 업체에 데이터를 넘기는 방법도 우리가 마음대로 할 수 없다. 하지만, 이런 저수준의 구현 상세함이 정해지지 않았다 하더라도 우리는 고수준의 기능을 구현할 수 있다. 비밀은 바로 DIP에 있다.
DIP를 적용해서 저수준 모듈 없이 고수준 모듈 구현하기
DIP는 Dependency Inversion Principle의 약자로, 이 원칙에 대한 설명은 본 글에서는 생략한다. 이에 대한 내용이 궁금한 독자는 http://en.wikipedia.org/wiki/Dependency_inversion_principle 글 또는 필자가 지은 '객체 지향과 디자인 패턴' 책을 참고하기 바란다.
DIP를 적용해서 저수준 모듈이 고수준 모듈에 의존하게 바꾸면, 저수준 모듈의 상세한 구현 없이도 고수준 모듈을 (어느 정도 수준까지) 만들어낼 수 있다. 아래 그림은 DIP를 적용한 결과를 보여주고 있다.
OrderInfoSync가 의존하는 타입은 모두 인터페이스이므로 Mock을 이용해서 얼마든지 다양한 시나리오의 테스트 코드를 만들 수 있다. 우리는 아래쪽에 붉은 색 상자안에 위치한 저수준 모듈 클래스의 구현이 존재하는지 여부에 상관없이 OrderInfoSync 클래스를 구현할 수 있다.
실제로 지금 이 방식으로 외부 연동을 위한 고수준 모듈의 코드를 한 줄 한 줄 만들어나가고 있다. 물론, 저수준 모듈의 구현없이 고수준 모듈을 완벽하게 구현할 순 없지만, 상당한 양의 구현을 사전에 미리 만들어 낼 수가 있다. 그리고 이 핵심에는 DIP가 있다!
안드로이드 기초 쌓기 - 해상도와 DP
안드로이드를 좀 더 잘 해 보기 위해 기초를 다지고 있는데, 그 중 첫 번째로 공부하고 있는 부분이 해상도 및 레이아웃과 관련된 내용이다.
안드로이드의 주요 단위
안드로이드 기기들이 해상도와 물리적인 크기가 저마다 다르기 때문에, UI 레이아웃을 기기별로 깨지지 않게 만들어주려면 주요 단위에 대한 이해가 필요하다. 다음은 안드로이드 개발시 알아야 하는 용어/단위를 정리한 것이다.
용어 및 단위 |
설명 |
Pixel | 화면상의 픽셀 |
해상도(Resolution) | 픽셀 단위의 화면 크기. 예를 들어, 갤럭시노트 10.1의 해상도는 1280*800인데, 이는 픽셀이 1280개 및 800개임을 의미한다. |
DPI (Dots Per Inch) / 밀도 |
물리적인 1 인치 당 포함되는 픽셀 개수. 예를 들어, 160 DPI는 1인당 픽셀이 160개 포함된다는 것을 의미한다. 주요 DPI는 다음과 같다. - LDPI (low) : 120 DPI - MDPI (medium) : 160 DPI - TVDPI : 213 DPI - HDPI (high) : 240 DPI - XHDPI (extra high) : 320 DPI |
스크린 크기 | 물리적인 크기의 종류를 나타낸다. 다음의 4종류가 존재한다. - X-Large: 주로 10.1 인치 이상의 디바이스 - Large: 주로 5인치 이상의 디바이스 - Normal: 3인치에서 5인치 미만의 사이의 디바이스 - Small: 3인치 미만의 디바이스 |
px | 픽셀 기반의 단위 |
dip (density-independent pixels) 또는 dp | 밀도 독립 단위로, 장치의 밀도에 상관없이 물리적으로 (거의) 동일한 크기를 갖는다. |
sp (scale-independent pixels) | 스케일 독립 픽셀 단위로 , dip와 유사하며, 글꼴 크기를 지정할 때 주로 사용된다. |
실제 테스트 해 볼 수 있는 기기별로 확인해보니 주요 값은 다음과 같았다.
갤럭시노트 10.1 |
옵LTE 2 |
넥서스7 |
옵Q |
|
해상도 (픽셀단위) |
800 x 1280 |
720 x 1280 |
800 x 1280 |
480 x 800 |
해상도 (DP 단위) | 800 x 1280 | 360 x 640 | 600 x 961 | 320 x 533 |
DPI | 160 DPI (mdpi) | 320 DPI (xhdpi) | 213 DPI (tvdip, hdip) | 240 DPI |
스크린 크기 | xlarge | normal | large | normal |
밀도 비율 (DPI / 160) | 1 | 2 | 1.331250 | 1.5 |
안드로이드의 기준 DPI는 중간 수준인 160 DPI이다. 160 DPI를 기준으로 DPI가 크면 밀도가 높아지고, DPI가 작으면 밀도가 낮아진다. 또한, 160 DPI인 경우 밀도독립 단위인 DP(DIP)와 픽셀이 같은 크기를 갖는다. 즉, 160 DPI에서 1 DP는 1 PX이 된다.
PX와 DP
옵LTE2와 넥서스7 그리고 갤럭시노트 10.1에서 트위터를 실행해보면, 기기의 크기는 다르지만, 상단 바 부분의 물리적 높이가 동일한 것을 확인할 수 있다. 또한, 글자 크기도 동일한 것을 확인할 수 있다.
[옵티머스LTE2(좌)와 넥서스7(우)에서 트위터를 실행한 화면. 상단 바와 메뉴의 높이가 (거의) 같다]
위 그림에서 두 기기의 높이 해상도는 1280이지만, 물리적인 크기는 넥서스7이 더 크다. 따라서, 위 그림에서 실제 px 단위의 높이 값은 좌측의 옵티머스LTE2가 넥서스7보다 커야 위와 같이 물리적으로 동일한 크기로 표시된다. 모든 기기마다 물리적으로 동일한 높이를 갖는 px 값을 구해서 계산한다는 것은 매우 힘든데, dp 단위를 사용하면 위 그림처럼 기기의 크기에 상관없이 물리적으로 동일한 크기로 레이아웃을 구성할 수 있다.
XML 레이아웃 설정 파일에서 dp 단위로 크기를 지정하면, 안드로이드는 내부적으로 알맞은 px 단위로 값을 변환해서 크기를 구성한다. 따라서, 개발자는 dp 단위를 사용해서 물리적으로 동일한 크기를 갖는 레이아웃을 구성할 수 있다.
코드에서 직접 크기를 설정하는 경우에는 픽셀 단위로 지정하게 되는데, 이 경우 다음의 공식을 이용해서 dp 단위의 값을 px 단위의 값으로 변환할 수 있다.
px = dp * (DPI / 160)
기기의 DPI 구하기
dp 단위의 값으로부터 px 단위의 값을 구하려면 기기의 DPI를 구해야 하는데, 다음의 코드를 이용하면 DPI를 구할 수 있다.
Display dis = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
dis.getMetrics(metrics);
// 해상도: dis.getWidth() * dis.getHeight() / metrics.widthPixels * metrics.heightPixels
// DPI: metrics.densityDpi
// 밀도비율 (DPI / 160) : metrics.density
참고자료
- 기기별 DPI/해상도/크기 등: http://developer.android.com/tools/revisions/platforms.html
- Supporting Multiple Screens: http://developer.android.com/guide/practices/screens_support.html