회고록/Project8 [42GG] LocalDateTime과 Timezone 이전 글 요약첫 번째 문제는 대회 스케쥴에 대한 Custom Validator에서 NullPointerException이 발생했습니다. @NotNull보다 Custom Validator가 먼저 실행되기 때문에 올바른 필드 값이 들어오지 않으면 null을 참조하게 되는 것이 원인이었습니다. 두 번쨰 문제는 Null Check하는 로직을 추가하면서 날짜 형식에 대한 Validation(@JsonFormat)을 추가했는데 해당 부분에서 데이터가 바인딩 되지 않는 문제가 추가로 발생했습니다. 프론트에서는 "yyyy-MM-dd'T'HH:mm" 패턴 형식으로 보내고, 백엔드에서는 "yyyy-MM-dd HH:mm" 형식으로 설정했기 때문이었습니다. 두 번째 문제를 해결하면서 Timezone과 관련된 문제점을 발견했.. 2024. 8. 30. [42GG] Custom Validator 실행 순서 1편: Custom Validator 실행 순서2편: LocalDateTime과 Timezone 문제 상황NullPointerException 발생프론트에서 API 테스트 중에 NullPointerException이 발생한다는 상황을 전달받았습니다. 로그를 확인해보니 리펙토링을 진행하면서 추가한 Custom Validator에서 NullPointerException이 발생하고 있었습니다. @Getter@AgendaCapacityValid@AgendaScheduleValid@NoArgsConstructor(access = AccessLevel.PROTECTED)public class AgendaCreateReqDto { // ... @NotNull @Future(message = "마감일은 현재 시간 이.. 2024. 8. 4. [42GG] 데이터 플로우 다이어그램 작성 데이터 플로우프로젝트를 진행하면서 분석/설계가 미흡하다는 것을 느꼈습니다. 대회와 팀 관련 로직에서 비즈니스 로직은 정리를 했지만, 대회와 팀 간에 데이터 플로우가 없어서 개발하는데 누락사항이 발생하거나, 비즈니스 로직을 코드에서 명확하게 표현하지 못하는 상황이 발생했습니다. 대부분 하나의 엔티티에서 발생하는 변경에 대해서는 잘 구현이 되었지만, 하나의 기능에 여러 엔티티의 값을 변경하는 로직에서 이런 실수들이 발생했습니다. 예를 들어서 대회가 취소되는 경우 참가 신청했던 모든 팀의 인원들의 티켓을 환불하는 로직, 대회가 시작했을 때 확정이 안된 팀들에 대해서 참가 취소 및 환불 처리 로직 등이 있습니다. 또한 비즈니스 요구사항이 계속 바뀌면서 커뮤니케이션이 힘들어졌습니다. 해당 기능을 구현하는 사람은 .. 2024. 7. 26. [42GG] 효율적인 TestFixture 관리 지난 회고에서 TestFixture에 대해 알게 되었고, 팀원들 모두 java-text-fixtures를 활용할 수있도록 gg-utils에 TestFixture를 생성하기로 결정했다. 추가적으로 현제 프로젝트에서 TestDataUtils라는 오직 하나의 클래스로 TestFixture를 모두 관리하고 있다는 문제점을 알게되었고, TestFixture 관련 논의에 이어서 추가적으로 어떻게 TestFixture를 효율적으로 관리할 수 있을지 논의했다. 먼저 현재 사용되고 있는 TestDataUtils의 가장 큰 문제점은 어떤 엔티티를 어디서 생성하는지, 즉 어떤 메서드가 존재하는지 파악하기 어렵다는 것이었다. 따라서 이를 해결하기 위해 먼저 TestDataUtils 분리해야한다. gg-utils ├── bui.. 2024. 7. 22. [42GG] UpdateDto와 TestFixture 42GG 프로젝트UpdateDto를 nullable 처리어제에 이어서 관리자 엔티티 업데이트 기능을 구현하다가 모든 필드를 @NotNull로 처리하기로 결정해서, NULL 예외처리를 하지 않고 진행중이었다. 하지만 테스트 코드를 작성하면서 결국 UpdateDto의 필드는 Nullable하게 처리하는게 좋을 것 같다는 결론을 내렸다. NULL 예외처리를 하지 않으면서 발생한 가장 큰 문제는 TestFixture를 구성할 때 DTO의 모든 컬럼에 대해 NULL이 아닌 실제 값을 넣어야한다는 것이다. public void updateLocation(Location location, List teams) { boolean conflictAgendaLocation = teams.stream().map(Age.. 2024. 7. 18. [42GG] JPA UPDATE 로직 (영속성 컨텍스트, @DynamicUpdate, 벌크 연산) 42GG 프로젝트프로젝트를 진행하면서 엔티티를 업데이트하는 기능을 맡아서 구현하고 있다. 업데이트 관련된 로직에서 JPA는 더티체킹을 통해 엔티티 변경을 감지한다.그리고 보통 엔티티는 setter를 구현하지 않고 명확한 의도를 가진 메서드를 구현한다. 하지만 엔티티에 필드가 많아지게 된다면 setter를 대신하는 메서드를 모든 필드에 대해서 구현해야하는 불편함이 있다. 이를 해결하기 위해서 여러가지 방법을 생각해보다가이번에 승수님과 함께 해당 부분에 대해서 심도 깊은 논의를 진행했다. 먼저 JPA에서 업데이트를 수행하는 로직은 다음과 같이 3가지가 있다. JPA 영속성 컨텍스트와 더티체킹을 사용해서 업데이트한다.@DynamicUdpate를 사용해서 특정 컬럼만 업데이트한다.JdbcTemplate이나 Sp.. 2024. 7. 17. 이전 1 2 다음