[251124] fix: App.js 로그 정리 및 최적화

🕐 커밋 시간: 2025. 11. 24. 09:08:54

📊 변경 통계:
  • 총 파일: 10개
  • 추가: +93줄
  • 삭제: -97줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/App/App.js
  ~ com.twin.app.shoptime/src/components/MediaItem/MediaItem.module.less
  ~ com.twin.app.shoptime/src/components/MobileSend/PhoneInputSection.module.less
  ~ com.twin.app.shoptime/src/components/TPopUp/TNewPopUp.module.less
  ~ com.twin.app.shoptime/src/hooks/useVideoPlay/useVideoPlay.js
  ~ com.twin.app.shoptime/src/views/DetailPanel/ProductOverview/ProductOverview.module.less
  ~ com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.jsx
  ~ com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx
  ~ com.twin.app.shoptime/src/views/MyPagePanel/MyPageSub/TermsOfService/TermsOfOptional.module copy.less
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx

🔧 함수 변경 내용:
  📄 com.twin.app.shoptime/src/App/App.js (javascript):
    🔄 Modified: resolveSpotlightIdFromEvent()
     Deleted: handleFocusLog(), handleBlurLog()
  📄 com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx (javascript):
    🔄 Modified: normalizeModalStyle()

🔧 주요 변경 내용:
  • 핵심 비즈니스 로직 개선
  • UI 컴포넌트 아키텍처 개선
  • API 서비스 레이어 개선

Performance: 코드 최적화로 성능 개선 기대
This commit is contained in:
2025-11-24 09:08:54 +09:00
parent 3b95810946
commit 6d0cf78534
10 changed files with 83 additions and 87 deletions

View File

