728x90
반응형

Nextjs 화면을 반응형으로 만들기 위해 우리는 bootstrap5를 이용할 것이다.

 

리액트에서의 bootstrap5는 아래 링크를 확인하면 된다.

https://designmodo.com/bootstrap-react-sass/#bootstrap-5-with-react-js

 

Getting Started with Bootstrap 5, React, and Sass

Get React JS and Bootstrap 5 install and integrate together using npm. Setup Sass for different screen resolutions of your app.

designmodo.com


SCSS에 관한 내용은 아래 링크를 참조하자.

https://typo.tistory.com/entry/Nextjs-%EA%B8%B0%EB%B3%B8%EA%B8%B0%EB%8A%A5-Built-In-CSS-SupportSCSS?category=895504 

 

Next.js | 기본기능 | Built-In CSS Support(SCSS)

리액트에서의 스타일 적용법은 다음 링크로 확인할 수 있다. https://typo.tistory.com/entry/Reactjs-%EC%9E%85%EB%AC%B8-CSS-SASS-SCSS?category=891266 React.js | 입문 | CSS, SASS, SCSS ReactJS에 CSS를 추..

typo.tistory.com


 

먼저 bootstrap을 설치한다.

$ npm i bootstrap@5.0.0-alpha3

 

_app.tsx 파일에 추가해준다.

_app.tsx

import { AppProps } from "next/app";
import { NextPage } from "next";
//store
import wrapper from "../store";
//css
import "bootstrap/dist/css/bootstrap.min.css";

const MyApp: NextPage<AppProps> = ({ Component, pageProps }: AppProps) => {
	return (
		<>
			<Component {...pageProps} />
		</>
	);
};

export default wrapper.withRedux(MyApp);

 

 

 

기존에 만들어 두었던 dashboard 페이지를 다시 확인하자.

 

src/dashboard/index.tsx

import axios from 'axios'
import type { GetServerSideProps, NextPage } from 'next'
import Link from 'next/link'
import cookies from 'next-cookies'
import jwtDecode, { JwtPayload } from 'jwt-decode'


interface Props {
    data : any
}


const Dashboard:NextPage<Props> = ({data}) => {
    const ClickHandler = () => {

    }
    return (
        <div>
            <div className='dashboard'>
                Dashboard
            </div>
        </div>
        )
}


export default Dashboard;

export const getServerSideProps:GetServerSideProps = async (context) => { // SSR
    try {
        const token = cookies(context).token;
        const decodedToken: JwtPayload = jwtDecode<JwtPayload>(token ? token : '');
        
        if(decodedToken) {
            return {
                props: {
                }
            }
        }
        else {
            return {
                redirect: {
                destination: '/',
                permanent: false,
                },
            }
        }
    }
    catch(e) {
        console.log(e)
        return {
            redirect: {
            destination: '/',
            permanent: false,
            },
        }
    }
}

 

버튼을 눌렀을 경우 position이 "absolute"인 NavBar를 만들자.

 

dashboard/index.tsx

const Dashboard:NextPage<Props> = ({data}) => {
    const [sidebarOpen,setSidebarOpen] = useState(false);
    const SidebarOpen = () => {
        if(sidebarOpen)
            setSidebarOpen(false);
        else
            setSidebarOpen(true);
    }
    return (
        <div>
            {/* header */}
            <div className={"w-100 d-flex align-items-center mx-auto border border-bottom-1"}
                style={{
                    height: "50px"
                }}>
                <div style={{width: "5%"}}>
                    <button
                        style={{color:"blue"}}
                        onClick={SidebarOpen}>
                    o
                    </button>
                </div>
                <div 
                    style={{ width: "75%"}}>
                    로고
                </div>
                <div style={{width: "20%"}}>
                    프로필
                </div>
            </div>
            {/* nav */}
            {sidebarOpen ? 
                <div
                    style={{
                    backgroundColor: "lightblue",
                    position: "absolute",
                    width: "200px",
                    height: "100%",
                    opacity: 1
                    }}>
                        we
                </div>
                : ""
            }
            {/* body */}
            <div className='dashboard'>
                Dashboard
            </div>
            {/* footer */}
        </div>
        )
}

 

