NUMBEL:: 쿠팡 클론 코딩 챌린지 [1회차] - 7.4 ~ 7.6 기록

HYl·2022년 7월 7일
0
  • Next.js에 emotion 세팅하기
    • Layout, theme 설정

emotion 설치

yarn dev @emotion/react @emotion/styled

tsconfig.json 추가

{
  "compilerOptions": {
	...
    "jsxImportSource": "@emotion/react",
	...
  }
}

_app.tsx

_app.tsx에 global, Layout, theme 를 추가해주었다.
styled-components와 구조가 매우 유사한 것 같다.

import { Global, ThemeProvider } from '@emotion/react';
import type { AppProps } from 'next/app';
import { useState } from 'react';
import { Hydrate, QueryClient, QueryClientProvider } from 'react-query';

import global from 'src/styles/global';
import Layout from 'src/styles/layout';
import theme from 'src/styles/theme';

function MyApp({ Component, pageProps }: AppProps) {
  const [queryClient] = useState(() => new QueryClient());

  return (
    <QueryClientProvider client={queryClient}>
      <Hydrate state={pageProps.dehydratedState}>
        <ThemeProvider theme={theme}>
          <Global styles={global} />
          <Layout>
            <Component {...pageProps} />
          </Layout>
        </ThemeProvider>
      </Hydrate>
    </QueryClientProvider>
  );
}

export default MyApp;

global.ts

import { css } from '@emotion/react';

const global = css`
  * {
    box-sizing: border-box;
  }

  html {
    font-size: 16px;
    font-family: 'Noto Sans KR', sans-serif;
  }

  body {
    font-family: 'Noto Sans KR', sans-serif;
  }

  select,
  input,
  button,
  textarea {
    border: 0;
    outline: 0 !important;
  }

  a {
    text-decoration: none;
  }
`;

export default global;

theme.ts

const size = {
  mobile: '400px',
  tablet: '768px',
  laptop: '1023px',
  desktop: '1240px',
};

const theme = {
  blue500: '#3182f6',
  blue700: '#1b64da',
  grey: '#ccc',
  white: '#ffffff',

  mq: {
    desktop: `@media only screen and (min-width: ${size.desktop})`,
    laptop: `@media only screen and (min-width: ${size.laptop})`,
    tablet: `@media only screen and (min-width: ${size.tablet})`,
    mobile: `@media only screen and (min-width: ${size.mobile})`,
  },
};

export default theme;

emotion.d.ts

타입스크립트를 사용할 경우, theme에 대한 타입 지정이 필요하다. theme.ts에서 설정한 것과 동일한 구조의 타입을 넣어주며, 파일 이름은 emotion.d.ts 로 설정해주어야 한다

import '@emotion/react';

declare module '@emotion/react' {
  export interface Theme {
    blue500: string;
    blue700: string;
    grey: string;
    white: string;

    mq: {
      desktop: string;
      laptop: string;
      tablet: string;
      mobile: string;
    };
  }
}

layout.tsx

반응형 설정을 해주기 위하여 Layout component를 생성하여 layout 설정하였다.

theme의 설정이 잘 되었다면, 컴포넌트에서 props로 지정된 theme를 사용할 수 있다.

import styled from '@emotion/styled';
import { ReactNode } from 'react';

interface LayoutProps {
  children: ReactNode;
}

const Layout = ({ children }: LayoutProps) => {
  return <LayoutWrap>{children}</LayoutWrap>;
};

const LayoutWrap = styled.div`
  max-width: 100%;
  width: 100%;
  padding: 0;
  margin: 0 auto;
  height: auto;

  // props로 지정된 theme를 사용할 수 있다.
  ${props => props.theme.mq.tablet} {
    max-width: 460px;
    
  }
`;

export default Layout;
  • tablet 768px을 기준으로 layout이 변하게 설정을 하였다.

회고

emotion을 사용하는 데 아직 익숙하지 않아 중간중간 오류가 빈번하게 발생하였었다.
( emotion 환경 설정, theme props로 받아오는 것, theme type 설정 등등. )
그래도 2회차에 들어가기 앞서 theme와 Layout을 미리 사전에 설정을 해두어 작업을 할 때 좀 더 편하게 할 수 있을 것 같다.

profile
꾸준히 새로운 것을 알아가는 것을 좋아합니다.

0개의 댓글