중복되는 컴포즈 코드를 줄여서 개발 속도를 높일수 있는 재사용 가능한 코틀린 헬퍼 함수 툴킷을 구축하자
이번주만 47번째로 같은 Modifier 체인, 로딩 래퍼, 조건부 UI 분기 , 거의 같은 애니메이션 타이밍을 또 쓰고 있다.
이 팀전체의 반복 10분을 어떻게 한 줄 호출로 바꿀까?
그떄 헬퍼 유틸이 유용하고, 생각보다 만들기 쉽다.
왜 헬퍼 유틸리티가 진짜로 중요한가
컴포즈는 강력하지만 구조 없이 쓴다면 그냥 기술부채가 됩니다.
ㅇㅕ러 화면에서 복잡한 UI를 만들다보면, 같인 Modifier, 상태 처리, 애니메이션 조합이 반복됩니다.
이런 헬퍼들은 단순 편의가 아니라
스프린트당 10개 기능을 내느냐 6개를 내느냐, 코드가 느껴지느냐 퍼즐처럼 흩어지느냐의 차이입니다.
모든 팀에 필수적인 헬퍼 유틸리티
조건부 표시 헬퍼
이건 거창한 말이 아니라, 조건부 UI를 만들때 if문을 그만쓰자는 이야기입니다.
대신 컴포넌트 합성에 익숙해져야합니다.
이 유틸리티는 투명도 애니메이션과 레이아웃 재배치를 자동으로 처리해줍니다.
@Composable
fun ConditionalDisplay(
visible: Boolean,
modifier: Modifier = Modifier,
animationDuration: Int = 300,
content: @Composable () -> Unit
) {
val alpha by animateFloatAsState(
targetValue = if (visible) 1f else 0f,
animationSpec = tween(durationMillis = animationDuration),
label = "visibility_alpha"
)
if (visible || alpha > 0f) {
Box(
modifier = modifier
.graphicsLayer { this.alpha = alpha }
) {
content()
}
}
}
실제 사용은 if로 감싸는 대신 ConditionalDisplay(isLoading) { LoadingSpinner() } 처럼 쓴다.
화면 하나당 8~12줄을 줄일수 있다.
중앙 로딩 오버레이
중앙 로딩 상태는 모든 앱에 필수다.
셋 중에 두번은 쓰이니, 한 번 만들어두고 계속 재사용하자
@Composable
fun LoadingOverlay(
isVisible: Boolean,
modifier: Modifier = Modifier,
backgroundColor: Color = Color.Black.copy(alpha = 0.3f),
content: @Composable () -> Unit = { CircularProgressIndicator() }
) {
if (isVisible) {
Box(
modifier = modifier
.fillMaxSize()
.background(backgroundColor)
.clickable(enabled = false) { },
contentAlignment = Alignment.Center
) {
content()
}
}
}
실제 사용: 화면 콘텐츠를 감싸고 isLoading만 넘기면됩니다.
이 오버레이가 입력 차단과, 중앙 정렬을 자동으로 처리해줍니다.
적응형 패딩 헬퍼
이제 화면 크기에 따라 패딩을 다르게 줘야한다. 값 하드 코딩은 그만하자
이 헬퍼는 화면 너비에 따라 패딩을 자동으로 선택해준다.
실사용에서는 Modifier.adaptivePadding() 하나로, 컴포저블 전반에 흩어진 화면 크기 체크를 대체합니다.
fun Modifier.adaptivePadding(
compact: Dp = 8.dp,
medium: Dp = 16.dp,
expanded: Dp = 24.dp
): Modifier {
return this.then(
Modifier.padding(
when (LocalConfiguration.current.screenWidthDp) {
in 0..600 -> compact
in 601..840 -> medium
else -> expanded
}
)
)
}
검색을 위한 상태 디바운서
검색어가 너무 자주 변경되면 요청이 과도하게 발생합니다. 이 헬퍼는 네트워크 스팸을 막아줍니다.
@Composable
fun <T> rememberDebouncedValue(
value: T,
delayMillis: Long = 300L
): T {
var debouncedValue by remember { mutableStateOf(value) }
LaunchedEffect(value) {
delay(delayMillis)
debouncedValue = value
}
return debouncedValue
}
val debouncedQuery = rememberDebouncedValue(searchText) 처럼 사용하고, API 호출은 debounedQuery 를 관찰해서 수행합니다.
닫힘 처리를 캡슐화한 바텀시트 헬퍼
바텀 시트는 닫힘 로직도 보작합니다. 그러니 이걸 캡슐화해야합니다.
@Composable
fun DismissibleBottomSheet(
isVisible: Boolean,
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
if (isVisible) {
ModalBottomSheet(
onDismissRequest = onDismiss,
modifier = modifier
) {
content()
}
}
}
이렇게 하면 바텀시트 상태를 5개 화면에서 따로 관리할 필요가없습니다.
한 번만 호출해서 쓰면됩니다.
자체 유틸리티 라이브러리 구축하기
헬퍼 유틸리티를 만들 떄에 모범 사례
- 하나의 목적만 유지하라: 한 가지 명확한 목적만, 과도한 설계는 피하라
- 설정 가능하게 만들어라: duration, colors, size 등을 노출해 포크 없이 조정가능하게하라
- 문서보다는 예제가 더 중요하다: 파라메터 설명 보다 실제 사용 예를 보여라
- 엣지 케이스를 처리하라 : 비어있는상태, 상태 전환, 회전 등 설정 변경을 고려하라
- 쉽게 리팩토링하지마라: 유틸리티 코드 변경은 코드 전반에 호환성 영향을 준다.
ROI는 실제로 나온다.
잘 설계된 헬퍼 유틸리티로 배포하는 팀들로부터 이런이야기를 듣습니다.
- 툴셋이 안정된 이후에는 장기적으로 기능 구현속도가 빨라졌습니다. (약30~40%)
- 화면 전반의 동작이 일관돼 UI 버그 감소
- 온보딩이 쉬워짐 신규 개발자는 복붙 대신 헬퍼를 읽습니다.
이건 이론이아닙니다. 개발자 4명이 1년에 200번 같은 조건부 표시 로직을 안쓰고 함 수 호출 한번으로 끝내면 실제로 이런 결과가 나옵니다.
작게 시작하고, 체계적으로 확장하라
ui/composables/helpers 패키지를 하나만들자.
이번 스프린트에서는 팀이 반복하고 있는 유틸 3개부터 시작한다.
문서화하고, 팀에 공유하고 점진적으로 확장하라
2~3스프린트만 지나면 팀을 실제로 더 빠르게 만드는 툴킷이 생깁니다.
가장 좋은 점은 이 유틸리티들이 이후에 모든 컴포즈 프로젝트에도 따라온다는 점입니다.
이게 바로 올바른 시점에 올바른 추상화를 만드는 힘입니다.
핵심 정리
1. 패턴을 인식하라 - 코드에서 어떤 컴포저블 로직이 반복되는가?
2. 가차 없이 캡슐화 하라 - 하나의 컴포저블은 하나의 명확한 이유만 가져야한다.
3. 설정가능하게 하라 - 유틸에 가정을 하드코딩하지마라
4. 팀과 공유할 가치가 있는 것만 - 많이 쓸수록 그 가치가 더 커진다
5. 버전 관리를 의도적으로하라 - 규모가 커질 수록 breaking change는 비싸진다.
애퓰리케이션 헬퍼 유틸은 단순히 코드 양을 줄이는게 아니다.
일관성을 보장하고, 보일러플레이트에 쓰는 사고 시간을 줄여 기능에 집중하게 만드는 것이다.
오늘 시작하라. 내일은 더 빠르게 배포하라
'영어 데일리' 카테고리의 다른 글
| 모바일 시스템 디자인 인터뷰: 내가 FAANG 인터뷰를 준비한 과정과 무료 연습자료 (1) | 2026.01.13 |
|---|---|
| MVI 보일러플레이트는 이제 작별, 코드를 대신 작성해주는 BuildKt MVI 라이브러리 소개 (1) | 2026.01.06 |
| 왜 hilt때문에 너의 앱이 느려지는가? (어떻게 수정할지) (1) | 2026.01.02 |
| RemoteCompose: 컴포즈에서 서버 주도 UI를 위한 또 다른 패러다임 (0) | 2025.12.02 |
| Bosch 안드로이드 개발자 인터뷰 경험 (0) | 2025.12.01 |