42_CheckIn 둘러보기

너무너무 불편해

단점을 장점으로 승화시키기

저에게는 오래 전부터 지독한 병이 하나 있습니다. 바로 불안감이 많아서 걱정하지 않아도 되는 것까지 강박적으로 확인하고 불안해하는 것이죠.
그래서 얼마 전 바뀐 42서울의 출입 시스템은 저에게 큰 스트레스였습니다.
입/퇴실 시에 직접 번호를 입력해야했고 제 닉네임도 입력해야했죠. 이 과정에서 과연 내가 들어올 때 쓴 번호와 나올 때 쓴 번호는 같은지, 닉네임이 대문자로 시작하는데 이런건 괜찮은건지… 걱정할 거리가 너무 많았습니다.
이런 불편함은 사실 저만 느끼고 있는 것은 아니었습니다. 폴라베어님이 진행한 유튜브 미팅에서도, 오프라인에서 만나는 주변 동료들도 하나같이 입을 모아 불편함을 이야기하고 있었죠.
다만 제가 조금 더 스트레스를 많이 받을 뿐이었습니다. 짜증만 낸다고 달라질 건 없겠죠. 남들보다 더 불편한 저의 단점을 남들보다 먼저 문제를 해결하려고 시도해본다는 장점으로 바꿔보고 싶었습니다.

생활의 불편을 해소하는 개발!

저의 진심, 모두의 불편함이 계기가 된 개발이라서 그랬을까요? 처음 완성된 서비스를 공개했을 때 반응은 제가 기대한 것보다 훨씬 좋았습니다.
무엇보다도 멘토님의 이런 반응이 저를 뿌듯하게 했어요.

지덕체 이후로 달라진 점

일단 저지를 수 있는 용기, 자신감

저의 블로그를 읽으신 분들, 혹은 저를 아시는 분들이라면 다들 아시겠지만 덕밥에서 지덕체로 이어지는 저의 프로젝트는 개발자로서의 저의 인생, 그리고 인간 김륜영으로서의 인생에 많은 변화를 가져왔습니다.
무엇보다도 가장 큰 것은 우유부단했던 제가 일단 해보고 싶은게 생기면 저질러 볼 수 있는 용기가 생겼다는 것, 그리고 그 용기를 뒷받침 할 수있는 아주 조금의 실력이라는 것이 생겼다는 점이었던 것 같습니다.
그래서 이번에도 해볼까?라는 생각이 들었을 때 지체없이 바로 시작할 수 있었습니다.

코드를 싸는(?) 사람은 되지 말자

사실 이렇게 빠른 기간 내에 서비스 하나를 만들어 본 또 한 번의 경험이 더 있었는데요. 바로 42서울 해커톤에서 만든 42OPGG였습니다.
다만 그 때 제가 가장 크게 느꼈던 것은 구조에 대한 깊은 고민도 없이 그냥 ‘빠르게 코드를 싸고 있는 것 같다’였습니다.
그래서 이번에는 빠르게 하지만 조금은 고민이 담긴 코드를 작성해보고 싶었어요.

가는 길이 명확하면 동료를 구하기 쉬워진다

분명히 길을 정하다

처음 이 서비스를 구상했을 때는 프론트와 백엔드 모두 빠르게 혼자서 하고 끝낼 생각이었습니다.
하지만 백엔드 개발자가 되어야겠다고 확고하게 결정한 이후로 프론트엔드 개발에 크게 흥미가 생기지 않았고 그러다 보니 시간도 오래걸리고 완성도도 떨어질 것 같았습니다.
그래서 프론트엔드 팀원을 구하고 대신 백엔드에 조금 더 많은 정성을 기울여 좋은 코드를 만들어보자고 생각했고, @juhlee님을 팀원으로 모시게 되었습니다.

빠르게 나아가기

일단 목표가 정해져있고, 백엔드가 거의 완성된 상태에서 팀원을 구했기 때문에 서비스 개발에 막힘이 없었습니다. 프론트 개발이 시작되고 얼마 지나지 않아 서버 환경 세팅을 마치고 서버에서 API를 바로 불러올 수 있는 환경까지 구성되어 둘 사람 다 빠르게 빠르게 서비스를 완성해나갈 수 있었습니다.

