전체 글 72

🧩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

모달창 구현하기 - RootLayout에 위치 vs createPortal

🚨  TroubleShotting보이는 것과 같이 모달창이 다른 요소들보다 가장 상단에 와야하는데 가장 밑에 위치한다.문제 발생의 배경 - As Is처음에 모달창 구현법에 대해서 고민을 했다.React-dom에서 제공하는 createPortal을 사용할 것인가?vs RootLayout.tsx에서 Modal.tsx 컴포넌트를 가장 상단에 위치시킬 것인가? 두 방법의 원리를 생각해봤다.createPortal은(1) HTML에 모달이 될 컴포넌트와 모달이 렌더링 될 DOM 노드를 (ex. ) 미리 위치시킨다.(2) 모달창 열기를 실시하면, 미리 위치시킨 DOM 노드를 document.querySelector 또는 getElementById로 가져와서 그 위치에 모달창을 렌더링 한다.장점: 모달창을 렌더링하고..

TIL 2024.07.10

Next.js Server-Action과 낙관적 업데이트

🚨  TroubleShotting문제 발생의 배경 - As IsNext.js의 App-Router를 사용하며 좋아요를 구현하던 중, 낙관적 업데이트를 구현하고 싶었다.그래서 처음에는 코드를 이렇게 짰다.submitQuizLike()라는 비동기 통신 로직이 실행되기 전에 setIsLiked로 낙관적 업데이트를 해야지라는 허접하고 야무진 소망(?)과 함께..ㅋㅋㅋconst LikeQuiz = ({ quiz_id }: { quiz_id: string }) => { ... const [isLiked, setIsLiked] = useState(userData && quizLikeData && quizLikeData.users?.includes(userData.user_id)); const queryClie..

TIL 2024.07.02