깃 커밋로그를 통해서 출석할 수 있는 시스템을 만들어 보았습니다.
LAB 426
220.67.124.108
Linux 톰캣 서버로 먼저 만들어서 현재는 html, javascript를 이용해서 만들었습니다.
이를 스프링부트를 사용하여 만들어보려고 합니다.
사용하는 github REST API
1. List repositories for a user
사용자의 레파지토리 정보를 가져옵니다.
name이라는 key에 대한 value를 가져와서 저장해두려고 합니다.
2. List commits
date라는 key에 대한 value를 가져와 현재 날짜와 비교하려고 합니다.
깃허브 api 의 시간이 한국시간과 달라서 +9시간을 더해줘야 됬습니다.
Spring에서 HTTP 요청을 위해 사용하는 라이브러리는 RestTemplate, WebClient등이 있고, RestTemplate은 Spring 3.0부터 지원하기 시작했으며, 동기식 요청만 처리 가능한 특징이 있습니다. 최근 Spring 5.0부터 WebClient를 표준으로 삼아 스프링에서 권유하고 있습니다.
Gradle 추가
implementation 'org.springframework.boot:spring-boot-starter-webflux'
1. 사용자의 레파지토리 받아오기
public ArrayList<String> getRepos(String gitId) {
WebClient client = WebClient.create();
String url = "https://api.github.com/users/" + gitId+ "/repos";
Mono<String> stringMono = client.get()
.uri(url)
.retrieve()
.bodyToMono(String.class);
String [] jsonList = stringMono.flux().toStream().findAny().toString().split(",");
ArrayList<String> repoList = new ArrayList<>();
for(int i = 0; i < jsonList.length; i++) {
if(jsonList[i].startsWith("\"name\"")) {
repoList.add(jsonList[i].substring(8, jsonList[i].length()-1));
}
}
return repoList;
}
- WebClient 객체를 생성합니다. 웹 클라이언트 객체는기본적으로 Immutable 하게 생성되므로 싱클톤으로 객체를 생성해서 설정을 그때그때 변경해서 사용할려면 mutable() 속성을 사용하여 생성할 수 있다고 합니다.
- retrieve와 exchange
- retrieve( ) : retrieve() 메소드는 CleintResponse 개체의 body를 받아 디코딩하고 사용자가 사용할 수 있도록 미리 만든 객체를 반환합니다.
- exchage( ) : ClientResponse를 상태값, 헤더와 함께 가져오는 메소드입니다.
Spring 5가 도입되면서 클라이언트 요청에 대해서 별도의 스레드를 생성하지 않고 싱글스레드 논블로킹 방식을 사용한다고 합니다. 원래 스프링은 요청된 작업이 오래걸리는 경우 요청에 대해 처리하기 까지 블록킹 되었는데 동시 요청처리를 위해 멀티스레드를 지원하였으며, 스레드가 많아진다는 것은 자원을 많이 차지하기에 비 효율적이 될 수도 있습니다.
여기서 Mono 클래스는 0~1개의 결과만을 처리하기 위한 Reactor 객체를, Flux는 0-N개의 결과물을 처리하기 위한 Reactor 객체를 말합니다.
++ 비동기 블록킹 프로세스로 동작하는 어플을 지원하기 위한 프로세스를 리액티브 프로그래밍이라고 한다.
2. 해당 레포들의 커밋들 받아오기
public ArrayList<String> getCommits() {
String gitId = "";
ArrayList <String> repoList = getRepos(gitId);
for(String temp : repoList) {
System.out.println(temp);
}
ArrayList<String> commitList = new ArrayList<>();
for(int i = 0; i < repoList.size(); i++) {
try {
WebClient client = WebClient.create();
String url = "https://api.github.com/repos/" + gitId + "/" + repoList.get(i) + "/commits";
Mono<String> stringMono = client.get()
.uri(url)
.retrieve()
.bodyToMono(String.class);
String[] jsonList = stringMono.flux().toStream().findAny().toString().split(",");
for (int j = 0; j < jsonList.length; j++) {
if (jsonList[i].startsWith("\"date\"")) {
System.out.println(jsonList[j]);
commitList.add(jsonList[i].substring(8, jsonList[i].length() - 3));
break;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
return commitList;
}
레포들을 받아오는 api와 마찬가지로 코드를 구성하였고, api에 대한 응답은 시간순서대로 정렬되기에 첫번째 커밋에 대한 시간만 저장하고 멈추었습니다.
3. 깃허브 시간과 한국시간으로 변경
public boolean addTime(String date_time) {
LocalDateTime localDateTime = LocalDateTime.parse(date_time);
localDateTime.plusHours(9);
if(LocalDate.now().isEqual(localDateTime.toLocalDate())) {
return true;
}
return false;
}
깃허브 시간과 9시간 차이나는 것을 해결하기 위해 LocalDate 클래스를 사용하여 비교하였습니다.
4. 커밋 시간을 통한 출석 체크
public String attendanceCheck() {
ArrayList<String> commitList = getCommits();
for(int i = 0; i < commitList.size(); i++) {
String date_time = commitList.get(i);
if(addTime(date_time)) {
return "오늘 출석하였습니다.";
}
}
return "출석하지 못하였습니다.";
}
너무 많은 API 호출로 인해서 403 forbidden 에러가 발생하였고 나의 IP가 금지된 것 같은데 이것을 해결하는 방법과 지금은 이해없이 인터넷에 있는 그대로를 사용하였는데 webclient나 mono, flux에 대해서도 이해해보려고 노력해보겠습니다.
참고자료
https://thalals.tistory.com/379
[Spring] WebClient 사용방법 가이드
아래의 글 순서대로 읽으시면 해당 글을 이해하시는데 족흠 도움이 됩니다 🙏 ⚙️ Block, Non-Block, sync(동기), Async(비동기) 의 간단한 개념 [Spring] Webclient 란❓ (RestTemplate vs WebClient) [Spring] WebClient
thalals.tistory.com
https://sunshower99.tistory.com/15
[WebClient] Spring에서 API 호출하기
🔹 배경 외부 API를 사용하기 위해 요청/응답을 처리하는 방법을 연습합니다. Spring에서 HTTP 요청을 위해 사용하는 라이브러리는 RestTemplate, WebClient등이 있습니다. RestTemplate은 Spring 3.0부터 지원하
sunshower99.tistory.com
https://docs.github.com/ko/rest?apiVersion=2022-11-28
GitHub REST API 설명서 - GitHub Docs
통합을 만들고, 데이터를 검색하고, 워크플로를 자동화하고, GitHub REST API를 사용하여 빌드합니다.
docs.github.com
'🍃 스프링' 카테고리의 다른 글
[SPRING] Entity, DTO (0) | 2023.07.24 |
---|---|
[SPRING] JPA (0) | 2023.06.05 |
[SPRING] IntelliJ 설정 (0) | 2023.05.15 |
[SPRING] 남의 코드 이해하기 (1) | 2023.05.07 |
[SPRING] Filter, Interceptor (0) | 2022.10.06 |