우당탕탕

좋은 코드를 위한 고민들

지덕체를 nestjs로 컨버팅하는 과정에서 아주 조금은 해봤지만 어쨌든 이번 서비스가 저에게는 처음으로 RDBMS를 이용해 개발하는 것이었습니다.
그래서 아주 간단한 엔티티 구조라도 신경을 써서 고민해봤습니다. 42CheckIn에는 두 개의 큰 엔티티가 존재합니다. 바로 user와 card인데요. 이들은 당일에는 1대1 관계이지만 전체적으로 보면 다대다 관계라고도 볼 수 있다고 생각했습니다. (오늘은 이 카드를 내일은 저 카드를 쓸 수 있으니까요. 마찬가지도 카드도 오늘은 저 사람에게 이용당하고 내일은 이 사람에게 이용당할 수 있구요.) 그래서 그 두가지 관계를 모두 풀어냈는데요. 먼저 user가 card를 가지는 단방향 연관관계를 만들고, 이후 log라는 엔티티를 하나 더 만들어 user와 card를 가지도록 단방향 연관관계를 설정했습니다. 이 때 모두 단방향 연관관계를 설정한 이유는 조금 더 join을 하는 한이 있더라도 nestjs에서 모듈로 분리되어있는 각 엔티티들끼리 최대한 의존관계를 줄이고 본인의 레포지토리나 서비스에서 모든 작업을 끝낼 수 있도록 해보자고 결정하고 개발했기 때문입니다. 이런 사소하지만 정답이 정해져있지 않은 고민 하나하나가 저를 성장시킬 것이라고 믿고 개발에 임했습니다.
멘토링 이후 제가 얼마나 개념적으로 부족한지 알게 되었습니다. FK가 성능적으로 미치는 악영향, 다른 사람이 코드를 읽거나 DB를 수정할 때 어려움이 생긴다는 것을 알게 되었고, 제 코드는 필요없이 과하게 정규화되어 있다는 것을 알게 되었습니다.
정합성이 필요할 때는 FK를 이용하여 정규화하고, 정합성보다 성능이 중요할 때에는 역정규화하는 과정이 필요하다는 것을 배울 수 있었습니다. 다만 이번 42CheckIn의 경우 42서울 사람들만 쓰기 때문에 트래픽이 몰리지 않는다는 점, 그리고 nestjs를 이용한 개발 특성상 완전히 갈아 엎어야한다는 점 때문에 구조는 변경하지 않고 유지하기로 했습니다.(이렇게 유지보수, 변경이 힘들다는 것이 nestjs의 단점이 될 수도 있겠다는 생각, 제가 정말 설계를 잘못했다는 깨달음이 있었습니다)
이번 기회를 통해 머리를 한 대 맞은 것 같았고 정말 더 열심히 공부해야겠다고 느낄 수 있었습니다.

OAuth가 뭔데?

물론 개발 과정에서 어려움이 없는 것은 아니었습니다. 저희 서비스는 42API에서 제공하는 OAuth 인증을 통해 사용자를 식별하여 DB에 저장하도록 고안되었습니다.
지금까지 42API를 사용해왔던 방식은 OAuth에서 grant type이 client credentials이었습니다. 즉, 자원의 소유자가 인증서버로 부터 직접 토큰을 얻어와 자원서버에서 정보를 받아오는 방식이었죠.
하지만 이번에 사용할 방식은 흔히 소셜 로그인에 사용되는 방식인 authorization code 방식이었습니다.
42API reference를 참고하여 열심히 코드를 짜봤지만 아무리해도 redirectUrl이 무엇을 의미하는지도 모르겠고, 계속 에러가 났습니다. 결국 멘토님께 찾아가 물었습니다.
Q. 42API에 토큰을 요청할 때 redirectUrl이 필수 파라미터가 아니라고 나와있는데 안 넣으니 에러가 나고 그렇다고 아무 url이나 넣으니 그것도 에러가 납니다!
A. 그건 OAuth에 대해 아무것도 몰라서 하는 말이니 OAuth에 대해 공부해봐라!
결국 저는 다시 돌아와 OAuth에 대해 공부하기 시작했습니다.
이 사이트를 보고 저의 질문이 얼마나 멍청한 것이었는지 알게 되었습니다.
등록된 redirectUrl을 통해 인증과정을 검증하는 방식인데 redirectUrl을 왜 넣어야하는지 모르겠다고 묻고 있었던 것입니다!
이까지는 잘 됐는데 이후 CORS에러에 빠졌습니다. 이것은 알고보니 클라이언트에서 서버로 로그인 요청을 보내면 서버에서 직접 42의 로그인 및 인증 페이지로 리다이렉트를 해주는데 이것을 직접 프론트에서 구현해야한다고 생각했기 때문이었습니다. 어쨌든 이런 우여곡절 끝에 42API로그인을 구현할 수 있었습니다.

