티스토리 뷰

반응형

 

 

대회 프로젝트를 진행하는데, 프론트엔드를 할 사람이 없었다.

이번 프로젝트는 한명이 빠지는 바람에 할 사람이 없다. 심지어 JS 자체를 모르는 분도 있다.

게다가 제 6회 KDT 해커톤 본선까지 진출해버리면서 구현 작업을 더 디테일하게 해야했다.

따라서 필자가 AI 백엔드 기본 구현, 작업 검수에 이어서 프론트엔드까지 전부 구현하고 맡게 되었다. 그러면서 1년 전 기억을 되살려내면서 꾸역꾸역 만들어낸 React 코드이다.

 

그 중에서도 오늘은 새롭게 알게 된 페이지 전환 애니메이션에 대해서 알아보려고 한다.

일단 간단하게 설명하자면 React-trainsition-group이라는 걸 쓴다.

 

개인적으로 framer는 뚝뚝 끊기는 느낌이 있어서 이게 더 낫다고 판단하여 쓰게 되었다.

 

코드는 아래와 같다.

import React from 'react';
import { BrowserRouter as Router, Route, Routes, useLocation } from 'react-router-dom';
import { TransitionGroup, Transition } from 'react-transition-group';
import ChatPage from './pages/ChatPage';
import HomePage from './pages/HomePage';
import Header from './components/common/Header';

const TIMEOUT = 300;

const getTransitionStyles = (status) => ({
  entering: {
    position: 'absolute',
    opacity: 0,
    transform: 'translateX(50px)',
    backgroundColor: '#DFD9CE',
  },
  entered: {
    transition: `opacity ${TIMEOUT}ms ease-in-out, transform ${TIMEOUT}ms ease-in-out`,
    opacity: 1,
    transform: 'translateX(0)',
    backgroundColor: '#DFD9CE',
  },
  exiting: {
    transition: `opacity ${TIMEOUT}ms ease-in-out, transform ${TIMEOUT}ms ease-in-out`,
    opacity: 0,
    transform: 'translateX(-50px)',
    backgroundColor: '#DFD9CE',
  },
  exited: {
    opacity: 0,
    transform: 'translateX(50px)',
    backgroundColor: '#DFD9CE',
  },
}[status]);

function AnimatedRoutes() {
  const location = useLocation();

  return (
    <div style={{ position: 'relative', width: '100%', height: '100%', backgroundColor: '#DFD9CE' }}>
      <TransitionGroup className="relative w-full h-full">
        <Transition key={location.pathname} timeout={TIMEOUT}>
          {(status) => (
            <div
              style={{
                ...getTransitionStyles(status),
              }}
              className="w-full h-full absolute top-0 left-0"
            >
              <Routes location={location}>
                <Route path="/" element={<HomePage />} />
                <Route path="/chat" element={<ChatPage />} />
              </Routes>
            </div>
          )}
        </Transition>
      </TransitionGroup>
    </div>
  );
}

function App() {
  return (
    <Router>
      <div style={{ 
        position: 'relative', 
        overflow: 'hidden', 
        width: '100%', 
        height: '100vh',
        backgroundColor: '#DFD9CE'  // 최상위 컨테이너에도 배경색 지정
      }}>
        <Header />
        <AnimatedRoutes />
      </div>
    </Router>
  );
}

export default App;

 

Header는 App.js에 고정하고,

나머지 page 코드나 이런 건 컴포넌트화해서 SOLID 패턴을 중요시했다.

사실 위의 코드도 보여주기식일 뿐, AnimatedRoutes로 컴포넌트화해서 쓸 생각이다.

 

확실히 쌩 Html로 작동할 때는 어느 코드가 어느 부분에 있는지, JS가 어디에 있는지 헷갈리는데, 리액트는 요소 관리가 편해서 좋다.

다만 이제 Vue보다 상태관리가 조금 더 어렵다는 게 흠이긴 하다.

 

그래도 동적으로 만들어진 프레임은 확실히 마음에 든다.

아래는 디자인이 없을 때의 시연영상인데, 비교해보면 위가 그래도 더 낫다는 평가를 들었으니 말이다.

 

혼자서 하려니 작업량이 진짜 많긴 하지만, 꼭 본선에서 다 갈아서 대상 타면 안 억울할거 같다.

그래도 열심히 해야지.

 

만든 코드는 https://github.com/bellkjtt/budrami-react-django 에서 볼 수 있다.

반응형