들어가기 전에: 아래 설명하는 내용은 2021년 여름방학을 이용한 첫 배포까지의 과정을 담고 있습니다. 2022년 3월에 저 혼자 진행한 2.0 버전에서는 많은 내용이 달라졌는데 이 내용이 궁금하시다면 댓글 바람.
서담서치 (ssodam search)는 서강대학교의 컴퓨터 중앙동아리 SGCC 멤버 다섯명이서 만든 크롬 익스텐션이다.
이 익스텐션은 서강대학교 de facto 공식 커뮤니티 사이트인 서담의 내용을 검색하는데 사용할 수 있다. 사용자는 본인이 서담 유저임을 인증하면, 익스텐션 내에서 검색 기능을 사용할 수 있다. 검색은 서담의 모든 게시물을 대상으로 하며, 본문과 제목 또는 둘 중 하나만 골라 형태소 검색을 할 수 있다.
https://bit.ly/ssodamsearch 에서 다운받을 수 있지만 서강대학교 학생이 아니면 사실상 사용이 불가능하다.
서담 자체에 검색 기능이 없나요? 있다. 그런데 문제가 많다:
예시를 들어보자면:
서담의 게시물이 다음과 같이 5개 있다고 해보자:
학교 주변에 미용실 좋은데 추천좀
신촌 주변 미용실 추천해주실 분 계신가요?
미용실추천좀미용실추천좀미용실추천좀미용실추천좀미용실추천좀제발추천좀
다미들아 학교 주변에 괜찮은 미용실 (남자) 추천좀!
대흥역 주변 남자 미용실 추천좀
이 상황에서 '미용실 추천좀'으로 검색했을 때 나오는 결과는 마지막 하나 뿐이다. '정확하게' 일치해야만 한다.
커뮤니티 사이트에서 검색 기능을 쓸 일이 많지는 않다. 보통은 가장 최근에 올라온 인기게시물만 보니까. 그렇지만 막상 검색할 때 불편한 건 사실이다. 이에 대해선 내가 다른 블로그에 쓴 글을 읽어보시길: https://roeniss.tistory.com/entry/모호한-질문의-문제점-부제-플랫폼의-책임
위와 같은 상황에서, 자연스러운 반응은 '업데이트를 건의한다' 내지는 '업데이트를 기다린다'일 것이다. 검색이라는게, 사이트 안에 존재하는게 아주 자연스럽지 않은가.
하지만 그럼에도 불구하고 별도의 익스텐션으로 분리해야겠다는 생각이 들었는데 그건 다음과 같은 이유들 때문이었다:
그리고 아래 설명할 4명의 멤버가 추가됨으로서, 두개의 목표가 더 추가되었다:
아무튼 그럼에도 불구하고 익스텐션이 있어야만 온전히 검색 기능을 누린다는 디자인은 분명 기괴하다. 하지만 뭐... 그건 일단 그 정도에서 생각을 중지했다.
서담 운영자에게 공식적으로 크롤링 허가를 받으면서 (mysql 데이터를 전달받는 것이 더 좋았겠지만, 귀찮아할 것 같아서 별로 안좋아할 것 같아서 아예 얘기도 안꺼냈다) 동시에 전체적인 청사진을 그렸다.
이 모든 것을 구축하는 건 나 혼자로도 어찌저찌 가능했을 것이다. 하지만, 그런 (나 혼자 뚝딱 해치우고 만족하는) 종류의 프로젝트에 순간적으로 염증이 났고, SGCC (Sogang Computer Club) 디스코드에서 멤버를 모집했다. 찾아보니.. 7월 5일이다:
[오후 1:54] roeniss: #서담서치 (좋은 이름 추천받음)
만들어야 하는 것
- 1. 크롤러 : 서담 글을 주기적으로 크롤링해서 검색 서버에 적용해야됨.
- 3. 크롬 익스텐션 : 아래 첨부한 네이버영어사전 같은 UI를 만들어야 됨.
- 5. API 서버 (및 CF 세팅) : 회원가입/로그인/계정인증 & 검색엔진에 요청 보내고 결과 리턴
- 6. 검색서버 : 엘라스틱 서치 서버
[오후 1:54] roeniss: (*위에 올린 다이어그램 이미지*)
[오후 1:55] roeniss: 대단한 실력자 찾는 거 아니고, 완벽하지 않아도 괜찮습니다. 어차피 코드 다 볼거니까...
이력서 프로젝트란에 적을 수 있는 형태로 만들어 가시면 될 듯 해요.
참여하실 경우 위에 4개 중 일부를 담당하게 되십니다.
아예 모르는 사람은 곤란하고, 적당히 아는 것 같은데 정확히 뭘 만들어야되는지 모호하다면 오늘 밤 11시 디코 음성채널에서 물어보세용 (10분동안 기다리고 아무도 안오면 감)
후배님들에게 좋은 포트폴리오 소재를 주고 싶다는 생각도 했지만, 이내 그건 본인이 알아서 잘 챙겨가는 거라고 고쳐 생각했다. '나는 밥상을 디자인하고, 상에 올라가는 찬들은 당신들이 만들고. 나는 다 된 밥상을 만들도록 가이드하고, 당신들은 하나씩 만들다가 뭔가 자랑할 게 생긴다면 ㅡ 혹은 자랑할 수준으로 만들 수 있다면 ㅡ 좋은거고.' 그런 생각이었다.
개발하지 않고 프로젝트를 완성하는 것이 나의 목표였다.
"어차피 코드 다 볼거니까"는 PR을 내가 리뷰한다는 뜻이었다. 어차피 멤버들이 가급적 서로 독립된 소스코드를 보도록 할 것이었기 때문에 상호 리뷰는 사실상 포기한 채 출발했다.
최종적으로 4명의 멤버가 추가되었다. 두 명의 파이썬 개발자 (한 명은 크롤링에 대하여, 다른 한명은 엘라스틱 서치에 대하여 오너십을 부여), 한 명의 리액트 개발자, 한 명의 노드(node.js) 개발자. 그 외의 것들 (인프라, 홍보, 대외협력(?), 문의접수, 프로젝트 관리)은 내가 했다.
매우 중요한 지점 하나는, 지원한 사람들에게 별도의 자격 또는 테스트를 요구하지 않았다는 점이다. 나는 그렇게 함으로서 그들에게 자기 제품에 대한 오너십을 줄 수 있을 것이라 판단했다. 가이드는 주되 구현에는 관여하지 않는 방향으로 말이다.
지라와 위키를 합쳐놓은 무언가인데, 젯브레인이 만들었기에 믿고 써봤다. 전반적으로 다루기 쉬웠는데 바꿔말하면 아주 약하게 다뤘기 때문에 심도있는 평가는 못하겠다.
도합 150개 이슈 정도가 완료 또는 진행중이고, v1.0.0 배포를 위한 이슈는 모두 처리되었다 (8/22 현재 배포 심사 진행중).
위 사진에서 볼 수 있듯 각 컴포넌트 별로 Project를 쪼개는 방법을 택했다. 사전작업
을 제외한 각 프로젝트는 각각 깃헙 레포 하나씩 연결되어있어서 PR 머지 커밋으로 Resolve 할 수 있다.
위 사진처럼 Knowledge Base 라고... 팀 내 위키를 운영할 수 있다. API 서버
쪽의 API 관련 문서는 이후 Swagger 로 대체되었고, 다음 스크럼 때 할 얘기
는 내가 까먹을까봐 몇가지 사항들을 가끔 적어놓던 것. 나머지는 문서로 남겨둘만하다고 판단되어 적은 것들이다.
개별 이슈는 이런 식으로 생겼다. 참고로 디폴트값으로는 State
가 한 여덟개 있는데 Submitted
, Resolved
, Canceled
빼고 다 지웠다. Progressing
인가? 하여튼 '진행중'을 나타내는 것을 지운 이유는 지라가 익숙치 않은 분들을 대상으로 너무 많은 것을 요구하는 것 같았기 때문이다.
Free-pan Orgranization 은 PR 리뷰어를 한 명만 지정할 수 있구나.. 그렇구나...
몇몇 컴포넌트는 main 브랜치에 커밋되면 (즉 main에 바로 푸시 또는 PR에서 머지) 라즈베리파이에 바로 반영되도록 하였다. '자주' 변경이 있을 것 같은 api 서버와 crawling 서버에 대해 적용했는데 아주 좋은 판단이었다. 참고로 작동하는 방식은:
circleCI에서 특정 레포의 워크플로우 활성화
코드 커밋
github에서 circleCI로 웹훅 전송
circleCI의 자체 서버가 돌아가기 시작
circleCI에 등록해놓은 ssh key로 라즈베리파이 접속
해당 레포 코드가 있는 폴더까지 이동
코드 최신화 (git pull)
도커 이미지 새로 굽기 (docker build . -t ssodam-search/ss-api:latest)
기존 컨테이너 부시고 새 컨테이너 올리기
그렇다. 무중단 배포 같은 건 없다.
아래에서 다시 설명하겠지만 모든 컴포넌트를 각각 도커로 말아서 적용했다. docker-compose
를 사용해볼까 했는데, 여러 서비스가 독립적으로 돌아가는게 맞다고 판단하여 그냥 각각 돌아가게 냅두기로 했다.
불쌍한 나의 라즈베리파이 (이하 Betty)는 별 의미도 없이 매일 열을 뿜는 기생충에서, 이번 기회로 유의미한 서버로 레벨업했다. 클라우드 서비스 대신 베티를 사용해야겠다는 생각은, 백준 온라인 저지가 자체 서버를 사용해 채점한다는 점에서 착안했다 (이젠 아닌듯).
그리고 계산해보니, 왜 클라우드가 비싸다고 하는지 알 수 있었다. 베티와 비슷한 성능의 ec2 인스턴스의 가격은 오하이오 리전 기준으로 최소 월 5만원은 필요했다. 반면에 우리의 베티는 대충 32기가 SD카드를 포함해 12만원 정도. 물론 bandwidth와 file I/O는 많이 후달리지만...
진행상황을 어떻게 요약하지.. 하다가 최종적인 결과물을 보면서 얘기하는게 낫겠다 싶어서 바로 결과로 진행한다.
중간중간, 그리고 거의 막바지에 멤버들에게 전체 아키텍쳐를 반복해서 설명했다. 이 프로젝트가 정말로 그들 자소서에 도움이 되려면, 본인이 맡지 않은 부분에 대해서도 이해하고 있어야 한다고 생각했다. 이 프로젝트는 MSA가 되도록 반쯤 의도했고 반쯤은 우연히 맞아 떨어졌기 때문에 더더욱 그러하였다.
그림이 좀 난해할 수도 있는데 위에서부터 보자.
R은 베티를 말하는 거고, 베티 속의 작은 네모들은 모두 도커 컨테이너다.
우리 서비스는 매우 특이한 인증 방식을 쓰고 있다. 이름하여 서담 간접 인증 시스템
. 방식은 이러하다.
이렇게 하지 '않으면서' 서강대 학생임을 인증하는 유일한 방법은 sogang.ac.kr 이메일로 본인인증을 하는 것이다. 그렇게 안 한 이유는:
참고로 이건 우리가 처음하는 건 아니다. 초창기 op.gg 와 solved.ac 가 이 방식을 직/간접적으로 채택했다. 흠흠.
아무튼 이런저런 단점과 장점이 다 있지만, 이미 서강대 학생이라고 잘(?) 인증된 사람만 가입할 수 있는 서담의 회원인지 확인하는 방법으로! 서강대 학생인증을 delegate 했다.
--rm
옵션이 붙어있다.ip updater
와 마찬가지로 베티의 크론잡으로 걸려있는 --rm
컨테이너다. 컨테이너로 할 필요는 없었는데 그냥 함.아키텍쳐와 그 구현에 대한 나의 총평은 "Recoverability는 확보했지만 Observability가 없음"이다. 장애가 났을 때 빠르게 인지하기 힘들고, Logging 이 부실하고 중앙화되지 않아 상황 파악이 어렵다. 따라서 어쩌다 한번씩 내가 베티에 접속해 떠있는 컨테이너들의 상태를 보지 않는 이상... 문제가 발생했는지도 모르는 상황이 생긴다. :(
이정도면... 설명해야 하는 건 다 설명한 것 같다. 이러한 종합적인 결과물을 구상한 가장 큰 이유는 (위에서도 말했지만) 후배님들이 '뭔가 실무스러운 것' 혹은 '자소서에 적을만한 신선할 것' 혹은 '그동안 못해본 프로젝트' 를 체험했으면 좋겠다는 생각이 있었기 때문이다. 그렇다. 나는 참말로 은혜로운 선배이다.
이 이상의 디테일한 설명이 필요한 부분은 댓글로 문의 주시라. 내가 답할 수 있는 선에서 최대한 자세히 얘기해드리겠다.
많이 있는데, 생각나는대로 두서없이 적어본다. 자세한 설명도 적지 않는다. 길게 말하는 편이 구차할테니.
그리고 혹시라도 우리 팀원 중 누군가 이걸 볼까봐 미리 말해두는데, 여러분은 단 한 명도 빼놓지 않고 모두 잘 임무를 완수했다. 그걸 잊으면 안된다. 물론 내가 생각한 것보다 살짝 지체되긴 했지만, 어쨌든 원래 계획대로 9월 개강 전에 할 수 있는 걸 다 했지 않은가. 고생하셨고, 잘해주셔서 감사.
ps) 미래의 나에게: https://muchtrans.com/translations/10xdeveloper.ko.html?hide-original=true
😄