왜 되지…? / 왜 안되지…?

백엔드 API를 모두 완성한 후에는 최대한 빠르고 쉬운 프론트엔드 개발을 위해 서버환경 세팅에 집중했습니다. 지덕체에서 사용하던 무중단 배포를 위한 docker compose를 이용한 blue/green 전략을 그대로 가져와 잦은 업데이트에 대응할 수 있도록 미리 환경을 구성했습니다.
이렇게 파일을 만들어 인프라를 자동화해둔 덕분에 도중에 한 번 서버가 고장나서 새로운 서버에서 처음부터 세팅할 때도 빠르게 끝낼 수 있었습니다. (서버가 고장난 이유는 커뮤니케이션 오류로 백엔드와 프론트엔드에 같은 URI가 있었고 백엔드 서버가 프론트엔드 정적 파일들을 서빙하는 구조에서 같은 URI를 가진 두 코드가 충돌한 것이 아닌가라고 추측하고 있습니다.)
다만 새로운 서버 세팅 과정에서 분명 전 서버에서는 잘 되던 것이 갑자기 안되는 또는 갑자기 잘되는 알 수 없는 오류들이 저를 힘들게 했습니다…ㅎㅎ

안 될거 없죠

처음 만들고자 한 모든 기능을 다 구현한 후 실제 카뎃들이 사용할 수 있도록 하기 위해 폴라베어님과 이야기를 나눴습니다. 폴라베어님께서는 기존에 구글폼을 이용해 출입을 관리할 때 연동되어 있던 스프레드시트에 DB의 데이터가 들어왔으면 좋겠다고 말씀하셨습니다. 찾아보니 다행히 구글에서 기능을 제공하고 있어 다음 사이트를 참고해 어렵지 않게 구현할 수 있었습니다.
이번 프로젝트에는 이렇게 안 될거 없다는 태도로 임할 수 있어서 개인적으로는 자존감을 높일 수 있었던 좋은 기회였습니다.

앞으로 남은 길

돌이켜 보니 이미 일이 벌려져 있었다

사실 처음에는 이 정도 완성하고 끝내려고 했습니다. 다만 멘토님께 서버도 제공받고 DNS 설정도 하고 이것저것 하다보니 어느샌가 판이 커져있었습니다. 사실 이러다 또 감당 못할 만큼 커져서 이도저도 아닌게 될까봐 두렵기는 하지만 조금씩 주변 사람들의 도움을 받으며 나아가 보고 싶습니다.

어차피 시작한거 제대로

그래서 먼저 지금 구상하고 있는 것은 멘토님께서 말씀하신 앱으로 제작하여 사용성을 높이고 새로운 기능들을 추가할 수 있는 기틀을 마련하고 싶습니다.
또 하나는 어드민 기능을 조금 더 강화하여 출입 관리에 편의를 더하고 UI를 개선하여 카뎃들의 편의성도 높이고 싶습니다.
그리고 최종 목표는 인포 데스크 직원 분들도, 학생들도 불편한 현재의 시스템을 최대한 자동화하여 실시간으로 클러스터 내에 있는 학생 수를 제한한다는 현재 시스템의 주 목적을 지키면서 모두의 불필요한 시간과 자원 낭비를 줄일 수 있는 출입 관리 시스템을 완성하는 것입니다. 그 때까지 지켜봐주시고 또 많은 도움 부탁드립니다!
긴 글 읽어주셔서 감사합니다.