Project

[개인 프로젝트] wanted-pre-onboarding-backend

newny 2023. 10. 19. 14:46
반응형

❓ 본 프로젝트를 시작하게 된 이유

원티드에서 주관하는 교육형 인턴십에 참여하려고 보니 사전 과제가 있었다. 현재까지 배운 기술들을 다 적용시켜 과제를 제출하는 것을 목표로 이 프로젝트를 시작하게 되었다.
 

📆 작업 기간 & 인원

2023.10.06 ~ 2023.10.18 (13일)
1명 (토이 프로젝트)
 

🎤 프로젝트 소개

  • 기업의 채용을 위한 웹 서비스
  • 회사는 채용공고를 생성하고, 이에 사용자는 지원할 수 있음

 

✅ 출제자 요구사항

  • 요구사항(의도)을 만족시킨다면 다른 형태의 요청 및 리스폰스를 사용하여도 좋습니다.
  • 필요한 모델: 회사, 사용자, 채용공고, 지원내역(선택사항) (이외 추가 모델정의는 자유입니다.)
  • 위 제공된 필드명은 예시이며, 임의로 생성 가능합니다.
  • 회사, 사용자 등록 절차는 생략합니다. (DB에 임의로 생성하여 진행)
  • 로그인 등 사용자 인증절차(토큰 등)는 생략합니다.
  • Frontend 요소(html, css, js 등)는 개발 범위에 제외됩니다. (구현시 불이익은 없지만, 평가에 이점 또한 없습니다.)
  • 명시되지 않은 조건 또한 자유롭게 개발 가능합니다.

 

⏳ 요구사항 분석

  • 사용자 가입은 아이디, 이름, 거주지역, 사용기술, 희망포지션을 입력해야 합니다.
  • 사용자는 사용자 아이디(userId)로 식별합니다.
  • 회사 가입은 회사명, 국가, 지역을 입력해야 합니다.
  • 회사명은 회사 아이디와 별개로 가입 시 중복되지 않게 해야 합니다.(companyName -> unique)
  • 회사는 회사 아이디(companyId)로 식별합니다.
  • 채용공고는 채용공고 아이디(employId)로 식별합니다.
  • 채용공고는 회사가 등록하고, 여러 채용공고를 등록할 수 있습니다.
  • 채용공고 등록에는 회사아이디, 채용 포지션, 채용 보상금, 채용 내용, 사용기술을 입력해야 합니다.
  • 채용공고는 회사정보와 채용공고 정보를 유지해야 합니다.
  • 공고 수정은 회사 아이디 이외 모두 수정 가능합니다.
  • 공고 지원은 공고 지원 아이디(applyId)로 식별합니다.
  • 사용자는 한 개의 채용공고당 1회만 지원 가능합니다.
  • 공고 지원 시 지원한 사용자 정보, 채용공고 정보를 유지해야 합니다.
  • 사용자는 모든 채용공고를 조회할 수 있으며, 채용 공고 정보를 유지해야 합니다.
  • 사용자가 특정 공고를 조회했을 경우 회사정보와 채용공고 정보를 유지해야 하며, 해당 공고를 올린 회사의 다른 공고들의 아이디를 확인할 수 있어야 합니다.

 

🧪 요구사항 분석에 따른 개체 추출

노션 작성 내용

 

🔨 구현 과정

키워드

Java, Spring Boot, MariaDB, JPA, RESTful Api, JSON, ExceptionHandler, logging, Custom Exception, Test code, Validation
 

개체 추출에 따른 ERD 작성

 

일관된 Response 객체 format

 이번 프로젝트는 UI 없이 진행되는 프로젝트이므로 Response 되는 정보의 format이 일관돼야 사용자 입장에서 불편함 없이 사용할 수 있을 것이라 생각하였다.
따라서 공통 response 객체로 CommonResponseDto, ExceptionResponse 클래스를 추가하여 format을 일관되게 유지하였다.

정상로직(왼) / 예외정보(오)

 

API 구현 - RESTful API

RESTful API 구현을 위해 미리 노션에 작성을 해 놓고 그것을 토대로 개발을 진행하였다.

노션 작성 내용

 

JPA

JPA 기초강의를 듣고 있어서 사용법에는 익숙하지 않은 상태였으나, 역시 직접 해보는 것만큼 습득이 빠른 것은 없는 것 같다. 프로젝트를 진행하면서 기본적인 부분들은 구현할 수 있을 정도로 습득하였다.

 
Transaction

