Skip to content

Conversation

@0Hooni
Copy link
Member

@0Hooni 0Hooni commented Oct 29, 2025

📌 이슈

✅ 작업 사항

  • Timer 객체를 약한 참조로 수정
  • Cell의 라이프 사이클에 맞춰 타이머를 정지
  • ViewController의 라이프 사이클에 맞춰 타이머 시작 또는 정지

Summary by CodeRabbit

릴리스 노트

  • 버그 수정
    • 배너 자동 스크롤이 화면 표시 시에는 시작되고 화면 이동 시에는 중지되도록 개선했습니다.
    • 배너 관련 메모리 누수를 해결했습니다.

- Timer 자체를 약한 참조로 수정
- reuse시 타이머 정지
- 홈 화면의 뷰 사이클에 맞춰 타이머 시작/정지
@0Hooni 0Hooni self-assigned this Oct 29, 2025
@0Hooni 0Hooni added the 🐛 fix 버그 수정, 잔잔바리 수정, 병합 시 충돌 해결 label Oct 29, 2025
@coderabbitai
Copy link

coderabbitai bot commented Oct 29, 2025

개요

홈 화면 컨트롤러의 생명 주기 이벤트와 배너 섹션 셀의 메모리 관리를 개선했습니다. 뷰가 나타날 때 배너 자동 스크롤을 재개하고, 사라질 때 중지하도록 구성했으며, 타이머 순환 참조를 방지하고 셀 재사용 및 해제 시 정리 로직을 추가했습니다.

변경 사항

응집도 / 파일 변경 요약
배너 자동 스크롤 생명 주기 관리
HomeController.swift
viewWillAppear에서 restartBannerAutoScroll() 호출 추가, viewWillDisappear에서 stopBannerAutoScroll() 호출 추가. 컬렉션 뷰의 첫 번째 항목(row: 0, section: 0)에서 ImageBannerSectionCell을 찾아 자동 스크롤 상태 제어
배너 셀 메모리 관리 및 타이머 최적화
ImageBannerSectionCell.swift
autoScrollTimer를 약한 참조로 변경하여 순환 참조 방지. prepareForReuse()와 deinit에서 stopAutoScroll() 호출 추가. stopAutoScroll() 메서드 확장: 타이머 무효화 외에도 중지 버튼 숨김, 재생 버튼 표시, isAutoBannerPlay 리셋 처리. deinit 추가하여 셀 해제 시 정리 보장

시퀀스 다이어그램

sequenceDiagram
    participant VC as HomeController
    participant CV as UICollectionView
    participant Cell as ImageBannerSectionCell
    participant Timer as AutoScrollTimer

    Note over VC: viewWillAppear()
    VC->>CV: indexPathForItem(row: 0, section: 0)
    CV->>Cell: 셀 조회
    Cell->>Timer: startAutoScroll() 시작
    Timer->>Cell: 자동 스크롤 활성화

    Note over VC: viewWillDisappear()
    VC->>CV: indexPathForItem(row: 0, section: 0)
    CV->>Cell: 셀 조회
    Cell->>Timer: stopAutoScroll() 중지
    Timer-->>Cell: 타이머 무효화
    Cell->>Cell: UI 업데이트 (버튼, 플래그)

    Note over Cell: prepareForReuse() 또는 deinit
    Cell->>Timer: stopAutoScroll() 호출
    Timer-->>Cell: 타이머 정리
    Note over Cell: 메모리 안전 보장
Loading

코드 리뷰 난이도 추정

🎯 2 (Simple) | ⏱️ ~12분

  • 주의 깊게 검토할 영역:
    • 약한 참조 전환 시 autoScrollTimer가 예기치 않게 해제되지 않는지 확인
    • stopAutoScroll()의 모든 호출 지점에서 UI 상태 업데이트(버튼 표시/숨김, 플래그 리셋)가 올바르게 수행되는지 검증
    • viewWillAppearviewWillDisappear에서 셀이 항상 찾아지는지, nil 처리 로직 확인
    • 메모리 누수 또는 이중 정리(double cleanup) 가능성 검토

