[프로젝트]원티드 프리온보딩 과제 수행 04 프로젝트 회고
프리온보딩 인턴십 수행과제
프로젝트는 🚀여기🚀에서 확인할 수 있다.
나의 첫 스프링 프로젝트가 묵묵부답으로 마무리되었다… 그치만 불합격이어도 알려주신다고 했잖아요….
처음에는 허탈함과 속상한 마음이 너무 컸지만, 프로젝트를 진행하면서도 해결하지 못한 점이나 부족한 점이 많은 걸 스스로도 느꼈기 때문에 충분히 예상한 결과이긴 했다. 마감 기한에 임박해 제출했기 때문에 완성도도 높지 않았고, 이런 저런 점들이 부족하지만 코스를 따라 가며 배우고 성장할 수 있지 않을까? 라는 안일한 생각을 가졌던 것 같기도 하다.
그렇지만 강의를 들으며 예제 코드만 따라 치다가 (비록 소규모이지만) 스스로 하나의 프로젝트를 설계부터 구현까지 해낸 경험 만으로도 얻을 수 있는 게 많았고, 코스에서 배울 실무 경험보다도 나의 얼렁뚱땅 프로젝트에서 먼저 해결하고 배워 나가야 할 점이 많기 때문에 오히려 좋다! 떨어져서 이렇게 본격적으로 공부해볼 시간도 있고 좋지 뭐! 불합격시켜주셔서 감사합니다(?)
마침 천재만재 개발자 최야호님께서 코드 리뷰를 도와준다고 하셔서 이 기회에 좀 더 공부해 보자는 마음가짐으로 프로젝트를 보완해 보는 시간을 갖기로 했다.
우선 내가 생각하기에 프로젝트에서 가장 미흡했던 점은 크게 두 가지로 정리할 수 있을 것 같다.
설계 부실
프로젝트가 처음이어서 어디서부터 어디까지 설계를 해두어야 하는가? 에 대한 감이 없었다. 사실상 어플리케이션 구성이나 API 설계도 프로젝트 진행 중에서야 어느 정도 윤곽이 잡혔고, 데이터 모델링이나 계층 구조도 모호하게 기획해 두어 프로젝트 중간에 재차 수정하기도 했다. 이 도메인이 어떤 역할과 책임이 있는가? 라든가 이 작업이 어느 단계에서 이루어져야 하는가? 와 같은 고민이 부족했기 때문에 객체나 객체 간의 관계, 서비스와 레퍼지토리의 역할에 대한 기준이 명확히 잡혀 있지 않았고, 이러한 점들이 코드를 작성할 때에도 일관성 없는 코드나 오류로 여실히 드러났던 것 같다.
논점에서 벗어난 풀이
해당 프로젝트에서는 프론트엔드 요소를 평가하지 않음을 명시해 주었다. 그러나 JSON 타입, 포스트맨 사용 등이 익숙하지 않기도 했고 개인적인 욕심으로 불필요한 부분에 시간과 에너지 소모가 컸던 것 같다. 서버를 매번 가동하여 테스트하고 고쳐나갈 시간에(당연히 부적절한 방식임을 알지만 테스트 코드 작성에 미숙했다…) 테스트 코드를 작성해보고 설계를 보완하고 코드를 리팩터링 했어야 했다..
이왕 미숙한 거 보기 좋게라도 만들어보자. 라는 생각에 낸 욕심이었던 것 같은데 결과적으로는 보기도 안좋고 부실공사로 와르르 무너지기 일보 직전이었던 거지….
그리고 😍야호😍씨의 피드백을 정리해 보면 이렇다.
마이너스 요소 / 아쉬운 점
- README 파일
- README 파일을 보다 간결하게 작성할 필요가 있다. 토글을 이용해 전체적인 흐름을 파악하기 용이하게 해주는 것도 방법이다.
- 클래스 다이어그램은 ERD의 일부일 뿐이다. ERD를 따로 그려볼 필요가 있으며, 현재 클래스 다이어그램에서도 DTO는 불필요하다.
- 필드명과 용어 명세해주자
- 설계
- 도메인과 엔티티를 따로 생각하자
- 관심사끼리 분리하고 확장성을 고려해보자. (그러나 확장성을 지나치게 고려하는 것은 지양하자.)
- 컬럼명은 일관성 있게 작성하고, 불필요한 중복은 삼가자. (채용 공고 자체만으로도 이미 ‘채용’이라는 의미가 담겨 있다. jobPosition -> position으로 바꿔주어도 충분히 이해 가능하다. jobPosting.getPosition())
- 서비스 단위와 도메인 단위는 다르다. 기준은 내가 설정해야 한다.
- DB 선택
- H2 데이터베이스보다는 실제 많이 사용하는 mysql이나 maria db를 사용하는 것이 더 유리하다.
- H2 는 보통 테스트 데이터베이스로 사용한다.
- 코드 컨벤션
- if-else 가 지나치게 많다. 가능하면 1 depth로 설계하자.
- for문은 stream으로 바꾸는 연습을 해보자.
- 같은 의미의 변수가 여러 개 있는 경우가 있다. 변수명을 혼용하는 것을 삼가고 불필요한 변수의 재정의도 줄이자.
- null의 경우 이를 처리해주는 방식이 일관적이지 않다. 예외를 터뜨리든 상태를 반환하든 통일시키자.
- 불필요한 어노테이션이나 함수 정의, import를 삼가자. 여기에 getter와 setter가 꼭 필요한가? 를 고민해보자.
- @GeneratedValue 에서는 default 값이더라도 명시해주는 게 좋다.
- 구현체가 언제 변경될 지 모르므로 변수명에 list 등의 타입을 넣는 것은 삼가자.
- 네이티브 쿼리의 경우 DB와 어플리케이션 중 어느 쪽이 성능이 더 좋은 지를 고민해보자.
- data.sql에서 ID로 인해 발생하는 문제는 @GeneratedValue 의 strategy를 identity로 변경해보자.
- DTO와 DTO를 매핑하는 메서드, applyJob 메서드는 서비스 위치에 있는 것이 적절하다. jobPostingList 또한 Company 보다는 레퍼지토리 위치가 적절할 것 같다. 나만의 기준을 세워야 한다!
Test Code 미작성
- 도메인
- 단위 테스트
레포지토리 테스트 (JpaRepository를 extends하는 경우 주로 생략한다.)
- 서비스
- 레포지토리를 mock
- 레포지토리까지 연결해 통합테스트 (spring boot test)
- 컨트롤러
- mockMvcTest
- spring boot test
- 인수 테스트(시나리오 테스트) -> restTemplate, WebClient
- 사용자의 시나리오를 써놓고 테스트 ex)회원이 가입해서 글을 조회했을때 어떤 목록이 노출된다.
- 비용이 많이 드나 한번쯤 해보는 것도 좋을 것 같다.
- 도메인
- Commit Convention
- 작업하고 있는 작업을 롤백할 수 있는 단위로 버전 관리하는 것이므로 커밋 컨벤션을 해야 Git을 쓰는 의미가 있다.
- 컴파일이 깨지지 않는, 동작되는 가장 작은 단위로 커밋하자.
- 커밋 단위가 어떤 흐름으로 어떻게 코드를 짜나갔는지를 보여주는 지표가 된다.
디테일하게 리뷰해 준 덕분에 구체적으로 어느 부분이 부적절한 지 확실하게 알 수 있었고, 정말정말 많이 배웠습니다.. 감사합니다 스승님… 최야호씨의 가르침과 피드백을 바탕으로 아래 부분들을 공부하고 계속해 채워나 갈 예정이다. 지켜봐주세요!
리팩터링
글이 길어질 것 같아 05 프로젝트 리팩터링 게시물에서 따로 다루고자 한다.
테스트 코드 작성
더 공부할 것
@RestController vs @Controller
TDD