[React] 모달 UI에 애니메이션 효과 추가하기

쫀구·2023년 1월 9일
0

모달을 조건부 렌더링으로 구현했지만, 애니메이션 효과가 없어 UI가 너무 딱딱하게 느껴졌다.

검색을 통해 대부분의 구현이 opacity 속성을 이용해 모달을 투명하게 만들고, 클릭 시 보이게 하는 방법을 사용한다는 것을 알게 되었습니다. 그러나 여러 시행착오 끝에 @keyframesanimation 속성을 이용해 모달에 애니메이션을 추가하여 문제를 해결했습니다.

모달 구현 시 고려할 3가지 조건

  1. 모달이 나타날 때 다른 요소보다 위에 렌더링되어야 한다.
  2. 모달 내부의 버튼들이 정상적으로 동작해야 한다.
  3. 모달 백그라운드를 클릭해도 모달이 닫힐 수 있어야 한다.

opacity 사용 시 문제점

  • 모달 백그라운드 뒤에 있는 버튼이나 요소들이 클릭되지 않거나 동작하지 않는 문제가 발생합니다. pointer-events: none 속성을 사용할 수 있지만, 이 경우 백그라운드 클릭으로 모달을 닫을 수 없으며, 모달 내부의 버튼도 사용할 수 없게 됩니다.
  • 브라우저에는 보이지 않지만, 실제로는 렌더링되어 있는 상태이므로 버그가 발생할 수 있으며, 대규모 웹에서 메모리 낭비로 이어질 수 있습니다.

모달 컴포넌트

모달을 보다 효율적으로 제어하기 위해 커스텀 훅을 사용하여 props 없이도 모달을 제어할 수 있도록 구현했습니다. 또한, 모달이 생성되면 백그라운드 클릭 또는 닫기 버튼(x) 을 눌러 모달이 사라지도록 기능을 추가했습니다.

// Modal.tsx
import React from 'react';
import { useModal } from './useModal';

const Header = () => {
  const { clickHandler } = useModal();

  return (
    <LoginSection>
      <p className="login" onClick={() => clickHandler(true)}>
        로그인
      </p>
    </LoginSection>
  );
};

const Modal = () => {
  const { isOpen, clickHandler } = useModal();

  return (
    <Container display={isOpen ? 'flex' : 'none'}>
      {/* 모달 백그라운드 클릭 시 모달 닫기 */}
      <ModalBackground onClick={() => clickHandler(false)} />
      <ModalWindow>
        {/* x 버튼 클릭 시 모달 닫기 */}
        <p className="close" onClick={() => clickHandler(false)}>
          &times;
        </p>
      </ModalWindow>
    </Container>
  );
};
// useModal.ts
import { useState } from 'react';

// 모달을 제어하는 커스텀 훅
export const useModal = () => {
  const [isOpen, setIsOpen] = useState(false);

  // 클릭 시 모달 열기/닫기 제어
  const clickHandler = (isClicked: boolean) => {
    setIsOpen(isClicked);
  };

  return { isOpen, clickHandler };
};

Styled-components로 애니메이션 구현

모달이 부드럽게 나타나고 사라지도록 애니메이션을 추가했습니다. 백그라운드를 클릭했을 때도 모달이 사라지도록 설정했습니다.

// modalstyled.ts
const Container = styled.div`
  display: ${(props) => props.display || 'none'};
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.6);
`;

const ModalBackground = styled.div`
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
`;

// 모달 애니메이션 설정
const ModalWindow = styled.div`
  position: relative;
  width: 380px;
  height: 550px;
  background: white;
  padding: 0 30px;
  animation: modaldown 0.5s linear;

  @keyframes modaldown {
    from {
      transform: translateY(-10%);
    }
    to {
      transform: translateY(0);
    }
  }

  .close {
    position: absolute;
    right: 15px;
    top: 5px;
    cursor: pointer;
    font-size: 25px;
  }
`;
  • 위 코드에서 animation: modaldown 0.5s linear;는 애니메이션의 이름과 지속 시간을 설정하는 부분입니다.
  • @keyframes에서 from은 애니메이션 시작 지점을, to는 종료 지점을 나타냅니다. transform: translateY(-10%)으로 모달이 약간 위에서 시작해 translateY(0)으로 원래 위치에 오도록 설정했습니다.

결과적으로 원하는 애니메이션 효과가 잘 구현되었습니다.

profile
Run Start 🔥

0개의 댓글