🐰 배너는 춤을 춘다네, 나타났다가 사라졌다가,
타이머는 약하게 손을 놓고, 순환은 끊겼네.
셀이 재사용될 때 정갈히 정리되고,
자동 스크롤은 생명 주기 속에서 안녕히~ 💫

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed PR 제목 "[FIX] Timer가 계속 메모리에 남아 동작하는 문제 수정"은 변경사항의 핵심을 명확하게 전달합니다. 실제 변경사항은 Timer를 약한 참조로 수정하고, Cell과 ViewController의 라이프사이클에 맞춰 타이머 제어를 추가한 것이며, 이는 메모리에 남아있던 타이머 문제를 해결하기 위한 수정입니다. 제목은 간결하고 구체적이며, 실제 변경사항과 일치합니다.
Description Check ✅ Passed PR 설명은 리포지토리의 템플릿을 적절히 따르고 있습니다. 필수 섹션인 "📌 이슈"에서 #180을 명시하였고, "✅ 작업 사항"에서 Timer 약한 참조 수정, Cell 라이프사이클 대응, ViewController 라이프사이클 대응의 세 가지 작업을 체크하여 나열했습니다. 이는 실제 변경사항과 정렬되어 있으며, 템플릿의 선택사항인 "🚀 테스트 방식"과 "👀 ETC" 섹션은 제거된 상태입니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/#180-stop-home-banner-timer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
Poppool/PresentationLayer/Presentation/Presentation/Scene/Home/Main/View/ImageBannerSection/ImageBannerSection/ImageBannerSectionCell.swift (1)

103-103: 들여쓰기 일관성 확인이 필요합니다.

이 줄의 들여쓰기가 주변 코드와 다른 것으로 보입니다(탭 문자 사용으로 추정). 프로젝트의 코딩 스타일 가이드에 맞춰 일관된 들여쓰기를 사용하는 것이 좋습니다.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 168cea9 and 9d9ec9a.

