지금까지 만든 토이프로젝트들은 Monolithic architecture(모놀리식 아키텍쳐: 일체형 구조) 소프트웨어 설계구조를 가졌다.
모놀리식은 하나의 서버에 서비스 할 모든 애플리케이션 소스가 존재하는 구조이다.
▶ Monolithic architecture 동작구조
1. 클라이언트가 요청을 보내면
2. 서버에 존재하는 웹 어플리케이션이 데이터베이스 서버와 통신하여 필요한 데이터들을 전부 가져온다.
3. HTML, CSS, JavaScript 파일들을 만들어서 클라이언트에게 제공한다.
4. 클라이언트는 제공받은 파일을 브라우저에 전달한다.
Monolithic 은 아키텍쳐가 단순하고, 프로덕트 와 DB 서버 2대만 운영하면 되어서 혼자 관리하기 용이했기 때문에
그동안 토이 프로젝트는 Spring 을 이용한 모놀리식 구조로 설계했었다.
이런 구조는 프로젝트가 커짐에 따라 다음과 같은 문제점이 발생한다.
- 조그마한 수정사항이 있어도 전체를 다시 빌드하고 배포해야 함
- 유지보수가 힘듦
- 프로젝트 규모가 커질수록 구동 시간이 늘어남
- 일부분의 오류가 전체에 영향을 미침
- 각 기능별로 알맞은 언어나 프레임워크를 선택하기가 까다로움
규모가 큰 프로젝트를 진행 준비를 위해 Decoupled Architecture (분리된 아키텍쳐)를 공부해보자.
백엔드와 프론트엔드 서버를 분리한다 .. ?
가장 먼저 떠오르는 궁금증은
클라이언트는 서버에 어떤 식으로 데이터를 요청하고
서버는 클라이언트에 어떤식으로 데이터를 전달하는가 ?
둘은 도대체 어떻게 통신을 한단말인가 ? 이다.
구글링을 해보면 React 로 구성한 프론트 환경에서는 서버와 통신을 하기 위해 fetch 또는 axios 를 사용한다고 한다.
무슨 말인지 잘 모르겠다.
백엔드 서버와 프론트엔드 서버가 fetch, axios 을 이용해 어떻게 통신하는지 알아보기 위해
환경을 구축해 클라이언트에서 서버에 데이터를 요청해보자.
▶ 환경구축
1. express 서버 구성하기
프로젝트를 진행할 폴더(React-request-server) 안에 server, client 폴더를 만든다

npm init
npm i express
server 에서 위 명령어를 사용해 package.json 만들고, express를 설치해준다.
npm 공식 사이트에 접속하고 express 를 검색해 sample code 를 복사한다.
server 폴더 내에 app.js 라는 파일을 만들어 붙여넣어준다. (서버 코드 짜기)
sample code 에 실행되었는지 확인할 수 있는 간단한 콜백함수를 추가한다.
const express = require('express')
const app = express()
app.get('/', function (req, res) {
res.send('Hello World')
})
app.listen(3000, ()=> {
console.log('Listening on port 3000');
});
node app.js //server 실행

2. 서버 API 테스트
2번 과정을 완전히 이해하기 위해서는 express api 에 관한 지식이 필요한데,
이번 포스팅의 주제인 [백엔드 서버와 프론트엔드 서버는 어떻게 통신하는가 ?] 에
깊게 연관된 것이 아니기 때문에 이해하지 못하고 넘어가도 된다.
(환경을 구축하기 위한 작업이다)
테스트를 하기 위한 데이터가 필요한데, DB 을 붙이지 않고 데이터를 메모리에 저장 해놓겠다.
const jjigae = [{
id : 1,
name : '김치찌개',
description : '주의: 우리집 김치로 만들어야 맛있음',
}];
▷ get 요청을 하는 api 생성
app.get('/api/jjigae',(req, res)=>{
res.json(jjigae); //json 형태로 jjigae 를 보내줌
})

