
Fragment Result API는 Fragment 사이에서 한 번 전달하고 끝나는 결과를 더 안전하게 주고받기 위한 공식 패턴입니다. 즉 shared state가 아니라 one-time result에 더 잘 맞습니다.
예전에는 interface callback이나 Activity 중계로 처리하는 경우가 많았지만, Fragment 생명주기와 back stack이 얽히면 참조 관계가 금방 복잡해집니다. Fragment Result API는 이 지점을 좀 더 느슨하게 풀어 줍니다.
Android Developers의 Fragments communication 가이드도 persistent data 공유에는 shared ViewModel을, one-time result에는 Fragment Result API를 설명합니다. 이 글에서는 그 선택 기준을 실무 감각으로 다시 풀어보겠습니다.
Fragment Result API가 해결하려는 문제
가장 흔한 장면은 이런 것입니다. 목록 화면에서 필터 화면을 열고, 필터를 고른 뒤 원래 화면으로 돌아오면서 결과를 전달해야 합니다. 또는 DialogFragment에서 확인 버튼을 누르고 이전 Fragment에 결과를 넘겨야 합니다.

- 선택 화면에서 고른 값 하나를 이전 화면으로 돌려주기
- DialogFragment 확인/취소 결과 넘기기
- 설정 화면에서 변경 완료 신호 전달하기
- 결과를 한 번 소비하고 끝나는 흐름 다루기
이런 경우에 shared ViewModel을 쓰면 상태가 필요 이상으로 오래 남거나, 단순 결과를 상태 저장 문제처럼 다루게 될 수 있습니다.
기본 사용 흐름은 어떻게 될까
class ListFragment : Fragment(R.layout.fragment_list) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
parentFragmentManager.setFragmentResultListener(
"filter_result",
this
) { _, bundle ->
val selectedCategory = bundle.getString("category") ?: return@setFragmentResultListener
applyFilter(selectedCategory)
}
}
}
class FilterFragment : Fragment(R.layout.fragment_filter) {
private fun onCategorySelected(category: String) {
parentFragmentManager.setFragmentResult(
"filter_result",
bundleOf("category" to category)
)
parentFragmentManager.popBackStack()
}
}구조는 단순합니다. 받는 쪽이 먼저 listener를 등록하고, 보내는 쪽이 같은 key로 result를 설정합니다. 두 Fragment가 직접 서로를 참조하지 않아도 된다는 점이 꽤 큽니다.

callback 방식보다 무엇이 덜 위험할까
interface callback 방식은 구조가 아주 단순할 때는 쓸 수 있습니다. 하지만 화면이 쌓이고 교체되고 재생성되는 흐름까지 가면, 누가 누구를 알고 있어야 하는지가 금방 복잡해집니다.
- sender와 receiver가 직접 강하게 연결되지 않는다
- FragmentManager가 중간 통로 역할을 한다
- listener가 STARTED 상태가 되면 결과를 받는 동작이 공식 문서 기준으로 정의돼 있다
- DialogFragment 같은 일회성 결과 흐름에 특히 잘 맞는다
즉 “콜백이 나쁘다”가 아니라, 생명주기와 화면 스택이 개입하는 구조에서는 결과 전달 통로를 직접 만들지 않는 편이 덜 위험하다는 뜻에 가깝습니다.
이 구분을 놓치면 가장 많이 헷갈립니다. shared ViewModel은 여러 화면이 오래 같이 바라봐야 하는 상태 공유에 잘 맞습니다. 반면 Fragment Result API는 결과를 한 번 전달하고 끝나는 흐름에 더 잘 맞습니다.
- 검색 필터 결과 한 번 전달 → Fragment Result API가 자연스럽다
- 여러 Fragment가 같은 화면 상태를 계속 본다 → shared ViewModel이 자연스럽다
- 확인 버튼, 날짜 선택, 권한 안내 후 응답처럼 소비 후 끝나는 이벤트 → Fragment Result API 쪽이 단순하다
상태를 오래 공유해야 하지 않는데도 shared ViewModel로 풀기 시작하면, 일회성 결과를 지우는 코드와 재소비 방지 코드가 늘어나는 경우가 많습니다.
STARTED 상태와 pending result는 왜 중요할까
공식 문서에서 중요한 포인트 하나는 받는 Fragment가 STARTED 상태가 되었을 때 callback이 호출된다는 점입니다. 이 동작을 이해하면 “왜 바로 안 오지?” 같은 혼란이 많이 줄어듭니다.
또 하나는 같은 key에 대해 listener와 pending result가 사실상 하나라는 점입니다. listener가 아직 STARTED가 아닌데 같은 key로 result를 여러 번 넣으면, 이전 pending result가 새 값으로 대체될 수 있습니다.

