2023년 2월 6일부터 2주가 안되는 기간 동안 토이 프로젝트를 진행했다.
프로젝트 목표는 내 GitHub의 Problem-Solving 레포지토리와 Profile 레포지토리의 README.md 파일 생성을 자동화하는 것이었고, 프로젝트를 마치면서 목표를 달성했다.
프로젝트 목표는 트위터에서 한 글을 읽고 정하게 되었다. 사실 동일한 주제다. 다른 점이라면 개발 언어 정도 되겠다.
트위터에서 즐기는 연로그
“[New Post] [토이 프로젝트] 깃허브 프로필에 최신 포스트 자동 업데이트하기 https://t.co/HU7AqP7RHj”
twitter.com
개발 언어를 Python으로 정한 이유는 다음과 같다(나는 주로 Java를 사용한다).
- 여러 언어를 잘 다루고 싶어서
- 알고리즘 문제 풀이용 언어를 바꾸고 싶어서(현재 Java를 사용한다)
- 서버에서 스크립트용으로 쉽게 사용할 수 있어서(shell script 대신에..)
프로젝트 개요
인원 : 김경석
기간 : 2023-02-06 ~ 2023-02-16
사용 기술 : #Python #GitHub Actions
Problem-Solving
프로젝트를 통해 해결할 문제는 GitHub 레포지토리 README.md 파일을 수동으로 갱신하는 것이었다. 나는 매일 1문제 이상의 알고리즘 문제를 풀고 풀이 코드를 GitHub에 올린 뒤에 README.md 파일에 링크를 추가해왔다. 과정을 정리하자면 다음과 같다.
- 알고리즘 풀이 코드 작성
- 풀이 코드를 GitHub에 push
- 링크를 README.md 파일에 추가
- README.md 파일을 GitHub에 push
위 과정에서 3, 4단계를 자동화하고 싶었다. 풀이 코드를 GitHub에 push 했을 때 GitHub Actions를 활용하면 자동화할 수 있을 것으로 생각했고, 실제로 가능했다.
Profile
Profile 레포지토리의 경우 그동안 주기적으로 내용을 갱신하지는 않았다. 다만 최근에 블로그에 스프린트 회고 글이나 정리 글을 작성하고 페이스복과 트위터에 블로그 글을 공유해왔는데, 트위터 글을 읽고 나서 GitHub Profile에도 블로그 글을 올려야겠다는 생각이 들었다. Problem-Solving 레포지토리 작업을 먼저 진행하면서 개발한 코드를 일부 재활용했기 때문에 큰 어려움 없이 진행할 수 있었다.
동작 과정
동작 과정은 Problem-Solving, Profile 레포지토리 모두 비슷하다. 이벤트 발생 시 레포지토리의 README.md 파일을 생성한다. 각 레포지토리의 이벤트는 GitHub Actions의 workflow 설정 파일에 정의하였고, 이벤트에 의해 GitHub Actions가 동작하면 Python 코드가 실행되어 README.md 파일이 생성된다.
- Problem-Solving, https://github.com/0xe82de/Problem-Solving/blob/master/.github/workflows/create-readme.yml
- push : git push 발생시 처리
- Profile, https://github.com/0xe82de/0xe82de/blob/master/.github/workflows/get-blog-recent-posts.yml
- workflow_dispatch : 수동 처리
- schedule : 특정 시간에 처리
- push : git push 발생시 처리
Problem-Solving 주요 로직
class SourceFile:
def __init__(self, filename):
tokens = filename.replace(".", "_").split("_")
self.site = tokens[0].lower()
self.number = int(tokens[1])
self.solving_count = tokens[2]
self.language = self.get_language(tokens[3])
self.filename = filename
def search(directory):
return reduce(lambda source_files, searched_source_files: source_files + searched_source_files,
[
search(os.path.join(directory, filename)) if os.path.isdir(os.path.join(directory, filename))
else [SourceFile(filename)]
for filename in os.listdir(directory)
],
[])
def search_source_files(directories):
return reduce(lambda source_files, directory: source_files + search(directory),
directories,
[])
directories = ["python", "java"]
Problem-Solving 레포지토리 Python 스크립트의 주요 로직은 알고리즘 풀이 코드 파일을 탐색하는 것이다. search_source_files 함수로 directories 리스트를 전달하면 search 함수로 하위 디렉터리에 존재하는 모든 소스 파일을 찾고 소스 파일 정보를 담는 SourceFile 객체 리스트를 생성한다. reduce를 활용해서 데이터를 처리했다.
디렉터리 구조는 다음과 같다.
전체 코드는 다음 링크에서 볼 수 있다.
GitHub - 0xe82de/Problem-Solving: 알고리즘 문제 풀이 코드
알고리즘 문제 풀이 코드. Contribute to 0xe82de/Problem-Solving development by creating an account on GitHub.
github.com
Profile 주요 로직
class Post:
def __init__(self, no, title, date):
self.no = no
self.title = title
self.date = date
self.link = TISTORY_BLOG_URL + str(no)
def parse_html():
response = requests.get(TISTORY_BLOG_URL)
soup = BeautifulSoup(response.content, "html.parser")
div = soup.find("div", {"id": "recent"})
return div.find_all("a")
def create_posts(a_tags):
return [Post(int(a_tag["href"][1:]),
a_tag.find("span", {"class": "title"}).text,
a_tag.find("span", {"class": "date"}).text)
for a_tag in a_tags]
posts = create_posts(parse_html())
Profile 레포지토리 Python 스크립트의 주요 로직은 블로그 웹사이트의 HTML을 파싱해서 블로그 글 정보를 가져오는 것이다(티스토리 API를 활용하려 했지만.. 실패했다. 관련 내용은 뒤에서 나올 아쉬운 점에서 확인할 수 있다). parse_html 함수로 블로그 웹사이트 HTML을 파싱하고 create_posts 함수로 블로그 글 정보를 담는 Post 객체 리스트를 생성한다. bs4 라이브러리를 활용해 HTML을 파싱했다.
전체 코드는 다음 링크에서 볼 수 있다.
GitHub - 0xe82de/0xe82de
Contribute to 0xe82de/0xe82de development by creating an account on GitHub.
github.com
느낀 점
아쉬운 점
아쉬운 점은 딱 한 가지다. Profile 레포지토리의 README.md 파일을 생성하는 과정에서 블로그 글 정보를 가져오는 방법으로 HTML 태그를 파싱하는 것이다.
블로그 글 정보를 가져오기 위해 처음에 시도한 것은 티스토리 API였다. 티스토리는 오픈 API를 제공하는데, 이 API를 사용해 블로그 글 정보를 가져올 수 있다. 문제는 GitHub Actions 만으로 티스토리 API 사용이 어렵다는 점이다.
우선 티스토리 API를 사용하려면 인증을 통해 Access Token을 받급받아야 한다. 이 과정은 OAuth 2.0의 Authentication Code 방식으로 수행된다.
Authorization Code 방식 · GitBook
No results matching ""
tistory.github.io
GitHub Actions에 의해 실행된 Python 코드에서 티스토리 API를 사용하는 과정을 정리해 보면 다음과 같다.
- GitHub Actions에 의해 Python code 실행
- 티스토리 API 인증 요청
- Authentication code를 전달받을 서버 주소를 redirect_url로 지정해야 한다.
- 인증 성공 시 티스토리는 redirect_url에 지정된 서버 주소(GitHub Actions)로 Authentication code를 보낸다.
- GitHub Actions는 Authentication code를 전달받아서 다시 티스토리로 Access Token 발급을 요청한다.
- 발급에 성공하면 응답으로 Access Token이 반환되고, 이 토큰을 사용해 블로그 글 정보를 가져온다.
위 과정에서 3단계가 불가능하다(혹시 가능하다면 댓글로 검색 키워드를 알려주시면 감사하겠습니다).
우선 3단계의 redirect_url은 다른 GitHub Actions workflow를 지정해야 한다. 이유는 GitHub Actions workflow는 시작될 때마다 endpoint 주소가 새롭게 생성되기 때문이다. 즉, 인증 요청 시 redirect_url을 알 수 없다.
따라서 GitHub Actions만을 사용한다면 인증 성공 시 Authentication code를 전달받을 새로운 workflow를 만들고, 해당 workflow에 workflow_dispatch 이벤트를 설정해 외부(티스토리)에서 이 workflow를 시작할 수 있도록 해야 한다.
문제는 여기서 발생한다. 외부(티스토리)에서 특정 GitHub Actions workflow를 동작하게 하려면 GitHub에서 발급받은 personal token을 사용해야 한다. 그런데, 티스토리에서 redirect_url에 지정된 서버(GitHub Actions workflow)로 Authentication code를 전달할 때 GitHub personal token을 함께 전달할 수 없다.
이 문제 때문에 티스토리 API를 활용하지 못했다. 티스토리 API를 사용하려면 Authentication code를 받기 위한 별도의 서버가 필요해 보인다.
좋았던 점
Python, 토이 프로젝트
Python으로 무언가 만들어본 것이 처음은 아니다. 2019년에 피싱사이트 탐지를 위해 웹사이트 정보를 가져와서 처리하는 프로그램을 Python으로 구현했었다(당시에는 개발 공부를 하지 않았고, 정보 보안을 공부했다. 이제 와서 생각해 보면 정보 보안을 잘 하려면 어느 정도의 개발 지식이 필요하다고 생각한다).
현재에 와서 나는 Java와 Spring을 사용하는 개발자가 되었고, 이 과정에서 Java만 공부하고 사용해왔다. 매일 Java를 사용하면서 다른 언어를 1~2개 정도 배우고 싶은 마음과 토이 프로젝트에 대한 갈증이 생기면서 토이 프로젝트를 진행하게 되었다.
그 결과 Python을 다시 공부하고 간단한 프로그램을 만들어보기까지 했다. 굉장히 간단하고 부족함이 많은 프로그램이지만, 몇 개월 동안 개발을 제대로 하지 못했던 스트레스가 풀리는 느낌이었다. 운영 위주의 실무와 이론 위주의 학습이 몇 개월 동안 지속되면서 개발에 대한 갈증이 쌓였는데, 이번 기회를 통해 어느 정도 해소가 된 것 같다(아직 많이 남아있지만..).
그래서 앞으로도 꾸준히 토이 프로젝트를 진행하려고 한다(업무와 관련된 공부도 꾸준히 하면서).
그리고 Python을 공부하고 사용하면서 들었던 생각이 몇가지 있었다. 아직 Python을 잘 모르기에 필요하다면 많은 공부를 할 생각이지만, 프로젝트를 진행하면서 들었던 생각을 아래에 적어두고, 나중에 드는 생각과 비교해봐야겠다.
- 명명 규칙이 Java와 달라 익숙해지는데 조금 시간이 걸렸다.
- 파이참 IDE는 쓸만하다.
- 문법이 간단해서일까? Java보다 개발 속도가 빠른 것 같다.
- 생성자 오버로딩이 안되어서 당황스러웠다.
- Python의 class는 아직 어렵다.
취업을 하고 나서 처음 토이 프로젝트를 진행해봤다. 역시 개발은 재밌다. ㅎㅎ
'후기 & 회고' 카테고리의 다른 글
1주 1스프린트 12회차 회고 (0) | 2023.02.25 |
---|---|
1주 1스프린트 11회차 회고 (0) | 2023.02.18 |
1주 1스프린트 10회차 회고 (0) | 2023.02.11 |
1주 1스프린트 9회차 회고 (0) | 2023.02.04 |
1주 1스프린트 8회차 회고 (0) | 2023.01.29 |
댓글