spring boot를 통해 rest api 서버를 구축하고, react를 통해 데이터를 가져와 화면에 뿌려주는 간단한 구현을 해보고자 한다.
매우매우 단순한 화면을 통해 프론트엔드 / 백엔드 연동 샘플을 만들고자 한다.
*참고 git) https://github.com/kimseonguk197/react_spring_connect
REACT 프로젝트 생성
커맨드창에 아래 명령어를 통해 react프로젝트를 생성한다.(mac기준, npm이 설치 됐다 가정하겠다.)
npm create react-app myreact
에러가 나지 않았다면 해당 폴더로 이동후에 react를 실행한다
cd react-app
npm start
3000번 port에 아래와 같은 이미지에 나왔다면, 정상
구체적인 코딩은 일단 스프링 API 서버를 먼저 만들고 나서 다시 해보도록 하자.
SPRING BOOT 프로젝트 생성
환경이 미리 세팅된 initializer를 통해 spring boot 프로젝트를 생성하고자 한다. 아래 url로 이동하자.
https://start.spring.io/
서버에서는 별도의 DB세팅 없이, 간단한 JSON형태의 데이터만 생성하고자 하니, 아래와 같이 gradle빌드에, Web, Lombok정도만 depency를 추가한 프로젝트로 심플하게 구성하자.
java가 설치 돼 있고, intellij가 미리 깔려 있다 가정하겠다.(위 사진의 버전대로 spring boot를 세팅하면 java 17이 기본이니 java17을 설치하면 되겠다.)
intellij를 통해 다운 받은 프로젝트의 build.gradle을 open 시키면, 알아서 필요한 라이브러리를 다운받게 된다.
그러면 최초에는 DemoApplication만이 만들어져 있을 것인데, 아래와 같이 Entity와 Controller를 만들어보자.
TestData.java
@Data
public class TestData {
int id;
String name;
int age;
}
TestController.java
@RestController
public class TestDataController {
@GetMapping("api/v1/testdata")
public TestData testData(){
TestData td = new TestData();
td.setId(1);
td.setName("kim");
td.setAge(20);
return td;
}
}
여기까지만 하고 나면, Postman으로 http://localhost:8080/api/v1/testdata GET호출을 해보도록 하자.
아래와 같은 데이터가 정상적으로 조회됨을 알수가 있다.
{
"id": 1,
"name": "kim",
"age": 20
}
아직 리액트 코드를 작성하진 않았지만, 이상태만으로 리액트 코드에서 API서버를 호출하게 되면 CORS에러가 발생할 것이다.
그래서 CORS에러를 방지해 주기 위해 아래 클래스를 하나 추가해두자. localhost 3000port의 모든 호출에 대해 allow 시키는 설정이다.
WebConfig.java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000");
}
}
파일의 위치는 Application 파일과 같은 위치에 있어야 함에 유의하자.
Spring 서버는 이제 완전히 끝났다. React로 돌아가보자.
React소스코드
리액트 프로젝트의 구조는 아래와 같다. 최초 create 시켰을때는 components 폴더와 services폴더가 없었을 것이다. 일단 2개 폴더에 TestMain.js, TestService.js 파일 2개를 깡통으로 만들어 두자.
그리고 App.js파일을 열어서 있는 소스코드를 모드 날려 버리고, 아래와 같이 수정해두자.
App.js
import './App.css';
import { BrowserRouter, Routes, Route } from "react-router-dom";
import TestMain from "./components/TestMain";
function App() {
return (
<BrowserRouter>
<Routes>
<Route index element={<TestMain />} />
</Routes>
</BrowserRouter>
);
}
export default App;
/ 과 같은 index호출일 경우 TestMain.js로 라우팅을 해서 TestMain에 있는 화면을 보여주겠다는 코드이다. 그런데, import 부분을 보면, react-route-dom 라이브러리가 있는데, package.json에 추가해주어야 import가 가능하다.
package.json
"dependencies": {
"axios": "^0.27.2",
"react-router-dom": "^6.3.0",
나머지는 있는 그대로 두고, 위와 같이 axio와 react-router-dom 2개만 추가하도록 하자.
아래 코드는 TestService에서 데이터를 가져 화면에 뿌려주는 Component이다. 자세한 내용은 주석을 참고 하길 바란다.
TestMain.js
import React, { useEffect, useState } from "react";
import TestService from "../services/TestService";
const TestMain = () => {
// return 문이 useEffect 보다 먼저 읽히므로, setLoading을 통해 화면에 데이터 렌더링 속도조절
const [loading, setLoading] = useState(true);
const [testData, setTestData] = useState(null);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
try {
// service에 서버로의 http호출을 분리
const response = await TestService.getTestData();
setTestData(response.data);
} catch (error) {
console.log(error);
}
// 다 읽어 왔으면 Loading을 false로 바꾸어 주어 rendering 가능하도록
setLoading(false);
};
fetchData();
}, []);
return (
<div>
{/* loading이 false인 경우 화면 렌더링 */}
{!loading && (
<div>
id : {testData.id}<br></br>name : {testData.name}<br></br>age : {testData.age}
</div>
)}
</div>
);
};
export default TestMain;
service부분 또한 단순한데, 여기서는 axios라이브러를 통해서 굉장히 쉽게 서버로 데이터를 가져온다는 것 정도만 유의해서 보시면 되겠다. ajax같은 레거시에 익숙한 분이라면, 코드가 굉장히 간결해졌음을 알수 있을 것이다.
TestService.js
import axios from "axios";
const TEST_API_BASE_URL = "http://localhost:8080/api/v1/testdata";
class TestService {
getTestData() {
// axios라이브러를 통해 쉽게 서버로 data호출
return axios.get(TEST_API_BASE_URL);
}
}
export default new TestService();
여기까지 끝났다면, myreact폴더 안에서 npm install을 다시 한번 해주고, npm start하면,
아래와 같이 3000port에서 8000번 spring 서버를 호출하여 가져온 데이터들을 화면에 잘 렌더링 해주고 있는 것을 알수가 있을 것이다.
'프로그래밍 > 프론트엔드' 카테고리의 다른 글
chat GPT를 활용하여 템플릿엔진(타임리프)에서 react(react-native)로 리팩토링해보기 (0) | 2023.04.13 |
---|---|
javascript 콜백문제 발생 이유 (0) | 2023.01.31 |
preflight시에 get만 cors에러나는 이유(post와의 차이 - origin null) (0) | 2023.01.12 |