@@ -465,56 +465,55 @@ function AppBase(props) {
// const termsFlag = useSelector((state) => state.common.termsFlag); // const termsFlag = useSelector((state) => state.common.termsFlag);
const termsData = useSelector((state) => state.home.termsData); const termsData = useSelector((state) => state.home.termsData);
// 🔽 Spotlight focus/blur 로그 (옵션) // // 🔽 Spotlight focus/blur 로그 (옵션)
useEffect(() => { // useEffect(() => {
if (!Config.FOCUS_DEBUG) { // if (!Config.FOCUS_DEBUG) {
return undefined; // return undefined;
} // }
const handleFocusLog = (event) => { // const handleFocusLog = (event) => {
const spotlightId = resolveSpotlightIdFromEvent(event); // const spotlightId = resolveSpotlightIdFromEvent(event);
if (!spotlightId || spotlightId === lastLoggedSpotlightId) { // if (!spotlightId || spotlightId === lastLoggedSpotlightId) {
return; // return;
} // }
console.log(`[SpotlightFocus] focus - ${spotlightId}`); // console.log(`[SpotlightFocus] focus - ${spotlightId}`);
lastLoggedSpotlightId = spotlightId; // lastLoggedSpotlightId = spotlightId;
}; // };
const handleBlurLog = (event) => { // const handleBlurLog = (event) => {
const spotlightId = resolveSpotlightIdFromEvent(event); // const spotlightId = resolveSpotlightIdFromEvent(event);
if (!spotlightId || spotlightId === lastLoggedBlurSpotlightId) { // if (!spotlightId || spotlightId === lastLoggedBlurSpotlightId) {
return; // return;
} // }
console.log(`[SpotlightFocus] blur - ${spotlightId}`); // console.log(`[SpotlightFocus] blur - ${spotlightId}`);
lastLoggedBlurSpotlightId = spotlightId; // lastLoggedBlurSpotlightId = spotlightId;
}; // };
const hasSpotlightListener = typeof Spotlight.addEventListener === 'function'; // const hasSpotlightListener = typeof Spotlight.addEventListener === 'function';
if (hasSpotlightListener) { // if (hasSpotlightListener) {
Spotlight.addEventListener('focus', handleFocusLog); // Spotlight.addEventListener('focus', handleFocusLog);
Spotlight.addEventListener('blur', handleBlurLog); // Spotlight.addEventListener('blur', handleBlurLog);
return () => { // return () => {
Spotlight.removeEventListener('focus', handleFocusLog); // Spotlight.removeEventListener('focus', handleFocusLog);
Spotlight.removeEventListener('blur', handleBlurLog); // Spotlight.removeEventListener('blur', handleBlurLog);
}; // };
} // }
if (typeof document !== 'undefined') { // if (typeof document !== 'undefined') {
document.addEventListener('spotlightfocus', handleFocusLog); // document.addEventListener('spotlightfocus', handleFocusLog);
document.addEventListener('spotlightblur', handleBlurLog); // document.addEventListener('spotlightblur', handleBlurLog);
return () => { // return () => {
document.removeEventListener('spotlightfocus', handleFocusLog); // document.removeEventListener('spotlightfocus', handleFocusLog);
document.removeEventListener('spotlightblur', handleBlurLog); // document.removeEventListener('spotlightblur', handleBlurLog);
}; // };
} // }
return undefined; // return undefined;
}, [Config.FOCUS_DEBUG]); // }, [Config.FOCUS_DEBUG]);
useEffect(() => { useEffect(() => {
// Chromium68 호환성을 위해 Optional Chaining 제거
if (termsData && termsData.data && termsData.data.terms) { if (termsData && termsData.data && termsData.data.terms) {
dispatch(getTermsAgreeYn()); dispatch(getTermsAgreeYn());
} }
@@ -525,7 +524,6 @@ function AppBase(props) {
const oldDb8Deleted = useSelector((state) => state.localSettings.oldDb8Deleted); const oldDb8Deleted = useSelector((state) => state.localSettings.oldDb8Deleted);
// const macAddress = useSelector((state) => state.common.macAddress); // const macAddress = useSelector((state) => state.common.macAddress);
// Chromium68 호환성을 위해 Optional Chaining 제거
const deviceCountryCode = (httpHeader && httpHeader['X-Device-Country']) || ''; const deviceCountryCode = (httpHeader && httpHeader['X-Device-Country']) || '';
useEffect(() => { useEffect(() => {
@@ -581,11 +579,11 @@ function AppBase(props) {
// appinfo // appinfo
// ); // );
console.log('[App.js] initService,httpHeaderRef.current', httpHeaderRef.current); // console.log('[App.js] initService,httpHeaderRef.current', httpHeaderRef.current);
console.log('[App.js] haveyInit', haveyInit); // console.log('[App.js] haveyInit', haveyInit);
// 앱 초기화 시 HomePanel 자동 기록 // 앱 초기화 시 HomePanel 자동 기록
console.log('[App.js] Recording initial HomePanel on app start'); // console.log('[App.js] Recording initial HomePanel on app start');
dispatch( dispatch(
enqueuePanelHistory( enqueuePanelHistory(
'homepanel', 'homepanel',
@@ -618,11 +616,11 @@ function AppBase(props) {
const launchParams = getLaunchParams(); const launchParams = getLaunchParams();
console.log( // console.log(
'initService...{haveyInit, launchParams}', // 'initService...{haveyInit, launchParams}',
haveyInit, // haveyInit,
JSON.stringify(launchParams) // JSON.stringify(launchParams)
); // );
// pyh TODO: edit or delete later (line 196 ~ 198) // pyh TODO: edit or delete later (line 196 ~ 198)
// Chromium68 호환성을 위해 Optional Chaining 제거 // Chromium68 호환성을 위해 Optional Chaining 제거
@@ -656,7 +654,7 @@ function AppBase(props) {
); );
const handleRelaunchEvent = useCallback(() => { const handleRelaunchEvent = useCallback(() => {
console.log('[App] handleRelaunchEvent triggered'); // console.log('[App] handleRelaunchEvent triggered');
const launchParams = getLaunchParams(); const launchParams = getLaunchParams();
clearLaunchParams(); clearLaunchParams();
@@ -709,8 +707,8 @@ function AppBase(props) {
}, [initService, introTermsAgreeRef, dispatch]); }, [initService, introTermsAgreeRef, dispatch]);
const visibilityChanged = useCallback(() => { const visibilityChanged = useCallback(() => {
console.log('document is hidden', document.hidden); // console.log('document is hidden', document.hidden);
console.log('document.visibilityState= ', document.visibilityState); // console.log('document.visibilityState= ', document.visibilityState);
if (document.hidden && typeof window === 'object') { if (document.hidden && typeof window === 'object') {
clearTimeout(foreGroundChangeTimer); clearTimeout(foreGroundChangeTimer);
} else { } else {
@@ -718,13 +716,13 @@ function AppBase(props) {
// set foreground flag using delay time. // set foreground flag using delay time.
clearTimeout(foreGroundChangeTimer); clearTimeout(foreGroundChangeTimer);
foreGroundChangeTimer = setTimeout(() => { foreGroundChangeTimer = setTimeout(() => {
console.log( // console.log(
'visibility changed !!! ==> set to foreground cursorVisible', // 'visibility changed !!! ==> set to foreground cursorVisible',
// Chromium68 호환성을 위해 Optional Chaining 제거 // // Chromium68 호환성을 위해 Optional Chaining 제거
JSON.stringify( // JSON.stringify(
window.PalmSystem && window.PalmSystem.cursor && window.PalmSystem.cursor.visibility // window.PalmSystem && window.PalmSystem.cursor && window.PalmSystem.cursor.visibility
) // )
); // eslint-disable-line no-console // ); // eslint-disable-line no-console
if (platform.platformName !== 'webos') { if (platform.platformName !== 'webos') {
//for debug //for debug
dispatch( dispatch(

View File

@@ -553,7 +553,6 @@
} }
} }
.forceFocus { .forceFocus {
// :global(.spottable):focus{
z-index: 20; z-index: 20;
:not(.favFocus) .thumbContainer { :not(.favFocus) .thumbContainer {
/*transform: scale(1.2);*/ /*transform: scale(1.2);*/

View File

@@ -72,7 +72,7 @@
/* Modifier: highlighted */ /* Modifier: highlighted */
.phoneInput__digit_highlighted { .phoneInput__digit_highlighted {
background: #E6E6E6; // var(--Color-Icon&Text*-primary) background: #E6E6E6; // var(--Color-Icon&Text*-primary)
box-shadow: 0px 10.285714149475098px 6.1714301109313965px rgba(0, 0, 0, 0.30); box-shadow: 0px 10.29px 6.17px rgba(0, 0, 0, 0.30);
color: #4C5059; // var(--Color-Icon&Text*-focused) color: #4C5059; // var(--Color-Icon&Text*-focused)
} }

View File

@@ -1103,16 +1103,3 @@
} }
} }
// optionalConfirm일 때만 기존 위치 스타일 무력화
// :global([id="floatLayer"]) :global(> div:not([id])) :global(> div) :global(> div:nth-child(2)) {
// .tNewPopUp.optionalConfirm & {
// bottom: unset !important;
// transform: none !important;
// top: unset !important;
// position: fixed !important;
// bottom: 0 !important;
// left: 50% !important;
// transform: translateX(-50%) !important;
// }
// }

View File

@@ -7,6 +7,7 @@ import {
stopBannerVideo, stopBannerVideo,
stopAndHideVideo, stopAndHideVideo,
hidePlayerVideo, hidePlayerVideo,
PLAYBACK_STATUS,
} from '../../actions/playActions'; } from '../../actions/playActions';
import fp from '../../utils/fp.js'; import fp from '../../utils/fp.js';
import { videoState } from './videoState.js'; import { videoState } from './videoState.js';
@@ -46,6 +47,7 @@ export const useVideoPlay = (options = {}) => {
const currentOwnerId = useSelector((state) => state.home.playerControl?.ownerId); const currentOwnerId = useSelector((state) => state.home.playerControl?.ownerId);
const bannerDataList = useSelector((state) => state.home.bannerData?.bannerInfos); const bannerDataList = useSelector((state) => state.home.bannerData?.bannerInfos);
const bannerVisibility = useSelector((state) => state.home.bannerVisibility); const bannerVisibility = useSelector((state) => state.home.bannerVisibility);
const reduxVideoPlayState = useSelector((state) => state.play.videoPlayState);
// 🔽 [단순화] 현재 재생 중인 배너 가져오기 // 🔽 [단순화] 현재 재생 중인 배너 가져오기
const getCurrentPlayingBanner = useCallback(() => { const getCurrentPlayingBanner = useCallback(() => {
@@ -64,6 +66,18 @@ export const useVideoPlay = (options = {}) => {
const playDelayTimerRef = useRef(null); const playDelayTimerRef = useRef(null);
const retryTimerRef = useRef(null); const retryTimerRef = useRef(null);
// 🔽 Redux 기반 실제 재생 상태
const isVideoPlaying =
reduxVideoPlayState?.isPlaying === true &&
reduxVideoPlayState?.playback === PLAYBACK_STATUS.PLAYING;
// 🔽 전역 videoState가 실제 재생 상태와 불일치할 때 정리
useEffect(() => {
if (!isVideoPlaying && videoState.getCurrentPlaying()) {
videoState.setCurrentPlaying(null);
}
}, [isVideoPlaying]);
// 🔽 [유틸리티] 배너 가용성 검사 (0부터 시작 통일) // 🔽 [유틸리티] 배너 가용성 검사 (0부터 시작 통일)
const isBannerAvailable = useCallback( const isBannerAvailable = useCallback(
(bannerId) => { (bannerId) => {
@@ -375,8 +389,10 @@ export const useVideoPlay = (options = {}) => {
getCurrentPlayingBanner, getCurrentPlayingBanner,
getLastPlayedBanner, getLastPlayedBanner,
isPlaying, isPlaying,
isVideoPlaying,
currentBanner, currentBanner,
bannerVisibility, bannerVisibility,
videoPlayState: reduxVideoPlayState,
bannerAvailability, // ✅ [최적화] 메모이제이션된 배너 가용성 bannerAvailability, // ✅ [최적화] 메모이제이션된 배너 가용성
// 🔍 유틸리티 // 🔍 유틸리티

View File

@@ -70,7 +70,7 @@
margin: 10px 0; margin: 10px 0;
span { span {
.font(@fontFamily: @baseFont, @fontSize: 20px); .font(@fontFamily: @baseFont, @fontSize: 20px);
line-height: 40ppx; line-height: 40px;
font-weight: 700; font-weight: 700;
color: rgba(234, 234, 234, 1); color: rgba(234, 234, 234, 1);
} }

View File

@@ -418,7 +418,7 @@ const MediaPanel = React.forwardRef(
const videoContainer = document.querySelector(`.${css.videoContainer}`); const videoContainer = document.querySelector(`.${css.videoContainer}`);
if (videoContainer && panelInfo.thumbnailUrl && !videoLoaded) { if (videoContainer && panelInfo.thumbnailUrl && !videoLoaded) {
try { try {
videoContainer.style.background = `url(${panelInfo.thumbnailUrl}) center center / contain no-repeat`; videoContainer.style.background = `url(${panelInfo.thumbnailUrl}) center/contain no-repeat`;
videoContainer.style.backgroundColor = 'black'; videoContainer.style.backgroundColor = 'black';
} catch (err) { } catch (err) {
if (DEBUG_MODE) console.warn('[MediaPanel] 썸네일 스타일 설정 실패:', err); if (DEBUG_MODE) console.warn('[MediaPanel] 썸네일 스타일 설정 실패:', err);

View File

@@ -2164,12 +2164,12 @@ const MediaPanel = React.forwardRef(
const videoContainer = document.querySelector(`.${css.videoContainer}`); const videoContainer = document.querySelector(`.${css.videoContainer}`);
if (panelInfo.thumbnail && !videoVerticalVisible) { if (panelInfo.thumbnail && !videoVerticalVisible) {
videoContainer.style.background = `url(${panelInfo.thumbnail}) center center / contain no-repeat`; videoContainer.style.background = `url(${panelInfo.thumbnail}) center/contain no-repeat`;
videoContainer.style.backgroundColor = 'black'; videoContainer.style.backgroundColor = 'black';
} }
if (broadcast.type === 'videoError' && videoThumbnailUrl) { if (broadcast.type === 'videoError' && videoThumbnailUrl) {
videoContainer.style.background = `url(${videoThumbnailUrl}) center center / contain no-repeat`; videoContainer.style.background = `url(${videoThumbnailUrl}) center/contain no-repeat`;
videoContainer.style.backgroundColor = 'black'; videoContainer.style.backgroundColor = 'black';
} }
}, [panelInfo.thumbnail, broadcast]); }, [panelInfo.thumbnail, broadcast]);

View File

@@ -757,10 +757,6 @@
background-color: #202020; /* 배경색 (테마에 맞게 조정) */ background-color: #202020; /* 배경색 (테마에 맞게 조정) */
padding: 0; /* TPanel 기본 padding 제거 */ padding: 0; /* TPanel 기본 padding 제거 */
// :global(.sand- তুরস্ক-TPanel_TPanel_header) {
// /* 모달 모드일 때 TPanel 헤더 숨기거나 다르게 스타일링 가능 */
// /* display: none; */
// }
.body { .body {
/* TPanel 내부의 TBody가 전체 높이를 차지하도록 */ /* TPanel 내부의 TBody가 전체 높이를 차지하도록 */

View File

@@ -2443,12 +2443,12 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
const videoContainer = document.querySelector(`.${css.videoContainer}`); const videoContainer = document.querySelector(`.${css.videoContainer}`);
if (panelInfo.thumbnail && !videoVerticalVisible) { if (panelInfo.thumbnail && !videoVerticalVisible) {
videoContainer.style.background = `url(${panelInfo.thumbnail}) center center / contain no-repeat`; videoContainer.style.background = `url(${panelInfo.thumbnail}) center/contain no-repeat`;
videoContainer.style.backgroundColor = 'black'; videoContainer.style.backgroundColor = 'black';
} }
if (broadcast.type === 'videoError' && videoThumbnailUrl) { if (broadcast.type === 'videoError' && videoThumbnailUrl) {
videoContainer.style.background = `url(${videoThumbnailUrl}) center center / contain no-repeat`; videoContainer.style.background = `url(${videoThumbnailUrl}) center/contain no-repeat`;
videoContainer.style.backgroundColor = 'black'; videoContainer.style.backgroundColor = 'black';
} }
}, [panelInfo.thumbnail, broadcast]); }, [panelInfo.thumbnail, broadcast]);