TIL 74

🧩 비동기 작업에도 우선순위가 있다 + 브라우저 페인팅 vs React 렌더링

✅ 문제 상황 요약setVoteLimit(payload.voteLimit)으로 상태를 업데이트한 후,setTimeout(() => { listenersRef.current.onVoteLimitReceived?.();}, 0);처럼 setTimeout으로 콜백을 예약했는데, 기대와 다르게 voteLimit의 최신 값이 반영되지 않고 여전히 null로 참조되는 문제가 발생했다.🤔 내가 기대한 흐름은?JS 이벤트 루프 기준으로 다음과 같은 순서를 기대했다:Microtask (예: Promise.then)React 상태 업데이트 → 컴포넌트 리렌더링Browser 렌더링 (페인팅)Macrotask (예: setTimeout)그래서 setTimeout은 React의 상태 업데이트와 리렌더링이 완료된 후 실행될 ..

TIL 2025.05.08

🧩 React와 웹소켓 타이밍 이슈, Closure

MakeCandidate.tsx에서는 WebSocket 응답으로 받은 voteLimit 값을 기반으로 조건 분기(voteLimit !== null)하여 공(ball)을 생성한다.하지만 예상과 달리 voteLimit이 null이 아님에도 null로 참조되어, 제한/무제한 여부가 잘못 반영되는 공이 생성되는 문제가 발생했다.🔍 원인 분석1. React 함수형 컴포넌트의 클로저 구조WebSocketProvider 컴포넌트에서 Websocket 응답을 받고 setVoteLimit으로 voteLimit 상태를 업데이트 하고 있다.아래 subscribeAll 함수 내부에서는 업데이트 된 voteLimit 값을 사용하고 싶었으나, 항상 null로 참조가 되었다. // AS-ISuseEffect(() => { //..

TIL 2025.05.08

🧩Webpack + SharedWorker + TypeScript 환경에서 발생한 트러블슈팅 기록

React 프로젝트에서 여러 탭 간 WebSocket 연결을 공유하기 위해 SharedWorker를 사용하려고 했고, 백엔드가 Spring Boot 기반이라 STOMP 프로토콜을 클라이언트에서도 사용해야 했다. 하지만 Webpack + TypeScript 환경에서 SharedWorker를 구성하는 과정에서 여러 문제가 발생했다.🔍 초기 설계 방향과 발생한 오해들1. 원래 SharedWorker는 이렇게 쓰는 줄 알았다. - 정적 경로 기반 접근에 대한 이해 부족const worker = new SharedWorker("/worker/sharedWorker.js");이 방식은 브라우저가 서버의 정적 경로(/worker/sharedWorker.js)로 워커 파일을 직접 요청함여기서 "서버"는 Webpack..

TIL 2025.03.30

🧩 WebSocket, Recoil로 관리해도 될까?

실시간 투표서비스를 개발하며 WebSocket을 사용 중에현재 서비스에서 전역상태 관리로 Recoil을 사용 중이니 웹소켓도 recoil로 관리할까? 싶었다.하지만 WebSocket은 단순한 값과는 성격이 다르기 때문에, Recoil로 관리하는 것이 오히려 문제가 될 수 있다는 걸 발견했다.📌 WebSocket은 "값"이 아닌 "리소스 객체"WebSocket은 단순한 데이터가 아니라, 서버와의 연결을 유지하는 연결된 객체다.연결된 객체란?life-cyle(연결, 해제, 에러, 브로드캐스트) 상태를 가진 객체onopen, onmessage, onerror, onclose 등 이벤트 루프에 등록된 이벤트 핸들러도 가지고 있음지속적으로 외부와 연결되어 있는 상태로, 명시적으로 해제-close() 하지 않으면..

TIL 2025.03.22

TimePicker 외부 클릭 시 다시 열리는 현상

🚨  TroubleShotting문제 발생의 배경 - As Is투표 시간을 설정하는 타이머에서 Input을 클릭하면 해당 시간 선택창(TimePicker)이 열리도록 하고,열려 있는 상태에서 외부를 클릭하면 TimePicker가 닫히도록 구현하고 있었다.이 과정에서 두 가지 큰 이슈를 겪었다:❗️ 문제[true, false] 상태에서 Input을 클릭하면 handleClickOutside가 실행되어 [false, false]로 닫혔다가,곧이어 다시 [true, false]로 다시 열리는 현상이 발생함.# 1) 이 상태에서 [false, false]로 상태를 변경하고자 함timeOpen => [true, false]# 2) 그런데 [false, false]가 되자마자 곧바로 다시 [true, false]..

TIL 2025.03.22

GitHub Actions + Docker 배포 트러블슈팅: .env 파일이 컨테이너에 들어가지 않는 이유?

