인스타그램 클론 프로젝트-(8)

Claudia Hong·2021년 8월 17일
0

Project

목록 보기
14/26
  1. 구독하기 뷰 렌더링

1) 구독상태 및 구독자수

DB가 위와 같을 때, 유저1이 유저2의 페이지에 갔을 때는 '구독취소' 버튼이 떠야 한다.

구독정보는 유저2가 구독한 수가 떠야 한다.

 SELECT COUNT(*) FROM subscribe WHERE followerId=2;

구독여부는 (유저1로 로그인/ 유저2 페이지로 감)
유저1이 유저2를 팔로우했으면 구독정보가 나온다.

SELECT * FROM subscribe WHERE followerId=1 AND followeeId=2;

카운트를 넣어주면 구독을 했는지(1) 안했는지(0)를 알 수 있다. >> 구독여부

SELECT COUNT(*) FROM subscribe WHERE followerId=1 AND followeeId=2;

UserProfileDto.java에 아래 변수를 만든다.

SubscribeRepository에서 구독자수와 구독여부를 알 수 있는 쿼리 만든다.

18줄 : SubscribeState에는 로그인한 유저아이디와 현재 페이지의 유저아이디
21줄 : SubscribeCount에는 페이지유저아이디

SELECT에는 @Modifying가 필요없다.
리턴하는 값이 int이므로 카운트의 값이 1 >> 구독상태

int를 리턴하므로 mSubscribeState() 카운트가 1이라는건 구독된 상태
mSubscribeCount()의 카운트수는 해당페이지의 주인이 구독한 구독자수

21줄 : SubscribeRepository를 UserService에 DI
37~8줄 : SubscribeRepository의 구독여부 및 구독자수를 구하는 쿼리의 값을 담는다.
40줄 : 구독여부의 카운트 값이 1이면 true(구독함) 아니면 false(구독안함>>구독하기 버튼이 뜬다)
41줄 : 구독자수의 카운트 값을 dto에 담는다.

37줄 : subscribeState가 true이면 구독을 했다.
38줄 : (css설정) cta는 그냥 버튼 디자인/cta blue 파란색으로 변함

2) 구독 취소하기 기능

구독취소하기 버튼을 누르면 this 라는 이벤트가 profile.js로 넘어간다. 토글????? 색이 바뀌고 구독취소 글자가 나오고 그런거...
암튼 여기에 기능을 넣어야하므로 ajax를 쓴다.

18줄 : 취소 >> delete
19줄 : url을 넣는데, 현재페이지의 유저ID(PageUserId)가 들어가야 한다. 이걸 toUserId로 넣어준다.(누구를??구독하는지)
22~3줄 : 구독취소에 성공하면 구독하기 버튼으로 바뀜
25줄 : 실패하면 콘솔에 찍음

반대경우도 똑같이 내용만 바꾸면 됨.

toUserId 값을 넘겨주기 위해 dto에서 유저아이디를 가져온다. (현재페이지의 유저아이디, 로그인한 유저아이디가 아님)

2) 구독정보 창

구독정보 클릭을 트리거로 구독한 유저 목록을 띄운다. JSP와 JS로.

리스트로 들고온다.

들고와야 하는 정보 프로필이미지/username/구독했는지에 대한 정보

(1) 하기 전에 생각해보기!!
로그인한 유저1이 유저2의 페이지에 가서 구독정보를 눌렀을 때 나오는 사용자들의 옆에 구독정보(구독취소/구독하기)버튼은 유저1의 입장에서의 구독여부를 보여줘야 함. (유저2의 구독정보에 있는 유저3을 유저1이 구독했는지 안했는지에 따라 구독취소/구독하기 버튼이 떠야 한다) + 로그인한 유저1이 유저2의 구독정보 화면에서 유저1, 유저3을 확인할 때, 자신이 있으면 구독버튼 자체가 없어야 한다. >> 이런 정보를 만들려면 DTO가 필요함

(2) DTO 만들기

13줄 : api 호출을 해야할때, 현재 로그인한 사용자의 id 외에 '누구를' 구독할지에 해당하는 followeeID가 필요.
16줄 : 구독한 상태인지 안 한 상태인지를 보여줌.
17줄 : 구독정보에 뜬 유저가 로그인한 유저와 동일인지를 true면 구독버튼을 없애고, false면 보여준다.
※Integer 라고 한 이유 MariaDB는 int로 하면 true 값을 못 받는다.

(3) API Controller 만들기

39줄 : api의 유저 {pageUserid=지금 들어간 현재 페이지의 주인}번을 구독하고 있는 모든 사람을 가져온다.
43줄 : 위에서 만든 SubscribeDto 리스트 정보에 SubscribeServie의 로직을 이용해 가져오는 정보를 넣고 그걸 리턴할 것이다.

(4) DB 쿼리 만들기

로그인한 유저1이 유저2의 페이지에 가서 구독정보를 눌렀을 때 나오는 사용자들의 옆에 구독정보(구독취소/구독하기)버튼은 유저1의 입장에서의 구독여부를 보여줘야 함.

2번의 구독정보를 눌렀을 때 (구독 중인) 1번과 3번의 정보(>>followeeId로 알 수 있음)가 구독 모달에 출력

아래 두 쿼리를 JOIN을 해서 뽑아야 한다.

SELECT *FROM user; //유저정보를 불러오면 전부 다 나옴

SELECT *FROM subscribe WHERE followerId=2;//2번이 구독하고 있는 유저들의 정보

무엇으로 JOIN 해야할까?? >> user.id = subscribe.followeeId
(INNER JOIN >> 같은것만 조인해라)

SELECT * 
FROM user u INNER JOIN subscribe s
ON u.id = s.toUserId
WHERE s.fromUserId =2;