Test code와 Service 구현 부분에 Transaction 처리를 하였다.
 

Validation

 UI를 구현하지 않았기 때문에 더욱더 서버에서 유효성검사를 신경 써줘야 했다. 유효성 검사로 인한 예외가 발생했을 때 예외처리를 어떻게 해야 할지에 대해 고민했다. 이때 발생 할 수 있는 exception이 HttpMessageNotReadableException과 MethodArgumentNotValidException 두 가지였다. (validation, typeMissMatch) 핸들러에서 이 두 가지 예외에 대한 처리를 진행하였다.

 
Exception Handler 사용

 강의로만 보았던 Handler를 실제로 구현하려 해 보니 어렵게만 느껴졌다. 심지어 강의에서 본 Handler는 return타입이 modelAndView였기 때문에 현재 진행 중인 프로젝트와는 맞지 않았다. 그래서 구글링을 통해 해결해 나갔다.
 일단 어떠한 exception이 발생되는가에 대해 고민해 보았다. 위의 글에서 보았듯 유효성 검사에서 일어나는 두 종류의 exception (HttpMessageNotReadableException, MethodArgumentNotValidException)과 서버 내에서 일어나는 runtime exception 정도 발생이 될 것이고, runtime exception의 경우 사용자가 데이터를 잘못 보냈을 경우와, 서버 자체의 문제일 경우로 나뉜다고 생각했다.
 사용자가 데이터를 잘못 보냈을 경우는 다음과 같다. 유효성 검사를 통과해 들어온 값이더라도 데이터베이스에 그 값이 없다면 예외가 발생한다. 사용자가 잘못된 요청을 했음에도 불구하고 그 예외는 서버 내에서 발생되었기 때문에 500 에러를 반환시켜 준다. 데이터베이스를 조회해 봐야 발생할 수 있는 예외이기 때문이다.
 이 부분을 개선하기 위해 스프링 부트나 JPA 내부의 exception을 사용하지 않고 직접 커스텀한 exception을 사용했고, 커스텀한 exception들의 상위 exception을 만들어서 HttpStatus를 담을 수 있게 만들었다. 같은 exception이더라도 메시지와 상태코드를 다르게 설정할 수 있다.
 그리하여 exception이 발생할 경우 HttpStatus를 핸들러에서 바꿔주는 것이 아닌, exception이 이미 가지고 있는 상태코드를 Reponse객체로 전달될 수 있게만 도와주는 역할로 핸들러를 사용하였다.

 

Logging

@Slf4j 어노테이션 사용하여 에러발생 시 발생 위치와 원인을 로깅했다. 그 외 개발 시 필요한 로그는 debug 레벨로 남겼다.
 

Test code 작성

처음에는 Repository 단위로 Test 코드를 남겼으나, exception 발생 확인을 위해 Service 단위로 Test code를 작성했다.
Test code는 메소드당 정상로직일 때의 기댓값과 예외가 발생했을 때의 기댓값 두 가지 정도로 작성하였다.
 

Commit Convension

커밋 컨벤션이란 단어를 처음 들어봤다. 왜 지켜야 하는지에 대해 구글링 해 보았다. 협업 시 빠른 개발 속도와 수월한 코드리뷰를 위해 공통적인 커밋 메시지 규약을 정하여 사용하는 것이 Commit Convension이라고 한다.
개발자라면 깃허브 사용과 협업은 당연한 부분이기에 최대한 Commit Convension을 지켜 작성하며 연습하였다.

 

❗ 프로젝트를 마친 후

 현재 다른 프로젝트를 리팩토링 하다가 중단한 상태인데 그 이유가 볼륨이 커서 손봐야 할 곳도 많고, 궁극적 목표가 MyBatis를 JPA로 바꾸는 것인데 JPA 숙지가 안되어있는 상태 때문이었다. 이번 프로젝트를 통해서 JPA 사용방법도 꽤 익숙해졌고, 김영한 님의 Spring강의에서 이론적으로 습득했던 부분들(validation, transaction, exceptionHandler 등)을 구현해 볼 수 있어서 굉장히 뜻깊었다. 특히나 ExceptionHandler 사용에 굉장히 애를 먹었었는데, 구글링을 통해 차근차근 해결하니 어려울 게 없었다.
 아직 많이 부족하지만 이번 프로젝트를 통해 조금씩 나아가고 있음을 느꼈다.
반응형