▷ post 요청을 하는 api 생성
- 프론트에서 서버에 데이터를 보낼 때 body 에 데이터를 넣어서 보낼것이다.
- express 에서 body 에서 데이터를 꺼내 쓰려면 body-parser 가 필요하다
app.use(express.json()) // for parsing application/json
app.use(express.urlencoded({ extended: true }))
( express 공식문서를 통해 위 두줄을 추가하면 body-parser 사용가능함을 알 수 있다 https://expressjs.com/en/4x/api.html )
api 작성
app.post('/api/jjigae',(req,res)=>{
const {jjigaeName , description} = req.body; //body-parser를 통해 데이터를 꺼내옴
jjigae.push({
id : id ++,
jjigaeName,
description,
});
return res.send('success');
});
POSTMAN TEST

json 데이터를 POST 로 보내면

보낸 데이터가 잘 추가된 것을 확인할 수 있다.
여기까지 서버에서 데이터를 보내는 환경을 만들었다.
다음은 프론트에서 데이터를 받는 환경을 구축해보자.
3. 리액트 구성하기
client 폴더로 이동해서 react 설치
npx create-react-app .
App.js
function App() {
return (
<div className="App">
<h1>찌개 리스트</h1>
</div>
);
}
export default App;
npm start //react 실행

서버를 실행하면 페이지가 잘 나오는 것을 확인할 수 있다.
드디어 환경 구축이 완료되고 클라이언트에서 서버에 데이터를 요청해볼 수 있게 되었다.
4. 클라이언트에서 데이터 요청하기
서버에 데이터를 요청하려면
- 서버의 주소를 알아야 한다.
- 어떤 HTTP METHOD 를 사용할지 알아야 한다.
앞서 리액트에서 서버에 데이터를 요청하는 방법은 fetch 와 axios 가 있다고 했는데, 차례대로 살펴보겠다.
▶ Fetch
자바스트립트에 내장된 API (ES6 이상)
fetch(url, [옵션]);
url - 접근하고자 하는 URL
options - method 나 header 등을 지정할 수 있다.
▷ fetch 기본 구조
fetch(url, {
method: 'POST',
headers : {
'Content-Type' : 'application/json'
},
body: JSON.stringify(data)
});
.then((response)=> response.json())
.chatch((error)=>console.log(error))
▷ fetch 사용하기
프론트에서 서버에 데이터를 요청하는 코드 작성
function App() {
fetch('http://localhost:4000/api/jjigae')
.then((response) => response.json())
.then((data)=>console.log(data));
return(
<div className="App">
<h1>찌개 리스트</h1>
</div>
);
}
export default App;
3000번 포트로 리액트를 실행시키고
4000번 포트로 노드를 실행시킨다.

코드를 작성하고 서버에 데이터 요청을 했더니 CORS 라는 에러가 발생한다.
CORS ERROR : Access to fetch at 'http://localhost:4000/api/jjigae' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
CORS 란 ?
Cross Origin Resource Sharing
클라이언트 : localhost:3000 리액트 개발서버
서버 : localhost:4000
둘은 PORT 가 다르기 때문에 데이터의 출처(Origin)가 다르다.
네이버에서 구글의 데이터를 빼가도 되는가 ? 안된다.
그래서 ' 오리진이 다르면 리소스를 꺼내갈 수 없다 ' 라는 정책(SOP)이 있고, CORS 에러를 해결하기 위해서는 서버에서 허용을 해줘야한다.
CORS 에 대한 자세한 내용은 아래 포스트로 정리했다.
https://feelfreetothink.tistory.com/165
[Decoupled Architecture] CORS
※ CORS (Cross-Origin Resource Sharing) 추가 HTTP 헤더를 사용하여 한 출처에서 실행중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제 ▶
feelfreetothink.tistory.com
CORS 모듈울 사용해 좀더 간편하면서 유기적으로 출처를 필터링 할수 있다.
server에 CORS 모듈설치
$ npm install cors
const cors = require('cors'); //공식문서에는 var 라고 되어있는데 const 로 바꿔주자
app.use(cors())
다시 요청을 하면 CORS 에러가 안뜨고
서버에서 요청한 데이터를 전달해준 것을 확인할 수 있다.

▶ axios
axios 설치
npm i axios
axios로 서버에서 데이터 요청하는 코드 작성
import axios from 'axios';
axios.get('http://localhost:4000/api/jjigae')
.then((response) = setJjigae(response.data);
fetch 로 작성한 코드와 동일하게 서버에서 데이터를 받아온다.
axios 는 fetch 보다 훨씬 간단하게 작성할 수 있고, async await 문법을 사용하면 더 직관적으로 작성이 가능하다.
(axios 는 다른 포스팅에서 자세히 다뤄보도록 하겠다)
서버가 분리된 환경에서 서버와 클라이언트는 어떻게 통신하는가 ?
에 대해 알아보기 위해 분리된 서버 환경을 구축해서
클라이언트에서 요청한 데이터를 서버에서 보내줘봤다.
https://it-eldorado.tistory.com/85
https://www.indicative.com/resource/decoupled-architecture/
'프로젝트' 카테고리의 다른 글
| [React & Typescript 프로젝트] Happy-Christmas ! (0) | 2022.12.30 |
|---|---|
| [Decoupled Architecture] CORS (0) | 2022.12.07 |
| [Kotlin + SpringBoot + RESTApi] 오늘의 찌개 Today's Jjigae (0) | 2022.11.22 |
| [Kotlin 토이프로젝트] CRUD 별 예외 처리 (0) | 2022.11.18 |
| [Kotlin 토이프로젝트] Handling Exceptions (0) | 2022.11.18 |