2. express 적용하기

React 2017. 7. 10. 11:14

필요 패키지 설치하기


express 모듈 설치

npm install --save express


개발 모드에서 사용할 babel 관련 모듈들과 nodemon 설치.

nodemon은 코드에 변화가 감지되면 서버를 재시작해주는 모듈입니다.

npm install -save-dev babel-cli babel-core babel-preset-es2015 nodemon


폴더 & 파일 생성하기

src폴더 하위 디렉토리로 server 폴더를 생성하고, index.js 파일을 생성해주세요.

그리고 server폴더 하위에 routes폴더를 생성하고, index.js파일을 생성해주세요.

추가적으로 server 폴더 하위에 scripts폴더도 생성하고, nodemon.js 파일을 생성해주세요.




메인 파일 작성 - src/server/index.js


import express from 'express';

const app = express();
const port = 3100;

app.use('/', express.static(__dirname + '/../../build'));

app.listen(port, () => {
console.log('Server is listening on port', port);
});



라우트 파일 작성 - src/server/routes/index.js


import express from 'express';

const router = express.Router();

const testData = {
name: 'jaro',
project: 'react'
}

router.get('/', (req,res) => {
res.json(testData);
});

export default router;

   

개발용 서버 실행 스크립트 작성 - src/server/scripts/nodemon.js


process.env.NODE_ENV = 'development';

var nodemon = require('nodemon');
nodemon('--exec babel-node --presets=es2015 ./src/server/index.js --watch ./src');

nodemon.on('start', function() {
console.log('[nodemon] App has started');
}).on('quit', function() {
console.log('[nodemon] App has quit');
process.exit();
}).on('restart', function(files) {
console.log('[nodemon] App restarted due to:', files);
});


development 스크립트를 굳이 스크립트파일을 따로 만든 이유는, 윈도우 / 유닉스 계열에서 NODE_ENV 설정하는 방식이 다르기 때문입니다.

 "development": "NODE_ENV=development nodemon --exec babel-node --presets=es2015 ./server/main.js --watch server",
 "win_development": "set NODE_ENV=development&nodemon --exec babel-node --presets=es2015 ./server/main.js --watch server"

스크립트 파일을 따로 만들기 싫으면 위와같이 package.json 에 스크립트를 작성해도 됩니다.

- 출처 : https://velopert.com/2037


자 그럼 우선 서버를 실행하여 제대로 작동하는지 알아보겠습니다.

package.json을 열어서 script를 추가해주세요

"start:server": "node ./src/server/scripts/nodemon.js",

후에 터미널에서 npm run start:server 를 입력하면, express 서버가 실행됩니다.

localhost:3100/api 로 접속하여 testData가 브라우져에 출력되는지 확인해주세요

정상 출력이 되는것을 확인했다면, 이제 ajax를 이용하여 통신을 하도록 해보겠습니다.


저는 axios라는 모듈을 사용하겠습니다.

물론 jquery 나 fatch 등과 같은 여러 모듈을 사용 가능합니다. 본인이 사용하기 편한 모듈을 선택하시기 바랍니다.


axios 설치

npm install -S axios

이제 테스트를 하기 위해 src/app.js 파일에 추가하겠습니다.


import React, { Component } from 'react';
import './App.css';
import axios from 'axios';

class App extends Component {

constructor(props) {
super(props);
this.state = {
name: '',
project: ''
}
this._onClick = this._onClick.bind(this);
}

_onClick() {
axios.get(`/api`)
.then( response => {
this.setState({
name: response.data.name,
project: response.data.project
});
}) // SUCCESS
.catch( response => { console.log(response); } );
}

render() {
const { name , project } = this.state;
return (
<div className="App">
<h1>{project}</h1>
<h1>Hello {name}</h1>
<button onClick={this._onClick}>api 호출</button>
</div>
);
}
}

export default App;


import axios from 'axios';

axios 모듈을 사용하겠다는 뜻입니다.


constructor(props) {
super(props);
this.state = {
name: '',
project: ''
}
this._onClick = this._onClick.bind(this);
}

