1일 1커밋을 습관화 하기 위한 스케줄러

짱구·2024년 3월 28일
13
post-thumbnail

개요

나는 원래 커밋에 강박을 가지는 사람이 아니었다.
커밋을 주기적으로 하지는 않았고 퇴근하고 집에서 공부, 작업한 것을 한번에 커밋했었다.
전에 다니던 회사 선배분이 매일 커밋하는 것을 습관화하셨고 꾸준히 공부하는 것을 지표로 남기는걸 보니 '나도 해봐야겠다' 라는 생각이 들어 1일 1커밋 이상을 목표로 하고 실천했다.

물론 가끔씩 커밋을 빼먹는 날도 있었고 예비군 동원 훈련을 가서 커밋을 하지 못하는 날도 있었다.
이왕하는거 매일하자 라는 생각으로 매일 커밋하는 것을 체크하고 반강제적으로라도 커밋을 일상화해야겠다고 생각했다.
그래서 나는 매일 전날의 커밋을 체크하고 커밋을 하지 않았다면 부모님, 혹은 여자친구에게 10,000원씩 송금을 하게 스케줄러를 개발했다.

Issue

하지만 api 형식으로 돈을 송금을 하려면 사업자등록이 필요하기도 했고 여러가지 문제가 되는 부분이 존재하여 문자 메시지로 알림 서비스를 구현을 했다.

    suspend fun sendSms() = coroutineScope {
        val message = Message(
            from = cherhyProperty.coolsmsFrom,
            to = cherhyProperty.randomPhoneNumber,
            text = "내일 저녁에 밥살게",
        )

        messageService.sendOne(
            SingleMessageSendingRequest(message)
        )
    }

1 Day 1 Commit

일단 개발 환경은 kotlin, webflux 환경이다.
이러한 기술을 선택한 이유는 아래 워크플로우를 보면 이해가 갈 것이다.

  • github에 api를 요청해서 '나의 모든 repository의 이름'을 가져와야한다.
  • 그리고 repository 이름을 모두 가져왔다면 repository 하나하나의 커밋 정보를 가져와야한다.
  • 그러면 내 public repository의 수만큼 api를 호출해야하는데 총 60번이상 api를 호출한다.
  • 동기 방식으로 하게된다면 스케줄러가 실행될 때 너무 오래 걸리기도 하고 현재 회사에서 webflux를 사용해야하기 때문에 학습의 목적을 둬서 비동기 방식으로 진행을 했다.

Code

	suspend fun getCommitsCountForYesterday() = coroutineScope {
        val githubRepositoryNames = getRepositoryNames()

        val commits = githubRepositoryNames.map { repositoryName ->
            async { getCommits(repositoryName.name) }
        }.awaitAll().flatten()

        commits.count { it.yesterdayCommit }
    }

getRepositoryNames, getCommits에 대한 메서드까지 적게 된다면 글이 쓸대없이 길어지기 때문에 간단하게 워크플로우만 정의했다.
만약 코드가 궁금하다면 하단에 있는 링크에서 코드를 확인해보면 좋을거같다 :)

커밋 성공 프로세스

커밋을 하루에 한번이상 했을 때는 Slack으로 수고했다는 메시지가 온다...ㅎ

1 Month 1 Blog

커밋에만 신경을 쓰고 블로그 작성을 최근에 하지않아 블로그도 1달에 한번 이상은 꼭 작성을 해야겠다고 생각을 했다.
퇴근 후 여유가 없어도 1달이라는 시간은 충분히 블로그도 작성할 수 있는 시간이라고 판단했고 기존 커밋 체크 스케줄러 서버에 블로그 체크 스케줄러를 추가했다.

Code

velog는 UI적으로 깔끔해서 좋지만 여러 open api를 지원해주지 않아서 직접 크롤링을 해야했다.
스케줄러가 돌아갈때 '마지막 게시물의 ID 값'과 '현재 Velog에서 크롤링 해온 최신 게시글의 ID 값'을 비교하는 방식으로 코드를 작성했다.
비용적인 부분을 생각해서 데이터베이스를 사용하지 않았고 마지막으로 작성한 블로그의 ID 값을 파일에 적어뒀다.

	coroutineScope {
		val thisMonthBlogId = async { blogClient.getLastPostId() }.await()
    	val lastMonthBlogId = async { fileComponent.readLastBlogId() }.await()
        // thisMonthBlogId 와 lastMonthBlogId 비교...최신화...로직은...생략하겠습니다...
    }
    
    suspend fun getLastPostId() = fetchRenderedBlog().latestId
    
    suspend fun readLastBlogId() = withContext(Dispatchers.IO) {
        val file = File(locationProperty.blogPath)
        file.readText()
    }

배포

스케줄러 서버기 때문에 많은 리소스가 필요하지 않아 aws ec2 프리티어로 배포했다.
local에서 build 된 jar file을 aws ec2로 복사하여 실행시켰다.

앞으로

주변에 열심히 하고 싶어하는 개발자들도 스케줄러에 같이 합류 시키고 싶은 바램이 있다.
또한 기회가 된다면 부모님의 사업자 등록증을 빌려 송금하기 api, 선물하기 api를 활용하고 싶다.
현재 하루에 1커밋을 최소로 두고 있지만 2커밋, 3커밋 이상씩 강도를 높혀 올해 4,000 커밋을 목표로 하고 있다.

Github 주소입니다 :)

profile
코드를 거의 아트의 경지로 끌어올려서 내가 코드고 코드가 나인 물아일체의 경지

2개의 댓글

comment-user-thumbnail
2024년 4월 9일

너무 멋지네요 :) 좋은 글 감사합니다~

1개의 답글