react에서 웹서버와 db서버 같이 연동하여 개인홈페이지 만드는데 막혔습니다.


(냠냠) #1

저는 React와 MysqlDB를 이용해 개인적으로 쓸 사이트를 만들고 있습니다.
참고로 새내기 대학생 1학년
그래서 남들이 주소를 입력해 들어올 수 있게 도메인도 구하고 db도 처음엔
호스트를 localhost:3000을 사용하다가 AWS의 RDS를 이용해 적용해보았습니다.

server.js

 const express = require('express');
 const cors = require('cors');
 const mysql = require('mysql');
const app = express();


const SELECT_ALL_PROJECTDB_QUERY = 'SELECT * FROM projectdb';


const connection = mysql.createConnection({
    host: 'database-1.c8mhpo4sz1qt.ap-northeast-2.rds.amazonaws.com',
    user: 'admin',
    password: 'DrjJzcFnAFJa12uATJ6e',
    database: 'ExampleDB',
    port: '3306'
});

connection.connect(err => {
    if(err) {
        return err;
    }
});

app.use(cors());

app.get('/', (req, res, rows) => {
    res.send('go to /projectdb to see project');
    
    console.log("it's god")
})

app.get('/projectdb/add', (req, res) => {       
    const { background, cardtitle, cardtext } = req.query;
    connection.query(`INSERT INTO projectdb (background, cardtitle, cardtext) VALUES ('${background}', '${cardtitle}', '${cardtext}')`, (err, results) => {
        if(err) {
            return res.send(err)
        }
        else {
            return res.send('successfully added pr')
        }
    })
    
})
app.get('/gamedb/add', (req, res) => {
    const { background, cardtitle, cardtext } = req.query;
    connection.query(`INSERT INTO gamedb (background, cardtitle, cardtext) VALUES ('${background}', '${cardtitle}', '${cardtext}')`, (err, results) => {
        if(err) {
            return res.send(err)
        }
        else {
            return res.send('successfully added game')
        }
    })
    
})

app.get('/picturedb/add', (req, res) => {
    const { background, cardtitle, cardtext } = req.query;
    connection.query(`INSERT INTO picturedb (background, cardtitle, cardtext) VALUES ('${background}', '${cardtitle}', '${cardtext}')`, (err, results) => {
        if(err) {
            return res.send(err)
        }
        else {
            return res.send('successfully added picture')
        }
    })
    
})

app.get('/noveldb/add', (req, res) => {
    const { background, cardtitle, cardtext } = req.query;
    connection.query(`INSERT INTO noveldb (background, cardtitle, cardtext) VALUES ('${background}', '${cardtitle}', '${cardtext}')`, (err, results) => {
        if(err) {
            return res.send(err)
        }
        else {
            return res.send('successfully added novel')
        }
    })
    
})

app.get('/projectdb', (req, res) => {
    connection.query(SELECT_ALL_PROJECTDB_QUERY, (err, results) => {
        if(err) {
            return res.send(err)
        }
        else {
            return res.json({
                data: results
            })
        }
    });
}),

app.get('/gamedb', (req, res) => {
    connection.query(`select * from gamedb`, (err, results) => {
        if(err) {
            return res.send(err)
        }
        else {
            return res.json({
                data: results
            })
        }
    });
});

app.get('/picturedb', (req, res) => {
    connection.query(`select * from picturedb`, (err, results) => {
        if(err) {
            return res.send(err)
        }
        else {
            return res.json({
                data: results
            })
        }
    });
});

app.get('/noveldb', (req, res) => {
    connection.query(`select * from noveldb`, (err, results) => {
        if(err) {
            return res.send(err)
        }
        else {
            return res.json({
                data: results

            })
            
        }
    });
});

app.listen(4000,)

localhost:4000/projectdb에 접속한결과

보신것처럼 mysql데이터를 성공적으로 불러왔습니다.

다음에 위에 있는 localhost:3000을 이용해 안에 있는 데이터를 불러와
표시하는 컴포넌트를 만들었습니다.
showdb.js

import React, { Component } from 'react';
import { Grid, Cell } from 'react-mdl';
import { Tabs, Tab } from 'react-mdl';

import RemoveDB from './removeDB';
import AddDB from './addDB';

class ShowDB extends Component {

  state = {
    activaTab: 0,
    projectdb: [],
    gamedb: [],
    picturedb: [],
    noveldb: [],
   }

  toggleCategories(){

    if(this.state.activaTab === 0){
        return(
          <div className="App">
            <p>Web</p>
            <pre>{JSON.stringify(this.state.projectdb, null,'\t')}</pre>
            
          </div>
        )
    }
    else if(this.state.activaTab === 1) {
      return (
          <div>
            <p>Projects</p>
            <pre>{JSON.stringify(this.state.gamedb, null,'\t')}</pre>
          </div>
      )
    }
    else if(this.state.activaTab === 2) {
      return (
          <div>
            <p>Pictures</p>
            <pre>{JSON.stringify(this.state.picturedb, null,'\t')}</pre>
          </div>
      )
    }
    else if(this.state.activaTab === 3) {
      return (
          <div>
            <p>novels</p>
            <pre>{JSON.stringify(this.state.noveldb, null,'\t')}</pre>
          </div>
      )
    }
    else if(this.state.activaTab === 4) {
      return (
          <div>
            <p>AddDB</p>
            <AddDB />
          </div>
      )
    }
    else if(this.state.activaTab === 5) {
      return (
          <div>
            <p>RemoveDB</p>
            <RemoveDB />
          </div>
      )
    }

  }

