1. 프로젝트 준비하기

이번 섹션에서는 프로젝트의 기반을 잡아보겠습니다. 기반을 잡는 과정에서 해야 할 것은, 프로젝트 생성, 리액트 라우터 적용, 스타일 시스템 설정입니다.

프로젝트 생성

$ yarn create react-app reacters

리액트 라우터 설치 및 적용

프로젝트 디렉터리에서 다음 명령어를 실행하여 리액트 라우터를 설치하세요.

$ yarn add react-router-dom

그 다음엔 페이지를 위한 컴포넌트들을 생성해주겠습니다.

페이지 컴포넌트들은 src 디렉터리에 pages 디렉터리를 만들어서 그 안에 파일을 생성해주세요. 각 페이지들이 어떤 용도로 사용되는지는 각 파일의 주석에 입력되어있는지 적혀있으니 참고하세요.

pages/PostListPage.js

import React from 'react';

/**
 * 여러 포스트 목록을 보여주는 페이지
 */
const PostListPage = () => {
  return <div>PostListPage</div>;
};

export default PostListPage;

pages/LoginPage.js

import React from 'react';

/**
 * 로그인 할 때 사용되는 페이지
 */
const LoginPage = () => {
  return <div>LoginPage</div>;
};

export default LoginPage;

pages/RegisterPage.js

import React from 'react';

/**
 * 회원가입 할 때 사용되는 페이지
 */
const RegisterPage = () => {
  return <div>RegisterPage</div>;
};

export default RegisterPage;

pages/WritePage.js

import React from 'react';

/**
 * 글쓰기 페이지
 */
const WritePage = () => {
  return <div>WritePage</div>;
};

export default WritePage;

pages/PostPage.js

import React from 'react';

/**
 * 포스트 읽는 페이지
 */
const PostPage = () => {
  return <div>PostPage</div>;
};

export default PostPage;

이렇게 5개의 컴포넌트를 모두 만들어주었나요? 이렇게 페이지 용도로 사용되는 컴포넌트들을 pages 디렉터리에 분류시켜주면 나중에 라우트를 관리 할 때 편리합니다.

추가적으로, 우리는 이 프로젝트에서 리덕스를 사용하게 될텐데, 페이지 컴포넌트에서 connect 를 사용하여 리덕스와 연동 하면 안되는 이유는 없지만 왠만하면 연동하는 것을 지향하고 리덕스와 연동된 컨테이너 컴포넌트를 따로 만들고, 이미 연동이 된 컴포넌트를 페이지 컴포넌트 내부에서 렌더링을 하시는 것을 권장드립니다.

꼭 그렇게 해야 하는 것은 아니지만, 만약에 페이지 컴포넌트 자체에 리덕스를 연동해주게 되면 컴포넌트의 소스코드 길이가 너무 길어질 수 있어서 유지보수성이 떨어 질 수 있습니다.

이제, index.js 에서 BrowserRouter 로 App 컴포넌트를 감싸고, App 내부에서는 각 경로에 연결시켜줄 컴포넌트를 설정해주겠습니다.

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

App.js

import React from 'react';
import { Route } from 'react-router-dom';
import PostListPage from './pages/PostListPage';
import LoginPage from './pages/LoginPage';
import RegisterPage from './pages/RegisterPage';
import WritePage from './pages/WritePage';
import PostPage from './pages/PostPage';
const App = () => {
  return (
    <>
      <Route component={PostListPage} path="/" exact />
      <Route component={LoginPage} path="/login" />
      <Route component={RegisterPage} path="/register" />
      <Route component={WritePage} path="/write" />
      <Route component={PostPage} path="/posts/:postId" />
    </>
  );
};

export default App;

리액트 라우터 적용이 끝났습니다! yarn start 를 하여 리액트 개발 서버를 실행하시고 우리가 준비해준 각 경로에 직접 주소를 입력하여 들어가서 알맞는 문구가 뜨는지 확인해보세요.

스타일 시스템 설정

이번에는 스타일 시스템을 설정 할 차례입니다. 스타일링의 경우엔 CSS, Sass, CSS Module, styled-components 등 정말 다양한 방법이 있고, 여러분들이 앞으로 각각 조금씩 사용해보면서 그 중에서 여러분의 취향에 가장 알맞는것을 선택하셔서 개발하시길 바랍니다.

이번 프로젝트에선 Sass 를 사용 할 것이고, Sass 믹스인이나 변수를 조금 더 쉽게 사용 하기 위하여 sass-loader 설정을 조금 커스터마이징 해줄 것입니다.

가장 먼저, node-sass 를 설치하세요.

$ yarn add node-sass

그 다음에는 src 디렉터리에 styles 디렉터리를 만들고 그 안에 main.scss 파일을 생성하세요.

styles/main.scss

// 추후 전체화면에 색상을 주는 상황을 위하여 html, body, #root 에 100% min-height / height 설정
html {
  height: 100%;
}
body {
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  box-sizing: border-box;
  min-height: 100%;
}

#root {
  min-height: 100%;
}

// 모든 엘리먼트 box-sizing 값을 border-box 로 설정하게 해줌
* {
  box-sizing: inherit;
}