결과 확인

여기서 필요한 정보만 뽑는다.

SELECT u.id, u.username, u.profileImageUrl
FROM user u INNER JOIN subscribe s
ON u.id = s.toUserId
WHERE s.fromUserId =2;

로그인한 유저(1)가 화면에 보여지는 1,3을 구독했는지 안 했는지 여부
유저1이 유저3을 구독했을 때, true(1)인지를 SELECT 한다.

SELECT true FROM subscribe WHERE fromUserId =1 AND toUserId=1;
SELECT true FROM subscribe WHERE fromUserId =1 AND toUserId=3;

이 값이 아래 코드의 결과 옆에 칼럼으로 추가되면 된다.

  • 스칼라 서브쿼리 : SELCET 절에 SELCET 절이 하나 더 나오는 것

단일행을 리턴해야 한다.(FROM을 넣을 수도 넣지 않을 수도 있다.)

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

u.id를 가져와서 비교를 한다.

동일 유저인지를 판단하는 쿼리를 만들어보기

로그인한 유저(1)와 u.id가 같으면 1 아니면 0

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

결과

이 쿼리의 결과가 SubscribeDto의 값들을 만든다.

추가 수정 - 값이 null이 나오지 않게, 1과 0으로만 나오게 함.

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;

이 쿼리는 SubscribeRepository에 넣을 수 없다. >> 리턴하는 값이 Subscribe moel 값이 아니기 때문이다.

(5) Controller에서 불러올 서비스 만들기

@Transactional을 걸어주는데 SELECT이므로 readOnly를 해준다.
쿼리를 Service에서 직접 네이티브 쿼리를 짤 것이다.

23줄 : EntityManager를 DI해야한다. >> 모든 Repository는 EntityManager를 구현해서 만들어져 있는 구현체이다. 여기서는 직접 만들겠음!

<쿼리 준비하기>
29~34줄 : 쿼리를 한줄씩 넣는다. 이때 꼭 끝에 한칸을 띄워준다! 꼭! >> 한칸을 띄우지 않으면 다음줄 앞이랑 붙어서 나와서 에러남!

30줄 : 첫번째 ? >> 로그인한 유저의 아이디(principalId)
31줄 : 두번째 ? >> principalId
34줄 : 동적으로 값(pageUserId)이 들어와야 하므로 ?를 넣음 (세미콜론 끝에 넣으면 절대 안됨!)

<쿼리 완성하기>
36줄 : 바인딩 하기 (javax.persistence 의 Query)
37줄 : 파라미터 넣기. 첫번째 ?의 파라미터는 principalId
38줄 : 두번째 ?의 들어가는 파라미터 >> principalId
39줄 : 세번째 ?에 들어가는 파라미터 pageUserId

<쿼리 실행하기- qlrm 라이브러리 필요>
41줄 : JpaResultMapper << qlrm에서 제공 << pom.xml에 직접 넣어야 함
42줄 : result.list(쿼리, 무엇으로 리턴 받을 것인지) >> 한건만 리턴받을게 아니라서 리스트 사용. 한건만 리턴 받을거면 uniqueResult를 쓴다.
43줄 : subscribeDtos에 넣어서 리턴한다.(26줄의 타입과 일치)

※ qlrm? DB에서 result된 결과를 DTO에 매핑해주는 라이브러리 >> 굉장히 편하게 dto로 받을 수 있음.

결과 확인 (ssar로 로그인/cos의 페이지의 구독정보 확인)

{
    "code": 1,
    "message": "구독자정보 리스트 불러오기 성공",
    "data": [
        {
            "id": 1,
            "username": "ssar",
            "profileImageUrl": null,
            "subscribeState": 0,
            "equalUserState": 1
        },
        {
            "id": 3,
            "username": "love",
            "profileImageUrl": null,
            "subscribeState": 1,
            "equalUserState": 0
        }
    ]
}

(6) ajax로 정보 뿌리기

42줄 :현재 페이지의 유저 id (pageUserId) JSP에서 날려줘서 JS의 ajax에서 받아 출력
46줄 : url을 호출해서 그 결과를 받을 때,
47줄 : 그 데이터 타입은 json
49줄 : 성공 시, 구독자정보 리스트에서 data만 뽑아온다.

위에 출력된 data를 토대로 그림을 만들어주면 된다.

51줄 : res.data를 forEach로 돌릴 때 한바퀴 돌 때마다 유저정보(u)를 들고온다.
52줄 : let item 은 아래의 함수(getSubscribeModalIte)를 호출해서 유저정보를 넘긴다
53줄 : JSP의 subscribeModalList를 찾아 append 해서 item을 붙여넣는다.

61줄 : id값은 고유해야 하므로, 뒤에 id를 붙여서 고유하게 만들어준다.
63줄 : 프로필이미지 url은 앞에 /upload/ 를 붙여준다.(지난 포스트 참고)
66줄 : 유저정보(u)에서 필요한 곳에 데이터를 뽑아와 넣는다.
70~76줄 : 동일유저여부/구독여부에 따른 구독버튼의 색, 내용 등 설정
70줄 : 동일 유저가 아닐 때 버튼이 만들어져야 한다.
72줄 : 동일 유저가 아닐 때, 구독한 상태이면 구독취소하기를 보여준다.
74줄 : 동일 유저가 아닐때, 구독 안한 상태 구독하기를 보여준다.

72,74줄 : onclick 했을 때, 맨위의 유저프로필페이지에서 구독하기, 구독취소하기 function을 실행하게 한다. 이때 넘겨야 하는 data가 userId, obj(event) 이므로 유저정보(u)에서 id와 이벤트인 this를 넘긴다.

0개의 댓글

관련 채용 정보