화면을 확인해보자.

 

 

버튼을 누르면 Navbar가 뜨고, 다시 누르면 사라진다. 너무 딱딱하니까 효과를 좀 넣어주자.

SCSS와 styled-components를 사용하기 위해 다음 모듈을 설치해준다.

 

$ npm install sass styled-components @types/styled-components

 

next.config.js 파일에 path를 import 하고 sassOptions를 설정해준다.

 

next.config.js

/** @type {import('next').NextConfig} */
const path = require('path');

module.exports = {
  sassOptions: {
    includePaths: [path.join(__dirname, 'styles'), path.join(__dirname, 'src')],
  },
  reactStrictMode: true,
  async rewrites() {
    console.log(process.env.NODE_ENV)
    if (process.env.NODE_ENV !== 'production') {
      return [
        {
          source: process.env.SOURCE_PATH,
          destination: process.env.DESTINATION_URL,
        },
      ];
    }
    else {
      return [
        {
          source: process.env.SOURCE_PATH,
          destination: process.env.DESTINATION_URL,
        },
      ];
    }
  },
}

 

dashboard 페이지에 SCSS와 styled-components를 활용해준다.

 

dashboard/index.tsx

import axios from 'axios'
import type { GetServerSideProps, NextPage } from 'next'
import Link from 'next/link'
import cookies from 'next-cookies'
import jwtDecode, { JwtPayload } from 'jwt-decode'
import { useState } from 'react'
import styled, {keyframes} from 'styled-components'


interface Props {
    data : any
}

// 투명도 설정
const fadein = keyframes`
 from {
     opacity : 0
 }
 to {
     opacity: 1
 }
`

// NavDiv에 효과 설정
const NavDiv = styled.div`
  animation-duration: 0.25s;
  animation-timing-function: ease-out;
  animation-name: ${fadein};
  animation-fill-mode: forwards
`


const Dashboard:NextPage<Props> = ({data}) => {
    const [sidebarOpen,setSidebarOpen] = useState(false);
    const SidebarOpen = () => {
        if(sidebarOpen)
            setSidebarOpen(false);
        else
            setSidebarOpen(true);
    }
    return (
        <div>
            {/* header */}
            <div className={"w-100 d-flex align-items-center mx-auto border border-bottom-1"}
                style={{
                    height: "50px"
                }}>
                <div style={{width: "5%"}}>
                    <button
                        style={{color:"blue"}}
                        onClick={SidebarOpen}>
                    o
                    </button>
                </div>
                <div 
                    style={{ width: "75%"}}>
                    로고
                </div>
                <div style={{width: "20%"}}>
                    프로필
                </div>
            </div>
            {/* nav */}
            {sidebarOpen ? 
                <NavDiv
                    style={{
                    backgroundColor: "lightblue",
                    position: "absolute",
                    width: "200px",
                    height: "100%",
                    opacity: 1
                    }}>
                        we
                </NavDiv>
                : ""
            }
            {/* body */}
            <div className='dashboard'>
                Dashboard
            </div>
            {/* footer */}
        </div>
        )
}


export default Dashboard;

export const getServerSideProps:GetServerSideProps = async (context) => { // SSR
    try {
        const token = cookies(context).token;
        const decodedToken: JwtPayload = jwtDecode<JwtPayload>(token ? token : '');
        
        if(decodedToken) {
            return {
                props: {
                }
            }
        }
        else {
            return {
                redirect: {
                destination: '/',
                permanent: false,
                },
            }
        }
    }
    catch(e) {
        console.log(e)
        return {
            redirect: {
            destination: '/',
            permanent: false,
            },
        }
    }
}

 

inline-css가 좋지는 못하다고 하나 나중에 한꺼번에 정리하려고 일단 기능이 되는대로 넣어놨다.

 

다시 버튼을 눌러보면 효과가 적용되어 나타나는 것을 확인할 수 있다.

 

 

728x90
반응형

+ Recent posts