// button 태그와 a 태그 기본 스타일 비활성화
button {
  outline: none;
  border: none;
  background: none;
  font-size: inherit;
}

a {
  color: inherit;
  text-decoration: none;
}

이 파일은 기존에 프로젝트에 있던 index.css 를 대체하게 됩니다. index.css 를 제거하시고, index.js 에서 기존의 index.css 를 우리가 방금 만든 main.scss 파일로 대체하세요.

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './styles/main.scss';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

스타일 유틸 설정하기

이제 여러 스타일 파일에서 불러와서 사용 할 수 있는 스타일 유틸을 설정해주겠습니다. 우선, 우리가 스타일링 할 때 색상 선정을 쉽게 해줄 open-color 과, 반응형 디자인을 쉽게 해줄 include-media 를 설치하겠습니다.

$ yarn add include-media open-color

그리고 styles 디렉터리에 utils.scss 파일을 생성하세요.

styles/utils.scss

@import '~open-color/open-color';
@import '~include-media/dist/include-media';

경로의 앞부분에 물결표시는 node_modules 에서 불러오겠다는 것을 의미합니다. 이렇게 만들어준 utils 파일은, 추후 우리가 scss 파일을 작성하게 될 때 기본적으로 상대 경로로 불러와서 사용해주어야합니다. 예를들어 다음과 같이 말이죠.

@import '../../styles/utils';

하지만, scss 파일에서는 자동완성도 잘 되지않기 때문에 디렉터리 구조가 복잡해질 수록 불러오기가 힘들어집니다. 따라서, 우리는 sass-loader 의 설정을 커스터마이징 하여 조금 더 쉽게 사용 할 수 있게 해주겠습니다.

그렇게 하기 위해서는 webpack 설정을 바꿔줘야하는데, yarn eject 를 해야 하므로 먼저 지금까지 한 작업들을 git 을 통하여 커밋해주세요. 커밋을 해주어야 yarn eject 명령어를 실행 할 수 있습니다.

$ git commit -am'Initial commit'

다음, config/webpack.config.js 를 열어서 다음 설정을 찾아보세요.

            {
              test: sassRegex,
              exclude: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 2,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                },
                'sass-loader'
              ),
              sideEffects: true,
            }

위 설정을 다음과 같이 수정하세요.

            {
              test: sassRegex,
              exclude: sassModuleRegex,
              use: getStyleLoaders({
                importLoaders: 2,
                sourceMap: isEnvProduction && shouldUseSourceMap
              }).concat({
                loader: require.resolve('sass-loader'),
                options: {
                  includePaths: [paths.appSrc + '/styles'],
                  data: `@import 'utils';`
                }
              }),
              sideEffects: true
            },

여기서 includePaths 는 어디서든지 styles 디렉터리에 있는 파일을 절대경로로 불러올 수 있게 해줍니다. 예를들어서 다음과 같이 말이죠.

@import 'utils';

그 아래의 data 의 경우엔 모든 scss 파일에 특정 코드를 삽입해줍니다. 현재 상황의 경우엔 모든 scss 파일에 @import utils 를 삽입해주기 때문에 우리가 별도로 불러오지 않아도 바로 사용 할 수 있습니다.

여기까지 설정이 끝나셨으면 리액트 개발 서버를 종료 후 재시작해주세요.

만약, Cannot find module '@babel/plugin-transform-react-jsx' 에 관련한 오류가 발상하게 된다면 node_modules 디렉터리를 제거 후 yarn 명령어를 한번 입력하여 모듈들을 재설치하시면 해결됩니다.

이제 컴포넌트를 위한 스타일 파일을 작성해주겠습니다.

pages/PostListPage.scss

.PostListPage {
  background: $oc-gray-9;
  color: white;
}

우리는 앞으로 CSS 클래스의 이름을 지어줄 때에는 가장 상위에 위치한 클래스 이름은 PascalCase 로 컴포넌트의 이름과 동일하게 하고, 그 내부에서는 snake-case 로 작성합니다. 예를 들자면 다음과 같습니다.

.MyComponent {
  .something-insode {}
  .hello {
    .world {

    }
  }
}

그리고 컴포넌트의 이름을 지어줄 때에는 언제나 고유하게 지어주겠습니다. 컴포넌트 이름을 고유하게 설정해주면 스타일이 다른 컴포넌트와 중첩 될 일이 없습니다.

$oc-gray-9 는 open-color 에 있는 색상변수입니다. 다른 색상들은 https://yeun.github.io/open-color/ 에서 확인해보세요. 변수를 사용 할 땐 $oc-색상이름-숫자 형태로 사용을 하시면 됩니다.

코드를 저장 후 컴포넌트에서 className 을 지정해주세요.

pages/PostListPage.js

import React from 'react';
import './PostListPage.scss';

/**
 * 여러 포스트 목록을 보여주는 페이지
 */
const PostListPage = () => {
  return <div className="PostListPage">PostListPage</div>;
};

export default PostListPage;

이제 http://localhost:3000/ 에 들어가서 상단에 검정 배경으로 흰 텍스트가 보여졌는지 확인하세요.

results matching ""

    No results matching ""