전체 글 111

[CSS] safari 폰트 관련 크로스 브라우징 이슈

WebView를 사용한 RN 프로젝트에서 ios는 폰트가 제대로 적용되지 않는 이슈가 있었다. 먼저 font-family의 적용 원리를 찾아보았다.font-family 의 원리font-family: [1순위], [2순위], [3순위], [...] 와 같은 원리로 현재 OS 에 있는 폰트가 적용된다고 알고 있습니다. 하지만 이렇게만 알면 안되고 정확한 알고리즘을 알아야 합니다. 알고리즘은 다음과 같습니다.[1순위]의 폰트가 OS 에 있는지 확인한다. 있으면 그것을 바로 적용한다.없으면 웹서버에 정의된 웹폰트가 있는지 확인한다.웹서버에 웹폰트가 있으면 다운을 받고, 없으면 [1순위]의 폰트는 없다 간주하고 [2순위]의 폰트를 검사하기 시작한다.1~3의 작업을 반복한다.문제는 OS에 적용하려고 했던 폰트가 없..

React.js 2025.05.08

[React] Framer-motion, HOC 관련 Runtime Error

import _ from "lodash";type HOC = ( WrappedComponent: any // functional or class component 모두 될 수 있다.) => React.FC;const MergeMotion = ( TargetComponent: React.ComponentType, hoc1: HOC, hoc2: HOC, hoc3?: HOC): React.FC => { return _.flowRight(_.compact([hoc1, hoc2, hoc3]))(TargetComponent);};export default MergeMotion;​빛이 지나가는 이펙트를 주기 위해 여러 컨텐트에서 공통으로 사용되고 있는 Glow 컴포넌트가 있다.미션 페이지에서 리스트를 뿌려..

React.js 2025.04.29

[CloudFront] S3 이미지 무효화와 적절한 프론트 캐시 정책 조사

프로젝트 진행 중 S3 버킷에서 관리되는 서버 이미지는 CloudFront를 통해 요청, 응답받았다.만약 하나의 이미지 파일에만 문제가 생겼을 경우 전체 이미지 버전을 업데이트하고 무효화시키기에는 부담이 조금 있어, 테스트 해본 결과 무효화를  진행하지 않을경우 Etag, 마지막 수정시간이 변경되어도 계속해서 캐싱을 하고있는것을 확인했다. 이 부분을 해결하기 위해 CloudFront의 캐시 정책을 조사하고 다른 방안이 있을지 살펴보았다.  테스트 시나리오를 통한 기존 이미지 캐시 동작 확인이미지 네트워크 요청 시 응답 헤더 확인 -->캐시 관련 헤더를 확인해 본 결과etag: W/"26xxxxxxx"last-modified: Thu, 27 Feb 2025 06:26:56 GMTx-cache: Hit fr..

AWS 2025.03.05

[React] createPortal을 사용한 z-index 제어

룰렛을 구현하던 중 React-Tooltip과 디자인이 맞물려 원하는대로 툴팁의 레이어가 위치하지 않게되는 문제가 발생하였다.우선 룰렛은Wheel(원판)outline(원판 외부 테두리)pointer(룰렛 포인터)tooltip(원판에 있는 각 아이템을 클릭했을 시 나오는 툴팁) 으로 구성이 되어있다.wheel: 1   outline: 2   tooltip: 4   pointer: 3그리고 각 요소의 z-index는 위와 같이 나타나야 한다. 즉 툴팁은 가장 상단에 위치해야하는 상황이다. 이 때 디자인상 컴포넌트 트리 구조가wheel 내부에 outline, tooltip이 위치해야 하였고, pointer는 wheel 외부에 독립적으로 존재해야하는 상황이였다. 이 때 문제는 tooltip이 wheel 안에 있..

React.js 2024.12.04

[Animation] Framer-motion, React Status에 따른 motion.div의 Animation이 실행되지 않던 이슈

{status !== "RESULT" && ( )} {status === "RESULT" && ( )}위와 같이 React Status에 따라서 조건에 맞는 컴포넌트가 mount, unMount 될 때 각각의 애니메이션이 실행되도록 motion.div를 사용하여 initial 값과 exit, animation의 값을 설정해주었다. 하지만 status가 변경되는 동시에 아무런 애니메이션이 실행되지 않았고, 원인을 찾아보았다. 원인은 생각보다 간단했다,,,Framer Motion이 DOM에서 제거되는 구성 요소를 처리하기 위해 AnimatePresence가 필요하기 때문에 MotionDiv..

React.js 2024.10.21

Ref와 Polling 방식을 사용하여 게임 데이터 준비 이후 실행 처리

서버에서 응답으로 내려주는 데이터 중 게임 실행 준비가 완료되었다는 상태가 있을 경우, 폴링을 사용하여 로딩 Indicator를 돌리다가 실행 처리를 해줄 수 있다. 위 기능을 간단하게 구현해보기 위해 hook을 하나 만들어주었다. const wrapPollingRef = useRef(false); 우선 Ref 하나를 생성해 준다. const { mutate: play, isLoading } = usePostAPIExEndPoint({ mutation: { onSuccess: (data) => { if (data.result === "SUCCESS") { showLoading(); setGameStatus({ ...gameS..

React.js 2024.10.08

[Next] Lighthouse 를 사용한 CSR, SSR 성능 차이 비교

Next/Image를 사용하여 이미지 최적화를 하기위해 Next.js로 프로젝트를 진행하고 있지만, 게임 특성 상 Loaing  상태일 경우 loading indicator가 보여지는게 더 적합할 것 같아 프로젝트 전체적으로 CSR을 사용하고 있었다. 이 때, 적합한 페이지는 SSR을 적용해봐도 좋지 않을까 고민하다 상점 페이지에 SSR을 적용해본 뒤 CSR을 했을때와 어느정도의 성능 차이가 있고, 어떤 방식이 더 효율적일지 테스트를 해봐야겠다고 생각했다. 상점은 API에서 특히 더 많은 양의 데이터를 받고 있으며 렌더되는 이미지의 양도 많았다. 우선 React-Query를 사용하고 있는 환경에서 SSR을 적용하기 위해 공식문서에 나와있는 대로 SSR을 위한 초기 설정을 해주었다.https://tanst..

Next.js 2024.06.26

[React] Queue 자료구조를 사용한 Task Scheduling

React Cycle 내에서 앱 전반적으로 Task를 Scheduling 할 수 있는 Core Class가 필요했다. Task를 순차적으로 처리해야 하므로 FIFO 구조의 Queue를 사용하였으며,  type Task = () => void;class TaskService_ { private queue: Task[] = []; private isProcessing: boolean = false; enqueue(task: Task): void { this.queue.push(task); } execute(): void { if (!this.isProcessing) { this.processQueue(); } } processQueue(): void { this.i..

React.js 2024.05.09

[React] Debounce를 활용한 중복 요청 방지

각종 이벤트, 미션을 통해 보상을 받는 경우 유저가 Claim 버튼을 단시간 내에 여러번 클릭하여 서버에 여러번 요청이 들어가고 중복 요청으로 인한 비정상적인 응답 및 에러가 발생하는 이슈가 있었다. 위 문제를 해결하기 위해 여러가지 방법을 사용할 수 있었고, 나는 lodash에서 제공하는 debounce 함수를 사용해 문제를 해결했다. View Model에서 mutation을 정의하고 const { claim, claimAll } = ExViewModel();위와 같이 mutate 함수를 구독해 사용하는 과정에서   const debouncedClaimAll = debounce(claimAll, 600); debounce를 걸어주면지정해놓은 시간이 끝나고 하나의 요청을 보낼 수 있었고, 문제를 해결할 ..

React.js 2024.05.09

[React] reverse() 함수 관련 크로스 브라우징 이슈

상위 컴포넌트에서 props로 배열을 받아 와 배열 요소를 뒤집어서 뿌려줘야하는 상황에서 크로스 브라우징 이슈가 발생했다. API에서 받아온 원본 배열의 무결성을 지키기 위해 하위 컴포넌트 내부에서 const copiedArr = [ ...apiArr, ].reverse(); 위와 같이 얕은 복사를 해주었다. chrome 환경에서는 reverse가 된 배열이 렌더되었지만, safari 환경에서는 reverse된 배열이 렌더되지 않았다. 디버깅 결과 copiedArr에 reverse된 데이터가 아닌 apiArr의 데이터가 있는 것을 확인하였고, 브라우저간의 렌더 과정에서 변수에 값을 할당하는 시점에 차이가 있을 것이라고 추측했다. dependancy를 걸어 apiArr의 값이 변할 경우 다시 얕은 복사를 ..

React.js 2024.04.18