인스타그램과 같이 피드에 여러개의 이미지가 있고, 그 이미지들 중 첫번째 이미지만 가져오는 로직을 작성하고 있습니다. 첫번째 쿼리의 경우에는 보시는바와 같이 FeedImage 엔티티에서, 해당 feedImage의 feed의 id 기준으로 커서를 설정하였으며, (왜냐면 사용자에게 보여줄 때에는 피드 순으로 보여주어야 하기 때문에) writer가 user와 같은 경우 해당 이미지를 선택하는 방식입니다. @Override public List findByFeedWriterAndIdLessThanOrderByIdDesc(User user, Long cursorId) { List feedImageList = queryFactory .selectFrom(feedImag..
이전에 이어 페이지네이션 관련 로직을 최적화해보도록 하겠습니다.https://soyeonnnb.tistory.com/124 [Spring] 오프셋 기반 vs 커서 기반 페이지네이션현재 진행중인 Restagram 프로젝트는 프론트엔드에서 무한스크롤을 통해 사용자에게 피드 리스트를 보여줍니다.이러한 리스트는 한번에 모든 데이터들을 가져오지 않고 페이지를 분리해서 가져soyeonnnb.tistory.com 먼저, 쿼리 DSL을 쓰지 않은 결과부터 보도록 하겠습니다.쿼리DSL 안쓴거다음과 같이 단순히 jpa와 pageable 객체를 이용해 데이터를 가져와주었습니다. List feedList = feedRepository.findByIdLessThanAndWriterInOrderByIdDesc(cursorI..
프로젝트를 진행하며 같이 스터디하는 분께서 코드 리뷰 중에 DTO에 Record를 적용해보면 어떻겠냐는 의견을 제시해주었습니다. 그래서 이번 포스팅에서는 Record에 대해 살펴보고, 프로젝트 DTO에 Record를 적용해보고자 합니다.Record 란?Record는 자바 14, 15 에서 preview로 추가된 이후 16버전 부터 정식 스펙이 되었습니다.2024년 6월 12일 현재, 스프링부트2의 지원이 종료되며 스프링부트3을 이용해 프로젝트를 진행하고 있는데, 스프링부트3부터는 자바17버전 이상만 지원을 하다보니 이러한 Record에 대해 알아보면 더 좋을 것 같습니다. 🤔 등장 배경일단 기본적인 DTO를 생각해봅시다.DTO를 구현할 때에는 필드를 명시하고, 해당 필드와 관련있는 getter, set..
오늘까지 작성한 코드를 쭉 리뷰를 해보았습니다. 시작 깃허브 기록은 다음과 같습니다.https://github.com/soyeonnnb/restagram-api/tree/0593db7bf7f0ab782011318d47932a1467da6bc4 GitHub - soyeonnnb/restagram-apiContribute to soyeonnnb/restagram-api development by creating an account on GitHub.github.com 다음과 같은 리스트가 나왔습니다. 오늘부터 차근히 하나씩 리팩토링해보도록 하겠습니다. 22/261. ✅ jwt filer 익명필터 넣기 -> 검색해보기 .permitall() 되는지 (24.06.10)jwt filter 내 비로그인 시 shou..
현재 진행중인 Restagram 프로젝트는 프론트엔드에서 무한스크롤을 통해 사용자에게 피드 리스트를 보여줍니다.이러한 리스트는 한번에 모든 데이터들을 가져오지 않고 페이지를 분리해서 가져오게 됩니다. 오프셋 기반 페이지네이션현재는 오프셋 기반으로 데이터를 보여주고 있습니다. @Override @Transactional(readOnly = true) public List getFeeds(Long userId, Pageable pageable) { User user = userRepository.findById(userId).orElseThrow(() -> new RestApiException(UserErrorCode.USER_NOT_FOUND)); // 팔로우 리스..
사용자가 쿠폰을 발급하는 과정에서 동시성 테스트를 해보았습니다. 동시성 문제 발생현재 로직은 다음과 같습니다.사용자가 쿠폰을 발급할 수 있는 상태를 확인하여 발급합니다.@Override@Transactionalpublic void issueCoupon(Long customerId, Long couponId) { Coupon coupon = couponRepository.findById(couponId).orElseThrow(() -> new RestApiException(CommonErrorCode.ENTITY_NOT_FOUND)); Customer customer = customerRepository.findById(customerId).orElseThrow(() -> new RestApiE..
스프링과 OAuth 를 이용한 프로젝트를 진행중입니다. 구매자는 예약을 할 수 있는데, 이러한 예약 내역에 대해 카카오 캘린더로 일정을 추가해주려고 합니다.이 로직을 작성해주기 위해 다음 카카오 톡캘린더 docs를 참고하여 로직을 작성해주었습니다.https://developers.kakao.com/docs/latest/ko/talkcalendar/rest-api Kakao Developers카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.developers.kakao.com 전체적인 로직은 다음과 같습니다. 보기에는 어려울 수 있으니 하나씩 천천히 해보도록 하겠습니다. 액세스 토큰 저장 (스킵 가능)카카오 API..
피드 작성을 하면서 S3에 요청할 일이 많았습니다. 하지만, 반복문을 통해 S3에 요청을 보내면서 시간이 너무 많이 걸린다는 것을 API 요청만으로도 느낄 수 있었습니다. 그래서, 이 작업에 대해 비동기 처리를 하게 되었고, 그에 대한 테스트 결과입니다. 사용자는 20건의 요청을 한번에 보내게 되고, 한번의 테스트 당 10개의 이미지(최대 10개로 잡았습니다.)를 보내도록 하였습니다. 1. 단순 반복문 사용기존 반복문을 사용하였을 때의 결과입니다.다음과 같이 for문을 이용하여 데이터를 저장해주었습니다.최소 787ms, 최대 1266ms, 평균 911ms라는 시간이 걸렸습니다. 2. S3 요청 비동기 처리이미지 처리를 다른 서비스로 넘기면서, Async 처리를 해주었습니다.또한 초기 쓰레드의 수를 최대 ..
프로젝트를 하며, id를 AI로 두고 객체를 생성하는 경우가 많았습니다. 그런데 이번에 객체 생성 중 id가 null이라는, 처음보는 에러를 발견하게 되었습니다. 제 에러로그는 다음과 같습니다.더보기더보기Hibernate: insert into chat_member (chatroom_id, user_id) values (?, ?) 2024-05-31T18:33:49.735+09:00 WARN 22400 --- [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1048, SQLState: 23000 2024-05-31T18:33:49.735+09:00 ERR..