🧠 먼저, "리컴포지션(Recomposition)"이 뭐야?
Jetpack Compose는 UI를 그리는 코드이자 데이터가 바뀌었을 때 그리기 다시 해주는 코드야.
예를 들어 이런 코드가 있다고 해보자:
@Composable
fun Hello(name: String) {
Text(text = "Hello, $name!")
}
여기서 name이 "Alice"였다가 "Bob"으로 바뀌면, Compose는 Hello() 함수를 다시 실행해서 화면을 다시 그림. 이게 바로 리컴포지션(recomposition)!
🎯 그럼 "Restartable"은 뭐야?
@Composable 함수는 두 가지 중 하나야:
- Restartable: 값이 바뀌면 함수를 다시 실행함 (리컴포지션 가능)
- NonRestartable: 값이 바뀌어도 다시 실행 안 함
Compose는 컴파일러가 자동으로 판단해서 어떤 Composable을 다시 실행할지 정해줘. 하지만 모든 걸 자동으로 판단하지는 않아. 때로는 우리가 **“이 함수는 다시 실행하지 마!”**라고 명확히 알려줘야 해.
🏷️ 그래서 등장한 @NonRestartableComposable
이 어노테이션은 말 그대로 **“이 함수는 절대 다시 실행하지 마!”**라고 Compose에게 알려주는 거야.
✨ 왜 이게 필요해?
만약 이런 코드가 있다고 해보자:
@Composable
fun Screen(name: String) {
Log.e("MyLog", "Recomposed with $name")
Text("Hello, $name")
}
이때 name 값이 바뀌면 Compose는 Screen()을 다시 실행해. 그러면 로그가 또 찍혀. 로그가 너무 많이 찍히면 보기 힘들겠지?
→ 이런 경우, 로그 찍는 부분은 다시 실행할 필요가 없어! → @NonRestartableComposable이 필요함!
🧪 진짜 예제!
@NonRestartableComposable
@Composable
fun LogOnce(message: String) {
Log.d("LogOnce", message)
}
@Composable
fun MyScreen(state: String) {
LogOnce("This should not be logged multiple times.")
Text(state)
}
- state가 바뀌어서 MyScreen()이 리컴포지션되더라도
- LogOnce()는 다시 실행되지 않아. 로그도 딱 한 번만 찍혀!
📌 정리하면 이렇게 이해하면 돼
용어 뜻 예시 / 설명
Composable | UI를 그리는 함수 | Text("Hello") |
Recomposition | 값이 바뀌면 다시 그림 | count++하면 UI 새로 그려짐 |
Restartable | 다시 실행 가능한 Composable | 기본값은 이거야 |
NonRestartable | 다시 실행 금지 | @NonRestartableComposable 붙이면 됨 |
왜 써? | 리컴포지션 방지해서 불필요한 실행 줄임 | 로그, 단발성 이벤트, 리소스 초기화 등 |
💡 비슷한 기능들도 있어!
어노테이션 설명 언제 쓰면 좋아?
@NonRestartableComposable | 다시 실행 금지 | 로그, one-time 이벤트 |
@NonSkippableComposable | 스킵도 금지 | 무조건 실행해야 할 함수 |
@DontMemoize | remember 자동 적용 막기 | 고정된 람다를 매번 새로 만들고 싶을 때 |
🎓 학생이 자주 하는 질문 정리
Q1. 리컴포지션되면 뭐가 문제야?
→ 함수가 다시 실행되면 불필요한 연산이 늘어나고, 로그가 중복되거나 API 재호출 같은 문제 생길 수 있어.
Q2. 그럼 모든 함수에 @NonRestartableComposable 붙이면 좋아?
→ ❌ 아니야!
Compose는 상태가 바뀌면 자동으로 UI를 갱신해야 해. 그걸 막으면 UI가 갱신되지 않아.
→ “다시 실행되면 안 되는 함수만 골라서” 붙여야 해!
✏️ 마무리 정리
- Compose는 데이터를 기준으로 UI를 다시 그리는 구조
- 모든 Composable 함수는 자동으로 restartable or non-restartable
- @NonRestartableComposable을 쓰면 다시 실행 안 됨
- 로그, 리소스 초기화, 애니메이션, 단발 이벤트 처리에 딱!
필요하다면 다음은 이런 내용도 추가 설명해줄 수 있어:
- remember, derivedStateOf, LaunchedEffect와 리컴포지션 차이
- Compose 최적화를 위한 Group Skipping, Memoization 내부 동작 원리
- 리컴포지션 디버깅하는 방법 (예: Recompose Highlighter 툴)
더 깊이 공부하고 싶으면 알려줘! 💪