일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 참조형변수
- 한국건설관리시스템
- 사용자예외클래스생성
- 다형성
- 오라클
- 어윈 사용법
- exception
- oracle
- 자동차수리시스템
- 컬렉션프레임워크
- cursor문
- 예외처리
- 생성자오버로드
- 객체 비교
- 정수형타입
- 집합_SET
- NestedFor
- Java
- 컬렉션 타입
- 제네릭
- 메소드오버로딩
- 인터페이스
- GRANT VIEW
- abstract
- 자바
- EnhancedFor
- 대덕인재개발원
- 추상메서드
- 예외미루기
- 환경설정
- Today
- Total
거니의 velog
(1) 프론트엔드 프로젝트 : 시작 및 회원 인증 구현 1 본문
* 이 장에서는 리액트 프로젝트를 생성하여 지금까지 만든 서버에 연동해 볼 것이다. 프로젝트를 만들어 가면서 지금까지 배운 다양한 기술을 활용해 줄 것이다. 이 과정을 통해 실무에서 프로젝트를 개발할 때 어떤 방식으로 작업하는지 알 수 있다.
* 프로젝트를 시작하기 전에 앞으로 어떤 기능을 개발하는 지 간략하게 살펴보자.
(1) 회원가입/로그인 기능
(2) 글쓰기 기능 : 이 과정에서 Quill 이라는 WYSIWYG 에디터 라이브러리를 사용한다.
* WYSIWYG 란 'What You See Is What You Get'의 약어이다.
사용자가 보는 대로 결과를 얻는다는 의미이며, '위지윅'이라고 읽는다.
위지윅 에디터에서는 글을 쓸 때 HTML을 직접 입력하면서 스타일을 설정하는 것이 아니라,
에디터에서 지원되는 기능을 사용하여 간편하게 스타일을 설정할 수 있다.
(3) 블로그 포스트 목록 보여주는 기능 / 포스트를 읽는 기능 구현
(4) 포스트를 수정하거나 삭제할 수 있는 기능까지 구현
* 이제 본격적으로 개발을 시작해 보자. 이 프로젝트는 총 네 번에 걸쳐서 진행되며, 이번 장의 실습은 다음 흐름으로 진행된다.
1. 작업 환경 준비하기
* 새 리액트 프로젝트를 생성해 보자. 리액트 프로젝트는 기존에 blog-backend 디렉터리가 있는 blog 디렉터리에 생성하자.
$ yarn create react-app blog-frontend
* 버전 충돌을 피하기 위해 package.json은 다음과 같이 세팅 후 재설치한다.
{
"name": "blog-frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"immer": "^3.1.3",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-redux": "^7.1.0",
"react-router-dom": "^5.0.1",
"react-scripts": "3.0.1",
"redux": "^4.0.1",
"redux-actions": "^2.6.5",
"redux-devtools-extension": "^2.13.8",
"styled-components": "^4.3.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
* 프로젝트를 VS Code로 열 때 새로운 창에서 열어도 되지만, 기존 blog-backend 디렉터리가 열려 있는 창에서 작업 영역에 폴더 추가... 기능으로 열면 VS Code 창 하나에서 두 프로젝트를 관리할 수 있어 좀 더 편하게 작업할 수 있다.
* 이렇게 추가하면 VS Code 에서 두 프로젝트를 한꺼번에 관리할 수 있다.
* 작업 영역을 만들고 나서 나중에도 이렇게 열고 싶다면 VS Code 메뉴의 파일 > 작업 영역을 다른 이름으로 저장 을 클릭하자. 작업 영역 파일을 blog 디렉터리에 blog라는 이름으로 저장하면 된다(이름은 원하는 대로 설정할 수 있다).
* 그냥 blog 디렉터리를 열었을 때보다 작업 영역을 통해 두 프로젝트를 열었을 때 자동 import 기능이 더욱 완벽하게 작동한다.
(1) 설정 파일 만들기
* 우리가 만든 프로젝트에 필요한 설정 파일을 만들어 보자. 먼저 프로젝트의 코드 스타일을 정리해 주는 Prettier의 설정 파일을 만들자. 여러분의 취향에 따라 옵션들을 커스터마이징해도 상관없다.
* 다음 파일을 blog-frontend 디렉터리에 생성하자.
{
"singleQuote": true,
"semi": true,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80
}
* 그리고 프로젝트에서 자동 import 기능이 제대로 작동할 수 있게 jsconfig.json 파일을 생성하자.
{
"compilerOptions": {
"target": "ES6"
}
}
(2) 라우터 적용
* 프로젝트를 처음 만들고 나서 설계를 시작할 때 가장 먼저 무엇을 하면 좋을까? 바로 리액트 라우터를 프로젝트에 설치하고 적용하는 것이다. 앞으로 만들게 될 주요 페이지의 라우트 컴포넌트를 미리 만들자. 먼저 틀을 갖춰 놓고 하나하나 개발하면 편하다.
* 우선 react-router-dom 라이브러리를 설치하자.
$ yarn add react-router-dom
* 다음으로 총 다섯 개의 페이지를 만든다. 라우트와 관련된 컴포넌트들은 src/pages 디렉터리에 만들겠다.
* 앞으로 만들 라우트 컴포넌트는 다음과 같다.
(1) LoginPage.js - 로그인
(2) RegisterPage.js - 회원가입
(3) WritePage.js - 글쓰기
(4) PostPage.js - 포스트 읽기
(5) PostListPage.js - 포스트 목록
* 자, 이제 이 컴포넌트를 하나씩 만들어 주자.
[src/pages/LoginPage.js]
import React from 'react';
const LoginPage = () => {
return <div>로그인</div>;
};
export default LoginPage;
[src/pages/RegisterPage.js]
import React from 'react';
const RegisterPage = () => {
return <div>회원가입</div>;
};
export default RegisterPage;
[src/pages/WritePage.js]
import React from 'react';
const WritePage = () => {
return <div>글쓰기</div>;
};
export default WritePage;
[src/pages/PostPage.js]
import React from 'react';
const PostPage = () => {
return <div>포스트 읽기</div>;
};
export default PostPage;
[src/pages/PostListPage.js]
import React from 'react';
const PostListPage = () => {
return <div>포스트 리스트</div>;
};
export default PostListPage;
* 라우트 컴포넌트 다섯 개를 모두 생성했는가? 이제 프로젝트 엔트리 파일인 index.js에서 BrowserRouter로 App 컴포넌트를 감싸자.
[src/index.js]
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root'),
);
* 다음으로는 App 컴포넌트에서 Route 컴포넌트를 사용하여 각 라우트의 경로를 지정해 주자.
[src/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';
function App() {
return (
<>
<Route component={PostListPage} path={['/@:username', '/']} exact />
<Route component={LoginPage} path="/login" />
<Route component={RegisterPage} path="/register" />
<Route component={WritePage} path="/write" />
<Route component={PostPage} path="/@:username/:postId" />
</>
);
}
export default App;
* 위 라우트 중 PostListPage를 보면 Path에 배열을 넣어 주었다. 이렇게 배열을 넣어 주면 한 라우트 컴포넌트에 여러 개의 경로를 쉽게 설정할 수 있다.
* 이렇게 배열을 사용하지 않는다면 다음과 같이 작성할 수도 있다.
<Route component={PostListPage} path="/" exact />
<Route component={PostListPage} path="/@:username" exact />
* Route 컴포넌트를 두 번 사용하는 것보다는 배열을 넣는 것이 훨씬 편하다. 이러한 기능은 리액트 라우터 v5부터 사용할 수 있다.
* 추가로 path에 '/@username' 이라고 입력한 것이 조금 생소할 수 있는데, 이 경로는 http://localhost:3000/@bbbb7788 같은 경로에서 bbbb7788을 username의 파라미터로 읽을 수 있게 해 준다. Medium, 브런치 같은 서비스에서도 계정명을 주소 경로 안에 넣을 때 주소 경로에 @ 을 넣는 방식을 사용한다.
* Route 지정을 모두 마쳤다면 blog-frontend 경로에서 yarn start 명령어를 입력한다. 그리고 다음 경로에 들어가서 알맞은 컴포넌트가 뜨는지 확인해 보자.
- http://localhost:3000/
- http://localhost:3000/@tester
- http://localhost:3000/write
- http://localhost:3000/@tester/1234
- http://localhost:3000/login
- http://localhost:3000/register
* 비어 있는 페이지 없이 이전에 라우트 컴포넌트 안에 넣어 준 '포스트 리스트', '회원가입' 등의 문구가 뜬다면 잘 작동하는 것이다.
(3) 스타일 설정
* 이번 프로젝트에서는 styled-components를 사용하여 스타일링할 것이다. 여러분이 styled-components 가 아닌 다른 방식으로 스타일링 하는 것을 좋아한다면, 여기서 사용하는 스타일을 참고하여 Sass, CSS Module 등의 방법으로 작성해도 좋다.
* 먼저 styled-components를 설치해 주자.
$ yarn add styled-components
* 다음으로 나중에 색상을 사용할 때 쉽게 뽑아서 사용할 수 있도록 색상 팔레트 파일을 만든다.
* src/lib/styles 디렉터리를 만들고, 그 안에 palette.js 라는 파일을 다음과 같이 작성하자. 색상 HEX 코드를 하나하나 입력하기가 번거로울 수 있으니 https://bit.ly/mypalette 경로에 들어가서 코드를 복사한 후 사용하자.
https://gist.github.com/velopert/fda9083ddedcbbef30bb40362f9d01c4
// source: https://yeun.github.io/open-color/
const palette = {
gray: [
'#f8f9fa',
'#f1f3f5',
'#e9ecef',
'#dee2e6',
'#ced4da',
'#adb5bd',
'#868e96',
'#495057',
'#343a40',
'#212529',
],
cyan: [
'#e3fafc',
'#c5f6fa',
'#99e9f2',
'#66d9e8',
'#3bc9db',
'#22b8cf',
'#15aabf',
'#1098ad',
'#0c8599',
'#0b7285',
],
};
export default palette;
* 위 색상은 open-color 라는 라이브러리에서 추출했다. 이 라이브러리를 yarn으로 설치하여 사용할 수도 있다. 하지만 이렇게 따로 palette를 만들어 사용하면 open-color에서 제공하는 모든 색상을 불러와 사용하는 것이 아니라 필요한 색상만 불러와서 사용할 수 있고, 자동 import가 좀 더 제대로 작동하기 때문에 더욱 편하다(open-color 라이브러리를 설치해서 사용하면 open-color 안의 색상들이 자동 import 되지 않는다).
(4) Button 컴포넌트 만들기
* 먼저 검정색 버튼을 스타일링해 보자. 이 버튼 컴포넌트는 다양한 곳에서 재사용할 예정이다. 그러므로 src 디렉터리에 components/common 디렉터리를 생성하고 그 안에 이 컴포넌트를 만들어 줄 것이다.
import React from 'react';
import styled from 'styled-components';
import palette from '../../lib/styles/palette';
const StyledButton = styled.button`
border: none;
border-radius: 4px;
font-size: 1rem;
font-weight: bold;
padding: 0.25rem 1rem;
color: white;
outline: none;
cursor: pointer;
background: ${palette.gray[8]};
&:hover {
background: ${palette.gray[6]};
}
`;
const Button = (props) => <StyledButton {...props} />;
export default Button;
* 사실 이 컴포넌트에서 StyledButton 을 바로 내보내도 상관없다. 하지만 굳이 Button 리액트 컴포넌트를 만들어서 그 안에 StyledButton 을 렌더링해 준 이유는 추후 이 컴포넌트를 사용할 때 자동 import 가 되게 하기 위해서이다. styled-components로 만든 컴포넌트를 바로 내보내면 자동 import가 제대로 작동하지 않는다.
* Button 컴포넌트를 만드는 과정에서 {...props}를 StyledButton에 설정해 주었는데, 이는 Button이 받아 오는 props를 모두 StyledButton에 전달한다는 의미이다.
* 컴포넌트를 다 만들었으면 이 컴포넌트를 PostListPage 컴포넌트에 렌더링해 보자.
[src/pages/PostListPage.js]
import React from 'react';
import Button from '../components/common/Button';
const PostListPage = () => {
return (
<div>
<Button>버튼</Button>
</div>
);
};
export default PostListPage;
* 브라우저의 http://localhost:3000/ 경로에 방금 만든 버튼이 잘 나타나는가?
* 버튼이 잘 만들어졌다면 프로젝트의 글로벌 스타일을 수정한다. index.css를 열어서 다음과 같이 수정해 주자.
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; /* 엘리먼트의 box-sizing 값을 border-box로 설정 */
min-height: 100%;
}
#root {
min-height: 100%;
}
/* 추후 회원인증 페이지에서
배경화면을 페이지의 전체 영역에 채우기 위한 용도 */
html {
height: 100%;
}
/* 링크에 색상 및 밑줄 없애기 */
a {
color: inherit;
text-decoration: none;
}
* {
box-sizing: inherit; /* 모든 엘리먼트의 box-sizing 값을 border-box로 설정 */
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
(5) 리덕스 적용
* 이제 프로젝트에 리덕스를 적용해 보자. 추후 비동기 작업을 관리하는 과정에서 redux-saga를 쓸 텐데 지금 당장은 미들웨어에 대한 관심은 접어 둔 채 리덕스 스토어를 생성하고 Provider 컴포넌트를 통해 프로젝트에 리덕스를 적용하는 과정만 다룰 것이다.
* 리덕스 사용에 필요한 라이브러리를 설치해 주자.
$ yarn add redux react-redux redux-actions immer redux-devtools-extension
* 이번 프로젝트에서 리덕스를 사용하는 데 immer 라이브러리가 꼭 필요하지는 않다. 하지만 immer를 사용하여 불변성을 좀 더 편하게 관리하려고 한다. 만약 immer 없이, spread 연산자를 활용하여 불변성을 관리하는 것이 더 편하다면 굳이 사용하지 않아도 된다.
* 라이브러리를 설치했으면 첫 번째 리덕스 모듈을 만들어 준다. 이 프로젝트에서는 Ducks 패턴을 사용하여 액션 타입, 액션 생성 함수, 리듀서가 하나의 파일에 다 정의되어 있는 리덕스 모듈을 작성할 것이다.
* src/modules 디렉터리를 만들고, 그 안에 auth.js 라는 모듈을 생성하자. 세부 기능은 추후 구현하겠다. 일단 리듀서의 틀만 만들어서 내보내 주자.
import { createAction, handleActions } from 'redux-actions';
const SAMPLE_ACTION = 'auth/SAMPLE_ACTION';
export const sampleAction = createAction(SAMPLE_ACTION);
const initialState = {};
const auth = handleActions(
{
[SAMPLE_ACTION]: (state, action) => state,
},
initialState,
);
export default auth;
* 다음으로 루트 리듀서를 만들자. 지금은 리듀서가 하나밖에 없지만, 나중에는 여러 가지 리듀서를 더 만들 것이다.
[src/modules/index.js]
import { combineReducers } from 'redux';
import auth from './auth';
const rootReducer = combineReducers({
auth,
});
export default rootReducer;
* 루트 리듀서를 만든 후에는 프로젝트의 엔트리 파일 index.js에서 스토어를 생성하고, Provider를 통해 리액트 프로젝트에 리덕스를 적용하자.
[src/index.js]
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import rootReducer from './modules/index';
const store = createStore(rootReducer, composeWithDevTools());
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>,
document.getElementById('root'),
);
* 리덕스를 적용한 뒤에는 크롬 개발자 도구의 Redux 탭을 열어서 auth 객체가 존재하는지 확인해 보자.
* 이제 프로젝트 작업 환경에 대한 준비를 마쳤다. 본격적으로 기능을 구현해 보자!
'React > React_프론트엔드 프로젝트' 카테고리의 다른 글
(6) 프론트엔드 프로젝트 : 시작 및 회원 인증 구현 6 (0) | 2024.02.22 |
---|---|
(5) 프론트엔드 프로젝트 : 시작 및 회원 인증 구현 5 (0) | 2024.02.22 |
(4) 프론트엔드 프로젝트 : 시작 및 회원 인증 구현 4 (0) | 2024.02.22 |
(3) 프론트엔드 프로젝트 : 시작 및 회원 인증 구현 3 (0) | 2024.02.22 |
(2) 프론트엔드 프로젝트 : 시작 및 회원 인증 구현 2 (0) | 2024.02.21 |