Fragment 개념

Fragment란?
Fragment는 Activity 내에서 동작하는 재사용 가능한 UI 컴포넌트입니다.
핵심 특징:
- Activity에 의존적이며 혼자 존재할 수 없음
- 자체적인 lifecycle을 가지지만 호스트 Activity의 lifecycle에 영향받음
- 모듈화와 재사용성 제공
- 동적으로 추가/제거/교체 가능
Fragment vs Activity
| 구분 | Activity | Fragment |
|---|---|---|
| 독립성 | 독립적으로 존재 가능 | Activity에 의존 |
| 용도 | 전체 화면 담당 | 화면의 일부분 담당 |
| 재사용성 | 제한적 | 높음 (여러 Activity에서 사용 가능) |
| 생명주기 | 독립적 | 호스트 Activity에 직접 영향받음 |
Fragment 상속 관계
Fragment 클래스 계층구조
Object (Java/Kotlin)
└── Fragment (Android)
├── DialogFragment
├── ListFragment (Deprecated)
├── PreferenceFragmentCompat
└── YourCustomFragment
Fragment 주요 특징:
- Fragment는 Object를 상속하며 여러 인터페이스를 구현
- IComponentCallbacks, IComponentCallbacks2, View.IOnCreateContextMenuListener 등을 구현
- Context를 상속하지 않음 - getContext()나 requireContext()로 접근해야 함
Fragment vs Activity 상속 비교
| 클래스 | 상속 관계 | Context 접근 |
|---|---|---|
| Activity | Context → ContextThemeWrapper → Activity | 직접 Context (this) |
| Fragment | Object → Fragment | getContext()로 간접 접근 |
Fragment Lifecycle 상세
Fragment 상태와 View Lifecycle 관계

