공부/whiteship-java

4주차 과제: live-study 대시보드

chulphan 2020. 12. 12. 10:30

[whiteship 라이브스터디]github.com/whiteship/live-study

 

whiteship/live-study

온라인 스터디. Contribute to whiteship/live-study development by creating an account on GitHub.

github.com

 

 

이번에는 live-study 의 대시 보드 작성 과제를 작성할 것이다

 

요구사항은 아래 이미지와 같다

 

과제 1번

사실 이미지 중에 위에 두 가지가 이번 과제에 대한 요구사항인 것 같다.

 

이미지 상에 명시된 Github 자바 라이브러리의 링크 => github-api.kohsuke.org/

 

GitHub API for Java –

What is this? This library defines an object oriented representation of the GitHub API. By "object oriented" we mean there are classes that correspond to the domain model of GitHub (such as GHUser and GHRepository), operations that act on them as defined a

github-api.kohsuke.org

 

위의 API 를 사용하면 Github의 많은 동작을 사용할 수 있다.

 

그리고 이번 과제를 사용하면서 많이 봤던 apidocs... 

이 문서를 보면 이번 과제를 해결하는데에는 크게 어려움은 없어보인다..(과연??)
github-api.kohsuke.org/apidocs/org/kohsuke/github/package-summary.html

 

org.kohsuke.github (GitHub API for Java 1.116 API)

A Issue has been assigned, unassigned, labeled, unlabeled, opened, edited, milestoned, demilestoned, closed, or reopened.

github-api.kohsuke.org

 

그럼 어떻게 과제를 수행했는지 살펴보자

 

 

 

▶ 시작은 github api 에 연결하는거 부터

처음에는 이 과제를 git에 따로 올릴 것도 아니어서 git의 유저이름과 비밀번호를 가지고 인증하려고 했었다.

 

GitHub github = new GithubBuilder()
		.withPassword("my-user-name", "my-password")
                .build();

하지만 위와 같은 방법으로 인증을 시도하면 아래와 같은 에러 메세지를 볼 수 있다

 

<에러메세지 이미지 삽입>

 

그래서 어떻게 할까... 하다가 github 에서 OAuth 토큰을 생성하고 그 토큰을 가지고 

인증을 진행하기로 했다.

 

※Github OAuth 토큰 발급 받는 방법

 

1. 먼저 github.com/settings/tokens로 진입한다

2. Generate new token 버튼을 클릭한다

tokens

3. 인증을 진행하고..

4. 이 화면 하단에서 Generate Token 버튼을 클릭하면 생성 완료! (체크박스는 아무것도 체크 안해도 된다)

 

¡ 주의사항

토큰이 생성되고 나면 토큰 목록 페이지에 우리가 생성한 토큰이 보여진다.

그런데 이 때 이 토큰을 어딘가에 보관해놓지 않으면 다시는 볼 수 없으므로 주의해야한다..

 

☞ 이제 토큰을 가지고 인증을 진행해보자

 

GitHub github = new GitHubBuilder().withOAuthToken("your-token").build();

your-token 자리에 여러분의 토큰을 집어넣으면 인증은 완료되고, 

github 변수를 통해서 이 라이브러리에서 제공하는 다양한 API 를 이용해서 github 조작이 가능하다.

 

▶ 이제 우리가 관심있는 저장소의 Issue 에 접근을 해보자

저장소의 Issue 에 접근을 하려면 아래의 API 를 통해서 먼저 저장소 객체를 가져와야 한다

 

이제 코드로 어떻게 가져오는지 보자

GHRepository repository = github.getRepository("whiteship/live-study");

위의 API 설명에 나와있는대로, owner/repo 이름 형태의 문자열을 getRepository 메소드의 인자로 전달해주면

repository 변수를 이용해서 저장소의 issue 에 접근할 수 있게 된다. 

 

issue 를 가져오기 위해서는 아래의 메소드를 이용하면 된다

 

getIssue

위 메소드는 GHIssueState 타입의 인자를 받는데, 뜯어보면 enum 으로 되어있으며 ALL, CLOSED, OPEN 상태가 존재한다.

 

요구사항은 18일차에 대한 참여율을 구하는 것이고, issue 에는 이미 18일차까지의 Issue 가 생성되어 있다

생성된 Issue 중에는 OPEN 된 것도 있고 CLOSED 된 것도 있기 때문에 GHIssueState.ALL 을 인자로 전달하여

Issue 에 존재하는 모든 issue 들을 가져올 수 있도록 했다

 

List<GHIssue> issueList = repository.getIssues(GHIssueState.ALL);

 

▶ 각 Issue 에 달린 comment 들에 접근해보자!

Issue 들에 달린 comment 의 목록을 가져오는 API 는 아래와 같다

 

getComments

이미 issue 들을 순회하고 있고, 현재 issue 에 대한 comment 를 가져오면 되니까 아래처럼 작성하면 된다.

 

List<GHIssueComment> comments = issue.getComments();

 

이제 위의 메소드를 통해 구한 comment의 목록을 순회하면서 작성자들의 이름을 세면 된다

 

▶ comment 의 작성자를 가져와보자

