[포토그램] 구독 리스트 출력

이전 포스팅

  1. Subscribe 클래스를 추가하고 JPA로 테이블 생성함
  2. SubscribeService 에서 구독하기/구독취소하기 구현. SubscribeApiController 가 구독 수행여부를 CMRespDto에 담아 반환한다.
  3. 유저 프로필 페이지 이동시 ID에 따른 유저정보를 UserService가 DB에서 가져온다. UserApiController는 UserProfileDto 에 정보들을 담고, model에 담아 뷰로 전송한다.

이번 포스팅은 프로필 페이지에서 구독 여부를 확인 및 해당 유저의 구독자 리스트에서 구독수행을 가능하도록 해보겠다.



프로필 페이지 - 구독여부 확인 & 구독자 수

1번으로 로그인 후 2번 유저페이지에 접속한 모습이다. 구독 여부에 따라 구독하기/구독취소 버튼이 생기며, 2번 유저의 구독자 수가 출력되어야한다. 이는 2번 유저페이지 띄울 때 표시되어야 하므로 UserProfileDto에 해당 정보를 담자.


UserProfileDto에 해당 유저의 구독자 수인 subscribeCount와, 세션 아이디(1번)이 프로필 아이디(2번)을 구독했는지 여부를 저장하는 subscribeState 변수를 추가하였다.


SubscribeRepository 에 principalId가 pageUserId를 구독하는지를 반환하는 메서드와 pageUserId의 구독자수를 반환하는 메서드를 네이티브 쿼리로 구현하였다.


userService에서 회원프로필 메서드에 userProfileDto에 데이터를 담을 때 위 두정보를 추가로 담는다.


userProfileDto는 컨트롤러가 뷰로 쏴줄 것이고, 뷰에서 구독했는지 여부에 따라 구독하기/구독취소를 출력한 모습이다.



프로필의 구독하기/구독취소 버튼으로 구독 수행

profile.jsp 에서 구독하기/구독취소 버튼은 toggleSubscribe 함수를 호출하며 pageuserId와 태그 자체를 넘겨준다.


profile.js의 toggleSubscribe 메서드이다. 우리는 구독하기 기능을 CMRespDto를 반환하도록 구현하였다. 따라서 구독하기/구독취소 버튼을 누르면 해당 컨트롤러로 요청을 수행하고, 텍스트를 변경하도록 구현하였다.



구독자 리스트 메서드 정의

1번로 로그인 후 2번유저의 구독자 리스트를 확인한다고 하자. 2번의 구독자 리스트가 출력되고, 해당 유저들을 1번 유저가 구독중인지, 자기 자신인지 여부에 따라 우측의 박스가 달라질 것이다. 따라서 리스트 출력시 해당 유저가 1. 세션유저 자기 자신인지 2. 세션유저가 구독중인 유저인지. 에 대한 정보가 필요하다.


즉 구독자 리스트 박스 하나마다 Id, 이름, 프로필 이미지, 세션 사용자가 구독했는지 여부, 세션 사용자 자기 자신인지 여부가 필요하고. 이를 저장할 SubscribeDto 클래스를 생성한다.


페이지 주인이 구독리스트 중에 세션 유저가 구독하고 있는 모든 유저를 가져올 subscrbieList 함수를 UserApiController에 정의한다. 결과로는 세션 유저의 구독자리스트를 반환한다. ResponseEntity 객체로 반환하는 것은 Ajax 통신에 사용하기 위해서이다.


이제 SubscribeService 에서 구독리스트 메서드를 정의하면 되는데. 구독리스트 메서드는 다음과 같은 특징을 갖는다.
1. 모든 페이지유저 구독목록을 출력
2. 1번 결과 중 세션유저가 구독하고 있는지 아닌지 여부 저장
3. 1번 결과 중 세션유저 자기 자신인지 아닌지 여부 저장

-- 1번 유저가 2번 유저 구독목록 눌렀을 때 출력되는 정보

SELECT u.id, u.username, u.profileImageUrl, 
if ((SELECT 1 FROM subscribe WHERE fromUserId = 1 AND toUserId = u.id), 1, 0
) subscribeState,
if((1 = u.id), 1, 0) equalUserState
FROM user u INNER JOIN subscribe s
ON u.id = s.toUserId
WHERE s.fromUserId = 2;

위와 같이 쿼리문이 정의된다.

쿼리문 수행결과는 위와 같다. 1번 로그인 -> 2번페이지 방문 -> 쿼리문 수행 시.
2번 구독 리스트에서 1번이 구독중인지, 1번 자기 자신인지가 함께 출력된다.


이제 해당 쿼리문을 바탕으로 SubscribeService의 구독리스트 메서드를 정의한다. 그런데 왜 구독리스트 메서드는 DB접근을 수행하는데 SubscribeRepository가 아닌 SubscribeService에 선언할까? 쿼리 수행 결과가 상수나 해당 객체(Subscribe)를 반환하는 형태가 아니면 Repository에 메서드를 정의할 수 없다.

EntityManager를 통해 NativeQuery를 짠 후, qlrm을 통해 쿼리문 수행결과를 자바 클래스에 매핑해준다. SubscribeDto 의 리스트 형태로 저장해주었다. 즉 구독리스트의 정보들을 List에 담아 반환해준다.


1번 유저로 접속 후 2번 유저를 파라미터로 구독리스트를 요청한 결과이다. SubscribeDto의 리스트 형태로 반환함을 알 수 있다.



구독 리스트 뷰에 출력

profile.jsp를 보자. 구독 정보를 클릭하면 subscribeInfoModalOpen 함수를 호출한다. 이는 profile.js 에 정의되어있다.


subscribeInfoModalOpen 메서드이다. SubscribeApiContoller로 요청을 해서 구독 리스를 받아 온 후. 안의 SubscribeDto 객체를 순환하며 getSubscribeModalItem 함수를 호출하고, 그 결과를 id가 subscribeModalList 인 태그 안에 넣어준다.


getSubscribeModalItem 함수이다. subscribeInfoModalOpen 함수에게 받은 SubscribeDto를 바탕으로 아래의 한칸 한칸에 해당하는 Html 을 만들어 반환하는 함수이다. 또한 버튼을 클릭했을 때 toggleSubscribe를 호출하여 구독/구독취소 전환을 수행한다.


위에서 subscribeInfoModalOpen 은 한칸 한칸을 만들어 subscribeModalList에 안에 넣어준다고 하였다. 위의 빨간색 박스 부분에 코드를 넣어주게 되고, 이를 바탕으로 동적 렌더링된다.


최종 수행 결과이다. 1번 유저 로그인 후 2번 유저 구독자 리스트를 조회하자. 자기 자신은 아무것도 표시되지 않고, 구독 여부에 따라 구독/구독취소 버튼이 출력된다.



서버단에서 로직을 수행할 때는 원하는 뷰를 그릴 때 어떤 정보가 필요한지 생각해야한다. 이번에 구독자 리스트를 출력하면서 필요한 정보는
1. 해당유저에 대한 정보
2. 해당 유저를 세션유저가 구독했는지 여부
3. 해당 유저가 세션유저 자기자신인지 여부
위의 세가지 정보가 담긴 페이지유저의 구독자 리스트였다.
따라서 1,2,3의 정보를 담기 위해 새로운 Dto를 선언하고, 쿼리문을 수행해 Dto의 List 형태로 클라이언트에게 반환하면서 원하는 뷰를 그릴 수 있었다.

좋은 웹페이지 즐겨찾기