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 를 하여 리액트 개발 서버를 실행하시고 우리가 준비해준 각 경로에 직접 주소를 입력하여 들어가서 알맞는 문구가 뜨는지 확인해보세요.
- http://localhost:3000/
- http://localhost/login
- http://localhost/register
- http://localhost/write
- http://localhost/posts/1
스타일 시스템 설정
이번에는 스타일 시스템을 설정 할 차례입니다. 스타일링의 경우엔 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/ 에 들어가서 상단에 검정 배경으로 흰 텍스트가 보여졌는지 확인하세요.