지난 주 리뷰 반영 내용

  1. LoginInterceptor 객체를 새로 만들지 않고 스프링이 주입하도록 수정

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    		LoginInterceptor loginInterceptor = new LoginInterceptor(jwtUtil);
    
    		registry.addInterceptor(loginInterceptor)
    

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    		registry.addInterceptor(loginInterceptor)
    
  2. jwt로 요청한 사용자가 누구인지 가져오는 로직이 중복되는 것을 loginInterceptor에서 처리 후 Controller에서 @RequestAttribute 어노테이션을 통해 사용자 객체만 받도록 수정

    ..., @RequestHeader("Authorization") String token) {
    
    		LoggedInUser loggedInUser = jwtUtil.extractedUserFromToken(token);
    

    ..., @RequestAttribute(LoggedInUser loggedInUser) {
    
    		// LoginInterceptor에서 사용자를 가져오는 로직 처리
    
  3. @JsonNaming 어노테이션을 사용해 클래스 레벨에서 매핑

    public class GithubToken {
    
        @JsonProperty("access_token")
        private String accessToken;
        @JsonProperty("token_type")
        private String tokenType;
        @JsonProperty("scope")
        private String scope;
    }
    

    @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
    public class GithubToken {
    
        private String accessToken;
        private String tokenType;
        private String scope;
    }
    
  4. JPAQueryFactory를 빈으로 등록하여 새로운 객체를 생성하지 않고 스프링으로부터 주입받도록 함

    /**
     * CategoryRepositoryImpl.class
     */
    
    public class CategoryRepositoryImpl implements CategoryRepositoryCustom {
    
        private final JPAQueryFactory queryFactory;
    
        public CategoryRepositoryImpl(EntityManager em) {
            this.queryFactory = new JPAQueryFactory(em);
        }
    

    /**
     * CategoryRepositoryImpl.class
     */
    
    public class CategoryRepositoryImpl implements CategoryRepositoryCustom {
    
        private final JPAQueryFactory queryFactory;
    
        public CategoryRepositoryImpl(JPAQueryFactory queryFactory) {
            this.queryFactory = queryFactory;
        }
    
    /**
     * JpaConfig.class
     */
    
    @Configuration
    public class JpaConfig {
    
        private final EntityManager entityManager;
    
        public JpaConfig(EntityManager entityManager) {
            
            this.entityManager = entityManager;
        }
    
        @Bean
        public JPAQueryFactory jpaQueryFactory() {
    
            return new JPAQueryFactory(entityManager);
        }
    }
    
  5. @Validated와 @Valid

    @PostMapping(consumes = {"multipart/form-data"})
    public ResponseEntity<CustomResponse<CreatePostResponseDto>> createPost(@Validated @ModelAttribute PostSaveDto postSaveDto, @RequestHeader("Authorization") String token) {
    

    @PostMapping(consumes = {"multipart/form-data"})
    public ResponseEntity<CustomResponse<CreatePostResponseDto>> createPost(@Valid @ModelAttribute PostSaveDto postSaveDto, @RequestAttribute LoggedInUser loggedInUser) {
    

  1. 조회 수 증가하는 로직의 동시성 제어 문제….

    pessimistic lock을 사용하면 성능이 많이 떨어질 것으로 예상됩니다.

    그래서 다른 방법을 생각한 것이

    findById 이후 update query를 보내는 것입니다. 하지만 이 방식은 데이터베이스에는 반영이 되지만 최종적으로 return 하는 객체에는 반영되지 않은 상태로 보내지게 됩니다.

    그래서 저희가 판단한 그나마 최선의 방법은

    update query 이후 findById + orElseThrow()를 사용하는데 현재 문제가 발생하지는 않지만 업데이트 후 객체 유무를 검사하는 로직 흐름이 어색하다고 생각이 듭니다. 어떻게 하는 것이 좋을 지 궁금합니다.