9. 전시 현장에서 생겼던 방명록 높이계산 알고리즘 문제
2025년 12월 10일
졸업논문 대체 웹사이트
방명록 레이아웃의 높이 계산 알고리즘 개선
졸업 전시 웹사이트의 방명록은 3개 컬럼에 메시지를 배치합니다. 각 메시지는 박스 형태이고, 높이는 내용에 따라 달라집니다. 목표는 세 컬럼의 높이를 최대한 균등하게 유지하는 것이었습니다.
초기 구현은 간단한 추정 알고리즘을 사용했습니다:
// 초기 코드 (문제가 있던 버전) const messageLines = Math.max(1, Math.ceil(msg.message.length / 30)); const estimatedHeight = Math.max( 11.67, 11.67 + (messageLines - 1) * 1.5 );
이 방식은 메시지가 적을 때는 큰 문제가 없었습니다. 하지만 전시가 진행되면서 메시지가 db에 쌓이고, 늘어나자 문제가 생겼습니다.
1. 누적 오차의 증가
각 메시지의 높이를 추정할 때 작은 오차가 발생합니다.(임시로 높이를 추정해서) 메시지가 적을 때는 오차가 작아 보이지만, 메시지가 많아지면 오차가 누적됩니다.
예를 들어:
- 메시지 10개: 각각 5px 오차 → 총 50px 오차
- 메시지 100개: 각각 5px 오차 → 총 500px 오차
2. 실제 렌더링과의 차이
추정 알고리즘은 다음과 같은 요소를 정확히 반영하지 못했습니다:
- 실제 폰트 렌더링 (폰트마다 문자 너비가 다름)
- 단어 단위 줄바꿈
- 한글/영문/숫자/특수문자 조합
- 브라우저별 렌더링 차이
3. 복잡한 텍스트 처리
실제 메시지는:
- 긴 문장과 짧은 문장이 섞임
- 줄바꿈이 포함된 경우
- 이모지나 특수문자 포함
이런 경우 추정이 더 부정확해집니다.
Canvas API 시도 (그리고 포기)
더 정확한 계산을 위해 Canvas API를 사용해 텍스트의 실제 너비를 측정했습니다:
// Canvas API를 사용한 시도 (최종적으로 사용하지 않음) const canvas = document.createElement("canvas"); const context = canvas.getContext("2d"); context.font = "400 9px Pretendard"; const metrics = context.measureText(testLine);
하지만 이 방법도 문제가 있었습니다:
- 폰트 로딩 타이밍: 폰트가 완전히 로드되기 전에 측정하면 부정확
- 실제 DOM 렌더링과의 차이: Canvas 측정과 실제 브라우저 렌더링이 다를 수 있음(실제로 약간 달랐음)
- 복잡도 증가: 코드가 복잡해지고 유지보수가 어려워짐
결국 Canvas API 방식은 제외했습니다.
최종 해결책: 실제 DOM 요소로 높이 측정
최종적으로 실제 DOM 요소를 생성해 높이를 측정하는 방식으로 변경했습니다:
// 최종 해결책: 실제 DOM 요소로 높이 측정 const tempContainer = document.createElement("div"); tempContainer.style.position = "absolute"; tempContainer.style.visibility = "hidden"; tempContainer.style.width = isMobile ? `${(containerRef.current.offsetWidth - 8) / 3}px` : `${containerRef.current.offsetWidth * 0.2}px`; document.body.appendChild(tempContainer); // 실제 스타일을 적용한 임시 박스 생성 const tempBox = document.createElement("div"); tempBox.style.width = "100%"; tempBox.style.padding = isMobile ? "12px" : `${containerRef.current!.offsetWidth * 0.0167}px`; // ... 실제 사용되는 모든 스타일 적용 // 높이 측정 const height = tempBox.offsetHeight;
- 정확성: 실제 브라우저 렌더링 결과를 그대로 사용
- 신뢰성: 폰트 로딩, 브라우저 차이 등이 자동으로 반영
구현 흐름
- 임시 컨테이너 생성: 보이지 않는 위치에 실제 너비의 컨테이너 생성
- 실제 스타일 적용: 실제 컴포넌트와 동일한 스타일 적용
- 높이 측정:
offsetHeight로 실제 렌더링 높이 측정 - 정리: 측정 후 임시 요소 제거
결과
- 메시지가 많아져도 컬럼 높이 차이가 크게 줄어듦
- 다양한 텍스트 길이와 내용에서도 안정적으로 동작
- CSS 변경 시 자동으로 반영되어 유지보수가 쉬움
주의해야할 점
- 추정 알고리즘의 한계: 작은 오차도 누적되면 큰 문제가 됨.. 혹시나 임시로 추정 알고리즘을 적용해 두었다면 무조건 추후에 기억하고 완전한 알고리즘 구현해야함
- 복잡한 Canvas 계산보다 실제 DOM 측정이 더 단순하고 효과적