app 컴포넌트 클래스가 생성되면서 불리는 생성자 함수입니다.

_onClick() {
axios.get(`localhost:3100/api`)
.then( response => {
this.setState({
name: response.data.name,
project: response.data.project
});
}) // SUCCESS
.catch( response => { console.log(response); } );
}

버튼을 눌렀을때 실행되는 함수입니다. 


<h1>{project}</h1>
<h1>Hello {name}</h1>

브라우져에 this.state 의 name과 project를 표시합니다.

기본값은 '' 이므로 처음에는 아무것도 표시되지 않다가, 버튼을 누르면 데이터를 받아 표시하게 됩니다.


<button onClick={this._onClick}>api 호출</button>

버튼을 추가하고, 버튼을 눌렀을때 실행되는 함수를 바인딩 해주었습니다.


이제 리액트 서버와 express 서버를 둘다 실행하여 확인해보겠습니다.

터미널 2개를 열어

한곳에서는 npm start

한곳에서는 npm run start:server

이렇게 2개를 실행시켜 주세요



버튼이 생성되어있고, 버튼을 눌러도 아무런 반응이 없습니다. 

콘솔창을 확인해보겠습니다.

에러가 떠있습니다.

받아올수 없다네요 크로스 도메인 문제라고 알고있습니다. ( 자세히 공부해서 포스팅 하겠습니다. )

이 경우에는 proxy를 통해 간단히 이 문제를 해결 가능합니다.

javascript에서 동일 서버의 URL을 호출하고, 
이 URL에서 내부적으로 다른 도메인의 URL을 호출하는 것으로, 

package.json에 proxy를 추가하여 해결하겠습니다.


"proxy": "http://localhost:3100/"

를 추가해주세요.

그리고 onClick 함수를 변경합니다.


_onClick() {
axios.get(`/api`)
.then( response => {
this.setState({
name: response.data.name,
project: response.data.project
});
}) // SUCCESS
.catch( response => { console.log(response); } );
}


자체에서 url을 호출한뒤 다시 proxy의 url을 호출하므로 기존에 get 주소중 localhost:3100을 지우면 됩니다.

그리고 서버들을 다 종료 후 다시 켜주세요.

그래야 제대로 작동합니다.

다시 서버가 실행되고 버튼을 누르면, 제대로 작동할것입니다.





이번 포스팅은 간단한 exress 적용과, ajax를 이용하여  웹서버와의 통신하는것을 간략하게 포스팅 하였습니다.

이번 포스팅에 사용된 소스는 https://github.com/JaroInside/tistory-react-express 에서 보실수 있습니다.

감사합니다.




추가적으로, 두개의 터미널을 띄워서 실행하는것이 불편하신분들은


npm-run-all 이라는 패키지를 설치하시기 바랍니다.

이 패키지는 npm의 여러 스크립트를 동시에 실행시켜줄수 있는 패키지로, 이번 포스팅처럼 리액트 서버와 웹서버를 동시에 실행하여야 할때 매우 간편합니다.


깃헙 주소

https://github.com/mysticatea/npm-run-all


설치

npm install -D npm-run-all


사용법

package.json의 script를 수정하겠습니다.


"start": "npm-run-all --parallel start:**",
"start:client": "react-scripts start",
"start:server": "node ./src/server/scripts/nodemon.js",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"


start 를 npm 스크립트들중 start: 로 시작하는것들을 모두 한번에 실행한다는 명령어로 바꾸었습니다.

기본의 start 명령어, 즉 react 개발서버 명령어는 start:client로 변경하였고,

웹서버 명령어는 start:server 명령어로 만들어 하나의 터미널에서 npm start 명령어 하나로 모든 명령어를 동시에 실행할수 있게 하였습니다.


'React' 카테고리의 다른 글

react-image-cropper 사용하기  (0) 2017.07.22
1. CRA로 프로젝트 생성  (1) 2017.07.10
블로그 이미지

Jaro

대한민국 , 인천 , 남자 , 기혼 , 개발자 jaro0116@gmail.com , https://github.com/JaroInside https://www.linkedin.com/in/seong-eon-park-16a97b113/

,