재작년에 React
를 강의나 실습없이 프로젝트를 통해 배운 적이 있다. 심지어 JavaScript
도 제대로 모른 채로. 그랬기 때문에 작은 프로젝트 하나도 몇 달을 걸려서 마무리 했고 기능 하나를 구현하는 데에도 수많은 에러를 마주쳤다. 아주 각종 에러란 에러는 다 마주쳤던 것 같다.
역시나 그럴 땐 검색을 통해 언어에 대한 문법, 기능 구현, UX, 숫자야구 알고리즘 등 많은 부분에서 도움을 받았기 때문에 나도 누군가의 도움이 될 수 있을까 하는 마음에 재작년에 완성했던 프로젝트를 올리고자 한다. 물론 그 사이에 React-Router
v6가 나오면서 코드가 최신화도 아니고 React를 처음 배웠기 때문에 지금보면 엉성한 코드이지만.
처음 React
를 시작할 때 Root.js
, App.js
... 등등 모든 것이 낯설어서 헤매었던 기억이 있어 상세한 CSS 코드를 제외한 모든 코드를 업로드할 예정이다.
우선 React
를 통해 프로젝트를 생성하자.
프로젝트를 구성할 폴더를 만들고 폴더에 들어간 후에 create-react-app
으로 프로젝트를 생성해야한다.
create-react-app 프로젝트 명
그리고 게임 화면 페이지를 구성해야하기 때문에 React-router
를 설치하자.
yarn add react-router-dom
초안은 이렇다.
또한 src
폴더 안에는 이미지 등을 담는 assets
과 컴포넌트 폴더인 components
, 폰트 폴더인 fonts
, 각 페이지의 내용인 view
로 구성을 했다.
추가로
Node.js
로 백엔드까지 구현했기 때문에simple-server
폴더도 구성했지만 추후에 적겠다.
index.js
파일의 코드이다.
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Root from './view/Root';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<Root />
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
Root.js
파일의 코드이다.
// src/view/Root.js
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
const Root = () => (
<BrowserRouter>
<App/>
</BrowserRouter>
);
export default Root;
App.js
파일의 코드이다.
// src/view/App.js
import React from 'react'
import { Route } from 'react-router-dom'
import Home from './Home/index'
import PlayGround from './Game/index'
import End from './End/index'
import JoinMembership from './JoinMembership/index'
const App = () => {
return (
<div className={'fill-height'}>
<Route exact path="/" component={Home} />
<Route path="/play-ground" component={PlayGround} />
<Route path="/End" component={End} />
<Route path="/JoinMembership" component={JoinMembership} />
</div>
)
}
export default App
App.js
에선 이미 라우트를 설정해 놓은 상태이다. 라우트를 설정해놓을 땐, Route
컴포넌트를 설정하고 경로는 path
값으로 설정한다.
이때 첫 번째 라우트의 경우엔 exact
가 붙어있는데 이게 붙어있으면 주어진 경로와 정확히 맞아 떨어져야만 설정한 컴포넌트를 보여준다.
만약 exact
를 하지 않으면, path='/play-ground'
와 path='/End'
에도 /
가 있기 때문에 매칭되어 Home
컴포넌트를 보여줄때 PlayGround
컴포넌트와 End
컴포넌트를 동시에 보여준다.
참고로
exact
는react-router v6
가 업데이트 되면서 사라진 옵션이다. 그러니 무시해도 좋다.
라우터로 설정한 컴포넌트는 3가지의 props
를 전달받는다. 각각 hitory
와 location
, match
의 형식이 있다.
라우트를 이동하는 방법은 HTML
의 a
태그 방식인 <a ref...>data</a>
의 방식으로 진행하면 안된다. 새로고침을 하기 때문이다. 그래서 라우트 이동은 Link
컴포넌트를 이용해 페이지를 새로 불러오는걸 막고, 원하는 라우트로 화면전환을 해준다.
해당 프로젝트에선 history
방식을 이용해서 파라미터를 읽고 이동시켰다. 코드는 다음과 같다.
// src/view/Home/index.js
import { useHistory } from 'react-router-dom'
const Home = () => {
const history = useHistory()
const onGameStartButtonClick = () => {
// '/play-ground' 페이지로 이동
history.push('/play-ground');
}
return(
<div className="container">
<button onClick={onGameStartButtonClick}>
게임 시작
</button>
</div>
)
}
export default Home
React
에서는 className
을 통해 선택자를 지정해준다. 하물며, 선택자의 이름은 카멜케이스를 적용하거나, 케밥케이스를 적용하기도 한다.
<div className='home-button' | 'home-btn'></div>
가장 상위 폴더에 css파일을 만들어서 하위 폴더에 모두 적용시킬 수 있도록 했다.
특히 fill-height
의 이름으로 설정해 놓음으로써 글로벌하게 사용하게 했다.
/* after */
/* src/index.css */
.container{
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.fill-height {
height: 100vh !important
}
해당 프로젝트에서 GmarketSansMedium
라는 폰트를 사용했다. 따로 디렉토리를 만들어 폰트를 관리했고, 최상단에서 @font-face
를 관리했다. 또한 폰트를 적용하고 싶은 곳에 font-weight
를 이용해서 적용해줬다.
/* // src/view/index.css */
@font-face {
font-family: 'GmarketSansMedium';
src: url('./fonts/GmarketSansOTF/GmarketSansMedium.otf') format('woff');
font-weight: normal;
font-style: normal;
}
/* src/view/Home/index.css */
.game-start-button {
...
font-family: 'GmarketSansMedium';
}
또한, 이번 프로젝트에서 부트스트랩이나 테일윈드같은 무료 템플릿 사이트를 이용해보고자 테일윈드 사이트를 참고했다. 먼저, 다음과 같이 최상단 index.css
에 tailwind
를 선언해주고 원하는 태그의 className
에 원하는 디자인을 적용시켜주면 된다.
테일윈드: https://tailwindcss.com/
/* src/view/index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* src/view/Home/index.css */
<button
className='logout-button text-gray-400 underline ...'
onClick={onlogoutButtonClick}>
로그아웃
</button>
반응형 웹 css
코드는 다음과 같다. 모바일, 태블릿, PC 화면 3가지로 나눠서 진행했고, 기준이 되는 max-width
는 다음과 같다.
/* src/view/Home/index.css */
/* 핸드폰 */
@media screen and (max-width: 620px) {
...
}
/* 태블릿 */
@media screen and (max-width: 900px) {
...
}