반응형
Notice
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- 네트워크보안
- 네트워크
- 자료구조
- 데이터과학
- I'm Sorry
- 버전관리
- 데이터베이스
- 프로그래밍
- springboot
- 컴퓨터비전
- Yes
- 보안
- 소프트웨어공학
- 데이터분석
- 데이터구조
- 사이버보안
- 프로그래밍언어
- 디자인패턴
- 빅데이터
- 클라우드컴퓨팅
- 웹개발
- 파이썬
- 머신러닝
- 소프트웨어
- 자바스크립트
- 인공지능
- 딥러닝
- 알고리즘
- 컴퓨터과학
- 컴퓨터공학
Archives
- Today
- Total
스택큐힙리스트
이어보기 완성! Iterator + Memento로 구현한 플레이백 히스토리 본문
반응형
동영상/오디오 앱에서 “지난번 보던 자리부터 이어보기” 는 필수 UX입니다.
이 기능은 사실 두 가지 디자인 패턴이 만나면 깔끔하게 풀립니다.
- Memento – 플레이어의 ‘스냅샷’을 저장·복원해 재생 위치를 되살린다.
- Iterator – 저장된 스냅샷 목록을 순회해 최근 기록을 탐색‧표시한다.
아래 예시는 조회수 높은 한국 안드로이드 블로그들의 패턴 사용법을 베이스로, 실제 서비스 코드 형태로 재구성했습니다.
1. 핵심 클래스 설계
- PlayerState (Memento)
@JvmInline value class PlayerState(val positionMs: Long)
- 불변(immutable)이라 복원 시 사이드이펙트 없음.
- VideoPlayer (Originator)
class VideoPlayer(private val exo: ExoPlayer) { fun save() = PlayerState(exo.currentPosition) fun restore(state: PlayerState) { exo.seekTo(state.positionMs) } }
PlayHistory (Caretaker + Iterable)
class PlayHistory : Iterable<PlayerState> {
private val history = ArrayDeque<PlayerState>() // 최신 → 오래된 순
fun push(state: PlayerState) { history.addFirst(state) } // 저장
fun iterator() = history.iterator() // Iterator 패턴
}
2. 저장·복원 흐름
val player = VideoPlayer(exo)
val history = PlayHistory()
// ► 사용자가 시청 중일 때 주기적으로 or onPause 시점 저장
lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onPause(owner: LifecycleOwner) {
history.push(player.save())
}
})
// ▶ 앱 재실행 후 이어보기
for (state in history) { // Iterator 순회
// UI에 “10분 12초까지 봤어요”처럼 표시
showResumeButton(state.positionMs)
}
resumeButton.setOnClickListener {
player.restore(history.first()) // 가장 최근 상태 복원
}
- Iterator 덕분에 for (state in history) 처럼 깔끔하게 순회합니다.
- Memento 로 캡슐화가 유지돼 VideoPlayer 내부 구현을 외부가 모를 수 있습니다.
3. 실전 팁
- 스냅샷 크기 최소화
위치·속도·자막 언어 등 필요한 필드만 담아 메모리 낭비를 줄입니다. - 저장 빈도 전략
- 배터리 절약을 위해 onPause, every 30 sec 와 같이 타임아웃을 두세요.
- 보관 주기 관리
ArrayDeque 용량을 제한하거나, 30일 이상 지난 항목은 Iterator 순회 전에 제거해서 DB‧SharedPref를 슬림하게 유지합니다. - 멀티 디바이스 싱크
Caretaker가 Firebase/Hasura 같은 실시간 DB로 직렬화-업로드하면 어떤 기기에서도 즉시 이어볼 수 있습니다. - Unit Test
Iterator는 단순 순서 보장만 확인하면 되므로 assertEquals(listOf(state3,state2,state1), history.toList()) 정도면 충분합니다.
4. 한 줄 정리
Iterator로 “히스토리를 탐색”하고, Memento로 “시간을 복원”하면 이어보기 UX가 자연스레 완성된다.
반응형
'개발' 카테고리의 다른 글
Visitor 패턴: “구조는 그대로, 기능은 덧붙여” (3) | 2025.07.30 |
---|---|
Memento 패턴: “되돌리기(Undo)”를 코드로 구현하는 가장 깔끔한 방법 (0) | 2025.07.30 |
MediatorLiveData 제대로 쓰는 7가지 실전 팁 (2) | 2025.07.30 |
Kotlin also 한눈에 이해하기 (1) | 2025.07.29 |
Mediator 패턴: 복잡한 객체 의존을 한 방에 정리하기 (2) | 2025.07.29 |
Comments