회사 생활을 하면서 Spring Boot로 웹서버를 만들어 본 경험이 있다. 이를 바탕으로 팀을 꾸려 AWS + Spring Boot + Python 에 React를 곁들인 MAIB(Match for AI Bot)프로젝트를 구현하기로 하였다. 이 프로젝트는 Battle Ground라는 게임에서 친구들과 다같이 할 경우 자동적으로 밸런스에 맞는 팀을 생성하게 도와주는 프로젝트이다. 먼저 Spring Boot를 통해 Oracle과 Python, React를 통신하는 API 서버를 만들어 보려 한다.
Spring boot 2.6.8 + Gradle 7.4.1 + Java 11 의 스펙으로 만들고 DB는 Oralce XE 11G R2버전으로 구현하려 한다.
먼저 Spring Initializr를 통해 Gradle 기반의 Spring Boot 프로젝트를 생성했다. 이름은 mas(Maib Api Server)로 지었다. 프로젝트를 생성했을 때 가장먼저 하는 작업은 java버전 및 gradle 버전을 확인 설정하는 과정을 한다. 이후 Maven Repository (https://mvnrepository.com/) 에서 필요한 라이브러리들을 추가하였다. 처음에 프로젝트를 만들 때 Spring Ititializr에서 추가 할 수 있지만, 어디에 사용되는지도 모르고 추가하는것보다는 필요한 라이브러리들을 찾아 그때 그때 추가하는 것을 선호한다(이게 공부에 더 좋은것 같다)👋. 나는 아래와 같이 라이브러리들을 추가하였다.
여기서 조금 헤매었던것이 롬복 관련설정이었다. 처음에는 compileOnly 'org.projectlombok:lombok:1.18.12'
만 추가해서 사용하는데 자꾸 Getter가 동작을 안하여 에러가 발생하였다. 그래서 찾아보니 Gradle 5버전 이상에서는 annotationProcessor 'org.projectlombok:lombok:1.18.12'
도 같이 추가해줘야 한다는것을 알고 같이 추가해줬다!
이후 나머지는 Oracle, JPA, MYBATIS관련 설정이다.
이 프로젝트는 AWS EC2환경에 Oracle을 올려 둔 상태이다. 따라서 application.properties에 아래와 같이 추가하였다. []에 들어가는 항목은 미리 설정해둔 Oracle 및 AWS설정에 맞게 입력하면 된다.
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:[HOST]:[PORT]/XE
spring.datasource.username=[USSERNAME]
spring.datasource.password=[PASSWORD]
보통 프로젝트를 생성하고 구조를 잡는데는 많은 스타일이 있다. 나도 처음 프로젝트를 진행 할 때에는 아래와 같이 프로젝트 구조를 잡았다.
project
controller
HomeController
BoardController
MemberController
...
model
HomeModel
BoardModel
MemberModel
...
repository
HomeRepositroy
BoardRepositroy
MemberRepositroy
...
service
HomeService
BoardService
MemberService
...
지금 다시봐도 정신이없다. BoardController를 찾으려면 controller 패키지를 열어 찾아야하며 지금은 3개만 보이지만 무수히 많은 컨틀로러가 있다고 하면.. 벌써 어지럽다..🤮
그래서 다음과 같이 프로젝트 구조를 변경하고 지금도 이 구조를 유지하며 사용하고 있다. 장점은 훨씬 깔끔하며 기능에 맞는 패키지를 찾아 그 안에서 해결할 수 있다.
project
home
controller
HomeController
model
HomeModel
repository
HomeRepositroy
service
HomeService
board
controller
BoardController
model
BoardModel
repository
BoardRepositroy
service
BoardService
member
controller
MemberController
model
MemberModel
repository
MemberRepositroy
service
MemberService
...
먼저 테스트를 위해 TEST라는 스키마 안에 HELLO라는 테이블에서 정보를 가져온느 api를 만들어 보려한다. 컨트롤러는 아래와 같이 구현을 하였다.
(오 그냥 기본이네~ 그런데 ResponseEntity는 뭐지..?)
나도 처음에 ResponseEntity가 뭐지 생각했다. 그냥 ResponseDto를 넘겨 주면 안되나 싶었다. 정답은 없다. 다만 ResponseEntity를 사용하는 이유는 명확하다.
먼저 ResponseEntity는 httpentity를 상속받아 HttpStatus상태코드도 함께 넘겨준다. 내가 이 상태코드도 같이 넘겨주려 하는 이유는 Exception을 관리 하기 위해서이다. 프로젝트를 진행하다 보면 Exception관리가 상당히 중요하다. 그래서 이 프로젝트에도 따로 BizExceptionCode를 구현하여 코드 관리를 해주었다.
Model에는 Entity, Response, Request 세가지를 사용하는데 이번에는 Request를 제외한 두가지만 사용하였다.
Entity에는 아래와 같이 스키마와 테이블을 명시해주었고, 그옆엔 Response이다.
JPA를 사용하기 위해 아래와 같이 Repository를 추가하였다.
그리고 JPA를 사용하면 쿼리를 잘 보지 않게 되는데 이를 방지하고 application.properties에 아래와 같이 추가하여 쿼리문을 log에서 볼 수 있게 하였다.
서비스 단은 아래와 같이 구현아였다. 여기서 중요한 부분은 findById에서 orElseTrow
를 통해 예외 관리를 해준 부분이다. 해당 코드를 보면 BizException이라는 커스텀 클래스를 통해 예외처리를 하고 있다.
Exception관리를 하기위해 아래 두 클래스를 생성하였다.
BizException에서는 RuntimeException을 상속받아 구현하였다.
BizExceptionCode에는 status, code, message를 통해 커스텀하게 에러관리를 할수 있게 구현하였다.
이와 같이 처음에 프로젝트 구조를 잡는일은 매우 중요하며, 시간을 들일 가치가 충분히 있다. 마지막으로 위에서 작성한 api의 테스트 결과이다.
프로젝트 정말 멋지네요 MAIB 프로젝트 구경 할 수 있을까요?