Posts DEVIL: 개인 피드 구현: 게시글 중복 문제
Post
Cancel

DEVIL: 개인 피드 구현: 게시글 중복 문제

문제

마이페이지 피드에서 게시글 목록을 출력한다. 유저가 팔로우하는 태그를 사용한 게시글이거나, 팔로우하는 유저가 작성한 게시글이여야 한다. 게시글은 최신순으로 출력하고, 중복되어서는 안 된다.

해결방법

SQL에서 피드 목록을 출력할 때의 조건

피드를 출력하기 위해서는 유저가 팔로우하는 태그를 사용하는 게시글 목록을 우선 select 하고, 유저가 팔로우하는 유저가 작성한 게시글 목록을 select해야 한다. 이때 함께 select하되 게시글은 중복되어서는 안 된다.

시도했지만 실패한 방법

  1. User가 팔로우하는 유저 목록과 태그 목록을 파라미터로 넘겨 이를 forEach로 반복해 where 조건을 걸려고 하였다. 이 경우 ArticleController에서 FollowService를 사용하여 유저 목록과 태그 목록을 가져오고, 이를 ArticleService.listFeed()의 파라미터로 넘겨주기 때문에 비효율적이다. 뿐만 아니라 DB에는 user의 일련번호 컬럼이 관계테이블인 usr_tag, follow뿐만 아니라 article 테이블에도 들어 있기 때문에 이 일련번호만 있으면 쿼리를 할 수 있다.

  2. 또한 한 쿼리문으로 usr_tag, follow 테이블을 조인하고, where 조건을 or를 줘서 게시글 목록을 select하려고 하였다. 이 경우 같은 게시글이 중복되어 select되는 문제가 있었다. SQL문을 두 개로 분리하고, 이를 합칠 필요를 느꼈다.

Union

이때 사용하는 sql 문법이 Union이다. Union은 여러 개의 SQL문을 합쳐 하나의 SQL문으로 만들어주는 방법이다. 두 개의 쿼리의 합집합을 만들어준다고 생각하면 쉽다.

UnionUnionAll은 두 쿼리문을 하나로 합쳐준다는 것에 공통점이 있다. 그러나 Union은 두 쿼리 결과의 중복값을 제거해서 보여주고, UnionAll은 중복된 값도 전부 다 보여준다는 차이점이 있다. Union은 중복값 제거를 위해 연산을 한 번 더 해야 하기 때문에 UnionAll이 Union보다 빠르다.

Union을 사용할 때는 컬럼명과 컬럼별 데이터타입이 같아야 한다. 컬럼명이 같지 않을 경우 as를 사용해 컬럼명을 같게 만들어줘야 한다.

완성된 SQL문

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
select 
  feed.arno,
  feed.title,
  feed.content,
  feed.cdt,
  feed.cano,
  feed.vw_cnt,
  feed.uno,
  feed.article_nick,
  feed.article_photo,
  feed.tno,
  feed.tag_name,
  feed.tag_color,
  feed.font_color
from (
  select
    a.arno, 
    a.title,
    a.content,
    a.cdt,  
    a.cano,  
    a.vw_cnt, 
    a.state,
    u.uno,
    u.nick article_nick,
    u.photo article_photo,
    t.tno,
    t.name tag_name,
    t.tag_color,
    t.font_color
  from
    article a 
    inner join follow f on a.writer = f.fwing_no
    inner join arc_tag at on at.arno = a.arno
    inner join tag t on at.tno = t.tno
    inner join user u on a.writer = u.uno
  where 
    fwer_no = #{no}
    
  union
  
  select
    a.arno, 
    a.title,
    a.content,
    a.cdt,  
    a.cano,  
    a.vw_cnt, 
    a.state,
    u.uno,
    u.nick article_nick,
    u.photo article_photo,
    t.tno,
    t.name tag_name,
    t.tag_color,
    t.font_color
  from 
    arc_tag at
    inner join usr_tag ut on at.tno = ut.tno
    inner join tag t on at.tno = t.tno
    inner join article a on at.arno = a.arno
    inner join user u on a.writer = u.uno
  where 
    ut.uno = #{no}
) feed
order by feed.arno desc
This post is licensed under CC BY 4.0 by the author.

DEVIL: DispatcherServlet을 admin과 app으로 분리

DEVIL: DispatcherServlet에 따른 비활성 상태의 데이터 추출 여부 변경

Loading comments from Disqus ...