일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- virtual Dom
- programmers
- deep
- BOJ
- Dive
- 가상 DOM
- 상태
- EventListener
- javascript
- LeetCode
- 상태 끌어올리기
- Java
- 프로젝트
- 원리
- API
- memory
- 요청
- 유용한 사이트
- 프로그래머스
- 개발
- react
- 꿀팁
- 백준
- Hook
- State
- axios
- DoM
- Today
- Total
탄탄한 기본기!
background image의 load 시점 감지하는 법? 본문
웹 개발을 하던 도중, 배경화면으로 사진들을 렌더링하고 그 위에 다른 HTML 요소를 렌더링 하고자 했다가 아래와 같은 상황이 발생하는 이슈가 있었다.

해당 이슈의 원인은, background 이미지로 사용되는 이미지가 load 되지 않았을 경우에 이를 포함하고 있는 컨테이너의 height가 auto이기 때문에 height가 0으로 취급되기 때문이었다.
그래서 고민하다가 이미지가 load 되었는지 상태를 감지해주면서 이미지가 load 되었을 때만 컨테이너 내부의 요소(컴포넌트) 들을 렌더링 하도록 로직을 작성해보았다.
import React, { useState } from "react";
import { styled } from "linaria/react";
interface IProps {
src: string;
alt: string;
children?: React.ReactNode;
}
const ImageDiv = styled.div`
position: relative;
display: block;
max-width: 100%;
height: auto;
min-height: 300px;
background-color: gainsboro;
`;
const Image = styled.img`
position: absolute;
width: 100%;
inset: 0;
`;
function LazyImageBackground({ src, alt, children }: IProps) {
const [isLoaded, setIsLoaded] = useState(false);
const [ratio, setRatio] = useState(0);
// 이미지가 로드되었을 때 width와 height를 구해 비율을 구한다.
const onImageLoaded = (e: React.SyntheticEvent<HTMLImageElement, Event>) => {
const { width, height } = e.target as HTMLImageElement;
const ratio = height / width;
setRatio(ratio);
setIsLoaded(true);
};
return (
<ImageDiv
style={{
paddingTop: `${ratio * 100}%`, // 구한 비율만큼 padding-top을 준다.
}}
>
<Image src={src} alt={alt} onLoad={onImageLoaded} />
{/* load가 되었을 때만 내부 자식들을 렌더링 해준다. */}
{isLoaded && children}
</ImageDiv>
);
}
export default LazyImageBackground;
즉, 이미지가 로드되었을 때만 witdh와 height를 계산하고, 이를 바탕으로 비율을 계산해 padding-top으로 비율 %를 부여함으로써 컨테이너의 크기를 정한 뒤 image를 absolute로써 부모 컨테이너에 맞게 늘려 배경 이미지로 활용하게 되는 것이다.
이 컴포넌트는 다음과 같이 사용할 수 있다.
<LazyImageBackground src="소스" alt="대체 텍스트">
<VideoDiv className={winningKidsVideoCss}>
<SVideo src="소스" poster="포스터" />
<VideoControlImg src="소스" />
</VideoDiv>
</LazyImageBackground>;
그럼 방금과 같은 상황이지만, 이미지를 배경으로 사용할 때와는 다르게 이제는 image의 onload 이벤트로 이미지의 load를 감지하기 때문에 load가 되지 않은 상황에서는 내부 요소들을 렌더링 하지 않아 방금과 같은 이슈가 발생하지 않는 모습을 보여준다.


즉, 보통의 경우에는 css의 background 프로퍼티로 배경 이미지를 설정하면 되지만 이미지의 로딩 시점을 알아서 상태로 관리하는 등의 작업이 필요할 때에는 위와 같은 방법을 활용하면 조건부 렌더링이 가능할 것이다.
'개인 공부 > JS (자바스크립트)' 카테고리의 다른 글
메모리 관리와 removeEventListener의 진실 (Garbage collection) (0) | 2022.01.28 |
---|---|
Async/Await 잘 활용하는 법 (0) | 2021.07.28 |
Promise 내부 구현 따라해보기 (0) | 2021.07.02 |
javaScript - Ajax (0) | 2021.06.27 |
javaScript - 디바운스(debounce), 스로틀(throttle) (0) | 2021.06.10 |