1. 리액트를 내가 만든 서버에서 사용하기
1) 노드js 설치
2) 작업할 폴더를 생성하고 해당 폴더를 에디터로 열기
3) server.js 파일을 생성하고 다음과 같이 코드 작성
const express = require('express');
const path = require('path');
const app = express();
app.listen(8080, function () {
console.log('서버가 8080 포트에서 실행 중입니다.');
});
4) 터미널을 열고 npm init -y 명령을 실행하여 package.json 파일을 생성
5) npm install express 명령을 실행
6) node server.js 명령으로 서버 실행해보기
7) 웹브라우저에서 localhost:8080으로 접속하면 웹 서버를 미리 볼 수 있습니다.
2. 리액트 프로젝트와 연동하기
1) 리액트 프로젝트 폴더 생성
server.js 파일과 같은 위치에 리액트 프로젝트를 위한 폴더를 생성합니다.
2) 리액트 프로젝트 생성
터미널에서 npx create-react-app 프로젝트명 명령을 실행하여 리액트 프로젝트를 생성하고 에디터로 프로젝트 폴더를 엽니다.
3) 리액트 앱 개발 및 빌드
리액트 프로젝트 폴더에서 필요한 개발 작업을 진행합니다.
개발이 완료되면 npm run build 명령을 실행합니다. 그러면 build 폴더에 빌드된 파일들이 생성됩니다.
4) 서버에서 리액트 앱 제공
server.js 파일에서 다음과 같이 코드를 작성하여 서버에서 리액트 앱을 제공합니다.
app.use(express.static(path.join(__dirname, 'react-project/build')));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '/react-project/build/index.html'));
});
위 코드는 express.static을 사용하여 정적 파일들을 제공하고, / 경로로 접속한 클라이언트에게는 리액트 앱의 index.html 파일을 제공합니다.
이제 서버를 실행하고 브라우저에서 http://localhost:8080에 접속하면 리액트 앱이 나타납니다.
3. 리액트에서 라우팅 처리하기
리액트에서 라우팅 처리하려면 react-router-dom을 사용합니다. 하지만 /list 페이지를 개발했을 때 localhost:8080/list 에 접속한다고 페이지가 뜨지는 않습니다. 브라우저가 URL 창에 보여주는건 서버에 요청하는거지 리액트 라우터에 요청하는 것이 아니기 때문입니다.
(server.js에 추가)
app.get('*', function (요청, 응답) {
응답.sendFile(path.join(__dirname, '/react-project/build/index.html'));
});
위 코드를 server.js에 추가하면 리액트가 라우팅을 할 수 있게 됩니다. 별표* 는 모든문자라는 의미입니다. 해당 코드는 항상 가장 하단에 놓아야 작동이 잘됩니다.
4. 리액트에서 DB 데이터 보여주는 방법
리액트에서 데이터베이스의 데이터를 가져와서 HTML로 보여주는 방법에는 서버 사이드 렌더링(Server-side Rendering)과 클라이언트 사이드 렌더링(Client-side Rendering) 두 가지가 있습니다.
1) 서버 사이드 렌더링(Server-side Rendering)
서버 사이트 렌더링은 서버에서 HTML을 생성하여 클라이언트에게 보내주는 방식입니다. 예를 들어, Node.js를 사용하여 다음과 같이 작업할 수 있습니다.
- DB에서 데이터 가져오기
- 가져온 데이터를 HTML 파일에 삽입하기
- 서버에서 해당 HTML 파일을 클라이언트에게 보내주기
2) 클라이언트 사이드 렌더링(Client-side Rendering)
클라이언트 사이드 렌더링은 리액트가 브라우저 내에서 HTML을 생성하는 방식입니다.
- 리액트가 서버에 GET 요청을 보내에 데이터베이스의 데이터를 가져옵니다.
- 가져온 데이터를 HTML로 생성하여 보여줍니다.
리액트를 사용하는 경우 일반적으로 클라이언트 사이드 렌더링을 사용합니다. 따라서 상품 목록과 같은 DB 데이터를 리액트에서 보여주기 위해 다음과 같은 코드를 작성합니다.
- 서버는 '/product'로 GET 요청이 오면 DB에서 데이터를 가져와서 API로 응답합니다.
- 리액트에서 상품 목록을 보여주고자 할 때, 서버의 '/product' 주소로 GET 요청을보내면 됩니다.
- 그러면 데이터가 받아와지고, 이를 활용하여 HTML에 삽입하거나 개발에 맞게 확용할 수 있습니다.
그래서 리액트에서는 서버와의 통신을 주로 AJAX를 통해 진행합니다. POST 요청이나 로그인과 같은 세션 생성도 AJAX를 통해 잘 처리할 수 있습니다.
[참고]
node.js 서버 파일 상단엔 다음과 같은 코드를 추가해야 리액트와 node.js 서버간의 ajax 요청이 잘 작동합니다.
app.use(express.json());
var cors = require('cors');
app.use(cors());
express.json()은 유저가 보낸 object/array 데이터를 출력하기 위해 필요하며, cors는 다른 도메인 간의 ajax 요청을 주고받을 때 필요합니다.
5. 리액트 프로젝트 코드 수정 시 build 작업 필요 여부
리액트 프로젝트 코드를 수정할 대마다 build 작업을 해야 할 필요는 없습니다. 이 작업은 사이트나 AWS나 Google Cloooud와 같은 곳에 배포할 때만 필요합니다. 평소에 개발할 때는 리액트를 localhost로 미리보기를 띄우고, 서버도 localhost로 미리보기를 띄워두면 문제없이 개발할 수 있습니다.
다만, 리액트에서 서버에 ajax 요청을 보낼 때 '/product'와 같이 입력하는 대신에 "http://서버주소/product"와 같이 정확한 주소를 입력하고, 서버에서 cors 옵션을 올바르게 설정해야 합니다. 서버 주소를 입력하는 것이 귀찮다면, 리액트 프로젝트의 package.json 파일을 열어 proxy 부분을 설정하여 서버 미리보기를 띄우는 주소인 localhost:포트번호로 설정해주면 됩니다. 그러면 리액트에서 ajax 요청을 해도 자동으로 loaclhost:포트번호로 ajax 요청이 전달됩니다. 참고
6. 서브디렉토리에 리액트 앱 발행하기
현재 메인 페이지가 리액트 앱이고, 그 외에도 '/react'와 같이 접속하면 리액트로 만든 HTML을 보여주고, '/'와 같이 접속하면 public 폴더에 있는 기본적인 HTML을 보여주고 싶은 경우 다음과 같이 설정할 수 있습니다.
(server.js)
app.use( '/', express.static( path.join(__dirname, 'public') ))
app.use( '/react', express.static( path.join(__dirname, 'react-project/build') ))
app.get('/', function(요청,응답){
응답.sendFile( path.join(__dirname, 'public/main.html') )
})
app.get('/react', function(요청,응답){
응답.sendFile( path.join(__dirname, 'react-project/build/index.html') )
})
(리액트프로젝트 내의 package.json)
{
"homepage": "/react",
"version": "0.1.0",
... 등
}
위와 같이 server.js의 라우팅 설정을 변경하고, 리액트 프로젝트 내의 package.json에 "homepage" 항목을 원하는 서브디렉토리명으로 설정하면 됩니다. 이렇게 설정하면 "/react"로 접속하면 리액트 프로젝트가, "/"로 접속하면 public 폴더에 있는 일반 HTML 파일이 보여지게 됩니다. 하지만, 이 설정은 대부분의 경우에 사용되지 않으므로 실제로 필요한 경우는 드물다는 점 참고해주세요
'React' 카테고리의 다른 글
React 쇼핑몰(state 변경 함수의 비동기 처리) (0) | 2023.10.31 |
---|---|
React 쇼핑몰(Progressive Web App) (0) | 2023.10.31 |
React 쇼핑몰(Automatic Batching, useTransition, useDeferredValue) (1) | 2023.10.30 |
React 쇼핑몰(memo, useMemo) (1) | 2023.10.29 |
React 쇼핑몰(개발자도구, lazy import) (0) | 2023.10.29 |