โ ๊ธฐ์กด์๋ width๋ฅผ $prop ์ผ๋ก ์ง์ ์กฐ์ ํ์ผ๋ โ๏ธlayout ๋ณํ ๋ฐ์&๋ฆฌํ๋ก์ฐ ๋ฐ์โ๏ธ
์ด๋ฅผ ํด๊ฒฐ ํ๊ณ ์ ๋ฆฌํฉํ ๋ง ์คํ
transform: scaleX(n)์
์์์ ๊ฐ๋ก ๊ธธ์ด(width)๋ฅผ n๋ฐฐ๋ก ํ๋/์ถ์
โข n = 1 โ ์๋ ํฌ๊ธฐ
โข n = 0.5 โ ๊ฐ๋ก ๊ธธ์ด๊ฐ ์ ๋ฐ
โข n = 2 โ ๊ฐ๋ก ๊ธธ์ด 2๋ฐฐ
โข n = 0 โ ๊ฐ๋ก ๊ธธ์ด 0 (์ ๋ณด์)
transform: scaleX(0.5);
์ด๊ฑด ํด๋น ์์๋ฅผ ์ผ์ชฝ ๊ธฐ์ค์ผ๋ก ๊ฐ๋ก๋ง 50%๋ก ์ค์ด๋ ํจ๊ณผ.
โ๏ธ ์ค์ํ ์ : ์ค์ width๋ฅผ ๋ฐ๊พธ๋ ๊ฒ ์๋๋ผ โ๋ณด์ฌ์ง๋ ํฌ๊ธฐโ๋ง ๋ฐ๋
โ ๊ทธ๋์ GPU(๊ทธ๋ํฝ ๊ฐ์)๋ก ์ ๋๋ฉ์ด์ ์ด ํจ์ฌ ๋ถ๋๋ฝ๋ค.
| ๊ธฐ์ค | width | transform: scaleX() |
|---|---|---|
| ๋์ | layout ๋ณํ ๋ฐ์ | layout ๋ณํ ์์ |
| ๋ฆฌํ๋ก์ฐ | ์๊น (๋๋ฆผ) | ์์ (๋น ๋ฆ) |
| ์ฑ๋ฅ | CPU ๊ธฐ๋ฐ | GPU ๊ฐ์ |
| ๋ถ๋๋ฌ์ | ์ค๊ฐ | โ ํจ์ฌ ๋ถ๋๋ฌ์ |
| ์ถ์ฒ | ๊ฐ๋จํ ๋ OK | ๊ณ ์ฑ๋ฅ UI์ ๊ฐ๋ ฅ ์ถ์ฒ |
scaleX()๋ ๋์ ๋ณด์ด๋
๊ธธ์ด๋ง ์ถ์/ํ๋
์ ๋๋ฉ์ด์ ์ต์ ํํ ๋ ์์ฃผ ์ฐ์ด๋ ํต์ฌ ์์ฑ.
ํ์ฌ ์ฝ๋์์ ProgressBar๋ฅผ transform: scaleX() ๊ธฐ๋ฐ์ผ๋ก ๊ฐ์ ํ ๋ด์ฉ๊ณผ,
๊ธฐ์กด width ๋ฐฉ์๊ณผ์ ์ฐจ์ด์ , ์ฅ๋จ์ , ์ต์ข ์ ์ผ๋ก ์ ์ด๋ ๊ฒ ๋ฐ๊ฟจ๋์ง๋ฅผ ํฌํจํ ๋ฌธ์.
๊ธฐ์กด width ๊ธฐ๋ฐ ์งํ๋ฐ์์
๋ ๋ถ๋๋ฝ๊ณ ์ฑ๋ฅ ์ข์ transform: scaleX() ๊ธฐ๋ฐ ์งํ๋ฐ๋ก ๊ฐ์ ํจ.
์ด ๋ฌธ์๋ ํด๋น ๋ฆฌํฉํฐ๋ง์ ๋๊ธฐ, ๊ธฐ์ ๊ฐ๋ , ์ฐจ์ด์ , ์ฅ์ , ์ฃผ์์ฌํญ์ ๋ชจ๋ ๋ฌธ์ํํ ์๋ฃ๋ค.
| ๊ธฐ์กด ๋ฐฉ์ (width) | ๋ฌธ์ ์ |
|---|---|
| width: ${progress}% | ๋ธ๋ผ์ฐ์ ๋ ์ด์์(Layout Reflow) ๋ฐ์ ๊ฐ๋ฅ์ฑ |
| transition ์ ์ฉ ์ ์ด์ง ๋๊น | ๋ถ๋๋ฝ์ง ์์, ์ ๋๋ฉ์ด์ ์ฑ๋ฅ ๋จ์ด์ง |
| DOM ์ฌ์ด์ฆ ์ง์ ์กฐ์ | ๋ธ๋ผ์ฐ์ ์ฐ์ฐ ๋น์ฉ ํผ (CPU) |
โ ๊ฐ๋ ์์ฝ
transform: scaleX(n);
โข ์์์ ๊ฐ๋ก ๋ฐฉํฅ ์ค์ผ์ผ์ ์กฐ์
โข n = 0 โ ๊ฐ๋ก ๊ธธ์ด 0%
โข n = 1 โ ๊ฐ๋ก ๊ธธ์ด 100%
โข n = 0.5 โ ๊ฐ๋ก ๊ธธ์ด 50%
โ ์ถ๊ฐ ์์ฑ
transform-origin: left;
โข ์ผ์ชฝ์ ๊ธฐ์ค์ผ๋ก ์ปค์ง๊ฑฐ๋ ์ค์ด๋ฆ
โข ์งํ ๋ฐ์ฒ๋ผ ์ผ์ชฝ โ ์ค๋ฅธ์ชฝ ์์ฐ์ค๋ฌ์ด ํ์ฅ ๊ฐ๋ฅ
๐ ์ ์ฒด ๋ฆฌํฉํฐ๋ง ์ฝ๋
const ProgressBarWrapper = styled.div`
position: absolute;
bottom: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 1;
`;
const ProgressFill = styled.div`
height: 100%;
width: 100%;
background-color: ${({ theme }) => theme.surface.brandDefault};
transform-origin: left;
transform: scaleX(${({ $progress }) => $progress / 100});
transition: transform 0.5s linear;
will-change: transform;
opacity: 0.8;
`;
return (
<ProgressBarWrapper>
<ProgressFill $progress={progress} />
</ProgressBarWrapper>
);
| ํญ๋ชฉ | ๊ธฐ์กด ๋ฐฉ์ (width) | ๊ฐ์ ๋ฐฉ์ (scaleX) |
|---|---|---|
| ๋ ๋๋ง ์ฑ๋ฅ | CPU ์ค์ฌ | โ GPU ์ค์ฌ (transform) |
| ์ ๋๋ฉ์ด์ | ๋๊น ์์ | โ ๋งค์ฐ ๋ถ๋๋ฌ์ |
| DOM layout ์ํฅ | layout ์ฌ๊ณ์ฐ ๋ฐ์ | โ layout ์ํฅ ์์ |
| ๋ฆฌ์์ค ๋น์ฉ | ๋์ | โ ๋ฎ์ |
| CSS transition | width transition | transform transition (๋ ๋ถ๋๋ฌ์) |
| ์๊ฐ์ ์ ์ด | ๋น๊ต์ ์ง๊ด์ | ์ด๊ธฐ ํ์ต ํ์ํ์ง๋ง ํจ๊ณผ ์ฐ์ |
| ํญ๋ชฉ | ์ค๋ช |
|---|---|
| transform-origin | ๋ฐ๋์ left๋ก ์ค์ ํด์ผ ์งํ๋ฐ์ฒ๋ผ ๋์ |
| transition | transform์๋ง ์ ์ฉํด์ผ ์์ฐ์ค๋ฌ์ |
| width: 100% ์ ์ง | ์ค์ผ์ผ ์กฐ์ ์ด๊ธฐ ๋๋ฌธ์ ์ค์ ๋ฐ์ค๋ ํญ์ 100%์ฌ์ผ ํจ |
| will-change: transform | ๋ธ๋ผ์ฐ์ ์ ์ฌ์ ํํธ ์ค์ ์ฑ๋ฅ ํฅ์ |
โข width ๊ธฐ๋ฐ์ ๊ฐ๋จํ์ง๋ง, ๋ถ๋๋ฝ์ง ์๊ณ ์ฑ๋ฅ ์ต์ ํ ์ด๋ ค์
โข transform ๊ธฐ๋ฐ์ GPU ๊ฐ์ โ ํ๋ ์ ๋๋ ์์ด ๋ถ๋๋ฌ์
โข ํนํ ์ ์ฌ์ ๋๋ฐ์ด์ค, ๋ชจ๋ฐ์ผ์์ ์ฒด๊ฐ ์ฐจ์ด ํผ
โข ์๊ฐ์ ์ผ๋ก๋ ํจ์ฌ ๋งค๋๋ฌ์ด UX ์ ๊ณต ๊ฐ๋ฅ
| ๋ด์ฉ | ์ค๋ช |
|---|---|
| ์ฌ์ฉ ์์ฑ | transform: scaleX(), transform-origin: left |
| ์ฑ๋ฅ | โ ๋ถ๋๋ฝ๊ณ ์ต์ ํ๋จ |
| ์ฐ์ | ์งํ๋ฐ, ๋ก๋ฉ๋ฐ, ๊ทธ๋ํฝ ์๊ฐํ |
| ๋ฆฌ์กํธ ์ฐ๋ ๋ฐฉ์ | ์ํ๊ฐ โ ์ค์ผ์ผ ๋น์จ๋ก ๋ฐ์ |