본문 바로가기

프로그래밍

개발자 할로윈 이벤트: 프론트엔드에서 소름 돋는 ‘공포’ 사례 모음 🎃👻

반응형

가볍게 웃고, 다시는 당하지 않도록 체크까지! 유명·전형적인 프론트엔드 “공포 사례”들만 뽑았어요. 바로 복붙해 재현도 가능한 미니 스니펫 포함.


1) 0.1 + 0.2 !== 0.3 — 부동소수점 악령

JS의 IEEE 754 덕분에 대표적인 놀람 포인트.

0.1 + 0.2 // 0.30000000000000004 (0.1 + 0.2) === 0.3 // false
대응: 반올림 비교(ε), 정수 변환해서 계산.


const eq = (a, b, e = 1e-10) => Math.abs(a - b) < e; eq(0.1 + 0.2, 0.3); // true

2) NaN은 자기 자신과 같지 않다

에러 지표 집계하다가 조건 누락되는 공포.

NaN === NaN // false Number.isNaN(NaN) // true ← 이걸 쓰자

3) React의 key 지옥 — 상태가 엉뚱한 아이템으로 이동

리스트 렌더링 시 index를 key로 쓰면 재정렬에 취약.

{items.map((it, i) => <Row key={i} item={it} />)} // 🙅 
{items.map(it => <Row key={it.id} item={it} />)} // 👍 안정적인 고유키

증상: 체크박스/입력값이 다른 행으로 “이동”하는 듯 보임.


4) Hydration Mismatch — 서버와 클라이언트가 다른 말을 할 때

Next.js/SSR에서 “시간/랜덤/브라우저 전용 API”가 초기 렌더에 섞이면:

Warning: Text content did not match. Server: "..." Client: "..."

대응: useEffect로 클라이언트 전용 처리, suppressHydrationWarning, 혹은 dynamic(..., { ssr: false }) 검토.


5) 이벤트 리스너 누수 — 스크롤이 점점 무거워진다

페이지 전환/모달 열닫 반복 시 detach 누락.

function mount() { 
	const onScroll = () => {/* ... */}; 
    window.addEventListener('scroll', onScroll, { passive: true }); 
    return () => window.removeEventListener('scroll', onScroll); 
}

대응: SPA 라우팅/컴포넌트 언마운트에 정리 필수.


6) passive: true 안 붙인 휠/터치 — 스크롤 잼(잦은 프레임 드랍)

window.addEventListener('touchmove', handler, { passive: true }); // 스크롤 차단 의도면 passive:false + preventDefault 필요 (신중히!)

현상: 메인스레드가 이벤트 대기 → 스크롤 끊김.


7) CSS z-index와 스태킹 컨텍스트의 미궁

position/transform이 만든 컨텍스트 때문에 “z-index 9999인데도 안 올라와요” 공포.

.modal { 
	position: fixed; 
    	z-index: 1000; 
} 
.parent { 
	transform: translateZ(0); 
} /* 새 컨텍스트 생성! 모달이 아래로 갇힘 */
 

대응: 컨텍스트 최소화, 모달은 루트 포탈로 렌더.


8) 100vh 이슈(iOS Safari) — 화면이 갑자기 잘린다

모바일 주소창/툴바 높이 변동으로 레이아웃 튀김.

/* 대안: 동적 뷰포트 단위 */ 
.container { 
	height: 100dvh; 
} 
/* 지원 브라우저에서 안전 */

혹은 JS로 --vh 커스텀 속성 세팅.


9) 날짜 파싱 지역차 — “브라우저마다 다르게 해석”

new Date('2020-01-01') // 브라우저/타임존에 따라 UTC or 로컬로 해석

대응: ISO+시간명시 2020-01-01T00:00:00Z, 라이브러리(dayjs/date-fns) 사용.


10) Cumulative Layout Shift(CLS) — 콘텐츠가 자꾸 밀린다

이미지 크기 미지정, 광고/위젯 늦게 로드 → 유저가 누른 버튼이 바뀌는 공포.

<img src="..." width="640" height="360" alt="">

대응: 사이즈 예약, skeleton/placeholder, content-visibility, aspect-ratio.


 

11) XSS & innerHTML — 문자열 신뢰하다가 벌어지는 일

container.innerHTML = userInput; // 🙅 위험 
container.textContent = userInput; // 👍 안전 출력

대응: 반드시 이스케이프/인코딩, 프레임워크의 안전한 바인딩 사용.


 

반응형