[Android] Fragment 개념 정리

2025. 8. 21. 21:20·CS 기초부터 한 걸음씩

Fragment 개념

다른 화면 크기에서 동일한 화면의 두 가지 버전. 왼쪽에 있는 큰 화면에는 활동에서 제어하는 탐색 창과 프래그먼트에서 제어하는 그리드 목록이 포함 오른쪽에 있는 작은 화면에는 활동에서 제어하는 하단 탐색 메뉴와 프래그먼트에서 제어하는 선형 목록이 포함 https://developer.android.com/guide/fragments?hl=ko

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 관계

프래그먼트  Lifecycle  상태와 프래그먼트의 수명 주기 콜백 및 프래그먼트의 뷰  Lifecycle 와의 관계 https://developer.android.com/guide/fragments/lifecycle?hl=ko

 

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들에 대한 작업(추가, 제거, 교체)을 수행하는 책임을 가진 클래스

주요 역할

  1. Fragment 관리: Fragment의 추가, 제거, 교체, 탐색
  2. Back Stack 관리: Fragment 트랜잭션의 백스택 관리
  3. 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

핵심 포인트 정리

  1. Fragment는 Activity에 의존적 - 혼자 존재할 수 없음
  2. FragmentManager가 Fragment들을 관리 - 추가, 제거, 교체 담당
  3. FragmentTransaction으로 변경사항을 원자적으로 처리 - 여러 작업을 하나의 단위로 그룹화
  4. setReorderingAllowed(true) 필수 - 백스택 사용 시 반드시 설정
  5. Lifecycle 콜백을 적절히 활용 - onPause는 포커스 잃을 때, onStop은 보이지 않을 때
  6. Fragment 전용 백스택으로 뒤로가기 동작 제어 - Activity 백스택과 별개
  7. Fragment는 Object 상속 - Context가 아니므로 getContext()로 접근
  8. 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
'CS 기초부터 한 걸음씩' 카테고리의 다른 글
  • [WSL2] 윈도우-리눅스 파일 시스템 상호운용성 정리
  • [Android] Jetpack Compose 기본 개념 - View 시스템과의 차이점
  • [Android] XML 레이아웃과 View 기본 개념
  • [Android] 안드로이드 앱 구조 정리
Celion
Celion
오늘도 평소처럼 화이팅!
  • Celion
    Orion Log
    Celion
  • 전체
    오늘
    어제
    • 전체 글 (144)
      • Uncompiled Thoughts (8)
        • 네이버 부스트캠프 10기 (5)
      • CS 기초부터 한 걸음씩 (34)
      • Code Odyssey (22)
      • Algorithm (77)
        • Coding Test Records (63)
      • Git (3)
      • reference (0)
  • 블로그 메뉴

    • 태그
    • 방명록
  • 태그

    Level3
    알고리즘고득점kit
    백준
    문법정리
    시뮬레이션
    프로그래머스
    java
    Kotlin
    Level2
    greedy
    boostcamp
    코테
  • 최근 글

  • 인기 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.4
Celion
[Android] Fragment 개념 정리
상단으로

티스토리툴바