6th UMC 프로젝트도 잘 마쳤으니 1박 2일 해커톤에 참여하더라도 충분히 뭐라도 할 수 있을 거라고(?) 생각해서 7th Ne(o)rdinary Hackathon[24.11.23 ~ 24.11.24]에 참가했다. 결론부터 말하자면... 아직 한참 부족하다. 🥲 프로젝트에 크게 기여하진 못 했지만 내가 뭘 했는지, 저번 해커톤과는 어떻게 다른지, 어떤 걸 배웠는지... 그런 것들을 전부 기록해두려고 한다. 이번엔 CMC분들도 함께 하는 프로젝트라 얻어갈 것도 많고, 아이디어 메이킹이나 프로젝트 개발도 신속하게 진행됐다.
아이디어 메이킹
나는 Web 개발자 3명과 Spring Boot 개발자 3명인 N팀에 배정됐다. 각 파트마다 CMC분들이 1명씩은 있어서 정말 든든했다. CMC분들은 해커톤에 거의 필참이라고 하셨다.
- CMC는 직장인도 대학생도 참여할 수 있는 IT 동아리다. 기획, 디자인, 프론트엔드, 백엔드 파트가 있고 UMC와는 다르게 면접이 정말 빡세다고 들었다. 또, UMC처럼 기초 지식 스터디를 하기보단 각자 원하는 스터디를 만들고 참여하는 방식이라고 한다.
이번 해커톤 주제는 [12월]이었다. 한 해를 마무리하는 달인 12월에 대한 아이디어를 생각해내야 했다. 솔직히 붕어빵이나 군고구마 밖에 생각나지 않아서 아이디어를 정할 때 소극적으로 참여했던 것 같다.
회고, 위시리스트 등 다양한 주제가 나왔는데, 한 해를 마무리하는 개념이 좋을 것 같아서 [회고]를 중심으로 아이디어를 발전시켰다. 결론은...
[리플리]
연말에 자신의 한 해를 돌아보고, 다가오는 한 해에 대한 계획을 세울 수 있는
랜덤 질문 서비스
로 결정됐다.
프로젝트 개발
아이디어 메이킹이 빨리 끝나서 프로젝트 개발도 빠르게 시작할 수 있었다.
송글송글님이 소셜 로그인과 S3 파일 저장부터 프로젝트 기초 세팅, VPC와 EC2, RDS까지 미리 만들어 왔다고 하셔서 정말 놀랐다... '이 정도 열정은 있어야 해커톤을 하는 거구나...!!' 싶었는데, 아쉽게도 소셜 로그인이나 S3 파일 저장 기능을 쓰지 않았다. 그래도 심사위원분들이 그 기능까지 포함해서 채점하신 것 같아서 다행이다.
VPC와 EC2를 만든 사람이 CI/CD까지 구현하는 게 좋아서 CI/CD도 송글송글님이 맡으셨다. CI/CD(GitHub Actions)는 금방 됐지만, 그 중간 과정인 [코드를 EC2에 배포하러 가는(?) step]이 12~13분 정도 걸려서 한 번 merge를 하면 서버가 15분 정도 죽는 상황이 생기게 됐다. 그때마다 다 같이 멍 때리면서 기다리기도 해서 조금 웃겼던 것 같다.
1. ERD 설계 & API 명세서 작성
주노님의 WF와 제리님의 플로우차트를 보면서 API 구현 전 기초 작업을 시작했는데, 놀랍게도 저번 해커톤보다 더 앙증맞은 ERD가 완성됐다. 심지어 API 개수도 똑같다.
- 질문과 답변 테이블이 있어야 한다는 것까진 이해했는데 중간에 매핑 테이블이 있어야 된다는 게 처음엔 이해되지 않았다. 중간에 매핑 테이블을 둬서 질문과 답변을 한 번에 조회할 수 있게 만든 거였다.
- ERD를 설계할 땐 조인이 자주 되는 테이블이 있다면 중간에 매핑 테이블을 두는 게 성능이나 구현 면에서 훨씬 효율적이라는 걸 알 수 있었다.
이후에 Enums이나 Service, Repository, Controller를 엔티티마다 만들어서 올렸다.
2. API 구현
위에 API 명세서에서 나는 [질문 조회 API]와 [답변 조회 API]를 맡았는데, 결국엔 지니님이 거의 다 만드셨다. 내가 건든 건 [질문 조회 API]뿐이다.
[질문 조회 API]
질문에는 category 필드가 있는데, 회고(RETROSPECT) 또는 새해 계획(PLAN)의 값이 들어간다. 사용자가 어떤 걸 고르냐에 따라 그에 맞는 질문들을 무작위로 조회할 수 있게 구현해야 하는 API였다.
내가 생각한 로직은 아래와 같다.
- category 값을 받아와서 리포지토리에 있는 각각의 질문 개수를 count 값에 저장
- Random 클래스를 사용해 count 값에 맞춰 무작위 난수를 생성해 randInt 값에 저장
- 리포지토리에서 randInt에 맞는 질문을 조회해 반환
2번째까지 구현하다가 3번째에서 뭔가 잘못 됐음을 깨달았다. 리포지토리가 category에 맞춰 분리돼있지 않기 때문에 randInt에 해당하는 질문을 가져오면 category가 일치하지 않는 질문이 반환될 수도 있었다.
지니님은 아래 로직으로 구현하셨다.
- category 값에 맞는 질문을 모두 조회해 List에 저장
- Random 클래스를 사용해 List 수에 맞춰 무작위 난수를 생성해 randInt 값에 저장
- List에서 randInt에 맞는 질문을 조회해 반환
다시 생각해 보면 간단하게 떠올릴 수 있었던 것 같은데... 너무 빨리 포기한 것 같아서 아쉽다. '백엔드 개발에서 알고리즘이 그렇게 중요할까?'라고 생각하곤 했는데, 왜 중요한지 깨달을 수 있었다. 🥲
3. QA(?)
나머지 API도 지니님이 다 구현하셔서 뭐라도 해야겠다는 생각이 들었는데, 마침 서버 심사 기준에 [200 OK가 나와야 되는 테스트가 통과하는지]와 [400 Client Error가 나와야 되는 테스트가 200 OK나 500 Server Error가 뜨는지] 이 두 개가 있어서 쿼리 파라미터나 Request Body에 이상한 걸 다 넣어봤다.
- Long 값만 받아야 되는 파라미터에 String도 넣어보고, 빈칸도 넣어보고 나오는 에러들을 지니님께 알려드려서 해결했다(?).
org.springframework.dao.InvalidDataAccessApiUsageException: No sources given
JSON parse error: Cannot deserialize value of type java.lang.Long from String \"a\": not a valid java.lang.Long value
또, Web분들이 웹뷰(?)를 만들어서 URL을 공유해 주셨길래, 버튼을 이것저것 눌러보면서 오류를 찾아서 알려드렸다.
- 해커톤을 할 때마다 느끼는 건데 백엔드보단 프론트엔드가 훨~~~씬 바쁜 것 같다. 화면 구현에 API 연동에 디자이너님과도 계속 소통해야 하고... 너무 고생하시는 게 느껴졌다.
아무튼 덕분에 심사할 때 점수가 덜 깎이지 않았을까 싶다. 😙........
4. 인프라 구조 그리기
서버 심사 기준에 [서버 아키텍처 다이어그램]을 제출해야 한다고 적혀 있어서 온라인 툴을 사용해 만들었다. UMC 6th 워크북을 보면서 이해한 걸 바탕으로 GPT한테 물어보면서 진행했다. 만들고 GPT한테 검사받고 또 고치면서 한 3번 정도 수정한 듯하다.
- 사실 정확한지도 잘 모르겠다. 기초 중의 기촌데... 너무 대충 배워둔 것 같다.
아래 온라인 툴을 사용했다.
프로젝트 발표
아무래도 12월이라는 한정된 주제다 보니, 주제가 살짝 겹치는 팀들이 많았다. 기능만 보면 우리의 상위호환인 팀도 있었다. 발표에서 GPT API를 활용해서 질문을 받는 기능을 만들었다고 하길래 '상은 저 팀이 받겠구나' 싶었는데, 시연 영상을 보니 기능 구현은 쉽지 않았던 것 같다.
솔직히 기능도 너무 간단하고 서비스 흐름도 간단해서 상을 받을 거라고는 생각도 못 했는데... 아무튼 상을 받게 됐다. N팀 이름이 불리고 나서 팀원들끼리 다 같이 10초 넘게 '이게 맞나...?' 하면서 서로 쳐다보고 있었다. 😄
솔직히 이번 해커톤은 QA로 참가했다고 봐도 될 것 같다. 🥲 아래는 앞으로 배워보고 싶은 것과 배워야 하는 것들을 정리해 봤다.
1. Git 기초 지식 정리(remote, clone, ...)
2. 알고리즘
3. AWS S3 - 사진 업로드
4. 소셜 로그인(OAuth) - 구글, 네이버, 카카오
5. 외부 API 사용 - ex. 네이버 지도 API, GPT 4.0
6. QueryDSL
7. Spring Data JPA
8. AWS 전반적인 기초 - ex. VPC, EC2, RDS
UMC 6th 워크북을 제작하신 똘이님이 심사위원으로 계셨는데, 워크북에도 있는 8번 내용이 제일 중요하다고 알려주셔서 AWS에 대한 것도 천천히 올려보려고 한다. 복학하기 전까지 위에서 절반 이상은 다룰 줄 아는 백엔드 개발자가 되자. 🙃