이전 포스트에서 Android로 계산기를 만든다고 했습니다.
그리고 계산기를 만들기 위해 developer.android.com 의 문서들을 정독하기 시작했습니다. Amazon Kindle로 Android Wireless Application Development를 구매하여 읽어보고 있고요. 그런데 생각처럼 쉽지가 않았습니다.
**코드로 UI 작성하기가 쉽지 않다. **
GUI 개발시 위지윅 에디터를 거의 사용하지 않는 버릇 때문에, 대부분의 UI 개발을 코드만으로 해오고 있었습니다. 복잡한 GUI 만들 때는 코드로 하면 더 어렵지 않느냐 생각하실 수도 있지만 결코 그렇지 않습니다. 복잡도가 높으면 높을수록 코드로 GUI를 뽑아내는 것이 더 높은 생산성을 보입니다. 컴포넌트들을 적절한 범주로 묶어 collection에 넣어 일괄처리할 수도 있고, 화면은 1장이여도 논리적인 기능 단위로 클래스를 분리할 수 있어 편리하기 때문입니다. 예를 들어 계산기를 만든다고 할 때, 버튼이 여러개가 있는데 이것들을 디자이너로 배치하고, 각 아이디를 할당하고 이벤트 핸들러를 붙이는 것은 곤욕입니다. for loop으로 생성하고 화면 resolution에 따라 적절히 컴포넌트의 크기위 위치를 할당하는 것이 개발속도가 더 빠릅니다. UI 생성 코드 로직들을 다 기억한다는 전제하에 유지보수하기도 훨씬 더 편리해집니다. 아주 오랜 시간이 지나, 어떻게 만들었었는지 기억을 거의 못할 때면, 디자이너를 열어서 버튼을 더블클릭하여 어느 핸들러와 연결되어있는지 확인하는 것도 더 편하겠지만, 우리는 문서 작성능력이 있고 기억해야할 것을 어딘가 노트해둘 수 있는 능력을 가진 인간입니다. (게다가 우리에겐 Swing, SWT, JavaFX를 지원하는 MiG Layout이 있습니다. :D)
안드로이드는 UI 생성을 XML 말고도 코드로도 생성할 수 있게 해줍니다. 하지만 그 지원이 생각만큼 높지 않습니다. 문서가 부족하기 때문입니다.
계산기의 현재 숫자를 표현하는 TextView를 만들려고 합니다. 그러면
<TextView
android:text="1,048,576"
android:gravity="center_vertical|right"
android:background="#000000"
android:textSize="36"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
이렇게 만들면 됩니다. UI가 XML로 분리되어 가지는 장점들은
로직과 UI를 파일단위로 분리할 수 있다.
소스코드 변경없이 리소스만 변경하여 UI를 바꿀 수 있다.
Portrait/Landscape, 화면 해상도 별, 언어별로 XML 파일을 따로 만들어두고 하나의 로직에 연결하여 사용할 수 있다.
디자이너(위지윅에디터)를 사용할 수 있다.
반면에 동일한 기능을 하는 UI를 코드로 작성해보면
view = new TextView(this);
view.setText("1,048,576");
view.setGravity(Gravity.CENTER_VERTICAL|Gravity.RIGHT);
view.setBackgroundColor(0x000000:
view.setTextSize(36.0f);
view.setLayoutParams(new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT, 0.0f));
로직과 UI는 클래스 단위로 분리할 수 있다.
소스코드 재컴파일, 그저 하면 된다.
수십년동안 많은 프로그래머들이 XML로 분리된 UI 없이도 가변 사이즈를 지원하는 UI를 코드로 작성해왔었고, 다국어 지원을 추가함에도 아무런 문제가 없었다.
코드가 더 복잡해지는 것은 아닙니다.
그러면 왜 코드로 UI 만들기가 어렵다고 했나요?
그 이유는, Android가 XML로 UI 만들기를 권장하고 있기 때문입니다. 코드로 UI 만드는 사람을 위한 친절한 문서가 거의 없기 때문입니다.
위의 TextView 생성 코드를 보시면, 수직 중앙 정렬과 우측 정렬을 하기 위해 android.view.Gravity 의 상수를 가져다 쓰고 있습니다. API 문서에는 setGravity(int)로만 되어 있고, See also 섹션에 Gravity 클래스의 링크가 있습니다. 후다닥 찾기가 애매합니다. XML에서는 그저 android:gravity="center_vertical|right" 라고 입력해주면 되는데 말입니다.
LinearLayout을 쓰고 싶은데, d.android.com 에서 제공하는 문서는 오직 XML 뿐입니다. 위의 코드를 보면 child 컴포넌트에 setLayoutParams(new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT, 0.0f)) 를 실행하여 android:layout_width="fill_parent", android:layout_height="wrap_content", android:layout_weight="0" 과 똑같은 동작을 하도록 했습니다.
가장 큰 어려움은 TextView 클래스에 setLayoutWidth 나 setLayoutHeight, setLayoutWeight 같은 이름을 가진 메서드가 존재하지 않는다는 것입니다. 결국, XML 문서만을 보고 추측하여 쉽게 코드로 옮길 수 없다는 문제가 있습니다.
XML에서 할 수 있는 모든 기능을 API로도 할 수 있습니다. 하지만 쉽게 찾을 수 없는 것이지요.
코드로 UI를 만드는 것이 어렵다고 했는데, 왜 구지 코드로 UI를 만들려고 하나요?
동일한 속성을 가지는 컴포넌트를 여러개 만들려고 할 때, XML 에서는 copy and paste가 불가피합니다. 계산기 앱의 경우 버튼이 4x4로 16개가 있습니다. 버튼의 배경색을 검정색에서 회색으로 바꾸고자 한다면 16번 손을 움직여야 합니다. 코드로 하면 루프 몇 번 돌아서 해결할 수 있는데 말입니다.
이렇게.. 안드로이드 계산기가 만들어져가고 있습니다.