재현 조건
테이블의 가용 폭, 고정·선택·액션 컬럼, 최소·최대 폭 제약이 함께 적용된 뒤 컬럼을 줄이거나 늘리면 선언된 폭과 실제 헤더 폭이 달라졌습니다.
FRONTEND PORTFOLIO / 2026
운영 화면에서 입력, 데이터, 오류가 만나는 지점을 나누고 검증합니다.
01 / CASES
제품 화면이나 기술 나열 대신, 실제 판단이 드러나는 세 가지 장면을 정리했습니다.
CASE 01 / CMP TABLE
업무 장면테이블 컬럼을 드래그로 줄였다 늘릴 때, 다음 리사이즈에서 폭이 갑자기 커지거나 작아지던 공통 컴포넌트
테이블의 가용 폭, 고정·선택·액션 컬럼, 최소·최대 폭 제약이 함께 적용된 뒤 컬럼을 줄이거나 늘리면 선언된 폭과 실제 헤더 폭이 달라졌습니다.
상태값만 다시 계산하면 이미 브라우저가 분배한 실제 폭을 알 수 없습니다. 마지막 헤더 행의 th.getBoundingClientRect().width를 기준으로 삼았습니다.
실측 폭을 최소·최대값으로 보정한 뒤 colgroup과 컬럼 상태에 함께 반영해, 다음 드래그가 화면에 보이는 폭에서 시작되게 했습니다.
// 렌더링 결과를 다음 리사이즈의 기준값으로 사용
const widths = headerCells.map((th) =>
th.getBoundingClientRect().width
);
applyDomMeasuredWidthsToAllCols(columns, colgroup, widths, state);
CASE 02 / DATA LIFECYCLE
업무 장면KeepAlive로 보관된 로그 화면이 창 포커스 복귀 뒤에도 자동 요청을 이어가던 상황
KeepAlive는 로그 화면을 메모리에 그대로 둡니다. 인시던트로 이동해도 로그 Query의 구독자는 남아 있었고, 창 포커스가 돌아오면 지금 보이지도 않는 로그 API가 다시 호출됐습니다.
처음에는 refetchOnWindowFocus: false를 전역으로 껐습니다. 숨겨진 로그 요청은 막혔지만, 실제로 로그 화면을 보고 있을 때도 포커스 복귀 최신화를 받지 못해 되돌렸습니다. 대신 "캐시된 화면인가"가 아니라 "지금 보이는 화면인가"로 기준을 바꿔, 활성 상태를 로그 관련 Query들의 enabled 조건에만 연결했습니다.
인시던트 화면에서는 숨은 로그 요청이 멈추고, 그 화면 자체의 포커스 재조회는 그대로 살아 있습니다. 로그로 돌아오면 남아 있던 캐시를 먼저 보여주고, stale 상태면 다시 조회합니다.
// 시도했지만 되돌린 방식 — 전역 옵션은 지금 보고 있는 화면까지 멈춥니다 // defaultOptions: { queries: { refetchOnWindowFocus: false } } // 최종 — 페이지 생명주기 → 해당 Query의 요청 권한 onActivated(() => logStore.setLogPageActive(true)); onDeactivated(() => logStore.setLogPageActive(false)); useQuery({ enabled: computed(() => logStore.isLogPageActive) });
CASE 03 / ERROR CONTAINMENT
업무 장면관리자 콘솔에서 하위 화면의 렌더링 오류가 상위 레이아웃까지 전파될 수 있는 구조
하위 컴포넌트가 낸 오류와 발생 맥락을 Boundary가 오류 상태로 보관합니다.
오류 전파를 멈춰 한 페이지의 실패가 RootLayout과 공통 네비게이션까지 번지는 경로를 차단합니다.
경로가 바뀌면 오류 상태를 초기화해 이전 화면의 실패가 다음 화면에 남지 않게 합니다.
03 / TOOLKIT
업무에서 사용한 기술과, 구조를 이해하기 위해 직접 학습·실험한 영역을 함께 기록합니다.