1. React에 Express 연동하기
yarn eject
위와 같은 명령어를 실행하면 프로젝트에 새로운 폴더가 생성됩니다. 결과는 아래와 같습니다.
config라는 폴더와 scripts 폴더가 생성된 것을 확인할 수 있습니다. 또한 심플했던 package.json 내용도 변경된 것을 확인할 수 있습니다. 우선은 여기까지 해놓고 Express 설치를 해보도록 하겠습니다.
2. Express 설치 및 서버 생성
yarn add express
위 명령어를 통해 express 를 설치하고 다음과 같이 폴더를 생성합니다.
my-app / server / server.js 구조입니다.
server 폴더를 생성하고 그 안에 server.js 라는 파일을 만든 후 다음과 같이 코드를 작성합니다.
const express = require('express');
const path = require('path');
const os = require("os");
const app = express();
const PORT = process.env.PORT || 4000;
app.use(express.static(path.join(__dirname, '..', 'public/')));
// if you need api routes add them here
app.get("/api/getUsername", function(req, res, next){
res.send({ username: os.userInfo().username });
});
app.listen(PORT, () => {
console.log(`Check out the app at http://localhost:${PORT}`);
});
express로 짜여진 서버 코드입니다.
포트 4000번에서 작동하며, app.get("/api/getUsername") 이 부분이 해당 URL로 들어오는 요청에 대한 처리를 담당하게 됩니다. 즉, api/getUsername 이라는 url로 요청을 하게되면 os.userInfo().username 함수를 통해 현재 OS에 로그인된 유저의 이름을 가져오고 해당 값을 res.send를 통해 반환합니다.
3. Webpack 설정
위 사진처럼 plugins : [ 로 시작하는 부분 위에 해당 코드를 입력합니다.
devServer: {
port: 4000,
open: true,
proxy: {
"/": "http://localhost"
}
},
여기서 설정된 포트와 proxy로 client에서 발생하는 요청이 해당 서버로 전송됩니다.
[ * 수정 ]
이상하게 프로젝트 진행을 하다 보니 갑자기 proxy가 먹히지 않는 현상이 있습니다.
package.json 맨 아래에 "proxy" : "http://localhost:4000" 을 입력해 주면 해결할 수 있습니다.
4. App.js 수정
그전에 우선 React가 어떤 방식으로 돌아가는지 한번 보도록 하겠습니다.
중요 파일을 보면 public / index.html , src / App.js , src / index.js. 크게 이렇게 3가지가 있습니다.
제일 처음 서버에 접속하게되면 public/index.html 을 렌더링하여 보여줍니다. index.html의 <body> 부분을 보게되면
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<div id="root"></div> 라는 태그를 볼 수 있습니다. 이 부분에 React의 js 파일들을 불러와 보여주게 됩니다.
그 역할을 해주는 파일이 src/index.js 파일입니다.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
밑에서 두번째 줄을 보게되면 ReacDOM.render(<App />, document.getElementById('root')); 라는 부분이 있는데 이 부분이 index.html에서 ID 값이 'root' 인 엘리먼트에 App이라는 오브젝트를 렌더링하겠다 라는 의미입니다.
4번째줄을 보게되면 import 를 통해 App.js 파일을 App이라는 이름으로 불러오고 있습니다. Javascript의 경우 확장자 js를 생략해도 됩니다.
그럼 마지막으로 App.js 파일을 보도록 하겠습니다.
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
export default App;
App class를 선언하고 render() 함수 내에 리턴 값으로 html 요소들을 반환하고 있습니다. 이러한 형태로 작성을 한 후 맨 마지막 줄의 export default App 이라는 선언을 하게 되면 어디서든 해당 프로젝트 내에서 어디서든 App이라는 이름을 통해 import 할 수 있습니다.
여기까지 대충 리엑트가 동작하는 방식을 알아봤으니, 다시 처음에 말한 것 처럼 Express 서버와 Client 가 잘 연동이 되는지 확인하기 위해 App.js 파일을 다음과 같이 수정합니다.
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
state = { username: null };
componentDidMount() {
fetch('/api/getUsername')
.then(res => res.json())
.then(user => this.setState({ username: user.username }));
}
render() {
const { username } = this.state;
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
<div>
{username ? <h1>{`Hello ${username}`}</h1> : <h1>Loading.. please wait!</h1>}
</div>
</div>
);
}
}
export default App;
해당 코드를 이해하려면 State 와 Lifecycle에 대해 공부를 해야 할 것 같습니다.
일단은 componentDidMount() 라는 함수는 Lifecycle 함수로서 페이지의 렌더링이 끝난 후에 호출됩니다. 그렇기 때문에 App 내부 render() 함수 결과가 먼저 뿌려지게 되는데 이때 username이라는 값은 null 값이기에 처음에는 Loading.. please wait! 라는 문구가 출력되게 됩니다.
하지만 곧바로 componentDidMount() 함수가 호출되고 fetch를 통해 /api/getUsername URL을 서버에 요청을 하고 받은 데이터를 username에 세팅하는 this.setState() 라는 함수를 사용하게 되면 Rerendering 을 하게 되어 username이 출력되는 것을 확인할 수 있습니다.
그럼 잘 작동 하는지 한번 테스트해보겠습니다.
우선. 커맨드 창을 열고 server 폴더로 이동하여 아래 명령어를 통해 Exrpess 서버를 실행합니다.
node server.js
그런다음 해당 프로젝트 내에서 ( my-app 폴더에서 ) 아래 명령어를 통해 Client 서버를 실행합니다.
yarn start
이와 같이 출력되면 Express 서버와 Client 간의 연결이 잘 된것입니다.
create-react-app 과 Express를 연동하는 법을 알아보았습니다. 다음 편에서는 Express 서버의 라우팅 설정을 해보도록 하겠습니다.