카테고리 없음

[60일차]배너/캐러셀 구현 및 반응형 웹 적용

PARKpatchnotes 2025. 12. 4. 00:10

1. 배너와 캐러셀 (Banner & Carousel)

웹 사이트의 메인 화면에서 중요한 정보나 프로모션을 효과적으로 보여주기 위해 배너와 캐러셀 UI가 자주 사용된다. 이를 구현하는 방식은 크게 CSS와 상태 관리를 이용하는 방법과 외부 라이브러리를 사용하는 방법으로 나뉜다.

구현 방법 1: CSS transform과 인덱스 활용

transform: translate() 속성과 현재 보여줄 배너 데이터의 인덱스를 조합하면 슬라이드가 옆으로 이동하는 애니메이션을 직접 구현할 수 있다. 특히 Styled Components와 같은 CSS-in-JS 방식을 사용할 때, props로 인덱스를 전달하여 동적으로 스타일을 제어하기 용이하다.

예시 코드

import React, { useState } from 'react';
import styled from 'styled-components';

const Banner = () => {
  const [currentIndex, setCurrentIndex] = useState(0);
  const banners = ["Banner 1", "Banner 2", "Banner 3"];

  const handlePrev = () => {
    setCurrentIndex((prev) => (prev === 0 ? banners.length - 1 : prev - 1));
  };

  const handleNext = () => {
    setCurrentIndex((prev) => (prev === banners.length - 1 ? 0 : prev + 1));
  };

  return (
    <BannerContainer>
      {/* translateX를 통해 현재 인덱스만큼 이동시킨다 */}
      <BannerTrack $currentIndex={currentIndex}>
        {banners.map((banner, index) => (
          <BannerItem key={index}>{banner}</BannerItem>
        ))}
      </BannerTrack>
      <div className="controls">
        <button onClick={handlePrev}>Prev</button>
        <button onClick={handleNext}>Next</button>
      </div>
    </BannerContainer>
  );
};

const BannerContainer = styled.div`
  overflow: hidden;
  width: 100%;
  position: relative;
`;

const BannerTrack = styled.div<{ $currentIndex: number }>`
  display: flex;
  transition: transform 0.5s ease-in-out;
  /* 인덱스 * 100% 만큼 왼쪽으로 이동하여 해당 배너를 보여준다 */
  transform: translateX(${({ $currentIndex }) => $currentIndex * -100}%);
`;

const BannerItem = styled.div`
  min-width: 100%;
  height: 300px;
  background-color: #eee;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
`;

export default Banner;

구현 방법 2: 라이브러리 활용 (React Slick 등)

직접 구현하는 것이 복잡하거나 터치 스와이프, 무한 루프, 오토 플레이 등 고도화된 기능이 필요할 때는 react-slick, slick-carousel과 같은 검증된 라이브러리를 활용하는 것이 효율적이다. 설치 후 설정(Settings) 객체만 조정하면 손쉽게 강력한 기능을 구현할 수 있다.


2. 추천 도서 구현 (컴포넌트 재사용 및 스타일 확장)

설명

기존에 만들어둔 컴포넌트(BookItem)를 재사용하되, 추천 도서 목록에서는 일부 정보(요약, 가격, 좋아요 등)를 숨겨야 하는 경우가 있다. Styled Components는 컴포넌트 자체를 스타일 타겟으로 삼을 수 있는 기능을 제공하므로, 이를 활용하면 원본 컴포넌트를 수정하지 않고도 특정 상황에 맞는 스타일 덮어쓰기가 가능하다.

예시 코드

아래 코드는 기존 BookItem을 가져와서 BookBestItemStyle 내부에서 스타일을 재정의하는 방식이다. display: none을 사용하여 불필요한 요소를 숨기고, 제목(h2)의 말줄임표 처리를 추가하였다.

import { Book } from "@/models/book.model";
import React from "react";
import styled from "styled-components";
import BookItem, { BookItemStyle } from "./BookItem"; // BookItemStyle을 함께 import 해야 한다

interface Props {
  book: Book;
  itemIndex: number;
}

const BookBestItem = ({ book, itemIndex }: Props) => {
  return (
    <BookBestItemStyle>
      {/* 기존 BookItem 컴포넌트 재사용 */}
      <BookItem book={book} view="grid" />
      {/* 순위 표시 추가 */}
      <div className="rank">{itemIndex + 1}</div>
    </BookBestItemStyle>
  );
};

const BookBestItemStyle = styled.div`
  ${BookItemStyle} {
    /* 추천 도서에서는 보이지 않아야 할 요소들을 숨김 처리 */
    .summary,
    .price,
    .likes {
      display: none;
    }

    /* 제목이 길어질 경우 2줄까지만 표시하고 말줄임표(...) 처리 */
    h2 {
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
      text-overflow: ellipsis;
    }
  }

  position: relative;

  .rank {
    position: absolute;
    top: -10px;
    left: -10px;
    width: 40px;
    height: 40px;
    background-color: var(--main-color);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-weight: bold;
    font-size: 1.2rem;
  }
`;

export default BookBestItem;

3. 모바일 대응 (반응형 웹, Responsive Web)

설명

스마트폰, 태블릿, 데스크톱 등 웹에 접속하는 기기의 화면 크기가 다양해짐에 따라, 프론트엔드 개발자에게 반응형 웹 적용은 필수적인 역량이 되었다. 반응형 웹이란 하나의 웹 사이트가 접속하는 기기의 화면 크기에 맞춰 레이아웃과 콘텐츠를 최적화하여 보여주는 기술을 말한다.

반응형 웹 구현의 핵심 요소

  1. Viewport Meta 태그:
    모바일 브라우저가 페이지의 너비와 배율을 어떻게 제어할지 설정한다. <head> 태그 내에 반드시 포함되어야 한다.

    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  2. 상대 단위를 활용한 유동형 레이아웃:
    px과 같은 고정 단위 대신, 부모 요소나 뷰포트 크기에 따라 변하는 상대 단위(%, vw, vh, rem, em)를 사용하여 레이아웃이 유연하게 늘어나거나 줄어들도록 해야 한다.

  3. 미디어 쿼리 (Media Query):
    CSS의 @media 규칙을 사용하여 특정 화면 너비(Breakpoint)에 따라 다른 스타일을 적용한다. 이를 통해 PC에서는 가로형 레이아웃을, 모바일에서는 세로형 레이아웃을 보여주는 등 화면 구성을 변경할 수 있다.

    /* 기본 스타일 (모바일 우선 또는 데스크톱 우선) */
    .container {
      width: 100%;
    }
    
    /* 태블릿 화면 (768px 이상) */
    @media (min-width: 768px) {
      .container {
        width: 80%;
      }
    }
    
    /* 데스크톱 화면 (1024px 이상) */
    @media (min-width: 1024px) {
      .container {
        width: 60%;
      }
    }