GHIssueComment 클래스에는 유저의 정보를 가져올 수 있는 메소드가 존재한다

 

그리고 GHUser 의 API 를 살펴보니 딱 봐도 이름을 가져올 수 있는 메소드가 눈에 띄었다

 

그런데 이 메소드를 통해서 가져오게 되면 null 을 출력할 때가 있다

 

왜냐하면 유저이름을 설정하지 않은 사용자도 있기 때문에 그런 것 같다

 

그래서 대표적으로 보이는 이름을 가져오려면 어떻게 해야되나 하고 찾아보니 딱 맞는 메소드가 있다

 

 

위 메소드를 통해서 이름을 가져오면 null 을 출력하는 일이 없다

 

위에 나열된 내용을 가지고 코드를 작성하면 과제를 충분하게 수행할 수 있을 것이다

 

 

∴ 결론

- 공식문서에 API 에 대한 예제가 적어 애를 먹었다. (하지만 문서와 설명을 잘 보니 삽질을 했지만 해쳐나갈만 했다)

- 예외처리 할 것들이 있었다. 

     1. 현재 해당 저장소 issue 의 목록은 18개가 아닌 19개이다 (왜냐하면 다른 사용자가 올린 issue도 있기 때문)

        owner 가 발행한 issue 에는 label 이 하나 이상 붙어있으므로 그걸 통해 걸러냈다

     

     2. 하나의 issue 에 코멘트를 여러 개 달아놓은 사용자도 있다. 코멘트를 하나만 세도록 처리하는 작업도 필요했다

- VO 객체 비스무리 하게 만들어서 진행할까 했지만 간단하게 Map 을 통해서 진행했다. 그리고 사실 방법이 잘 떠오르지 않았다..

- 내가 짠 코드가 엉망이어서 그런지..... 이 코드를 수행하는 걸리는 시간이 꽤 걸린다ㅠㅠ

 

그리고 이번 과제를 계기로 처음 블로그에 글도 써보고, 자바를 다시 스터디 하게 되었다.

블로그에 기술관련 글들 등등을 써보고 싶다는 생각을 하고만 있었는데, 

백기선님께서 주최하신 스터디 덕분에 실천으로 옮길 수 있게 되었다

 

이런 귀한 경험을 하게 해주신 백기선님께 감사드립니다!

 

 

[전체코드]

package com.live_study.chulphan;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.kohsuke.github.GHIssue;
import org.kohsuke.github.GHIssueComment;
import org.kohsuke.github.GHIssueState;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;
import org.kohsuke.github.GitHubBuilder;

public class App 
{
    public static void main( String[] args )
    {
    	
    	try {
    		GitHub github = new GitHubBuilder().withOAuthToken("enter-your-api-key").build();
        	GHRepository repository = github.getRepository("whiteship/live-study");
        	
        	List<GHIssue> issueList = repository.getIssues(GHIssueState.ALL);
        	
        	issueList = issueList
        			.stream()
        			.filter(issue -> issue.getLabels().size() > 0)
        			.collect(Collectors.toList());
        	
        	final int numOfHomework = issueList.size();
        	
        	Map<String, Integer> attendeeList = new HashMap<String, Integer>();
        	Map<String, Double> attendeeListWithAttendanceRate = new HashMap<String, Double>();
        	
        	for (GHIssue issue: issueList) {
        		if (issue.getState().equals(GHIssueState.OPEN)) {
        			continue;
        		}
        		
        		List<String> tempUserNameList = new ArrayList<String>();
        		
        		for (GHIssueComment comment: issue.getComments()) {
        			String attendeeName = comment.getUser().getLogin();
        			
        			if (!tempUserNameList.contains(attendeeName)) {
        				tempUserNameList.add(attendeeName);
        			}
        		}
        		
        		for (String attendeeName: tempUserNameList) {
        			if (attendeeList.containsKey(attendeeName)) {
        				int numOfAttendance = attendeeList.get(attendeeName);
        				attendeeList.put(attendeeName, ++numOfAttendance);
        			} else {
        				attendeeList.put(attendeeName, 1);
        			}
        		}
        	}
        	
        	for (String attendee: attendeeList.keySet()) {
        		BigDecimal bd = new BigDecimal(attendeeList.get(attendee) / ((double) numOfHomework)).setScale(2, RoundingMode.HALF_UP);
        		double attendanceRate = bd.doubleValue();
        		
        		attendeeListWithAttendanceRate.put(attendee, attendanceRate);
        	}
        	
        	for (Map.Entry<String, Double> entry: attendeeListWithAttendanceRate.entrySet()) {
        		System.out.println(entry.getKey() + "     " + entry.getValue());
        	}
    		
    	} catch (Exception e) {
    		System.out.println(e);
    	}
    }
}

 

'공부 > whiteship-java' 카테고리의 다른 글

7주차: 패키지  (0) 2021.01.01
6주차: 상속  (0) 2020.12.24
5주차: 클래스  (0) 2020.12.19
4주차 과제: JUnit5  (0) 2020.12.11
4주차: 조건문, 반복문  (0) 2020.12.10