SpringBoot를 간단히 공부를 해보고 ‘이제는 프로젝트를 개발하면서 부족한 부분들을 채워야 겠다’
라는 생각으로 React+SpringBoot를 이용한 프로젝트를 개발하려는데..
기획부터 DB설계, 디자인, 개발, 배포 등등.. 아직 혼자 프로젝트를 개발해 본적이 없는 저에겐
너무 막막하달까..
그래서 회사 선임분께 조언을 구하니 “처음부터 프로젝트 전부 다 개발하지말고 기능 하나씩 해봐~ 로그인 해보면 좋겠네”라고 해주셔서
역시.. 시니어는 다르군..
그래서~ 프로젝트 개발하기 전에 기능들을 하나씩 개발해보려 합니다~!
먼저 로그인 기능을 구현하면서 Spring Security 프레임워크를 공부해 보겠습니다!
[구현중인 프로젝트 깃 주소]
시작이 반이다..
19버전
3.5.0
21
VScode
, IntelliJ
리액트 프로젝트는 아시다시피 간단하게 생성이 가능합니다.
최근에는 npm 명령어말고 다른 방법으로도 생성한다고 하니 검색해 보시면 좋을 것 같습니다.
프로젝트를 생성할 경로에 가서 명령어를 쳐줍니다.
npx create-react-app frontend
그랬더니 저는 이런 명령어가 떠서
You are running `create-react-app` 5.0.1, which is behind the latest release (5.1.0).
We recommend always using the latest version of create-react-app if possible.
The latest instructions for creating a new app can be found here:
https://create-react-app.dev/docs/getting-started/
확인해 보니 현재 사용 중인 create-react-app(CRA)의 버전이 최신이 아니라고 안내해 주는 것이라고 합니다.
그래서 아래 명령어로 프로젝트를 생성하였습니다.
npx create-react-app@latest frontend
프로젝트를 생성한 후 npm start
를 해서 올바르게 프로젝트가 동작하는지 확인합니다.
다음으로 SpringBoot 프로젝트를 생성해 줍니다.
부트 프로젝트에 대한 설명을 잘해주신 블로거가 있어서 참고하시면 좋을 것 같습니다.
[프로젝트 생성 참고]
프로젝트를 생성하고 설정 부분은 일전에 작성했던 내용을 참고하였습니다.
[프로젝트 설정 참고]
설정을 마치고 빌드 후 각자의 Application.java
파일을 실행하여 올바르게 실행되는지 확인합니다.
뭔가 잘못된 것처럼 보이지만 단순히 정적 리소스 경로에 index.html과 같은 파일이 없어서 나타나는 화면입니다. 걱정없이 기기
React, SpringBoot 프로젝트를 각각 생성하였다면 두 프로젝트를 연동시켜야 합니다.
이때 반드시 넣어줘야 하는게 CORS 설정입니다.
하나의 로컬에서 두 개의 서버를 구동시킬 때 서로의 포트에 접근하기 위해서 설정을 해야한다..?
[CORS 설정하기 참고]
위 CORS 설정하기 참고 블로그에 4번 CORS 설정하기를 보면 WebMvcConfigurer
인터페이스를 구현하는 부분이 나오는데 해당 부분이 이해가 잘 가지 않아 GPT와 [WebMvcConfigurer 구현 참고] 블로그를 참고하였습니다.
블로그를 참고하면서 예제를 하나씩 만들어보기 귀찮을 것 같은 분들을 위해 간략하게 CORS 설정하는 방법을 알려드리겠습니다.
먼저 frontend, backend 폴더 구조를 참고해 주세요~!
# backend
login/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── login/
│ │ │ ├── config
│ │ │ │ ├── WebConfig.java
│ │ │ ├── controller
│ │ │ │ ├── LoginController.java
│ │ │ ├── model
│ │ │ │ ├── UserInfo.java
│ │ │ └── LoginApplication.java
│ │ └── resources/
│ │ └── application.yml
├── build.gradle
├── settings.gradle
# frontend
frontend/
├── node_modules
├── public
├── src
│ ├── components
│ │ ├── views
│ │ │ └── home
│ │ │ ├── MainHome.js
│ ├── App.js
├── package.json
1.리액트 포트 설정: 3000
리액트 앱이 3000 포트로 실행되도록 지정합니다.
기본적으로 리액트는 3000 포트를 사용해서 실행합니다. 다른 포트를 원할 경우 아래 설정으로 변경할 수 있습니다.
/* package.json */
"scripts": {
"start": "PORT=3000 react-scripts start",
...
}
8085
# application.yml
server:
port: 8085
servlet:
context-path: /login # 애플리케이션 기본 경로를 '/login'으로 고정, 모든 URL 경로가 '/login'으로 지정됨
spring:
application:
name: login
package.json
에서 주석을 다는 방법이 따로 존재하진 않고, 아래처럼 __...
과 같은 방식으로 주석을 처리한다고 하여 한 번 해봤습니다 :)/* package.json */
"__comment2": "프론트 개발환경에서 API 요청을 백엔드(SpringBoot)로 우회(Proxy)시키기 위한 설정",
"proxy": "http://localhost:8085",
http://localhost:3000
에서 백엔드에 요청할 수 있도록 허용해 주었습니다.WebConfig.java
클래스 생성
/*
SpringBoot는 기본적으로 @SpringBootApplication 어노테이션이 붙은 클래스가 위치한 패키지와 그 하위 패키지들을 스캔하여
@Configuration, @Component, @Service, @Repository 등의 어노테이션이 붙은 클래스를 자동으로 감지하고 설정합니다.
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 모든 경로에 대해
.allowedOrigins("http://localhost:3000") // 허용할 출처(React 개발 서버)
.allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드
.allowedHeaders("*") // 허용할 헤더
.allowCredentials(true); // 쿠키, 인증 정보 허용 여부
}
}
MainHome.js
컴포넌트 생성
import React, { useEffect, useState } from 'react'
const MainHome = () => {
const [data, setData] = useState({});
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('/login/getUserInfo'); // GET요청
const data = await response.json();
console.log("### 데이터 확인 ### \n", data);
setData(data);
} catch (error) {
console.log("FETCH ERROR ", error);
}
};
fetchData();
}, []);
return (
<div>
<h1>등록된 회원정보</h1>
{data && (
<div>
<p>Email: {data.email}</p>
<p>Name: {data.name}</p>
</div>
)}
</div>
)
};
export default MainHome;
MainHome 컴포넌트
를 호출하도록 App.js
수정
import './App.css';
import MainHome from './components/views/home/MainHome';
function App() {
return (
<div className="App">
<MainHome />
</div>
);
}
export default App;
LoginController.java
, UserInfo
클래스 생성
package com.example.login.controller;
import com.example.login.model.UserInfo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
//@RequestMapping()
public class LoginController {
@GetMapping("/getUserInfo")
public Object getUserInfo() {
UserInfo userInfo = new UserInfo();
// ##### 예제 데이터 반환 #####
userInfo.setEmail("YoonHan0@naver.com");
userInfo.setName("한영윤");
return userInfo;
}
}
아직 DB까지는 연결하지 않았지만 개발을 진행하면서 DB 연결은
[DB연결 참고]블로그의 3번 데이터베이스 생성 부분을 참고할 예정입니다.