Fragment는 Fragment 자체의 Lifecycle과 View의 별도 Lifecycle을 가집니다.
| Fragment Lifecycle | View Lifecycle | 설명 |
|---|---|---|
| INITIALIZED | - | Fragment 인스턴스 생성됨 (onCreate 이전) |
| CREATED | INITIALIZED | Fragment 생성, View 생성 준비 |
| CREATED | CREATED | View가 생성됨 |
| STARTED | STARTED | Fragment와 View 모두 보이기 시작 |
| RESUMED | RESUMED | Fragment와 View 모두 활성 상태 |
| STARTED | STARTED | onPause() 호출 시 |
| CREATED | CREATED | onStop() 호출 시 |
| CREATED | DESTROYED | onDestroyView() 호출 시 |
| DESTROYED | - | Fragment 완전 소멸 |
Fragment Lifecycle 콜백 메서드
1. onAttach()
- 상태 변화: - → INITIALIZED
- View Lifecycle: -
- 주요 작업:
- Activity 참조 저장
- Activity나 리소스에 대한 참조 획득
- Context가 필요한 초기화 작업
override fun onAttach(context: Context) {
super.onAttach(context)
Log.d(TAG, "onAttach")
// Activity 참조 저장, Context 관련 초기화
}
2. onCreate()
- 상태 변화: INITIALIZED → CREATED
- View Lifecycle: -
- 주요 작업:
- Fragment의 기본 컴포넌트 초기화
- savedInstanceState로부터 상태 복원
- 네트워크 호출이나 데이터베이스 작업 등 백그라운드 작업
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate")
// 데이터 초기화, 상태 복원
}
3. onCreateView()
- 상태 변화: CREATED → CREATED (View: - → INITIALIZED)
- View Lifecycle: INITIALIZED
- 주요 작업:
- 레이아웃 인플레이션
- View 계층구조 반환
- UI 관련 초기화
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
Log.d(TAG, "onCreateView")
return inflater.inflate(R.layout.fragment_example, container, false)
}
4. onViewCreated()
- 상태 변화: CREATED → CREATED (View: INITIALIZED → CREATED)
- View Lifecycle: CREATED
- 주요 작업:
- View 초기화 (findViewById 등)
- 리스너 설정
- Adapter 설정
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Log.d(TAG, "onViewCreated")
// View 초기화, 이벤트 리스너 설정
}
5. onStart()
- 상태 변화: CREATED → STARTED
- View Lifecycle: CREATED → STARTED
- 주요 작업:
- Fragment가 보이기 시작할 때의 작업
- 애니메이션 시작
- 리스너나 옵저버 등록
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart")
// 애니메이션 시작, 브로드캐스트 리시버 등록
}
6. onResume()
- 상태 변화: STARTED → RESUMED
- View Lifecycle: STARTED → RESUMED
- 주요 작업:
- Fragment가 활성 상태가 되어 사용자와 상호작용 가능
- 서비스 시작
- 센서나 위치 리스너 등록
- 카메라 등 독점 리소스 활성화
override fun onResume() {
super.onResume()
Log.d(TAG, "onResume")
// 독점 리소스 활성화, 실시간 업데이트 시작
}
7. onPause()
- 상태 변화: RESUMED → STARTED
- View Lifecycle: RESUMED → STARTED
- 주요 작업:
- Fragment가 더 이상 포어그라운드에 있지 않을 때 (여전히 보이지만 포커스 잃음)
- 애니메이션 일시 중지
- 사용자 입력 관련 리스너 해제
- 영구적으로 저장할 데이터 커밋
- 멀티윈도우 등 아직 보이지만 포커스를 잃은 상태 우선 변경사항 확정으로 이해함
override fun onPause() {
super.onPause()
Log.d(TAG, "onPause")
// 애니메이션 일시중지, 사용자 데이터 저장
}
8. onStop()
- 상태 변화: STARTED → CREATED
- View Lifecycle: STARTED → CREATED
- 주요 작업:
- Fragment가 더 이상 보이지 않을 때
- 백그라운드 서비스 중단
- 네트워크 연결 해제
- 리소스 집약적인 작업 중단
- 영구 상태 저장
override fun onStop() {
super.onStop()
Log.d(TAG, "onStop")
// 백그라운드 서비스 중단, 네트워크 해제, 리소스 정리
}
9. onDestroyView()
- 상태 변화: CREATED → CREATED (View: CREATED → DESTROYED)
- View Lifecycle: DESTROYED
- 주요 작업:
- Fragment의 View 계층구조가 소멸될 때
- View 관련 리소스 정리
- View 바인딩 해제
override fun onDestroyView() {
super.onDestroyView()
Log.d(TAG, "onDestroyView")
// View 리소스 정리, 바인딩 해제
}
10. onDestroy()
- 상태 변화: CREATED → DESTROYED
- View Lifecycle: -
- 주요 작업:
- Fragment가 소멸될 때
- 최종 정리 작업
- 메모리 해제
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy")
// 최종 정리 작업
}
11. onDetach()
- 상태 변화: DESTROYED → (제거됨)
- View Lifecycle: -
- 주요 작업:
- Fragment가 Activity에서 분리될 때
- Activity 참조 정리
- Context 관련 리소스 해제
override fun onDetach() {
super.onDetach()
Log.d(TAG, "onDetach")
// Activity 참조 해제
}
FragmentManager
FragmentManager란?
앱의 Fragment들에 대한 작업(추가, 제거, 교체)을 수행하는 책임을 가진 클래스
주요 역할
- Fragment 관리: Fragment의 추가, 제거, 교체, 탐색
- Back Stack 관리: Fragment 트랜잭션의 백스택 관리
- Fragment 탐색: ID나 태그로 Fragment 찾기
FragmentManager 접근 방법
Activity에서
val fragmentManager = supportFragmentManager
Fragment에서
// 부모 Fragment의 관리자 (호스트 Activity의 FragmentManager)
val parentFragmentManager = parentFragmentManager
// 자식 Fragment들을 관리하는 관리자
val childFragmentManager = childFragmentManager
주요 메서드
Fragment 탐색
// ID로 Fragment 찾기
val fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
// 태그로 Fragment 찾기 (FRAGMENT_TAG는 add/replace 시 설정)
val fragment = supportFragmentManager.findFragmentByTag("MAIN_FRAGMENT")
Back Stack 관리
// Back Stack에서 최상위 트랜잭션 제거
supportFragmentManager.popBackStack()
// 특정 이름까지 Back Stack 제거 (해당 이름 포함하여 그 위의 모든 트랜잭션 제거)
supportFragmentManager.popBackStack("FRAGMENT_TRANSACTION_NAME", 0)
// 특정 이름까지 Back Stack 제거 (해당 이름 제외하고 그 위의 트랜잭션들만 제거)
supportFragmentManager.popBackStack("FRAGMENT_TRANSACTION_NAME", FragmentManager.POP_BACK_STACK_INCLUSIVE)
popBackStack 차이점:
- 그냥 제거: 최상위 트랜잭션 하나만 제거
- 특정 이름까지 제거: 여러 트랜잭션을 한번에 제거 가능
FragmentTransaction
FragmentTransaction은 FragmentManager의 작업 방식
FragmentTransaction란?
Fragment에 대한 변경사항들을 하나의 원자적 단위로 그룹화하는 트랜잭션 클래스
트랜잭션 = 여러 Fragment 작업을 하나의 원자적 단위로 묶는 개념
// 1. 트랜잭션 시작
val transaction = supportFragmentManager.beginTransaction()
// 2. 여러 작업을 하나의 트랜잭션에 추가
transaction.add(R.id.container, Fragment1())
transaction.replace(R.id.container2, Fragment2())
transaction.remove(existingFragment)
// 3. 커밋 = 트랜잭션 실행 명령
transaction.commit()
커밋이 필요한 이유:
- Fragment 작업들을 배치(batch)로 처리하여 성능 최적화
- 원자성 보장: 모든 작업이 성공하거나 모두 실패
- 애니메이션과 백스택 관리를 일관되게 처리
주요 메서드들
add()
- 용도: Fragment를 컨테이너에 추가
- 상태 변화: Fragment가 RESUMED 상태로 이동
transaction.add(R.id.fragment_container, MyFragment(), "MY_TAG")
replace()
- 용도: 기존 Fragment를 제거하고 새 Fragment 추가
- 내부 동작: remove() + add()
- 메모리 효율: 이전 Fragment 완전 제거
transaction.replace(R.id.fragment_container, NewFragment())
remove()
- 용도: Fragment를 FragmentManager에서 제거
- 메모리 효율: Fragment와 View 모두 완전 제거
val fragment = supportFragmentManager.findFragmentByTag("TAG")
transaction.remove(fragment)
show() / hide()
- 용도: Fragment의 가시성 제어 (View.setVisibility() 호출)
- 리소스 사용: Fragment가 메모리에 계속 유지되어 메모리 사용량이 많음
- 주의사항:
- 설정 변경(화면 회전) 시 상태가 유지되지 않음
- hidden 상태에서도 lifecycle 콜백은 계속 호출됨
- 많은 Fragment를 hide로 관리하면 메모리 부족 위험
transaction.show(fragment) // 보이기 (VISIBLE)
transaction.hide(fragment) // 숨기기 (GONE/INVISIBLE)
attach() / detach()
- 용도: Fragment를 Activity에 연결/분리
- 리소스 사용: detach 시 View는 파괴되지만 Fragment는 메모리에 유지 (중간 수준)
- detach(): View 계층구조는 파괴되지만 Fragment는 STOPPED 상태로 유지
- attach(): View 재생성하여 다시 연결
transaction.detach(fragment) // View 제거, Fragment는 유지
transaction.attach(fragment) // View 재생성
addToBackStack()
- 용도: 트랜잭션을 Fragment 백스택에 추가하여 뒤로가기 시 되돌릴 수 있게 함
- 동작: 사용자가 뒤로가기 버튼 누르면 FragmentManager가 백스택에서 트랜잭션을 pop
transaction.addToBackStack("TRANSACTION_NAME") // 이름은 선택사항
Fragment 백스택 vs Activity 백스택:
- Activity 백스택: 시스템이 관리하는 Activity들의 스택
- Fragment 백스택: FragmentManager가 관리하는 Fragment 트랜잭션들의 스택
setReorderingAllowed()
- 용도: FragmentManager가 트랜잭션을 올바르게 실행할 수 있도록 재정렬 허용
- 필수: 백스택 사용 시 반드시 설정
transaction.setReorderingAllowed(true)
Fragment와 Tag 설정
// FRAGMENT_TAG 설정 방법
transaction.add(R.id.container, MyFragment(), "MAIN_FRAGMENT")
transaction.replace(R.id.container, NewFragment(), "DETAIL_FRAGMENT")
// 나중에 태그로 찾기
val fragment = supportFragmentManager.findFragmentByTag("MAIN_FRAGMENT")
커밋 메서드들과 트랜잭션 개념
commit()
- 특징: 비동기 실행, Activity 상태 저장 후 호출 시 IllegalStateException 발생
- 사용 시기: 일반적인 상황에서 사용
transaction.commit()
commitAllowingStateLoss()
- 특징: 상태 손실을 허용하면서 커밋
- 위험: UI 상태가 예기치 않게 변경될 수 있음
- 사용 시기: 상태 손실이 허용되는 특수한 경우에만
transaction.commitAllowingStateLoss()
commitNow()
- 특징: 즉시 동기 실행
- 주의: addToBackStack()과 함께 사용 불가
transaction.commitNow()
Fragment View Binding
Fragment에서 View Binding 사용
Fragment도 Activity처럼 View Binding을 사용할 수 있으며, 메모리 누수 방지를 위한 특별한 패턴이 필요합니다.
공식 문서 예시 코드
class ExampleFragment : Fragment() {
private var _binding: FragmentExampleBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentExampleBinding.inflate(inflater, container, false)
return binding.root
}
// onCreateView 랑 비교하기 위해 추가함
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// View 초기화
binding.textView.text = "Hello Fragment"
binding.button.setOnClickListener {
// 클릭 처리
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null // 메모리 누수 방지 : 참조 끊기 > GC
}
}
패턴 설명
- _binding: nullable한 실제 바인딩 객체
- binding: non-null getter (편의를 위한 프로퍼티)
- onDestroyView()에서 null 설정: View가 파괴될 때 바인딩 해제로 메모리 누수 방지
Fragment 주의사항
Fragment는 View의 생명주기가 Fragment 생명주기와 다르기 때문에:
- View가 파괴되어도 Fragment는 메모리에 남을 수 있음
- onDestroyView()에서 반드시 바인딩을 null로 설정해야 함
- onCreateView()에서 매번 새로운 바인딩 객체 생성
Activity와 Fragment의 관계
Lifecycle 의존성
Fragment의 lifecycle은 호스트 Activity의 lifecycle에 직접적으로 영향받습니다.
| Activity 상태 | Fragment에 미치는 영향 |
|---|---|
| Activity.onCreate() | Fragment.onCreate() 트리거 |
| Activity.onStart() | Fragment.onStart() 트리거 |
| Activity.onResume() | Fragment.onResume() 트리거 |
| Activity.onPause() | 모든 Fragment.onPause() 트리거 |
| Activity.onStop() | 모든 Fragment.onStop() 트리거 |
| Activity.onDestroy() | 모든 Fragment.onDestroy() 트리거 |
Fragment 계층 구조
Activity
├── FragmentManager (supportFragmentManager)
│ ├── Fragment A
│ │ └── FragmentManager (childFragmentManager)
│ │ ├── Child Fragment 1
│ │ └── Child Fragment 2
│ └── Fragment B
참고자료
- Android Developer 공식 문서 - Fragment
- Android Developer 공식 문서 - Fragment Lifecycle
- Android Developer 공식 문서 - FragmentManager
- Android Developer 공식 문서 - Fragment Transactions
- Android Developer 공식 문서 - View Binding
핵심 포인트 정리
- Fragment는 Activity에 의존적 - 혼자 존재할 수 없음
- FragmentManager가 Fragment들을 관리 - 추가, 제거, 교체 담당
- FragmentTransaction으로 변경사항을 원자적으로 처리 - 여러 작업을 하나의 단위로 그룹화
- setReorderingAllowed(true) 필수 - 백스택 사용 시 반드시 설정
- Lifecycle 콜백을 적절히 활용 - onPause는 포커스 잃을 때, onStop은 보이지 않을 때
- Fragment 전용 백스택으로 뒤로가기 동작 제어 - Activity 백스택과 별개
- Fragment는 Object 상속 - Context가 아니므로 getContext()로 접근
- Fragment View Binding - onDestroyView()에서 null 설정하여 메모리 누수 방지
리소스 사용량 관련 주의:
- add/remove: 메모리 효율적, 완전 생성/소멸
- attach/detach: 중간 수준, View만 소멸/재생성
- show/hide: 메모리 사용량 많음, View 계속 유지
'CS 기초부터 한 걸음씩' 카테고리의 다른 글
| [WSL2] 윈도우-리눅스 파일 시스템 상호운용성 정리 (0) | 2026.02.26 |
|---|---|
| [Android] Jetpack Compose 기본 개념 - View 시스템과의 차이점 (2) | 2025.08.25 |
| [Android] XML 레이아웃과 View 기본 개념 (0) | 2025.08.20 |
| [Android] 안드로이드 앱 구조 정리 (1) | 2025.08.19 |
| [Android] Android Studio Logcat과 로그 레벨 (3) | 2025.08.18 |