-
Notifications
You must be signed in to change notification settings - Fork 2
[refactor] 둘러보기, 나의 cd 코드 리팩토링 #106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0af3a3e
e58de60
610304d
5d6988a
c9450ba
2ea1fc6
7b6700c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,4 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { createContext, useState, useContext, type ReactNode } from 'react' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { createContext, useState, useContext, useRef, useCallback, type ReactNode } from 'react' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { PlaylistInfo } from '@/entities/playlist' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -13,6 +13,8 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nextTrack: () => void | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| prevTrack: () => void | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| updateCurrentTime: (time: number) => void | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| playerRef: React.MutableRefObject<YT.Player | null> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handlePlayerStateChange: (event: YT.OnStateChangeEvent) => void | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface PlaylistProviderProps { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -23,37 +25,58 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const PlaylistProvider = ({ children }: PlaylistProviderProps) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [currentPlaylist, setCurrentPlaylist] = useState<PlaylistInfo | null>(null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [currentTrackIndex, setCurrentTrackIndex] = useState<number>(0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [isPlaying, setIsPlaying] = useState<boolean>(false) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [currentTime, setCurrentTime] = useState<number>(0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [currentTrackIndex, setCurrentTrackIndex] = useState(0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [currentTime, setCurrentTime] = useState(0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [isPlaying, setIsPlaying] = useState(false) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const playerRef = useRef<YT.Player | null>(null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const setPlaylist = (playlist: PlaylistInfo, trackIndex?: number, time?: number) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setCurrentPlaylist(playlist) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (trackIndex !== undefined) setCurrentTrackIndex(trackIndex) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (time !== undefined) setCurrentTime(time) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setIsPlaying(true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (playerRef.current) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (time !== undefined) playerRef.current.seekTo(time, true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| playerRef.current.playVideo() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const play = () => setIsPlaying(true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const pause = () => setIsPlaying(false) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const play = useCallback(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (playerRef.current) playerRef.current.playVideo() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setIsPlaying(true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, []) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const pause = useCallback(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (playerRef.current) playerRef.current.pauseVideo() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setIsPlaying(false) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, []) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const nextTrack = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const nextTrack = useCallback(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (currentPlaylist && currentTrackIndex < currentPlaylist.songs.length - 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setCurrentTrackIndex((prevIndex) => prevIndex + 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setCurrentTrackIndex((prev) => prev + 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setCurrentTime(0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (playerRef.current) playerRef.current.seekTo(0, true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [currentPlaylist, currentTrackIndex]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+56
to
63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다음 트랙 이동 시 seekTo(0)는 세그먼트 기반 모델에서 오동작 가능 앨범 1개 영상에 트랙 세그먼트를 매핑(누적 시간 모델)한다면, 트랙 시작 누적 시점으로 seek 해야 합니다. 0초로 이동하면 항상 영상 처음으로 돌아갑니다. getAccTime 유틸을 활용해 누적 시작 시점으로 이동하도록 수정 제안합니다. - const nextTrack = useCallback(() => {
- if (currentPlaylist && currentTrackIndex < currentPlaylist.songs.length - 1) {
- setCurrentTrackIndex((prev) => prev + 1)
- setCurrentTime(0)
- if (playerRef.current) playerRef.current.seekTo(0, true)
- }
- }, [currentPlaylist, currentTrackIndex])
+ const nextTrack = useCallback(() => {
+ if (!currentPlaylist) return
+ if (currentTrackIndex >= currentPlaylist.songs.length - 1) return
+ const nextIndex = currentTrackIndex + 1
+ setCurrentTrackIndex(nextIndex)
+ setCurrentTime(0)
+ // FIXME: 아래 trackLengths는 실제 트랙 길이(초) 배열로 매핑하세요.
+ // 예: const trackLengths = currentPlaylist.songs.map((s) => s.lengthSec)
+ // 혹은 데이터 구조에 맞는 속성으로 교체
+ const trackLengths: number[] =
+ currentPlaylist.songs.map((/* s */) => /* lengthSec */ 0) // TODO: implement
+ if (playerRef.current) {
+ const acc = getAccTime(trackLengths, nextIndex, 0)
+ playerRef.current.seekTo(acc, true)
+ }
+ }, [currentPlaylist, currentTrackIndex])추가: 상단 import -import { createContext, useState, useContext, useRef, useCallback, type ReactNode } from 'react'
+import { createContext, useState, useContext, useRef, useCallback, type ReactNode } from 'react'
+import { getAccTime } from '@/shared/lib'📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const prevTrack = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const prevTrack = useCallback(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (currentTrackIndex > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setCurrentTrackIndex((prevIndex) => prevIndex - 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setCurrentTrackIndex((prev) => prev - 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setCurrentTime(0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (playerRef.current) playerRef.current.seekTo(0, true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [currentTrackIndex]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+64
to
71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이전 트랙 이동도 누적 시작 시점으로 seek 필요 prevTrack도 동일하게 누적 시작 시점으로 이동해야 합니다. - const prevTrack = useCallback(() => {
- if (currentTrackIndex > 0) {
- setCurrentTrackIndex((prev) => prev - 1)
- setCurrentTime(0)
- if (playerRef.current) playerRef.current.seekTo(0, true)
- }
- }, [currentTrackIndex])
+ const prevTrack = useCallback(() => {
+ if (!currentPlaylist) return
+ if (currentTrackIndex <= 0) return
+ const prevIndex = currentTrackIndex - 1
+ setCurrentTrackIndex(prevIndex)
+ setCurrentTime(0)
+ const trackLengths: number[] =
+ currentPlaylist.songs.map((/* s */) => /* lengthSec */ 0) // TODO: implement
+ if (playerRef.current) {
+ const acc = getAccTime(trackLengths, prevIndex, 0)
+ playerRef.current.seekTo(acc, true)
+ }
+ }, [currentPlaylist, currentTrackIndex])
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const updateCurrentTime = (time: number) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setCurrentTime(time) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const updateCurrentTime = (time: number) => setCurrentTime(time) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Style Guide ReferencesFootnotes |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handlePlayerStateChange = useCallback( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (event: YT.OnStateChangeEvent) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (event.data === window.YT.PlayerState.ENDED) nextTrack() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [nextTrack] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const value = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| currentPlaylist, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -66,6 +89,8 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nextTrack, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| prevTrack, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| updateCurrentTime, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| playerRef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handlePlayerStateChange, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return <PlaylistContext.Provider value={value}>{children}</PlaylistContext.Provider> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -73,10 +98,8 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default PlaylistProvider | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const usePlaylist = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const context = useContext(PlaylistContext) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (context === undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error('usePlaylist must be used within a PlaylistProvider') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!context) throw new Error('usePlaylist must be used within a PlaylistProvider') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return context | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setPlaylist함수를useCallback으로 감싸서 불필요한 리렌더링을 방지하는 것이 좋습니다. 현재 구현에서는PlaylistProvider가 리렌더링될 때마다 새로운setPlaylist함수가 생성되어, 이를 사용하는 자식 컴포넌트들도 함께 리렌더링될 수 있습니다.setState함수와ref는 항상 동일한 참조를 유지하므로 의존성 배열은 비워두어도 괜찮습니다. 1Style Guide References
Footnotes
React의
useCallback을 사용하여 불필요한 함수 생성을 방지하고, 이를 통해 자식 컴포넌트의 불필요한 리렌더링을 줄여 성능을 최적화해야 합니다. (link) ↩