- 이번에는 구독 모달에 사용자가 구독한 구독 정보가 리스트 형태로 보여지며 해당 모달에서도 구독하기와 구독취소가 가능하도록 구현해보려고 합니다.
📝 DTO
- 우선 구독 정보를 리스트로 나열하기 위해 필요한 항목들을 아래와 같이 구현해보았습니다.
package com.cos.photogram.web.dto.subscribe;
...
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class SubscribeDto {
private BigInteger id;
private String username;
private String profile_image_url;
private Integer subscribe_state;
private Integer equal_user_state;
}
- id: 현재 페이지의 사용자가 구독한 사용자 아이디
- username: 현재 페이지의 사용자가 구독한 사용자 이름
- profile_image_url: 현재 페이지의 사용자가 구독한 사용자의 프로필 사진
- subscribe_state: 현재 접속중인 사용자가 해당 페이지의 사용자가 구독한 사용자를 구독했는지 여부
- 구독 여부에 따라 구독하기 또는 구독취소 버튼이 나타도록 할 것임
- equal_user_state: 현재 접속중인 사용자와 해당 페이지의 사용자가 동일한 사용자인지 여부
- 자기 자신의 페이지일 경우 구독 버튼이 나타나지 않도록 할 것임
참고: 자료형을 BigInteger, Integer로 설정한 이유는 MariaDB의 경우 Long 타입과 int 타입을 위와 같이 설정하지 않으면 잘 동작하지 않는 경우가 있기 때문입니다.
📝 Service
- 위와 같이 구독자 정보를 리스트로 뿌리기 위해 아래와 같은 쿼리문을 만들었습니다.
SELECT u.id, u.username, u.profile_image_url,
if ((SELECT 1 FROM subscribe WHERE from_user_id = ? AND to_user_id = u.id), 1, 0) subscribe_state,
if ((? = u.id), 1, 0) equal_user_state
FROM user u
INNER JOIN subscribe s
ON u.id = s.to_user_id
WHERE s.from_user_id = ?;
- 다만 위와 같은 네이티브 쿼리를 실행하기 위해서는 Repository에 함수를 생성하는 방식은 사용할 수 없고 따로 쿼리를 직접 만들어 실행시켜주어야 합니다.
- 자세한 방법은 아래와 같습니다.
package com.cos.photogram.service;
import org.qlrm.mapper.JpaResultMapper;
...
@RequiredArgsConstructor
@Service
public class SubscribeService {
private final EntityManager em;
...
@Transactional
public void unSubs(Long fromUserId, Long toUserId) {
subscribeRepository.unSubscribe(fromUserId, toUserId);
}
@Transactional(readOnly = true)
public List<SubscribeDto> subscribeList(Long principalId, Long pageUserId) {
//쿼리 준비
StringBuffer sb = new StringBuffer();
sb.append("SELECT u.id, u.username, u.profile_image_url, ");
sb.append("if ((SELECT 1 FROM subscribe WHERE from_user_id = ? AND to_user_id = u.id), 1, 0) subscribe_state, ");
sb.append("if ((? = u.id), 1, 0) equal_user_state ");
sb.append("FROM user u INNER JOIN subscribe s ");
sb.append("ON u.id = s.to_user_id ");
sb.append("WHERE s.from_user_id = ?");
//쿼리 완성
Query query = em.createNativeQuery(sb.toString())
.setParameter(1, principalId)
.setParameter(2, principalId)
.setParameter(3, pageUserId);
//쿼리 실행
JpaResultMapper resultMapper = new JpaResultMapper();
List<SubscribeDto> list = resultMapper.list(query, SubscribeDto.class);
return list;
}
}
- 위 방법은 QLRM 라이브러리를 사용하여 직접 쿼리를 작성하고 실행시킨 구문으로, 위와 같은 방법을 통해 조인과 스칼라가 포함된 쿼리를 실행하여 결과를 얻어낼 수 있습니다.
📝 Controller
- 컨트롤러에서 위 함수를 호출합니다.
package com.cos.photogram.web.api;
...
@RequiredArgsConstructor
@RestController
public class UserApiController {
private final SubscribeService subscribeService;
...
@GetMapping("/api/user/{pageUserId}/subscribe")
public ResponseEntity<?> subscribeList(@PathVariable Long pageUserId, @AuthenticationPrincipal PrincipalDetails principalDetails) {
List<SubscribeDto> subscribeDto = subscribeService.subscribeList(principalDetails.getUser().getId(), pageUserId);
return new ResponseEntity<>(new CMRespDto<>(1, "구독 정보 목록 가져오기 성공", subscribeDto), HttpStatus.OK);
}
}
📝 Javascript
- 마지막으로 js 파일에 아래와 같은 함수를 구현해주었습니다.
// (2) 구독자 정보 모달 보기
function subscribeInfoModalOpen(pageUserId) {
$(".modal-subscribe").css("display", "flex");
$.ajax({
url: `/api/user/${pageUserId}/subscribe`,
dataType: "json"
}).done(resp => {
console.log(resp);
resp.data.forEach((u) => {
let item = getSubscribeModalItem(u);
$("#subscribeModalList").append(item);
});
}).fail(error => {
console.log(error);
});
}
function getSubscribeModalItem(u) {
let item = `<div class="subscribe__item" id="subscribeModalItem-${u.id}">
<div class="subscribe__img">
<img src="/upload/${u.profile_image_url}" onerror="this.src='/images/person.jpeg'" />
</div>
<div class="subscribe__text">
<h2>${u.username}</h2>
</div>
<div class="subscribe__btn">`;
if (!u.equal_user_state) {
if (u.subscribe_state)
item += `<button class="cta blue" onclick="toggleSubscribe(${u.id}, this)">구독취소</button>`
else item += `<button class="cta" onclick="toggleSubscribe(${u.id}, this)">구독하기</button>`
}
item += `
</div>
</div>`;
return item;
}
- 해당 함수는 구독정보 버튼을 클릭할 시 호출되는 함수로써, 전달받은 구독자 정보를 화면에 출력해줍니다. 또한 해당 모달에서 구독취소 또는 구독하기 버튼을 클릭할 시 동일하게 기능을 수행합니다.
'🚗 Backend Toy Project > Photogram' 카테고리의 다른 글
[Photogram] 좋아요 구현하기 (0) | 2022.07.15 |
---|---|
[Photogram] 스토리 페이지 (0) | 2022.07.14 |
[Photogram] 구독하기 - 기능 구현 (0) | 2022.07.12 |
[Photogram] 구독하기 - 뷰 렌더링 (0) | 2022.07.12 |
[Photogram] 프로필 페이지 - 뷰 렌더링 (0) | 2022.07.11 |