[우아한테크코스 4기] 220630 F12 개발일지

Jihoon Oh·2022년 6월 30일
0

우아한테크코스 4기

목록 보기
13/43
post-thumbnail

오늘 진행한 일

오늘도 그저께와 마찬가지로 5인 페어를 진행했다. 1차 데모 데이까지의 스프린트가 끝나기 전 까지는 계속해서 5인 페어를 하면서 코딩 컨벤션에 적응하며 팀원들 간에 개발 속도를 맞춰가고, 1차 데모 데이 이후 부터는 기능 별로 나눠서 각자 개발을 진행하고 Pull Requests를 활용한 코드 리뷰를 통해 프로젝트를 진행해 나갈 것이다.

Review 도메인에 대한 Create 기능 구현 (완료)

Review 도메인에 대한 Create 기능 구현을 완료했다. CRUD 중 C를 완성하는데는 크게 어려움이 없었는데, 굳이 고려해 볼 만한 사항이 있었다면 테이블 상으로 Review는 Product(현재 상황에서는 Keyboard)와 연관관계를 맺어야 하는 상황인데, JPA를 사용함에도 불구하고 필드로 Product 객체를 가지는 것이 아니라 Product의 id값을 가지도록 하는 사항이었다.

나는 우선은 Product의 id 값을 필드로 가지는 것을 주장했는데,

  • Review의 식별자로 productId가 필요하기는 하지만, Review를 조회해 올 때 Product를 함께 조회해 올 일은 없다. 다시 말하자면 Review → Product로 객체 그래프 탐색을 사용할 일이 없다.
    • 만약 사용할 일이 생긴다면 그 때 가서 id 대신 엔티티를 매핑해 주면 된다.

라는 이유에서였다. 실제로 사이드 프로젝트를 진행하면서 우선 id를 넣어놓고 객체 그래프 탐색을 사용할 필요가 있을 때 엔티티로 교체해 주었는데 훨씬 효율이 좋았다고 생각했다.

처음에는 "JPA를 쓰니까 당연히 객체를 필드로 가져서 연관관계 매핑을 해줘야 하는 것 아니야?"라던 팀원들도 엔티티 대신 식별자 값만 필드로 가지는 방안에 동의했다.

Review 도메인에 생성 시간 필드 추가

팀원들이(FE, BE 모두) 함께 api 구조를 논의한 결과, 리뷰를 조회할 때 정렬 기준을 최신순, 평점순 두 가지의 경우를 두기로 결정했다. 처음에 나는 최신순 정렬을 id의 역순(당연히 먼저 생성된 순서대로 id가 부여될테니 id의 역순이면 최신순이라고 생각)으로 정렬하려고 생각했다. 그런데 팀원들 사이에서 이런 의견이 나왔다.

최신순 정렬은 비즈니스 로직인데 비즈니스와 관련 없는 대리 키를 사용해도 될까?

지금은 auto_increment 옵션을 쓰니까 id 역순이 최신순이지만 영원히 그걸 보장할 수 있을까?

먼저 id 역순이 최신순을 영원히 보장하느냐는 측면에서는 물론 영원히 라고 단정지을 수는 없지만 바뀔 일이 거의 없다고 생각해서 문제가 크게 없지 않을까라고 생각했다. (예를 들어 시퀀스를 사용하는 다른 DB로 바꾸더라도 생성 순서대로 id를 부여받을테니까) 하지만 비즈니스와 관련 없는 대리 키로 비즈니스 로직을 다룬다는 점이 괜찮을까 라는 의견에는 충분히 납득할 수 있었다. 또한 생각해봤을 때, 생성 시간을 가지고 있는 것이 일종의 로그 역할을 할 수도 있다는 생각도 들어 생성 시간 값을 주고 해당 값으로 정렬하는 것이 좋겠다는 팀원들의 의견에 동의했다.

당시 Review 테이블 설계에는 생성 시간에 대한 컬럼이 들어있지 않았으므로, Review 도메인에 생성 시간 필드를 추가할 필요가 있었다. 다행히 JPA에는 생성 시간을 편하게 매핑할 수 있는 기능이 있다.

@CreatedDate
@Column(name = "created_at")
private LocalDateTime createdAt;

@CreatedDate 어노테이션을 사용하면 LocalDateTime, LocalDate 타입에 엔티티의 생성 시점을 매핑할 수 있다. (처음 본 크루들도 있었는데 오오 역시 JPA 하면서 신기해했다.) 나도 자주 써본 어노테이션은 아니었는데, 정확히 지금 상황에 적용할 수 있을 것 같다 새로 createdAt 필드를 만들어주고 어노테이션을 매핑해줬다.

하지만 문제가 발생했는데, 실제 정렬 기능을 만들고 보니 createdAt을 기준으로 한 정렬이 먹히지 않는 문제가 발생했다. 트러블 슈팅 끝에 이유를 찾아냈다. createdAt 값에 null이 들어가고 있었다.