실전 예시 1: DialogFragment 결과 전달
class ConfirmDeleteDialog : DialogFragment() {
private fun onConfirm() {
parentFragmentManager.setFragmentResult(
"delete_result",
bundleOf("confirmed" to true)
)
dismiss()
}
}
class DetailFragment : Fragment(R.layout.fragment_detail) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
parentFragmentManager.setFragmentResultListener("delete_result", this) { _, bundle ->
if (bundle.getBoolean("confirmed")) {
deleteItem()
}
}
}
}이 장면은 shared ViewModel보다 Fragment Result API 쪽이 더 읽기 쉽습니다. 정말 필요한 정보가 “삭제를 확정했는가” 한 번뿐이기 때문입니다.
실전 예시 2: 필터 선택 화면에서 목록 화면으로 돌아가기
목록 → 필터 → 목록 복귀 흐름에서는 back stack과 결과 전달이 같이 엮입니다. 이때 sender가 직접 receiver 메서드를 호출하려고 들면 화면 재생성이나 참조 해제 타이밍에서 구조가 불안해지기 쉽습니다.
Fragment Result API는 “누가 지금 살아 있느냐”보다 “같은 FragmentManager에서 같은 key를 누가 기다리느냐”로 생각하게 만들어 줍니다. 이 사고 전환이 의외로 큽니다.
자주 하는 실수
parentFragmentManager대신 잘못된childFragmentManager에 listener를 다는 것- key를 화면마다 제각각 써서 sender와 receiver가 안 맞는 것
- 일회성 결과인데 shared ViewModel로 과하게 끌고 가는 것
- listener 등록 시점을 너무 늦게 잡아 흐름을 이해하기 어렵게 만드는 것
- 같은 key로 여러 결과를 쌓을 수 있다고 오해하는 것
특히 “왜 결과가 안 오지” 문제의 상당수는 API 자체보다 어느 FragmentManager를 쓰는지와 같은 key를 쓰는지에서 생깁니다.
빠르게 결정하는 기준
- 결과가 한 번 전달되고 끝나는가? → Fragment Result API를 먼저 본다
- 여러 화면이 같은 상태를 계속 공유해야 하는가? → shared ViewModel을 먼저 본다
- Dialog 결과, 선택 결과, 확인 결과인가? → Fragment Result API가 잘 맞는다
- 화면 트리에서 어느 FragmentManager를 통해 연결되는지 먼저 확인한다
Navigation 구조와 FragmentManager 감각이 아직 헷갈린다면 Navigation Component와 FragmentManager 차이 글을 같이 보면 전체 그림이 더 잘 잡힙니다.
결과 전달을 상태 공유처럼 다루면 왜 꼬일까
일회성 결과를 shared ViewModel 상태처럼 다루기 시작하면 소비 후 초기화, 재소비 방지, 화면 복귀 시점 제어 같은 코드가 불필요하게 늘어날 수 있습니다.
그래서 Fragment Result API의 핵심 가치는 “전달하고 끝나는 결과”를 상태 관리 문제로 키우지 않게 해 준다는 데 있습니다.
마무리
Fragment Result API의 핵심은 “Fragment끼리 직접 알고 지내지 말고 결과 통로만 공유하자”에 가깝습니다. 특히 one-time result에서는 이 방식이 callback보다 덜 끈적이고, shared state보다 덜 무겁습니다.
짧게 정리하면 이렇습니다. 상태를 오래 공유할 일은 shared ViewModel, 한 번 넘기고 끝나는 결과는 Fragment Result API가 기본 출발점이 되면 덜 헷갈립니다.