프론트엔드만 하면서 궁금했던 백엔드를 이번 기회에 Spring Boot로 발가락만 살짝 담가보기로 했다.
웹의 인기 있는 라이브러리와 프레임워크인 프론트엔드의 React와 백엔드의 Java Spring Boot를 연동해 보자!
개발환경: Visual Studio(React), InteliJ(Spring), Mysql Workbench(DB Tools)
웹 백엔드 프레임워크인 spring을 복잡한 초기설정 없이 개발에만 집중할 수 있도록 spring boot가 나왔다.
spring initializer: https://start.spring.io/
프로젝트 이름은 따로 바꾸지 않고 Dependencies만 몇 가지 추가했다.

Spring Web: 스프링 웹 필수 도구
MariaDB Driver, Spring Data JPA: 데이터 베이스 연동
Lombok: 반복적인 코드 간략화 ex) @Getter, @Setter 메소드로 간략화
나는 InteliJ 환경을 사용하였다. 개발 환경에서 생성한 스프링 프로젝트를 열고 DemoApplication의 초록 화살표를 눌러 실행하면 오류가 뜰 것이다.

해당 오류를 없애기 위해 File -> settings... 에 들어가서 Gradle로 되어있는 두개를 InteliJ IDEA로 바꾸면 된다.

그러나 프로젝트가 실행은 되지만, 또 오류가 뜬다.
이것은 우리가 Dependencies에 DB에 관한 것을 추가 해줬기 때문에 DB연동 까지 마치면 성공적으로 실행 될 것이다.

mysql, mysql workbench를 설치하고, cmd창에서 mysql -V가 정상적으로 작동되는지 확인한다.

mysql workbench를 실행하여 플러스 버튼을 눌러 connection을 연결한다.

Connection Name: 본인이 마음에 드는 이름 (상관 없음)
Username: mysql workbench 생성 했을 때의 username (보통은 root로 함)
Password/Store in Vault... : mysql workbench 설치 했을 때의 password

Connection 생성 완료 및 진입

스키마 생성

이름은 practice로 하고 Apply하도록 하자

생성된 스키마의 Tables에서 우클릭 Create Table... 선택한다.
테이블 이름을 user로 하고, column 형식을 다음과 같이 생성한다.

다시 InteliJ로 돌아와서 resource/application.properties의 파일에 다음 코드를 작성 해준다.
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mariadb://localhost:3306/board

다시 스프링 프로젝트를 실행해 보면 오류가 없이 정상적으로 실행되는 것을 볼 수 있다.

브라우저에 localhost://8080 입력하고, 아래와 같이 에러 페이지가 뜨면 성공이다.

MVC 패턴에 대해서는 여기서 다루지 않도록 하겠다.
Spring은 MVC 패턴으로 프로젝트 구조를 다음과 같이 파일을 생성해 주자각각의 패키지 안에 java 및 interface파일을 추가한다.

각각의 파일에 다음 코드를 작성하도록 하자
UserController.java
package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
public class UserController {
@Autowired
private UserService userService;
@ResponseBody
@GetMapping("/user")
public List<User> userApi() {
return userService.getUserApi();
}
}
User.java
package com.example.demo.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;
@Data
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private Integer age;
private String introduce;
}
UserRepository.java
package com.example.demo.repository;
import com.example.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
}
UserService.java
package com.example.demo.service;
import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> getUserApi() {
return userRepository.findAll();
}
}
백엔드 구현 및 DB 연동이 끝이 났다. 이제는 mysql workbench에 데이터를 입력하고 Web Api를 사용할 수 있게 Local 환경에 띄어보자.
mysql workbench에 다시 들어간 다음 user 테이블 옆에 표시한 버튼을 클릭하면 표가 나온다. 표를 클릭하면 입력을 할 수 있다.

다시 스프링 프로젝트를 실행하고, localhost:8080/user에 들어간다.
성공적으로 실행 된다면, 다음과 같이 JSON형태로 프론트 엔드에서 사용할 수 있는 api형식의 데이터가 나오게 된다.

React는 웹 UI를 편리하게 만들 수 있게 하는 프론트엔드 라이브러리이다.
http요청으로 데이터를 받아올 것이기 때문에 리액트 프로젝트의 경로는 상관없다. (스프링 프로젝트 안에 껴 넣지 않아도 된다는 뜻)
본인이 원하는 프로젝트 이름으로 생성한다.
npx create-react-app webfront
터미널 경로를 생성한 프로젝트로 이동한다.
cd webfront
만든 프로젝트에서 src하위 파일에 App.js와 index.js만 남겨두고 제거한다.

App.js와 index.js도 우리가 사용할 수 있게 정리한다.
App.js
import { useEffect, useState } from "react"
import axios from "axios"
export default function App() {
const [users, setUsers] = useState();
useEffect(() => {
async function getUser() {
const response = await axios.get(`/user`);
const data = response.data;
setUsers(data);
}
getUser();
}, []);
return (
<div>
{
users ? users.map((user) =>
<div key={user.id}>
<h3>{user.name} {user.age}</h3>
<p>{user.introduce}</p>
</div>
) : null
}
</div>
)
}
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<App />
);
axios는 자바스크립트 라이브러리이며, http요청을 할 때 사용된다.
이것을 통해 우리가 Spring Framework에서 만들었던 api 서버의 데이터를 프론트엔드로 가져올 수 있다.
axios를 패키지에 추가하도록 하자
npm i axios
웹 브라우저는 보안상의 이유로 url이 다른 경로의 자원을 가져다 쓸 수 없게 막아두었다. 이것에 대한 자세한 내용은 CORS 정책을 살펴보면 된다.
CORS 문제를 해결하기 위해 NodeJS 패키지의 http-proxy-middleware을 사용한다. 이 패키지는 로컬 환경에서만 사용한다.
해당 미들웨어를 패키지에 추가하도록 하자
npm i http-proxy-middleware
src폴더 하위경로에 setupProxy.js파일을 생성하고 코드를 작성한다.

setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/user',
createProxyMiddleware({
target: 'http://localhost:8080',
changeOrigin: true,
})
);
};
실행할 때에는 스프링 프로젝트를 실행시킨 상태에서 리액트 앱을 실행시킨다.
※참고: setupProxy파일을 작성하고 리액트 앱을 다시 실행시켜야 Proxy가 적용된다.
npm start
실행시키면 다음과 같이 우리가 만든 서버의 데이터를 프론트엔드에 우리의 입맛에 맞게 사용할 수 있게 되었다.

mysql workbench에 데이터를 입력하면 입력한 모든 데이터가 계속 출력될 것이다.
이번 포스팅을 작성하면서 프론트엔드와 백엔드의 관계가 상당히 독립적이며, 어떻게 분업이 되는지 파악하기 좋은 경험이였다.
위에서 작성하신 대로 따라했으나 proxy 과정에서 404 에러가 발생하는 이유가 뭘까요..?