이번 4주차 프로젝트는 5주차까지 이어지는 2주 간의 프로젝트이다. 4주차 주말에 글을 완성하지 못해 5주차와 함께 다시 작성 후 업로드하기로 하였다.
두번째 프로젝트가 끝나고 새로운 프로젝트가 시작됐다. 협업이 아닌 개인 프로젝트로 진행되었고 새롭게 배우는 Jetpack Compose를 이용하여 구현을 하는 것이 이번 프로젝트에서의 주요 포인트였다. 예전에 간단하게 Compose를 사용해본 적이 있지만 기본적인 부분들이었기 때문에(1 ,2, 3, 4 참고) 프로젝트에 적용하기에는 많은 공부가 필요했다. 새롭게 배우는 기술을 2주라는 제한된 시간안에 잘 적용하는 것이 중요했던 프로젝트였다. 또한 DI 라이브러리 Hilt나 객체 지향 설계 원칙도 함께 배웠는데 HIlt는 사용은 해봤지만 아직 이해가 더 필요했고 객체 지행 설계 원칙 SOLID는 몇 번 들어본 정도였기 때문에 이 부분도 공부가 많이 필요했다. 다음 프로젝트가 시작되기 전에 배운 것을 정리해보자.
Jetpack Compose
기존의 xml형태의 명령형 UI와 다르게 선언형 UI인 Jetpack Compose는 처음부터 화면 전체를 개념적으로 재생성한 후 필요한 변경사항만 적용하는 방식으로 작동한다. 변경사항이 있을 때마다 화면 전체를 재생성한다면 물론 비효율적이겠지만 Compose는 특정 시점에 UI의 어떤 부분을 그려야할 지를 선택할 수 있으므로 비용을 줄일 수 있다.
Recomposition
Compose에서는 새 데이터로 업데이트하면 Composable한 함수를 다시 호출한다. 이러면 함수가 다시 Recompostion, 재구성되어 새로 그려지게 된다. 이 때 Composable 함수는 새 입력을 기반으로 재구성되기 때문에 매개변수가 변경되지 않은 함수나 람다는 모두 건너뛰게 되어 선택적으로 UI를 다시 그려낼 수 있도록 한다.
State
remember API를 통해 메모리에 객체를 저장할 수 있다. 관찰 가능한 MutableState<T>를 remember와 함께 선언하면 값, value가 바뀔 때 recompostion될 수 있다.
value값을 구독하고 있는 RecomposeScope에 의해서 value가 바뀔 때 recompostion이 일어나는 것으로 보인다. 만약 같은 값이 쓰여진다면 recomposition이 일어나지 않기 때문에 비용을 줄일 수 있다.
rememberSaveable을 사용하면 configuration이 변경되어 Activity등이 재생성되더라도 UI 상태를 복원할 수 있다. 이번 프로젝트에서는 이 부분을 놓쳐 화면 회전으로 인한 상태 유지에 대해 고민을 했었는데 rememberSaveable로 해결할 수 있지 않았을까 싶다.
State Hoisting
state를 가지고 있는 composable 함수는 재사용성이 줄어들고, test에 불리하다. state를 가지고 있는 stateful한 composable을 stateless형태로 변화시키기 위해 state를 함수 호출부분으로 끌어올릴 수 있다. 각각의 composable에 state가 종속되어 있지 않아 재사용성은 올라가고 파라미터 형태로 state를 전달하면 value가 바뀔 때 UI가 그려질 수 있는 형태로 구현할 수 있다.
Jetpack Compose에 대한 내용은 이외에도 많고 새로운 내용이 계속 추가되고 있다.(https://android-developers.googleblog.com/2022/07/jetpack-compose-1-2-is-now-stable.html)
이번 프로젝트에서는 Compose로 프로젝트를 모두 구현하는 것이 목표였기 때문에 UI를 그리는데에 많은 시간을 쏟게 되어 더 많은 부분을 공부하지는 못했다. 각 Composable에 대해 미리 알고 있다면 시간을 많이 아낄 수 있을 것이고 많이 주목받고 있는만큼 틈틈이 공부할 수 있도록 하여야겠다.
Hilt
구글에서 지원하는 DI 라이브러리이다. DI, 의존성 주입은 특정 객체를 외부에서 생성하여 전달하는 방식으로 재사용성을 높여주고 Test에 용이해진다. 객체를 생성해놓고 주입하기 때문에 다른 부분에서 필요하다면 그 객체를 재사용할 수 있고, 인터페이스를 이용하면 따로 Test를 위한 구현체를 만들어서 넘길 수 있기 때문에 단위 Test에 용이하다.
안드로이드 공식 문서( https://developer.android.com/training/dependency-injection/hilt-android?hl=ko#inject-provides)를 참고해서 사용법을 정리해보았다. 흐름 상 어노테이션을 사용되어지는 순서로 작성하였다.
- @HiltAndroidApp과 @AndroidEntryPoint 어노테이션을 이용해서 종속성을 담을 Application을 지정하고, 종속성을 삽입할 Android 클래스(Activity, Fragment, Serivce 등)을 지정할 수 있다.
- @Inject 어노테이션을 통해 종속 항목을 가져올 수 있다.
- @Inject로 종속 항목을 가져오려면 종속 항목의 인스턴스를 제공하는 방법을 알아야 한다. 생성자에서 @Inject 어노테이션을 사용해서 Hilt에게 인스턴스를 생성하는 방법을 알려줄 수 있고, Hilt 모듈을 통해 알려줄 수 있다.
- @Module 어노테이션을 통해 Hilt 모듈 클래스를 지정할 수 있고, 생성자 Inject가 불가능한 경우에 Hilt 모듈 클래스에서 인스턴스를 제공하는 방법을 정의할 수 있다.
- 인터페이스의 경우 생성자 삽입이 안되기 때문에 이 때는 @Binds 어노테이션을 통해 해결할 수 있다. 또한 외부 라이브러리에서 제공하는 클래스를 사용하는 경우에도 생성자 삽입이 불가능하므로 이 때는 @Provides를 사용하여 인스턴스를 삽입할 수 있다.
- 동일한 유형을 여러 경우에 사용한다면 @Qualifier와 @Retention 어노테이션을 이용해서 식별하는데 사용할 수 있고, 매개변수에서 사용하는 경우에도 이를 이용할 수 있다.
지금까지, 그리고 이번 프로젝트에서조차도 Hilt에서 제공하는 여러 어노테이션을 깊이 생각하지않고 사용해왔다. @Inject 어노테이션이 필요하지 않은 경우에서도 사용한다거나 @Binds와 @Provides를 제대로 사용하지 않는 등 적절하지 못한 사용이 많았는데 리팩토링 과정을 통해 고칠 필요가 있어보이고 다음 프로젝트부터는 제대로 사용할 수 있기를 바라 본다.
'활동 > 우아한테크캠프5기' 카테고리의 다른 글
우아한 테크캠프 6,7주차 (0) | 2022.08.21 |
---|---|
우아한 테크캠프 4,5주차 - 2 (0) | 2022.08.08 |
우아한 테크캠프 3주차 - 2 (0) | 2022.07.26 |
우아한 테크캠프 3주차 - 1 (0) | 2022.07.23 |
우아한 테크캠프 2주차 - 2 (0) | 2022.07.18 |
댓글