📒 Files selected for processing (2)
  • Poppool/PresentationLayer/Presentation/Presentation/Scene/Home/Main/HomeController.swift (2 hunks)
  • Poppool/PresentationLayer/Presentation/Presentation/Scene/Home/Main/View/ImageBannerSection/ImageBannerSection/ImageBannerSectionCell.swift (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Poppool/PresentationLayer/Presentation/Presentation/Scene/Home/Main/HomeController.swift (1)
Poppool/PresentationLayer/Presentation/Presentation/Scene/Home/Main/View/ImageBannerSection/ImageBannerSection/ImageBannerSectionCell.swift (2)
  • stopAutoScroll (86-92)
  • startAutoScroll (96-110)
🔇 Additional comments (5)
Poppool/PresentationLayer/Presentation/Presentation/Scene/Home/Main/View/ImageBannerSection/ImageBannerSection/ImageBannerSectionCell.swift (3)

14-14: 타이머 약한 참조 변경이 적절합니다.

Timerweak으로 선언한 것은 올바른 접근입니다. scheduledTimer로 생성된 타이머는 run loop에 의해 유지되므로, 셀이 타이머를 강하게 참조할 필요가 없으며 이를 통해 잠재적인 retain cycle을 방지할 수 있습니다.


76-76: 셀 재사용 시 타이머 정리가 적절합니다.

prepareForReuse()에서 stopAutoScroll()을 호출하여 셀이 재사용될 때 타이머를 정리하는 것은 좋은 관행입니다. 이를 통해 이전 셀 인스턴스의 타이머가 계속 실행되는 것을 방지할 수 있습니다.


81-83: deinit에서의 정리가 적절합니다.

셀이 메모리에서 해제될 때 stopAutoScroll()을 호출하여 타이머를 정리하는 것은 리소스 누수 방지를 위한 좋은 방어적 프로그래밍입니다.

Poppool/PresentationLayer/Presentation/Presentation/Scene/Home/Main/HomeController.swift (2)

43-46: 뷰가 사라질 때 타이머를 중지하는 것은 좋습니다.

메모리 누수를 방지하기 위해 viewWillDisappear에서 타이머를 중지하는 것은 적절한 접근입니다.

다만, stopBannerAutoScroll()이 셀이 보이지 않을 때 작동하지 않을 수 있으므로, 사용자가 스크롤하여 배너 셀이 화면 밖에 있을 때의 동작을 테스트하여 타이머가 적절히 중지되는지 확인하세요.


40-41: viewWillAppear에서의 배너 재시작 시점 재검토 권장

코드는 if let으로 안전하게 nil을 처리하므로 크래시 위험은 없습니다. 다만 viewWillAppearviewDidAppear보다 먼저 호출되므로, 이 시점에 컬렉션 뷰 레이아웃이 완료되지 않아 셀이 접근 불가능할 수 있습니다. 결과적으로 배너 자동 스크롤이 화면 전환 시 신뢰성 있게 시작되지 않을 수 있습니다.

다음 중 하나를 고려하세요:

  • viewDidAppear로 변경 (레이아웃 완료 후)
  • 또는 컬렉션 뷰의 layout completion을 기다린 후 타이머 시작

Comment on lines +138 to +150
private func stopBannerAutoScroll() {
let indexPath = IndexPath(row: 0, section: 0) // 배너 섹션 인덱스
if let cell = mainView.contentCollectionView.cellForItem(at: indexPath) as? ImageBannerSectionCell {
cell.stopAutoScroll()
}
}

private func restartBannerAutoScroll() {
let indexPath = IndexPath(row: 0, section: 0)
if let cell = mainView.contentCollectionView.cellForItem(at: indexPath) as? ImageBannerSectionCell {
cell.startAutoScroll()
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

cellForItem(at:) 사용의 한계를 고려해야 합니다.

두 헬퍼 메서드 모두 cellForItem(at:)을 사용하여 배너 셀에 접근하는데, 이 메서드는 셀이 현재 화면에 보이는 경우에만 셀을 반환합니다. 사용자가 스크롤하여 배너가 화면 밖에 있는 경우, 이 메서드들은 아무 동작도 하지 않습니다.

더 견고한 접근 방법을 고려하세요:

  • 셀 자체의 생명주기 메서드(willMove(toWindow:) 등)에서 타이머를 관리
  • 또는 뷰 컨트롤러에서 배너 섹션의 타이머 상태를 직접 추적

다음 개선 방안을 적용할 수 있습니다:

private func stopBannerAutoScroll() {
    let indexPath = IndexPath(row: 0, section: 0)
    if let cell = mainView.contentCollectionView.cellForItem(at: indexPath) as? ImageBannerSectionCell {
        cell.stopAutoScroll()
    }
    // 대안: 섹션 데이터 모델에 상태를 저장하여 셀이 나타날 때 적용
}

private func restartBannerAutoScroll() {
    let indexPath = IndexPath(row: 0, section: 0)
    if let cell = mainView.contentCollectionView.cellForItem(at: indexPath) as? ImageBannerSectionCell {
        cell.startAutoScroll()
    }
    // 대안: 섹션 데이터 모델에 상태를 저장하여 셀이 나타날 때 적용
}

또는 UICollectionViewDelegatewillDisplay 메서드를 활용하는 방법도 고려하세요.

🤖 Prompt for AI Agents
Poppool/PresentationLayer/Presentation/Presentation/Scene/Home/Main/HomeController.swift
lines 138-150: stopBannerAutoScroll() and restartBannerAutoScroll() rely on
cellForItem(at:) which returns a cell only if it's visible, so they silently do
nothing when the banner cell is offscreen; fix by tracking the banner timer
state in the controller or section model and ensuring the cell applies that
state when it appears, or move timer control into the cell lifecycle: (1) add a
Bool flag (e.g., isBannerAutoScrollEnabled) in the view controller or section
data and set it in stopBannerAutoScroll/restartBannerAutoScroll instead of only
calling cell methods, (2) implement collectionView(_:willDisplay:forItemAt:) to
start/stop the cell’s auto-scroll based on that flag when the cell is about to
appear, or (3) alternatively, move timer management into ImageBannerSectionCell
(override willMove(toWindow:) or didMoveToWindow) so the cell starts/stops its
timer when added/removed from window and expose public start/stop only for
explicit controller overrides.

@0Hooni 0Hooni merged commit 799fbd7 into develop Nov 12, 2025
3 checks passed
@0Hooni 0Hooni deleted the fix/#180-stop-home-banner-timer branch November 12, 2025 13:04
0Hooni added a commit that referenced this pull request Nov 12, 2025
fix/#180: Timer가 계속 메모리에 남아 동작하는 문제 수정

- Timer 자체를 약한 참조로 수정
- reuse시 타이머 정지
- 홈 화면의 뷰 사이클에 맞춰 타이머 시작/정지
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 fix 버그 수정, 잔잔바리 수정, 병합 시 충돌 해결

Projects

None yet

Development

Successfully merging this pull request may close these issues.

홈화면 무한 캐러셀이 지속적으로 다른 페이지에서도 동작하는 문제 수정

2 participants