🚨  TroubleShotting문제 발생의 배경 - As Is프로젝트를 GitHub Actions와 Docker를 활용해 EC2에 배포하는 과정에서, .env 파일이 도커 컨테이너에 정상적으로 들어가지 않는 문제가 발생했다.단순히 .env 파일 하나의 문제였지만, 이를 해결하는 과정에서 빌드타임과 런타임, 그리고 webpack.config.js에서의 환경변수 처리까지 여러 가지 중요한 개념을 제대로 이해하게 되었다.이번 글에서는 내가 겪은 문제의 원인과 해결 방법, 그리고 이를 통해 정리한 배포 흐름을 기록해본다.❗️ 문제 GitHub Actions에서 .env 파일을 생성하고 EC2에 복사했음에도도커 컨테이너 내부에는 .env 파일이 존재하지 않았음[ec2-user@ipxxxx ~]$ docker ..

TIL 2025.03.21

SSL 인증서 발급과 IP 주소

트러블 슈팅은 아니고 새롭게 알게 된 사실 기록..서버에서 SSL 인증서를 발급한 뒤, https://{{raw한 IP 주소}/api/votes 로 요청을 보내니 다음과 같은 오류가 났다.그런데 요청 주소를 https://api.golaping.site/api/votes 로 요청을 보내니 성공했다.SSL 인증서는 IP 주소 자체보다 도메인 이름에 대해 발급되기 때문이었다.IP 주소는 변경 가능하고 유동적일 수 있기 때문에특정 도메인을 고유하게 식별하고 보장하기 위해 도메인 이름을 기반으로 인증을 검증SAN(Secure Alternative Name) 또는 IP 기반 인증서가 있지만, 드물고 일반적이지 않다.

TIL 2025.03.03

요청에 쿠키가 안 담겨요.. SameSite=None? Strict?

🚨  TroubleShotting문제 발생의 배경 - As Is현재 웹소켓을 기반으로 한 실시간 투표 서비스를 개발 중이다. 서비스의 간단함을 고려하여 로그인 기능이 굳이 필요없다고 판단했지만, 투표의 주체인 유저 식별 기능은 필요했다.따라서, 세션을 이용해서 서버에서 세션 ID를 발급 및 쿠키에 담아주면 - 프론트에서 요청마다 쿠키를 포함하는 방식으로 유저를 식별하고자 했다.그런데 분명히 서버에서 sessionID를 발급해서 쿠키에 넣어주었고, 프론트에서도 document.cookies로 쿠키 확인이 가능하나,요청에는 쿠키가 포함되지 않는 현상How(과정) ?시행착오 1Websocket 요청 헤더에 투표 정보를 담아서 백엔드로 보내려고 했다.실패웹소켓 요청은 처음에는 http로 시작하여 핸드쉐이크 -..

TIL 2025.03.02

배포방법 고민 - 🛠 EC2 + NginX vs CloudFront + S3

새로운 사이드 프로젝트를 하는 도중 프론트 배포를 무엇으로 할지 고민에 빠졌다.💡 우리의 서비스는웹소켓 기반의 실시간 투표 서비스아직 정적 파일은 많지 않지만, 앞으로 투표 이미지나 아이템 등 시각적 요소들이 들어갈 가능성 多제목의 EC2 + NginX 와 CloudFront + S3 두 방법의 특징과 장단점, 현재 프로젝트에 무엇이 더 적합할지 알아보았다. 1️⃣ CloudFront + S3📦 Amazon S3 (Simple Storage Service)정적 파일 저장 전용: HTML, CSS, JS, 이미지, 폰트 등서버리스 기반, 서버 관리 ❌✅ 장점무제한 확장성 & 높은 내구성 (데이터 유실 걱정 거의 없음)서버 관리 필요 없음 → 운영 부담 낮음❌ 단점웹소켓 미지원GET 요청만 처리 가능→ ..

TIL 2025.01.11

npx? npm? pnpm?

보통 React 앱을 만들 때 많이 쓰는 npx create-react-app simple-deploy 이 명령어, 문득 npx란 무엇일까? 라는 의문이 들었다.npx란?-      Node Package eXecute의 약자로-      Node.js와 함께 설치되는 명령어 실행 도구-      주로 패키지 실행에 쓰임역할🔹  글로벌 설치 없이 패키지 실행그럼, 글로벌 설치란? npm install -g create-react-app처럼 -g 옵션을 사용글로벌 설치를 하면 내 컴퓨터 전체 어디서나 해당 패키지를 사용할 수 있게 됨즉, 패키지가 내 컴퓨터의 글로벌 패키지 폴더에 영구적으로 설치됨=> npx는 최신버전을 일시적으로 다운로드해서 바로 실행 후 사용 후에는 삭제함🔹 일회성 실행패키지를 설치..

TIL 2024.11.10