  getProducts = _ => {   //products 정보를 state에 입력
    fetch('http://localhost:4000/products')
    .then(response => response.json())
    .then(response => this.setState({ products: response.data }))
    .catch(err => console.error(err))
  }

  componentDidMount() {
    this.getprojectdb();
    this.getgameDB();
    this.getpictureDB();
    this.getnovelDB();
    
}
    
     getprojectdb = _ => {   //products 정보를 state에 입력
      fetch('http://localhost:4000/projectdb')
       .then(response => response.json())
       .then(response => this.setState({ projectdb: response.data }))
       .catch(err => console.error(err))   
        
    }
     getgameDB = _ => {
        fetch('http://localhost:4000/gamedb')
        .then(response => response.json())
        .then(response => this.setState({ gamedb: response.data }))
        .catch(err => console.error(err))  
     }
     getpictureDB = _ => {
        fetch('http://localhost:4000/picturedb')
        .then(response => response.json())
        .then(response => this.setState({ picturedb: response.data }))
        .catch(err => console.error(err))  
     }
     getnovelDB = _ => {
        fetch('http://localhost:4000/noveldb')
        .then(response => response.json())
        .then(response => this.setState({ noveldb: response.data }))
        .catch(err => console.error(err))  
     }
  
  addProduct = _ => {
    const { product } = this.state;
    fetch(`http://localhost:4000/products/add?name=${product.name}&price=${product.price}`)
    .then(this.getProducts)
    .catch(err=> console.error(err))

  }

  renderProductOnlyName = ({ product_id, name, price, products}) => 
  <div key={product_id}>
   {name}
  </div>

  render() {
    
    
    return (
        <div className="category-tabs">
        <Tabs activeTab={this.state.activaTab} onChange={(tabId) => this.setState({ activaTab: tabId})} ripple>
            <Tab>Web</Tab>
            <Tab>Projects</Tab>
            <Tab>Picture</Tab>
            <Tab>Nobel</Tab>
            <Tab>AddDB</Tab>
            <Tab>RemoveDB</Tab>
        </Tabs>

        
            <Grid >
                <Cell col={12}>
                    <div className="content">{this.toggleCategories()}</div>
                </Cell>
            </Grid>
      </div>
      );
    
}
}
export default ShowDB;

결과


보시다시피 잘 표시가 됩니다.
하지만 이는 localhost:4000에서 데이터를 불러와 리액트 컴포넌트가 있는 localhost:3000으로 옮기는
형식입니다.
이는 localhost를 사용할 수 없는 다른 컴퓨터에서 접속할 떄 데이터를 볼 수 없어서 곤란합니다.
실제로 이 코드 그대로 제가 만든 도메인을 다른 컴퓨터에서 접속을 해보면

이처럼 데이터가 표시되지 않습니다.

제가 생각한 해결법은 localhost말고 누구나 접속할수 있는 다른 주소에 데이터를 저장하고 거기서
홈페이지에 필요한 데이터를 불러오는 형식입니다.
이를 위해서 server.js에서 기본적으로 연결되는 localhost:4000에서 localhost말고 다른 주소를
사용하기 위해 찾아봤습니다. server.js에서 맨 아래엔
app.listen(4000,)
이있습니다. 숫자 4000은 포트를 뜻하기에 localhost:4000으로 연결되는건 알았으나
node_moudule이나 package.json을 뒤지거나 구글링을 해도 바꾸는 방법을 알수가 없어서
react개발자 사이트에 회원가입을 하고 글을 올립니다.
개발자분들 저를 도와주시기 바랍니다.
이외 궁금한점 있으면 댓글 달아주세요~.


(이종은(Jong Lee)) #2

세번 읽어보면서 이해하려 했지만 정확히 어떤 상황인지 정확히 이해하기 힘듭니다.
일단 제가 이해한 바로는

localhost 4000포트에는 node 서버가 떠 있고
localhost 3000포트로 react 파일을 제공하는 서버가 떠 있는 것이며
로컬에서는 잘 동작하는 도메인 연결하면 안된다인건가요?

여러가지 개선점이 보이지만 일단 이 구조를 그대로 외부에서 접속 가능하게 옮긴다고 했을 때 4000포트와 3000포트에 해댕하는 서버가 외부에 필요합니다. 외부에는 어떻게 설정했는지에 대한 이야기가 빠진 것 같은데 좀 더 자세히 정리해서 알려주시면 다른 분들이 좀 더 수월히 도움을 줄 수 있을 겁니다.


(Joonseok Hu) #3

만드신 nodejs 애플리케이션이 퍼블릭 웹서버에 있어야 합니다. aws의 ec2 에 node 설치하셔서 켜두셔야 하고요.
웹서버 위치를 고정하기 위해 aws의 elastic ip 으로 고정아이피 지정, 도메인연결을 위해 route53으로 dns 연결작업도 추가적으로 필요할수 있습니다


(냠냠) #4

해결했습니다. 정말 감사합니다.ㅠㅠㅠ
aws의 ec2에 접속해서 server.js파일 그대로 옮기니까
ec2 인스턴스 퍼블릭DNS 주소뒤에 포트 추가된 채로 작동되네요
이 주소를 react의 fetch로 불러와서 하니까 잘 됬습니다…