본문 바로가기

전체 글72

댓글 조회 리팩토링중 - feat.인덱스 전에 게시글들을 보았으면 내가 얼마나 멍청하게 댓글들을 불러왔는지 알 수 있다.사실 블로그에 글을 쓰고 인지를 하여 그냥 모든 개발이 끝나고 리팩토링 해야지 했는데 자꾸 걸려서 미리 리팩토링 하게 되었다. 전에는 댓글을 페이지네이션 하나 없이 모든 댓글 + 대댓글을 다 불러왔다. 사실 소량의 데이터면 상관은 없는데사용자의 사용성은 나눠서 보여주는 게 낫기 때문에 한 번에 다 보여주는 것보단대댓글은 숨기고 보여주고 할 필요가 있다고 생각했다. 페이지네이션은 잘 마쳤다!(페이지네이션에 대한 내용은 전에 게시글 페이지네이션 했던 글 봐주세요) 이제 댓글에 대댓글이 있는지 정보를 클라이언트에 보내줘야 클라이언트가 -대댓글 더보기..- 뭐 이런 UI를 달아줄 수 있기 때문이다. 백엔드 쪽에선 단순히 true/.. 2025. 6. 18.
게시글 조건 조회 - QueryDSL (동적 쿼리) feat. 페이징 안 그래도 댓글과 대댓글을 각각 페이징 해서 불러오지 않고 한꺼번에 모든 게시글의 댓글을 불러오게 구현해서 나중에 리팩터링 해야겠다고 생각했던 참이었는데 메인 화면에 보일 게시글들을 조건에 맞게 조회해와야 하는 일이 생겼다. 어차피 댓글은 나중에 리팩토링 할 거고 지금 한 번 구현바로 해볼 생각에 기분이 좋아졌다. 일단 게시글은 최신순, 좋아요 순, 조회순으로 조회가 가능해야한다! 그러면 각각 쿼리를 따로따로 만들어야 하나? 복잡해요.. 저번 포스팅에 잠깐 얘기했던 QueryDSL을 사용할 시간이다.동적 쿼리를 사용할 땐 QueryDSL을 사용하면 굉장히 편하고 효율적으로 작성할 수 있다. 그리고 나중에 최신순, 좋아요 순, 조회순 이런 간단한 게 아니라막 좋아요 10개 이상, 특정 키워드 포함,.. 2025. 6. 15.
게시글의 댓글을 어떻게 불러와야 할까? - N+1 문제의 늪(2) + 대댓글 트리 정렬 https://changbroblog.tistory.com/213 게시글의 댓글을 어떻게 불러와야 할까? - N+1 문제의 늪(1)게시글에 달린 댓글을 조회하는 기능을 구현하게 되었다.단순히 생각하면 별 것 아닌 기능처럼 보이지만, 막상 구현에 들어가 보니 생각보다 고민할 부분이 많았다.왜냐하면 "대댓글" 때문이다.changbroblog.tistory.com 전 포스팅에 이어서 n+1을 어떤 식으로 해결했는지 보자 내가 선택한 방법은 JPQL + fetch join 조합이다! 필요한 연관 엔티티를 한 번에 join해서 가져오는 쿼리를 직접 작성했다 @Query(""" SELECT c FROM comments c JOIN FETCH c.user LEFT JOIN FETCH c.p.. 2025. 6. 13.
게시글의 댓글을 어떻게 불러와야 할까? - N+1 문제의 늪(1) 게시글에 달린 댓글을 조회하는 기능을 구현하게 되었다.단순히 생각하면 별 것 아닌 기능처럼 보이지만, 막상 구현에 들어가 보니 생각보다 고민할 부분이 많았다.왜냐하면 "대댓글" 때문이다. 현재 내 목표는 다음과 같다 클라이언트(프론트)에게 댓글 리스트를 줄 때,각 댓글이 부모 댓글인지, 대댓글인지를 구분해서 내려주는 것. 아래처럼 말이다[ { "id": 1, "content": "부모 댓글", "children": [ { "id": 2, "content": "대댓글" } ] }] 처음에는 내가 너무 순진했다. 단순히 댓글을 Post 기준으로 전부 불러오고 createdAt 기준으로 최신순 정렬만 하면 끝이라고 생각했다. 그래서.. 2025. 6. 12.
로그아웃 기능 (AccessToken 블랙리스트 + RefreshToken 삭제) 현재 이메일 인증, 회원가입 기능, 로그인 등이 구현이 되었고 로그아웃 차례가 왔다. 내가 로그아웃 글을 쓰는건 로그아웃을 할때 AccessToken을 블랙리스트 처리하는 과정이 신기하면서도특별한 경험이었다고 생각했기 때문이다. 현재 AccessToken은 로그인시에 클라이언트에 저장하고RefreshToken은 Redis에 로그인 한 사람의 이메일과 key:value로 저장되어 있는 구조이다. 처음에는 그냥 Redis에서 RefreshToken을 삭제해서 로그아웃을 시켜야겠다고 생각했지만그러고보니 현재 AccessToken의 유효기간이 끝나기 전엔 로그인이 된다는 것이다. 그래서 로그아웃 처리된 AccessToken을 남은 기간동안 Redis에 저장해서블랙리스트 처리하여 로그아웃을 했지만 클라이언트에 남.. 2025. 6. 6.
Google SMTP로 이메일 인증 구현하기 회원 가입을 할 때 없는 이메일을 사용하거나 이메일 중복가능하게 하면 이메일을 받는 이유도 없고너무 악용할 가능성이 많다고 생각해서 이메일 인증을 도입하기로 했다. 많은 기능 중에 Google SMTP를 사용하기로 한 이유는설정도 간편하다고 생각했고 무료이면서 안정적인 기술이기 때문이다. 또한 구글 인프라 위에서 놀기 때문에 전송 안정성과, 보안 수준이 높다. 일단 메일을 발송할 Gmail에 로그인해서 계정 설정 -> (검색) 앱 비밀번호 -> 앱 비밀번호 발급을 진행하여 앱 비밀번호를 받고 SMTP를 사용하기 위한 의존성을 추가해 준다.implementation 'org.springframework.boot:spring-boot-starter-mail' 그리고 properties에서 Gmail SM.. 2025. 6. 5.