๐Ÿ”ฎ Airbnb ์ˆ™์†Œ ํŽ˜์ด์ง€ ํด๋ก  ์ฝ”๋”ฉ: CSS-in-JS ์‚ฌ์šฉ๊ธฐ

hyeondoongeยท2021๋…„ 2์›” 20์ผ
0
post-thumbnail


(์‹ค์ œ airbnb ์‚ฌ์ดํŠธ)

์š”์ฆ˜ ๋งŒ๋“ค๊ณ  ์žˆ๋Š” ๊ฑด Carousel ๋งŒ๋“ค๊ธฐ! ๐Ÿคธโ€โ™€๏ธ
์•„๋ฌด๋ž˜๋„ ๋™์ ์ธ ๋ถ€๋ถ„์ด ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ณด๋‹ค ๋งŽ์ด ์š”๊ตฌ๋˜๋Š” ๋ถ€๋ถ„์ด๋ผ ์†์ด ๋งŽ์ด ๊ฐ”๋‹ค.
React๋ฅผ ์ ‘ํ•˜๋ฉด์„œ styled-components ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด CSS-in-JS๋ฅผ ์‚ฌ์šฉํ•ด์˜ค๊ธด ํ–ˆ์ง€๋งŒ, Carousel์„ ๊ตฌํ˜„ํ•˜๋ฉด์„œ ์œ ์šฉํ•œ ํŒ์„ ๊ฝค ๋ฐœ๊ฒฌํ•ด์„œ ๊ธ€์„ ๋‚จ๊ฒจ๋ณด๋ คํ•œ๋‹ค. ๐Ÿ˜

๋ถ€ํŠธ์ŠคํŠธ๋žฉ์—์„œ ์ง€์›ํ•˜๋Š” carousel์„ ์“ฐ๋ คํ–ˆ์œผ๋‚˜ ์นœ์ ˆํ•œ ์œ ํŠœ๋ธŒ ์Šจ์ƒ๋‹˜์˜ ๊ฐ•์ขŒ๋ฅผ ๋ณด๋ฉฐ ์ง์ ‘ ๊ตฌํ˜„ํ–ˆ๋‹ค.
๐Ÿ‘‰ https://youtu.be/eywZbJ5PVjg

ํฌ๊ฒŒ ๋ณธ Carousel์€ ๋ฐฉํ–ฅํ‚ค๋ฒ„ํŠผ๋“ค๊ณผ ์Šฌ๋ผ์ด๋“œ๋“ค์˜ ๋žฉํผ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

const Carousel = () => (
  <StyledCarousel className="border">
    <CarouselKeyAnchor className="prev" direction="prev" />
    <CarouselImageWrapper sources={srcArr} />
    <CarouselKeyAnchor className="next" direction="next" />
  </StyledCarousel>
);

์ค‘์š”ํ•œ ์Šคํƒ€์ผ์€, ๋ฐฉํ–ฅ๋ฒ„ํŠผ์€ ์ด๋ฏธ์ง€ ์œ„์— ๋†“์—ฌ์•ผ ํ•œ๋‹ค.
๋”ฐ๋ผ์„œ ํ•„์ˆ˜์†์„ฑ์„ ๋ฐ‘๊ณผ ๊ฐ™์ด ์„ค์ •ํ•œ๋‹ค.

const StyledCarouselKeyAnchor = styled.a`
  ...
  z-index: 1;
  position: absolute;
  ...
`;

์—ฌ๊ธฐ๊นŒ์ง€ํ•˜๋ฉด, prev๋ฒ„ํŠผ๊ณผ next๋ฒ„ํŠผ์ด ๊ฒน์ณ๋ณด์ผ ๊ฒƒ์ด๋‹ค.
์™œ๋ƒํ•˜๋ฉด ์•„์ง ๊ณตํ†ต๋œ ์†์„ฑ๊นŒ์ง€๋งŒ ์คฌ๊ธฐ ๋•Œ๋ฌธ์—..
์ด์   ๋ถ„๋ช…ํžˆ ๋ฒ„ํŠผ์˜ ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์œ„์น˜์— ๋‘๊ณ  ์‹ถ์„ ๊ฒƒ์ด๋‹ค. ๐Ÿ”ฅ
์ž ์ด์ œ ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•  ๊ฒƒ์ธ๊ฐ€ ์•Œ์•„๋ณด์ž.

