카타르 아시안컵 16강날 해축갤 트래픽 분석 : 인기 게시물의 파워

2024. 2. 1. 12:11Project 해축갤/고민

728x90

예전에 쿼리 튜닝을 한 상황의 가정은 다음과 같았습니다.

손흥민이 월드컵에서 골을 넣으면 해축갤에 미친 듯한 드립(게시물)이 올라오고 퍼갈 것이다.
이때 '%흥민%' 이라는 키워드로 검색이 많이 일어날 것이다.

그래서 게시물에 약 1억 건의 데이터를 넣고 느려진 게시물 조회 쿼리를 개선을 했었습니다. (4분20초 -> 0.0019초)

 

2024.01.29 - [Project 해축갤/데이터베이스] - 1억 데이터 쿼리 최적화: 풀텍스트 인덱스의 한계와 LIKE 절의 귀환

 

1억 데이터 쿼리 최적화: 풀텍스트 인덱스의 한계와 LIKE 절의 귀환

배경 최근 데이터를 200만 개에서 1억 개로 늘리고 난 뒤 기존 API의 성능이 얼마나 나오는지 궁금해 쿼리를 한번 테스트해 봤습니다. 정신 나갔다,,, 쿼리 응답시간 4분 20초…? 해축갤은 제 자식과

xpmxf4.tistory.com

그 후, 서비스 고민을 하다 이런 생각들이 들었습니다.

💡 사실상 가장 빈번하게 조회가 되는, 가장 많은 트래픽을 받는 건 인기 게시물이지 않을까?

아래보단 검증된 인기 게시물이 먼저 눈에 띈다.

이 화면에서 우리는 밑에 있는 글보다는 상단에 있는 인기 게시물에 더 눈이 갑니다.

해축갤 디자이너도 그렇게 유도하도록 웹의 UI 를 그렇게 배치하기도 했지만.

그렇다면 다음 의문점이 듭니다.

인기글의 기준은 뭘까?

 

(정보) 개념글 기준, 올리는 방법 - 201910~202110 스트리머 갤러리

 

(정보) 개념글 기준, 올리는 방법 - 201910~202110 스트리머 갤러리

념글 기준은    일정 갯수 댓글 + 추천수 임.  활성화된 갤일수록 기준치가 높고  망갤일수록 기준치가 낮음.  (현재 인방갤  댓글6개 추천22개 정도)우선조건이 댓글이고 그다음이 추천수.추

gall.dcinside.com

빠르게 요약하자면 좋아요 수, 댓글 수의 기준대로 인기글이 기준입니다.

즉 사람들에게 가장 많은 관심을 받는 글이라는 건 자명합니다.

하지만 갑자기 이런 고민에 빠졌습니다.

인기글이라서 해서 실제로 조회는 얼마 안 될 수도 있지 않을까? 
(사실 무조건 높을 거 같지만)
실제로 측정으로 수치를 봐야 하나?

 

마침 이 글을 쓰기 시작한 1월 31일의 오전1시에는 한국 vs 사우디 16강이 있었습니다.

후,,, 진짜 이겨서 다행,,,

극적인 승리이기도 하니, 평소의 인기게시물보다

크롤링으로 얻을 수 있는 조회수, 즉 트래픽을 관측할 수 있을거라는 생각

좋다고 생각, 바로 분석 및 코드를 짰습니다.

HTML 코드를 열어보자.

개발자도구로 볼때 .concept_txtlist 안에 li 태그들이 인기게시물임을 확인할 수 있다.

그리고 각각의 제목은 <a>로 하이퍼링크가 걸려있어 원본 게시물의 링크가 걸려있고

이를 타고 들어가면 다음과 같이 조회수를 확인할 수 있다.

타고 들어가야 조회수를 볼 수 있다.

💡 조회수 == 게시물 조회 API 콜 == 게시물 조회 쿼리 실행

라는 공식을 세워본다면, 조회수는 조회 API 호출 횟수,

조회 쿼리 실행 횟수라고도 볼 수 있습니다.

데이터 수집 및 분석

목표는 해외축구 갤러리의 인기 게시물들의 조회수를 추적하고 분석하는 것.

이를 위해 Java를 사용하여 크롤링 코드를 작성하고 얻은 데이터를 기반으로 분석을 진행할 예정입니다.

1.main( ) 메서드

public static void main(String[] args) {
    try {
        List<Post> postsList = trackPopularPosts();
        savePostsToJsonFile(postsList, "popular_posts.json");
    } catch (IOException e) {
        System.err.println(e.getMessage());
    }
}

main 메서드입니다.

trackPopularPosts 호출하여 웹사이트에서 게시물 데이터를 가져오고,

결과를 savePostsToJsonFile 전달하여 JSON 파일로 저장합니다.

2. 게시물 추적 - trackPopularPosts( )

public static List<Post> trackPopularPosts() throws IOException {
    // URL 정의 및 Jsoup으로 문서 파싱
    String url = "http://gall.dcinside.com/board/lists/?id=football_new8"; // 해축갤 주소
    Document postDocs = Jsoup.connect(url).get();

    // 게시물 선택 및 현재 날짜 설정
    Elements posts = postDocs.select(".concept_txtlist li a");
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String currentDate = formatter.format(new Date());

    // 각 게시물 처리
    List<Post> postsList = new ArrayList<>();
    for (Element post : posts) {
        // ...
    }
    return postsList;
}

지정된 URL에서 Jsoup 사용하여 페이지의 HTML 파싱합니다.

페이지에서 게시물을 선택하고 각 게시물에 대한 데이터(제목, 링크, 조회수)를 추출,

Post 객체에 저장한 , 이를 List<Post> 추가합니다.

3. 게시물 처리 루프, POJO - trackPopularPosts( ) 내부

@Getter
@Builder
public class Post {
    private String title;
    private String link;
    private int totalViews;
    private String lastUpdated;

}

먼저 Jackson 을 사용하기 위한 POJO Object 인 Post 를 생성해줍니다.

for (Element post : posts) {
    String postLink = "";
    try {
        // 게시물 제목 및 링크 추출
        String postTitle = post.text();
        postLink = post.attr("href").replace("https", "http");

        // 게시물 링크 정리 및 조회수 추출
        if (postLink.contains("amp;")) {
            postLink = postLink.replace("amp;", "");
        }
        Document postDoc = Jsoup.connect(postLink).get();
        Element view = postDoc.selectFirst(".view_content_wrap .gall_count");
        int count = Integer.parseInt(view.text().replaceAll("[^\\d]", ""));

        // Post 객체 생성 및 추가
        Post postObject = Post.builder()
                        .title(postTitle)
                        .link(postLink)
                        .totalViews(count)
                        .lastUpdated(currentDate)
                        .build();

        postsList.add(postObject);
    } catch (NumberFormatException e) {
        System.err.println("Parsing error for post: " + postLink + " - " + e.getMessage());
    } catch (Exception e) {
        System.err.println("Error processing post: " + postLink);
    }
}

그리고 각 게시물의 제목과 링크를 추출 후 상세 페이지로 이동하여 조회수를 가져옵니다.

데이터는 Post 객체에 저장되고, 객체는 리스트에 추가됩니다.

예외가 발생할 경우, 오류 메시지를 출력합니다.

4. JSON 파일 저장 - savePostsToJsonFile( )

public static void savePostsToJsonFile(List<Post> postsList, String fileName) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.enable(SerializationFeature.INDENT_OUTPUT);

    String json = mapper.writeValueAsString(postsList);
    Files.write(Paths.get(fileName), json.getBytes());
    System.out.println("Saved posts to " + fileName);
}

List<Post> 입력으로 받아 Jackson 라이브러리의 ObjectMapper 사용,JSON 문자열로 변환합니다.

문자열은 지정된 파일 이름으로 파일 시스템에 저장됩니다.

JSON 출력은 가독성을 위해 들여쓰기로 정렬됩니다.

5. 결과물 확인 및 결론

수집된 JSON 데이터는 다음과 같습니다. (1월31일 13시경 기준)

[
  {
    "last_updated": "2024-01-31 13:01:09",
    "link": "http://gall.dcinside.com/board/view/?id=football_new8&no=6129145",
    "total_views": 13631,
    "title": "찬밥이 요르단, 사우디한테 턴오버 존나 당하는거 보면"
  },
  {
    "last_updated": "2024-01-31 13:01:09",
    "link": "http://gall.dcinside.com/board/view/?id=football_new8&no=6129111",
    "total_views": 13306,
    "title": "확실한건 지금 대표팀을 흔드는건 엠생 손까임"
  },
  {
    "last_updated": "2024-01-31 13:01:09",
    "link": "http://gall.dcinside.com/board/view/?id=football_new8&no=6129254",
    "total_views": 27720,
    "title": "오늘자 손흥민 머리채 잡는 사우디 선수...gif"
  },
  ...
  ]

이렇게 수집된 JSON 데이터를 chart.js 를 통해 시각화한 결과는 다음과 같습니다.

(matplotlib 도 써봤는데 차트가 너무 못생겨서 chart.js 썼습니다🥲)

chart.js 를 통한 시각화 결과물

즉, 카타르 아시안컵 16강정도 경기에서

다이나믹한 승부차기로 승리한 날(1/31 01:00)의 조회수는 총 197,368 입니다.

 

이날 측정한 시간은 13:00, 즉 12시간 정도 안에 몰린 트래픽은 197,368 로 볼 수 있습니다.

이를 TPS 로 환산한다면 대략 다음과 같습니다.

197,368(조회수) / 12(시) * 3600(초) ≈ 4.5687 (tps)

즉 중요한 경기가 있는날 해축갤의 인기게시물의 TPS 는 4.5687 정도입니다.

생각보다 TPS 가 그렇게 높지는 않아서 의외입니다...!

(대한민국이 월드컵 우승이라도 해야 폭발하려나...?)

평소와 비교해보기

인기게시물에 197,368회 조회수가 몰렸고, 위 게시물들의 평균 조회수는 17,943 회입니다.

그렇다면 일반게시물들의 조회수는 얼마나 몰릴까요?

최우측 컬럼이 조회수이다.

저 중 13,829 회의 조회수를 달성한 인기 게시물을 제외한

일반 게시물의 평균 조회수는 약 35.1 회입니다.

즉 인기와 일반 게시물의 평균 조회수의 차이는 약 511.19 배입니다.

우리는 이런 공식을 세워볼 수 있습니다.

💡 인기 게시물은 일반 게시물보다 평균적으로 조회수가 511.19 배 정도 몰린다!

결론

  • 오늘은 중요한 경기가 있는날 해축갤에 트래픽이 얼마나 몰리는지를,
  • Java 크롤러를 통해 조회수를 계산, 그리고 이를 수치로 나타내는 방법,
  • 그리고 인기 게시물과 일반 게시물의 조회수의 차이

이 3 가지에 대해 알아봤습니다!

코드

 

GitHub - xpmxf4/GalleryFetchCnt

Contribute to xpmxf4/GalleryFetchCnt development by creating an account on GitHub.

github.com

 

728x90