함께 성장하는 프로독학러
Memo_app 02. 작업환경 설정 및 디렉토리 구조 이해 본문
안녕하세요, 프로독학러 입니다.
저번 포스팅에서는 Memo app 을 제작하기 위한 기본 개념들에 대해서 알아보았는데요, 이번 포스팅에서는 설치부터 본격적으로 진행해 보도록 하겠습니다.
*본 튜토리얼은 Velopert 님의 'React.js Codelab 2016' 을 기반으로 되었습니다.
(여러 모듈들의 버전업에 따라 작성방법이 조금씩 달라진 코드를 버전에 맞게 수정하고, 제가 튜토리얼을 따라함에 있어 이해가 쉽지 않았던 부분에 설명을 추가하는 방식으로 진행합니다.)
* Velopert 님의 원본 튜토리얼을 보고싶으신 분들은 아래의 링크를 참고해 주세요.
<React.js codelab 2016 - Velopert>
1. React.js 설치
우리가 만들게 될 Memo app 은 React.js 를 기반으로 한 SPA(Single Page Application) 입니다.
따라서 가장먼저 해야할 것은 React 프로젝트를 만드는 것입니다.
React.js 를 설치하고 프로젝트 파일을 생성하는 과정은 이전에 제가 React.js 포스팅을 할 때 올렸던 자료를 참고하셔서 진행하시면 되겠습니다.
<리액트 환경 설정하기 - React.js, Node.js, babel, webpack4>
* Node.js 를 이미 설치하신 분이라면 위의 링크 중 2. React project 설정 부터 따라하시면 되겠습니다.
* 프로젝트의 이름(디렉토리명)은 Memo_app_tuts 로 하겠습니다. (원하시는 이름으로 네이밍하면 되겠습니다)
* ./dist/index.html 과 ./src/index.js 의 내용은 아래 코드로 변경해 주세요
(./dist/index.html)
1 2 3 4 5 6 7 8 9 10 | <!DOCTYPE html> <html> <head> <title>Memo_app_tuts</title> </head> <body> <div id="root"></div> <script src="/bundle.js"></script> </body> </html> | cs |
(./src/index.js)
1 2 3 4 5 6 7 8 9 10 11 12 | import React from 'react'; import ReactDOM from 'react-dom'; const title = 'Memo_App'; ReactDOM.render( <div>{title}</div>, document.getElementById('root') ); module.hot.accept(); | cs |
위의 링크를 통해 React.js 와 webpack, babel 까지 설정을 완료했습니다.
2. 프로젝트 dependencies 설치
React 프로젝트를 구성한 뒤엔 Memo 어플리케이션에서 사용할 dependencies 를 설치해야합니다.
설치할 모듈들은 다음과 같습니다.
2-1) Global dependency 설치
babel-cli : 콘솔 환경에서 babel 을 사용할 수 있게 해주는 모듈
nodemon : development 환경에서 파일이 수정될 때마다 서버를 재시작해주는 모듈
cross-env : 윈도우 / 리눅스 / OSX 에서 환경변수 값을 설정해주는 모듈
2-2) Local Dependency 설치
express : Node.js 웹 프레임 워크
body-parser : JSON 형태의 데이터를 HTTP 요청에서 파싱할 때 사용(req.body 로 접근할 수 있도록)
2-3) Dev Dependency 설치
babel-preset-es2015 : npm 스크립트를 통해서 개발 서버를 열 때 es2015를 사용할 수 있도록 해 주는 모듈
2-4) Express 코드 작성
Express 를 이용하여 서버파일을 생성해 줍니다.
(./server/main.js)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import express from 'express'; import path from 'path'; const app = express(); const port = 3000; app.use('/', express.static(path.join(__dirname, './../dist'))); app.get('/hello', (req, res) => { return res.send('Hello Memo_App'); }); app.listen(port, () => { console.log('Express is listening on port', port); }); | cs |
2-5) NPM 스크립트 수정
(./package.json)
1 2 3 4 5 6 7 8 9 10 | ..., "scripts": { "start": "webpack-dev-server --config ./webpack.config.js --mode development", "test": "echo \"Error: no test specified\" && exit 1", "clean": "rm -rf build public/bundle.js", "build": "babel server --out-dir build --presets=es2015 && webpack", "win_start": "cross-env NODE_ENV=production node ./build/main.js", "win_development": "cross-env NODE_ENV=development nodemon --exec babel-node --presets=es2015 ./server/main.js --watch server" }, ... | cs |
package.json 파일의 script 부분을 위와 같이 수정합니다.
script 부분에 필드를 추가하면 명령프롬프트(cmd)에서 'npm run (스크립트에 추가한 필드명)' 으로 파일을 실행할 수 있습니다.
개발서버를 실행해려면 프로젝트파일 경로에서 'npm run win_development' 명령어를 통해 실핼할 수 있습니다.
2-6) Webpack 개발서버용 설정파일 만들기
루트 경로에 webpack.dev.config.js 파일을 생성하고 아래의 코드를 붙여넣습니다.
(./webpack.dev.config.js)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | import webpack from 'webpack'; module.exports = { mode: 'development', /* webpack-dev-server를 콘솔이 아닌 자바스크립트로 실행 할 땐, HotReloadingModule 를 사용하기 위해선 dev-server 클라이언트와 핫 모듈을 따로 entry 에 넣어주어야 합니다. */ entry: [ './src/index.js', 'webpack-dev-server/client?http://0.0.0.0:4000', // 개발서버의 포트가 이 부분에 입력되어야 제대로 작동합니다 'webpack/hot/only-dev-server' ], output: { path: '/', // public 이 아니고 /, 이렇게 하면 파일을 메모리에 저장하고 사용합니다 filename: 'bundle.js' }, // 개발서버 설정입니다 devServer: { hot: true, filename: 'bundle.js', publicPath: '/', historyApiFallback: true, contentBase: './public', /* 모든 요청을 프록시로 돌려서 express의 응답을 받아오며, bundle 파일의 경우엔 우선권을 가져서 devserver 의 스크립트를 사용하게 됩니다 */ proxy: { "**": "http://localhost:3000" // express 서버주소 }, stats: { // 콘솔 로그를 최소화 합니다 assets: false, colors: true, version: false, hash: false, timings: false, chunks: false, chunkModules: false } }, plugins: [ new webpack.HotModuleReplacementPlugin() ], module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: ['babel-loader'] } ] }, performance: { hints: process.env.NODE_ENV === 'production' ? "warning" : false } }; | cs |
코드의 네 번째 줄에서 mode 를 설정해주고, 58번째 줄에서 모드가 production 일 경우에는 경고창을 띄우고 아닐 경우에는 경고창을 띄우지 않도록 했습니다.
2-7) server 메인 파일 수정
development 환경일 때 개발 서버를 켜는 코드를 추가하도록 하겠습니다.
(./server/main.js)
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 | import express from 'express'; import path from 'path'; import WebpackDevServer from 'webpack-dev-server'; import webpack from 'webpack'; const app = express(); const port = 3000; const devPort = 4000; app.use('/', express.static(path.join(__dirname, './../dist'))); app.get('/hello', (req, res) => { return res.send('Hello Memo_App!!'); }); app.listen(port, () => { console.log('Express is listening on port', port); }); if(process.env.NODE_ENV == 'development') { console.log('Server is running on development mode'); const config = require('../webpack.dev.config'); const compiler = webpack(config); const devServer = new WebpackDevServer(compiler, config.devServer); devServer.listen( devPort, () => { console.log('webpack-dev-server is listening on port', devPort); } ); } | cs |
3. MongoDB 설치
MongoDB 데이터베이스의 설치는 아래의 링크를 참조해주세요. (MongoDB에 익숙치 않으시다면 해당 카테고리의 포스팅을 모두 읽어 보시는것을 추천드립니다)
* Node.js 환경에서 MongoDB 를 사용하는 모듈인 mongoose 의 사용법에 대해 익숙치 않으신 분들은 아래의 링크를 참조해주세요.
4. 미들웨어 및 기타 모듈설치
server 의 main.js 파일에서 사용할 미들웨어 및 기타 모듈을 설치하도록 하겠습니다.
설치할 미들웨어 및 모듈은 다음과 같습니다.
morgan : HTTP 요청을 로그하는 미들웨어
mongoose : mongoDB 데이터 모델링툴 (MongoDB 의 데이터를 Javascript 객체로 사용할 수 있도록 해주는 모듈)
express-session : express 에서 세션을 다룰 때 사용하는 미들웨어
server/main.js 에서 추가한 모듈들을 사용하는 코드를 추가해 줍니다.
(./server/main.js)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | import express from 'express'; import path from 'path'; import WebpackDevServer from 'webpack-dev-server'; import webpack from 'webpack'; import morgan from 'morgan'; // HTTP REQUEST LOGGER import bodyParser from 'body-parser'; // PARSE HTML BODY import mongoose from 'mongoose'; import session from 'express-session'; const app = express(); /* mongodb connection */ const db = mongoose.connection; db.on('error', console.error); db.once('open', () => { console.log('Connected to mongodb server'); }); // mongoose.connect('mongodb://username:password@host:port/database='); mongoose.connect('mongodb://localhost/Memo_app_tuts'); app.use(session({ secret: 'CodeLab1$1$234', resave: false, saveUninitialized: true })); app.use(morgan('dev')); app.use(bodyParser.json()); const port = 3000; const devPort = 4000; app.use('/', express.static(path.join(__dirname, './../dist'))); app.get('/hello', (req, res) => { return res.send('Hello Memo_App!!'); }); app.listen(port, () => { console.log('Express is listening on port', port); }); if(process.env.NODE_ENV == 'development') { console.log('Server is running on development mode'); const config = require('../webpack.dev.config'); const compiler = webpack(config); const devServer = new WebpackDevServer(compiler, config.devServer); devServer.listen( devPort, () => { console.log('webpack-dev-server is listening on port', devPort); } ); } | cs |
5. 디렉토리 구조 이해하기
여기까지 잘 따라오셨다면 이제 본격적으로 어플리케이션을 만들 준비가 된 상태입니다.
본격적으로 코드를 작성하기 이전에 프로젝트의 디렉토리 구조가 어떻게 되는지 이해하고 가도록 하겠습니다.
- dist (리액트 컴포넌트를 렌더링할 대상)
- index.html
- server (BACK-END)
- models
: mongoose 모델이 위치하는 디렉토리
- routes
: API 들이 위치하는 디렉토리
- main.js : 서버를 위한 js 파일
- src (FRONT-END)
- actions
: actionType, action 생성자 함수, thunk 가 위치할 디렉토리
- components
: 기능을 가진 컴포넌트 (작은단위의 컴포넌트) 들이 위치할 디렉토리
- containers
: 컴포넌트를 포함하는 상위 개념의 컴포넌트 (라우트에 렌더링할 컴포넌트) 들이 위치할 디렉토리
- reducers
: 액션객체를 전달받아 Redux state 를 업데이트하는 함수가 위치할 디렉토리
- index.js : 리액트 설정 파일 (렌더링 위치, 라우트 등을 지정)
- style.css : 스타일시트
dist 디렉토리에는 렌더링을 진행할 대상인 HTML 파일이 위치하고, server 디렉토리에는 BACK-END 관련 파일이, src 디렉토리에는 FRONT-END 파일이 위치합니다.
위의 디렉토리를 여러분의 프로젝트 파일에도 똑같이 생성해 주세요. 파일을 튜토리얼을 진행하며 생성할 예정이니 폴더만 생성해 주시면 됩니다.
./server/main.js 파일에 API 라우터들을 불러오는 코드와 ./dist/index.html 을 렌더링하기 위한 코드를 추가해줍시다.
(./server/main.js)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | import express from 'express'; import path from 'path'; import WebpackDevServer from 'webpack-dev-server'; import webpack from 'webpack'; import morgan from 'morgan'; // HTTP REQUEST LOGGER import bodyParser from 'body-parser'; // PARSE HTML BODY import mongoose from 'mongoose'; import session from 'express-session'; //file import import api from './routes'; const app = express(); /* mongodb connection */ const db = mongoose.connection; db.on('error', console.error); db.once('open', () => { console.log('Connected to mongodb server'); }); // mongoose.connect('mongodb://username:password@host:port/database='); mongoose.connect('mongodb://localhost/Memo_app_tuts'); app.use(session({ secret: 'CodeLab1$1$234', resave: false, saveUninitialized: true })); app.use(morgan('dev')); app.use(bodyParser.json()); // routes '/api' 로 들어오는 요청울 routes 폴더의 라우트들로 위임 app.use('/api', api); const port = 3000; const devPort = 4000; app.use('/', express.static(path.join(__dirname, './../dist'))); app.get('*', (req, res) => { res.sendFile(path.resolve(__dirname, './../dist/index.html')); }); app.get('/hello', (req, res) => { return res.send('Hello Memo_App!!'); }); app.listen(port, () => { console.log('Express is listening on port', port); }); if(process.env.NODE_ENV == 'development') { console.log('Server is running on development mode'); const config = require('../webpack.dev.config'); const compiler = webpack(config); const devServer = new WebpackDevServer(compiler, config.devServer); devServer.listen( devPort, () => { console.log('webpack-dev-server is listening on port', devPort); } ); } | cs |
위의 코드의 11, 30 번째 줄이 라우트를 위한 설정이고, 36 번째 줄은 렌더링 설정입니다.
여기까지...
Memo 어플리케이션을 작성하는데 있어 필요한 환경설정을 마쳤습니다.
다음 포스팅부터는 인증 부분부터 구현하도록 하겠습니다.
감사합니다.
**참고 자료 (항상 감사드립니다)
*이 포스팅이 도움이 되셨다면 다녀가셨다는 표시로 공감 부탁드릴게요! (로그인 하지 않으셔도 공감은 가능합니다 ㅎㅎ)
'Programming > tutorials' 카테고리의 다른 글
Memo_app 06. 메모(Memo) - Retrieve 기능 구현 (메모읽기) / 무한스크롤링 구현 (0) | 2018.06.27 |
---|---|
Memo_app 05. 메모(Memo) - Create 기능 구현 (메모작성) (0) | 2018.06.26 |
Memo_app 04. 인증(authentication) - 로그인, 로그아웃, 로그인 확인 구현 (0) | 2018.06.26 |
Memo_app 03. 인증(authentication) - 회원가입 구현 (3) | 2018.06.23 |
Memo_app 01. 시작하기에 앞서 (2) | 2018.06.20 |