공부하는 블로그

React | React - Node.js 연동하기 본문

React

React | React - Node.js 연동하기

치킨닮은닭 2020. 1. 7. 20:30

React - Node.js

 리액트를 클라이언트 사이드로, Node.js를 서버 사이드로 연동하는 방법에 대해 알아보자. 연동하는 방법은 여러가지가 존재하지만 이 포스팅에서는 'http-proxy-middleware'라는 미들 웨어를 이용하여 간편하게 프록시(Proxy)를 설정하는 방법을 이용한다. 

* Proxy : 서버와 클라이언트 사이에 중계기로서 대리로 통신을 수행하는 것.  클라이언트가 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해준다.

 

proxy의 도식화. 두 컴퓨터 사이에 끼어있는 컴퓨터가 프록시 서버이다.

  리액트 애플리케이션(localhost:3000)에서 프록시를 통해 구축된 Node.js 서버 사이드(localhost:3001/api)로 요청을 보내 데이터를 받아오는 방식이다. 따라서 두 개의 포트를 각각 클라이언트 사이드로, 서버 사이드로 할당하여 동시에 서버를 작동시켜주어야 한다.

01. React App 생성

 'create-react-app'을 이용하여 클라이언트 사이드로 사용할 리액트 애플리케이션을 생성하도록 하자.

 

$ npm -g install create-react-app
$ create-react-app <project_name>

02. Node.js 서버 생성

 생성한 리액트 애플리케이션에 server 폴더를 생성하고 기본적인 서버코드를 작성하자. 서버 프레임워크로 익스프레스를 사용하였다.

 

프로젝트 폴더 구조

$ npm install express --save

 

// server/server.js

const express = require('express');
const app = express();
const api = require('./routes/index');

app.use('/api', api);

app.listen(3001, () => console.log('Node.js Server is running on port 3001...'));

 

 서버 생성 코드이다. 포트번호는 3001번으로 할당하였으며 '/api'의 경로 요청을 라우팅해주었다.

 

// server/routes/index.js

const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
    console.log('http://localhost:3001/api/');
    res.send({title: 'hello react!'});
});

module.exports = router;

 

 /api 라우터 코드이다. 기본 경로 요청 시 title을 json 형식으로 반환하도록 하였다.

03. Proxy 설정

 리액트 애플리케이션의 src 폴더에 setProxy.js 파일을 생성한 뒤 'http-proxy-middleware' 모듈을 이용하여 프록시를 간편하게 설정하였다. 'http-proxy-middleware'는 외장 모듈이므로 따로 설치해주어야 한다.

 

$ npm install http-proxy-middleware --save

 

// src/setProxy.js

const proxy = require('http-proxy-middleware');

module.exports = function (app) {
    app.use(
        proxy('/api', {
            target: 'http://localhost:3001/'
        })
    );
}

 

 설정된 프록시는 클라이언트 사이드에서 Node.js 서버 사이드인 'http://localhost:3001/api'로의 요청을 처리하여 서버 데이터를 가져올 수 있도록 해준다.

04. 요청한 서버 데이터를 클라이언트에서 표현하기

 이제 클라이언트 사이드에서 프록시를 통해 서버 사이드에 요청하여 데이터를 받아오는 방법에 대해 알아보자. 리액트의 라이프사이클 메소드인 'componentDidMount()'를 사용하면 서버 사이드로의 접근이 가능하다.

 

// src/App.js

import React from 'react';
import logo from './logo.svg';
import './App.css';

class App extends React.Component{
  constructor(props) {
    super(props);
    this.state = {
      title: null
    }
  }

  componentDidMount() {
    fetch('http://localhost:3001/api')
      .then(res => res.json())
      .then(data => this.setState({title: data.title}));
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <div>
            {this.state.title? <h1>{this.state.title}</h1>:<h1>loading...</h1>}
          </div>
        </header>
      </div>
    );
  }
}

export default App;

 

 'componentDidMount()'는 첫 렌더링이 완료된 후 진행되며 'fetch()'를 이용하여 서버 사이드로의 url 요청을 할 수 있다. 요청한 데이터(title)를 받아 'setState()'를 이용하여 state 값을 변경하면 리액트 앱은 다시 렌더링이 진행되어 변경된 state를 페이지에 띄울 수 있게 된다.

 

 모든 준비가 완료되었으니 서버를 두 개의 터미널에서 각각 실행시켜 'http://localhost:3000'으로 접속해보자!

 

$ node ./server/server.js	// 서버 사이드 실행

 

$ npm start		// 클라이언트 사이드 실행

 

 

 서버의 작동 순서를 설명해보자면 아래와 같다.

 

1. http://localhost:3000 URL 요청

2. App 컴포넌트의 constructor() 실행 -- this.state.title = null

3. render() 실행 -- this.state.title이 null 이므로 처음에는 loading... 이라는 문구가 페이지에 띄워짐

4. 렌더링 완료 후 componentDidMount() 실행 -- fetch()를 통해 서버 사이드 url 요청

5. 서버 사이드에서 {title: 'hello react!'} 데이터 반환

6. 전송받은 서버 사이드의 데이터(data)를 이용하여 setState() 실행

7. setState()로 인해 state값이 변경되어 rerendering

8. this.state.title이 'hello react!'이므로 전송받은 문구가 페이지에 띄워짐


※ Cross-Origin Read Blocking (CORB)

 

 위의 과정을 따라 코드를 전부 작성하여 두 개의 서버를 실행할 때 간혹 클라이언트 사이드에서 서버 사이드의 데이터를 가져오지 못할 경우가 있다. 크롬 개발자도구를 이용하여 콘솔을 확인해보면 아래와 같은 문구를 발견할 수 있을 것이다.

 

 

 이는 크로스 도메인을 할 때 나타나는데 그 이유는 자바스크립트로 다른 웹페이지에 접근할 때는 보안상 같은 출처(same origin)의 페이지에서만 접근이 가능하도록 되어있기 때문이다.

 

 해결 방법은 서버 코드에서 'cors' 모듈을 사용하는 방법이 있다. 

 

$ npm install cors --save

 

const cors = require('cors');
app.use(cors());

 

 서버 파일(server.js)에 위의 코드를 삽입하면 정상적으로 서버 데이터를 가져올 수 있다.

'React' 카테고리의 다른 글

React | Form  (0) 2020.01.11
React | Event Handling  (0) 2020.01.10
React | Props & State  (0) 2019.12.30
React | Component  (0) 2019.12.30
React | Introduction  (0) 2019.12.29
Comments