브라우저에서 Input 창에 데이터를 입력 후 "추가"와 같은 버튼을 누르면 자바를 통해서 DB에 데이터가 추가되는 예제.
프론트단은 리액트,
백엔드단은 인텔리제이와 Spring,
DB는 MySQL을 기준으로 쓰여졌습니다.
1.요약
프로트엔드
: 이름, 비밀번호, 전화번호를 입력하고 '추가하기' 버튼을 누르면
서버의 "/user" 엔드포인트로 Post 요청
백엔드
서버에서의 요청 처리
: 컨트롤러 클래스의 @PostMapping : POST 요청 처리.
@RequestBody : JSON데이터를 Dto객체로 변환 및 매개변수로 받음
DB 저장 및 쿼리 실행
Mapper 인터페이스의 메서드 호출(매개변수:Dto) -> .xml의 인터페이스 구현체(Mybatis)를 통해
DB에 접근, insert SQL문을 통해 DB에 저장
2.프론트엔드(React)
2.1 Html Form
먼저 간단한 데이터 입력창과 버튼을 만들어주고 Input에는 UseState 변수를 생성하고
상태가 변하면 각 항목의 값을 변경하도록 했다.
function Main(props) {
const [ userInput, setUserInput ] = useState({
userId:"",
username:"",
name:"",
phone:""
});
const handleUserInputChange = (e) => {
setUserInput({
...userInput,
[e.target.name]: e.target.value
});
}
return (
<div>
<div><input type="text" name='userId' placeholder='userId' onChange={handleUserInputChange} /></div>
<div><input type="text" name='username' placeholder='username' onChange={handleUserInputChange} /></div>
<div><input type="text" name='name' placeholder='name' onChange={handleUserInputChange} /></div>
<div><input type="text" name='phone' placeholder='phone' onChange={handleUserInputChange} /></div>
<button onClick={handleRegisterCode}>추가하기</button>
<button onClick={handleUpdateCode}>수정하기</button>
<button onClick={handleDeleteCode}>삭제하기</button>
</div>
);
}
그리고 실전(?)과 같이 유지보수성을 높이기 위해 파일을 여러개로 나누어서 서버에 데이터를 보내도록 한다.
2.2 api.js : Axios 인스턴스
import axios from "axios"
const api = axios.create({
baseURL: "http://localhost:8080"
});
export default api;
axios.create메서드를 만들고 Axios인스턴스를 생성했다. axios 객체는 서버와의 HTTP통신을 편리하게 해주는 JS 라이브러리로 이해하면 편하다.
스프링부트를 사용중이기에 포트번호는 8080으로 했다. 그리고 export 시켰다.
2.3 users.js : post요청 메서드
위에서 만든 api를 이용해 Get과 달리 http 메세지의 Body에 담아 전송하는 post 요청을 보내려고 한다.
import api from "../api";
export const registerUser = async (user) => {
return api.post("/user", user);
}
사용자 정보(user)를 파라미터로 받아와 body에 담고, "/user"엔드포인트로 Post요청을 보낸다.
비동기함수 Async를 사용했기 때문에 요청이 완료될때까지 대기하고, 서버로부터 받은 응답을 반환하게된다. 그리고 해당 메서드를 사용하도록 버튼에 클릭이벤트를 추가한다.
const handleRegisterCode = () => {
registerUser(userInput);
}
결과
백엔드 단을 만든지 않은 상태로 요청을 보내보았다. (당연히 되지않는다)
개발자 도구 네트워크탭을 열어 확인해보면 위와 같이 대기중이였다가,
커넥션 에러가 뜨는 모습을 볼수있다. 에러코드도 없다. 서버가 없으니까.
3.백엔드(자바)
3.1 라이브러리 등 설정
3.1.1 MyBatis
MyBatis Spring Boot Starter는 Spring Boot 프로젝트에서 MyBatis를 설정을 간편하게 해주는 라이브러리다.
MyBatis 설정 자동화, Spring Boot와 통합, 자동 데이터베이스 연결 관리, Spring Boot의 자동 구성, Spring Boot의 프로퍼티 파일 지원 ,스프링과 통합된 트랜잭션 관리 등의 기능을 한다고 한다 (펌)
그럼 MyBatis는 뭔가? MyBatis도 Java용 데이터베이스 접근 라이브러리로,
'매핑'을 통해 SQL을 DB에 전달하고, DB결과를 Java객체로 변환하는 일련의 상호작용을 도와준다.
이 기능 외에도 설정파일 사용, 동적SQL, 다양한 DB지원 등의 기능을 한다고한다. 생소한 용어가 있어서 설명은 여기까지. 대충 DB에 집중해서 작업할 수 있도록 잘 도와주는 라이브러리.
3.1.2 MySQL 커넥터
를 pom.xml에 dependency 추가.
MySQL Connector는 말그대로 MySQL과 연결하게 해주는 JDBC(Java Database Connectivity)드라이버로 DB와 Java간의 상호작용을 도와준다.
3.1.3 Mybatis : mapper.xml 작성
https://mybatis.org/mybatis-3/getting-started.html
링크에 보면,
부분의 코드를 복사.
SpringBoot의 resources 폴더에 mappers 폴더를 만들어주고,
user_mapper.xml파일을 만들어 주었다. 그리고 여기에
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.aws.spring_study.repository.UserMappers">
</mapper>
위와같이 작성해주었다. <mapper> 내부의 namespace는 아래에서 만들 파일의 경로이고,
<mapper> </mapper> 사이의 공간은 앞으로 쿼리문을 작성할 공간이다.
3.1.4 application.yml: Spring Boot 프로젝트의 설정.
학원 강의에서는 이 파일을 application.yml 로 리팩토링 후 사용하였다.
아마 인텔리제이 무료버전에서의 자동완성이 지원되지 않음이 이유였다.
글을 작성하며 찾아보는데, properties와 yml의 차이에 대해 잘 작성된 글이 있어 소개한다.
https://colabear754.tistory.com/90
여튼, 각 파일마다 표기방법이 다르므로, 본 포스팅에서는 .yml을 기준으로 작성되었다.
이러한 설정파일 덕분에 모든 파일마다 일일히 지정해주지 않더라도 중앙집중적으로 관리할 수 있다.
여기에서는 아래와 같이 작성해주었다.
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/spring_study
username: root
password: 비밀
mybatis:
mapper-locations:
- /mappers/*.xml
url과 username, 경로들은 예시로서 일부러 숨기지 않았다.
간단한 설명을 하자면,
-사용할 JDBC 드라이버의 클래스 이름을 지정
-데이터베이스 연결을 위한 JDBC URL을 지정
-데이터베이스에 연결할 사용자 이름 및 비밀번호를 지정
MyBatis 매퍼 XML 파일의 위치를 설정 : 위에서 작성한 쿼리문을 작성할 .xml파일의 위치.
4.DB 셋팅
형식상 대분류이긴 하지만 정말 별게 없다.
스키마와 테이블을 만들어주었다.
간단한 예시이기에 등록할 컬럼은 user_id, username, name, phone 으로 설정해주었다.
5.세팅은 끝, 이제 시작
5.1 인터페이스 생성
인터페이스를 만들어준다. 나의 경우 SpringBoot의 java폴더 하위의 'com.~'로 시작하는 하위폴더에
'repository' 폴더를 만들어주고 UserMappers 인터페이스를 만들어주었다.
@Mapper
public interface UserMappers {
public int saveUser(RegisterUserReqDto registerUserReqDto);
}
//참고
@NoArgsConstructor
@AllArgsConstructor
@Data
public class RegisterUserReqDto {
private String username;
private String name;
private String phone;
}
여기서 중요한것은, @Mapper 어노테이션이다. MyBatis 매퍼 인터페이스임을 의미하는데,
MyBatis에서는 이 어노테이션을 사용해, 이 인터페이스를 구현하는 SQL매퍼를 자동으로 생성한다.
모두 알겠지만 인터페이스는 클래스에서 구현을 해야한다. 하지만 Mapper 인터페이스에서는 xml에서 대신 구현한다.
클래스가 아닌 xml파일에서 구현하기때문에, 자바에서도 우리는 DB의 Workbench에서 쿼리문 작성하는 형태와 똑같이 작성할 수 있다.(필자의 이전 게시글 https://dogfoot-er.tistory.com/31)
에서 작성한 모습을 본다면 정말 혁신적이다.
5.2 쿼리문 작성
이제는 위의 인터페이스를 .xml파일에서 구현하면 된다.
위의 user_mapper.xml에서 쿼리문을 작성해주었다.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.aws.spring_study.repository.UserMappers">
<insert id="saveUser" parameterType="com.aws.spring_study.controller.dto.RegisterUserReqDto">
insert into user_tb
values (0, #{username}, #{name}, #{phone})
</insert>
</mapper>
이때 <insert id="~" parameterType="~"> 에서 주의할점은,
1.매퍼 인터페이스의 메소드 이름과 xml파일의 id는 같아야한다.
2.위 메서드는 추상메소드이므로, 파라미터도 그대로 가져가야한다.
- 따라서, 파라미터 매개변수 타입인 ReqDto파일을 참조시켰다.
또한 쿼리문의 ' #{username}, #{name}, #{phone} ' 부분은 MyBatis의 파라미터 매핑 문법으로,
RegisterUserReqDto 객체의 필드와 매핑된다. 그렇게 클라이언트로부터 받은 요청의 Body파일을 들고오고,
Mybatis의 매핑을 통해 DB에 쿼리문이 전달되며 데이터가 insert된다.
5.3 컨트롤러 클래스
위에는 요청을 받은 후의 일을 정의했다면, 이제는 서버가 요청을 받는 부분이다.
@RestController
public class UsersController {
@Autowired
private UserMappers userMappers;
@CrossOrigin
@PostMapping("/user")
public ResponseEntity<?> registerUser(@RequestBody RegisterUserReqDto registerUserReqDto) {
Integer count = userMappers.saveUser(registerUserReqDto);
return ResponseEntity.ok().body(count);
}
}
어쩌면 가장 핵심적이고 한 부분 한 부분마다 공부할 내용이 많은 부분인데,
본 포스트 주제를 고려해 자세한 내용은 별론으로 하고 간단하게만!
@RestController : Controller + RequestBody. 요청과 응답을 처리하는 클래스로 RESTful 웹서비스 컨트롤러.
@Autowired : 의존성 주입(Dependency Injection)을 사용, 위에서 작성한 인터페이스의 구현체를 주입함. 작성했다시피 위 매퍼는 DB와 상호작용을 함.
@CrossOrigin : CORS (Cross-Origin Resource Sharing) 정책을 허용하도록 설정. 허용을 해야 다른 도메인에서 이 API에 접근할 수 있다.
@PostMapping("/user") : /user 경로로 들어오는 HTTP POST 요청을 처리.
public ResponseEntity<?> registerUser(
@RequestBody Reg~Dto reg~Dto : 어노테이션을 통해 클라이언트가 요청한 Json데이터를 Reg~Dto 객체로 주입함
userMappers.saveUser(registerUserReqDto) : 인터페이스에서 만든 saveUser메서드를 호출, DB에 저장
return ResponseEntity.ok().body(count); : 상태 코드 200, count값을 반환함.
6.실행결과 확인
이상 간단한 프론트-백엔드-db연동 끝.
'Back-End > Spring' 카테고리의 다른 글
SpringBusinessLayer(Layered Architecture) 이해하기 (0) | 2023.07.28 |
---|