@EnableJpaAuditing@EntityListeners

두 가지 어노테이션을 사용하지 않아서 생기는 문제였다. 하나는 @EnableJpaAuditing이고, 하나는 @EntityListeners였다. @EntityListeners는 엔티티 클래스에 붙이는 어노테이션으로, 이벤트가 발생할 때 마다 특정 로직을 실행시키도록 지정하는 어노테이션이다. 코드에서는 @EntityListeners(AuditingEntityListener.class)로 매핑해주었는데, callback으로 지정된 AuditingEntityListener 클래스 내부에 touchForCreate, touchForUpdate 메서드가 있어서 엔티티의 생성과 수정 시간을 기록할 수 있게 해준다. 때문에 @CreatedDate@UpdatedDate를 사용하려면 @EntityListeners(AuditingEntityListener.class) 어노테이션을 클래스에 붙여주어야 한다.

하지만 단지 이 어노테이션을 붙이기만 하면 여전히 null 값이 들어간다. 해당 클래스에 audit 기능을 사용할 수 있도록 해줬지만 전체 애플리케이션은 JPA auditing을 사용하고 있지 않기 때문이다. 그래서 해당 기능을 사용할 수 있도록 main 메서드에 @EnableJpaAuditing 메서드를 붙여주었다.

이 과정을 거치고 나니 정상적으로 @CreatedDate의 값이 매핑되고, 정렬도 정상적으로 진행됨을 확인할 수 있었다.

페이징

F12 프로젝트는 모든 목록 조회에 대해 무한 페이징 기능을 적용하기로 결정했다. 때문에 목록 조회 시 일반적인 조회 메서드처럼 List의 형태로 받아오는 것이 아니라 Slice 형태로 데이터를 받아올 필요가 있었다.

페이징의 결과물은 세 가지 타입으로 받을 수 있는데, 각각 Page, Slice, List다. List 타입은 당연히 순수한 자바의 List 객체를 말한다. 페이징을 경험해보지 않은 크루들은 Page와 Slice 타입을 처음 보는 듯 했는데, 둘에는 미묘한 차이가 있다는 점을 설명했다.

  • Page
    • 데이터의 총 개수(totalElements), 다음 페이지의 존재 여부, 페이징해서 가져온 데이터를 확인할 수 있다.
    • 데이터의 총 개수를 가지고 있기 때문에 조회 시 count 쿼리를 한번 더 실행한다.
  • Slice
    • 다음 페이지의 존재 여부와 페이징해서 가져온 데이터는 확인할 수 있으나 데이터의 총 개수에 대한 정보를 가지고 있지 않다.
    • count 쿼리 대신 limit + 1조회를 통해 마지막 페이지인지 정보를 확인한다.
    • 때문에 Page에 비해 아주 조금의 성능 상의 이점이 있다.

우리 프로젝트는 스크롤링을 통한 무한 페이징 방식으로 페이징을 처리하기 때문에, 굳이 전체 데이터 개수를 알 필요가 없다. 그저 다음 페이지가 존재하는지, 아니면 현재 조회한 페이지가 마지막 페이지인지만 알면 된다. 그래서 페이징이 적용된 조회 메서드에서 Slice를 반환하기로 결정했다.

오늘 발생한 이슈

해결한 이슈

  • 커밋 메시지의 커밋 타입에 대한 확실한 정의가 존재하지 않음
    - 팀원들과 의논을 통해 상황에 따른 커밋 타입 정의

해결되지 않은 이슈

  • Review 도메인의 평점(rating) 값은 1~5 사이의 정수만 들어가야 하는데 도메인 생성 시 검증하지 않음
    • 검증 로직을 작성하고 검증 실패시 발생할 exception 클래스의 작성 필요
    • 검증 로직이 정상적으로 작동하는지 테스트 필요(현재는 Review 도메인의 테스트 존재 x)

내일 목표

Review 도메인에 대한 조회 기능이 아직 완성되지 못했다. 때문에 최우선적으로 Review 조회 기능을 완성하고, 여력이 된다면 Keyboard 도메인의 조회에서 아직 만들지 못한 Keyboard 목록을 받아오는 기능 작업을 시작하려고 한다.

또한 GitHub Actions를 이용해 Pull Request가 open되면 자동으로 빌드를 진행해 보는 스크립트를 짜기로 했는데, 해당 부분에서 아직 이해가 되지 않는 부분이 있어 좀 더 공부해보고 스크립트를 작성하는 것을 목표로 한다.

profile
Backend Developeer

1개의 댓글

comment-user-thumbnail
2022년 6월 30일

우와 이거 너무 꿀잼이네여
CreatedAt과 JpaAudit 관련 잘 담아갑니다!!!
commit type convention도 너무 깔끔하고요
F12 짱짱맨~~~😆👍

답글 달기