Skip to content

[Fix] 식당 정보 바텀시트 Glide 크래시를 방지해요#497

Merged
PeraSite merged 1 commit intodevelopfrom
fix/glide-load-crash
Mar 15, 2026
Merged

[Fix] 식당 정보 바텀시트 Glide 크래시를 방지해요#497
PeraSite merged 1 commit intodevelopfrom
fix/glide-load-crash

Conversation

@PeraSite
Copy link
Member

@PeraSite PeraSite commented Mar 9, 2026

Summary

바텀 시트를 닫은 직후 식당 이미지 로드가 이어지면 Fragment가 detach된 상태에서 Glide.with(fragment)가 호출되어 NPE가 발생했어요.

  • CoroutineScope(Dispatchers.Main)로 띄운 작업이 view lifecycle과 분리되어 있어서 BottomSheet가 닫힌 뒤에도 UI 업데이트가 이어질 수 있었어요.
  • 코루틴을 viewLifecycleOwner.lifecycleScope에 묶고, 뷰가 살아있을 때만 binding/Glide를 사용하도록 바꿨어요.

Describe your changes

  • InfoBottomSheetFragment.kt
    • CoroutineScope(Dispatchers.Main)viewLifecycleOwner.lifecycleScope로 변경
    • 코루틴 재개 시 _binding이 null이면 바로 return 하도록 방어 로직 추가
    • Glide.with(this@InfoBottomSheetFragment) 대신 Glide.with(binding.ivCafeteriaPhoto)로 요청을 view에 묶음
    • onDestroyView()에서 binding 정리 추가

Issue

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 식당 정보 바텀 시트가 닫힌 직후 이미지 로딩이 진행될 때 발생할 수 있는 NullPointerException 크래시를 해결합니다. 뷰의 라이프사이클과 독립적으로 실행되던 코루틴 작업을 뷰 라이프사이클에 종속시키고, 뷰 바인딩 객체에 대한 안전한 접근 로직을 추가하여 프래그먼트가 detach된 상태에서 UI 업데이트가 시도되는 것을 방지합니다.

Highlights

  • 코루틴 스코프 변경: 기존의 CoroutineScope(Dispatchers.Main)viewLifecycleOwner.lifecycleScope로 변경하여 뷰의 라이프사이클에 맞춰 코루틴 작업을 안전하게 관리하도록 했습니다.
  • 바인딩 안전성 강화: 코루틴 재개 시 _binding이 null인지 확인하는 방어 로직을 추가하여 프래그먼트가 detach된 상태에서 UI 업데이트 시 발생할 수 있는 NullPointerException을 방지했습니다.
  • Glide 컨텍스트 개선: Glide.with() 호출 시 프래그먼트 대신 특정 뷰(binding.ivCafeteriaPhoto)를 컨텍스트로 사용하여, 뷰의 라이프사이클에 더 안전하게 이미지 로딩이 바인딩되도록 했습니다.
  • 뷰 바인딩 정리: onDestroyView() 메서드에서 _binding을 명시적으로 null로 설정하여 메모리 누수를 방지하고 뷰가 파괴된 후 바인딩 객체에 접근하는 것을 막았습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • app/src/main/java/com/eatssu/android/presentation/cafeteria/info/InfoBottomSheetFragment.kt
    • CoroutineScope(Dispatchers.Main)viewLifecycleOwner.lifecycleScope로 변경했습니다.
    • 코루틴 내에서 _binding이 null일 경우 작업을 즉시 종료하는 방어 로직을 추가했습니다.
    • Glide.with()의 컨텍스트를 프래그먼트에서 이미지 뷰로 변경했습니다.
    • onDestroyView() 메서드에서 _binding을 null로 설정하여 바인딩을 정리했습니다.
Activity
  • 작성자가 InfoBottomSheetFragment에서 바텀 시트 dismiss 이후 Glide.with(...) 호출 시 발생한 NPE 관련 크래시를 해결하기 위해 PR을 생성했습니다.
  • 작성자는 BottomSheet를 빠르게 열고 닫을 때 이미지 로드가 안전하게 취소되는지 리뷰어에게 확인을 요청했습니다.
  • 작성자는 로컬 빌드 환경 문제로 인해 특정 확인을 수행하지 못했음을 언급했습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@PeraSite PeraSite requested a review from HI-JIN2 March 9, 2026 02:48
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

안녕하세요. 식당 정보 바텀시트에서 발생하는 Glide 크래시를 해결하기 위한 변경 사항을 리뷰했습니다. CoroutineScopeviewLifecycleOwner.lifecycleScope로 변경하고, 뷰의 생명주기에 맞춰 바인딩 객체를 안전하게 처리하도록 수정한 점이 인상적입니다. 이로써 Fragment가 detach된 이후에 UI 업데이트를 시도하여 발생하던 NPE를 효과적으로 방지할 수 있을 것으로 보입니다. 한 가지 가독성 향상을 위한 제안을 리뷰 코멘트로 남겼으니 확인 부탁드립니다.

Comment on lines +46 to 56
val binding = _binding ?: return@launch

restaurantInfo?.let {
binding.tvLocation.text = it.location
binding.tvTime.text = it.time
binding.tvEtc.text = it.etc

Glide.with(this@InfoBottomSheetFragment)
Glide.with(binding.ivCafeteriaPhoto)
.load(it.image)
.into(binding.ivCafeteriaPhoto)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

코루틴 내에서 binding이라는 이름의 지역 변수를 선언하여 사용하고 계십니다. 이 변수는 클래스 레벨의 binding 프로퍼티를 가리는(shadowing) 효과가 있어, 코드를 읽을 때 혼동을 줄 수 있습니다. 가독성 향상과 잠재적인 버그 방지를 위해, safeBinding과 같이 명확한 이름으로 변경하는 것을 제안합니다.

Suggested change
val binding = _binding ?: return@launch
restaurantInfo?.let {
binding.tvLocation.text = it.location
binding.tvTime.text = it.time
binding.tvEtc.text = it.etc
Glide.with(this@InfoBottomSheetFragment)
Glide.with(binding.ivCafeteriaPhoto)
.load(it.image)
.into(binding.ivCafeteriaPhoto)
}
val safeBinding = _binding ?: return@launch
restaurantInfo?.let {
safeBinding.tvLocation.text = it.location
safeBinding.tvTime.text = it.time
safeBinding.tvEtc.text = it.etc
Glide.with(safeBinding.ivCafeteriaPhoto)
.load(it.image)
.into(safeBinding.ivCafeteriaPhoto)
}

Copy link
Member

@HI-JIN2 HI-JIN2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이런 버그가 있었군요;;;
이것도 컴포즈로 고고링

@PeraSite PeraSite merged commit 38ecefb into develop Mar 15, 2026
2 checks passed
@PeraSite PeraSite deleted the fix/glide-load-crash branch March 15, 2026 23:37
@PeraSite PeraSite mentioned this pull request Mar 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants