Velog 통계 서비스 개발해보기!

심애림·2023년 12월 27일
0

📍 개발 동기

Velog에 글을 쓰다보니 한가지 불편한 점이 있었다.
바로 조회수를 보려면 게시물마다 들어가서 하나하나 통계를 눌러야 한다는 점...😨

아직은 게시물이 그리 많지 않아서 일일히 들어가서 확인할 순 있지만 여간 귀찮은 일이 아니였다.

그래서 한눈에 게시물들의 조회수를 확인할 수 있는 서비스를 개발해보기로 결정!
(조회수를 바라고 작성한 글들은 아니지만 내심 궁금한 건 어쩔 수 없다ㅋㅋㅋ)

🚫 Spring Boot 입문자가 개발한 서비스라 아직 미흡한 부분이 있을 수 있습니다. 감안하고 봐주시면 감사하겠습니다 😁

자세한 건 Github velog_dashboard 레포지터리에서 확인 가능합니다!


🙌 결과물

  • 간단하게 게시물의 썸네일, 제목, 조회수, 바로가기 링크만 구현했다.

🖥 개발 환경

Spring Boot를 공부한 김에 활용해볼 겸 Spring Boot를 사용했다.

  • Java 21
  • Spring Boot
  • Gradle 8.5

📒 개발 내용

Post 엔터티

@Data
public class Post {

    // ID
    private String id;

    // 제목
    private String title;

    // 전체 조회수
    private Integer totalViews;

    // 썸네일
    private String thumbnailURL;

    // 바로가기 링크
    private String url;
}

Velog에 등록된 게시물 리스트를 가져오는 서비스

  • GraphQL을 이용해 Velog에 등록된 게시물을 가져올 수 있다.
  • 게시물 리스트를 가져올 때에는 access-token이 필요없다.
  • 쿼리문을 작성하고 이를 Json으로 변환한 뒤 이를 헤더와 함께 HttpEntity 객체를 생성했다.
    public List<Post> posts() throws ParseException {
        RestTemplate restTemplate = new RestTemplate();

        // Header Setting
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("content-type", "application/json");

        String query = String.format("""
                {
                    "operationName": "Posts",
                    "variables": {
                        "username": "%s"
                    },
                    "query": "query Posts($cursor: ID, $username: String, $temp_only: Boolean, $tag: String, $limit: Int) {
                        posts(cursor: $cursor, username: $username, temp_only: $temp_only, tag: $tag, limit: $limit) {
                            id
                            title
                            thumbnail
                            url_slug
                        }
                    }"
                }
                """, velogUserName);
        JSONParser jsonParser = new JSONParser();
        JSONObject jsonObject = (JSONObject) jsonParser.parse(query);

        HttpEntity<JSONObject> entity = new HttpEntity<>(jsonObject, httpHeaders);

        // Request
        String response = restTemplate.postForObject(velogUrl, entity, String.class);

        // 데이터 정리
        JSONObject jsonResponse = (JSONObject) jsonParser.parse(response);
        JSONObject data = (JSONObject) jsonResponse.get("data");
        JSONArray posts = (JSONArray) data.get("posts");

        List<Post> list = new ArrayList<>();
        for (int i = 0; i < posts.size(); i++) {
            JSONObject jsonPost = (JSONObject) posts.get(i);
            String id = (String) jsonPost.get("id");
            String title = (String) jsonPost.get("title");
            String thumbnailURL = (String) jsonPost.get("thumbnail");
            String urlSlug = (String) jsonPost.get("url_slug");

            Post post = new Post();
            post.setId(id);
            post.setTitle(title);
            post.setThumbnailURL(thumbnailURL);
            post.setUrl(String.format("https://velog.io/@%s/%s", velogUserName, urlSlug));

            list.add(post);
        }

        return list;
    }

Velog 게시물의 조회수를 가져오는 서비스

  • 게시물의 리스트를 가져오는 방식과 비슷하다.
  • 대신, 헤더에 access-token을 넣어줘야 한다.
	public Post stats(Post post) throws ParseException {
        RestTemplate restTemplate = new RestTemplate();

        // Header Setting
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("content-type", "application/json");
        httpHeaders.add("cookie", "access_token=" + velogAccessToken);

        String query = String.format("""
                {
                    "operationName": "GetStats",
                    "variables": {
                        "post_id": "%s"
                    },
                    "query": "query GetStats($post_id: ID!) {
                        getStats(post_id: $post_id) {
                            total
                        }
                    }"
                }
                """, post.getId());
        JSONParser jsonParser = new JSONParser();
        JSONObject jsonObject = (JSONObject) jsonParser.parse(query);

        HttpEntity<JSONObject> entity = new HttpEntity<>(jsonObject, httpHeaders);

        // Request
        String response = restTemplate.postForObject(velogUrl, entity, String.class);

        // 데이터 정리
        JSONObject jsonResponse = (JSONObject) jsonParser.parse(response);
        JSONObject data = (JSONObject) jsonResponse.get("data");
        JSONObject stats = (JSONObject) data.get("getStats");

        post.setTotalViews(Integer.parseInt(stats.get("total").toString()));

        return post;
    }

✨ 느낀점

Spring Boot 환경에서 외부 API를 사용해본 것은 처음이라 생각보다 많이 헤맸다 😅
지금 돌이켜보면 굉장히 간단한 프로젝트인데 말이다...ㅎ
지금은 아주 간단하게 기능만 구현한 상태라 디자인이나 더 필요한 기능은 앞으로도 더 디벨롭해나갈 예정이다.


👀 참고

profile
뭐든지 노력하는 백엔드 개발자, 심애림입니다.

0개의 댓글