์ด๋•Œ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒƒ์€ props ๋ฐ์ดํ„ฐ์ด๋‹ค.
๋‚ด๊ฐ€ ๋ณธ ๋งŽ์€ ์˜ˆ์‹œ๋Š” ์†์„ฑ๊ฐ’์ด ์ „๋‹ฌ๋˜์ง€ ์•Š์•˜์„ ๋•Œ ๊ธฐ๋ณธ ๊ฐ’์„ ์„ค์ •์„ ํ•  ๋•Œ ์‚ฌ์šฉ์„ ํ•˜๊ณ ์žˆ์—ˆ๋‹ค.

๋ฐ‘์€ styled-component ๊ณต์‹๋ฌธ์„œ์—์„œ ์ œ์‹œํ•˜๊ณ  ์žˆ๋Š” ์˜ˆ์‹œ๋‹ค.

const Button = styled.button`
  /* Adapt the colors based on primary prop */
  background: ${props => props.primary ? "palevioletred" : "white"};
  color: ${props => props.primary ? "white" : "palevioletred"};

  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

render(
  <div>
    <Button>Normal</Button>
    <Button primary>Primary</Button>
  </div>
);

์ข€ ๋” ๋ฌธ์„œ๋ฅผ ์ฐพ์•„๋ณธ ๊ฒฐ๊ณผ ํ•ด๋‹ต์„ ์–ป์–ด ๋‚ผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์กฐ๊ฑด์— ๋”ฐ๋ผ ์†์„ฑ๊ฐ’๋งŒ ์–ป๋Š”๊ฒŒ ๋ชฉ์ ์ด๋ผ๋ฉด ๋‚ด๊ฐ€ ์–ป๊ณ  ์‹ถ์€ ๊ฐ’๋งŒ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋œ๋‹ค. ์œ„์˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ!

ํ•˜์ง€๋งŒ ๋‚˜๋Š” ์†์„ฑ๊ฐ’ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์†์„ฑ๋„ ๋‹ฌ๋ฆฌํ•ด์•ผํ•˜๋Š”๊ฒŒ ๋ชฉ์ ์ด์˜€๊ธฐ์— ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

const StyledCarouselKeyAnchor = styled.a`
  ...
  ${({ direction }) => {
    if (direction === 'prev') {
      return css`
        left: 5px;
      `;
    }
    return css`
      right: 5px;
    `;
  }}
   ...
`;

ํฐ ์ฐจ์ด์ ์€ 'css'๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค๋Š” ์ ์ด๋‹ค.
์‚ฌ์šฉํ•˜๋ ค๋ฉด styled-component์—์„œ ๋ถˆ๋Ÿฌ์˜ค๋ฉด ๋œ๋‹ค.

์ด์ฒ˜๋Ÿผ ๊ณตํ†ต ์†์„ฑ์ด ๋Œ€๋ถ€๋ถ„์ด๊ณ  ์ผ๋ถ€ ์†์„ฑ๋งŒ์„ ๋‹ฌ๋ฆฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ์“ฐ์ด๋Š” ๊ธฐ์ˆ ์ด๋‹ค.

์•„์ง์€ ์ •์  ํŒŒํŠธ๋งŒ ๊ตฌํ˜„ํ•œ ์ƒํƒœ์ด๊ณ  ๋™์  ํŒŒํŠธ๋„ ๊ตฌํ˜„ํ•  ์˜ˆ์ •์ด๋‹ค โ—

0๊ฐœ์˜ ๋Œ“๊ธ€