본문 바로가기

취업, 인턴

백엔드 개발 인턴 회고

학원 장고 수업 3.18~4.12

회사 생활 4.15~7.17

 

미니 프로젝트 코드

https://github.com/copyNdpaste/MiniYogiyo

 

3개월 간의 회사 생활에 대해 아무렇게나 의식의 흐름대로 작성한다.

 

아주 운이 좋게도 서초역에 있는 핫한 회사에서 인턴 생활을 하게 되었다.

 

첫 한 달 간은 종로에 있는 아주 구린 IT 학원에 가서 장고 기초 수업을 들었다.

 

이후 집에서 지하철과 버스를 타고 서초역 근처 회사로 출근했다.

회사 문화는 아주 좋았다. 애자일스러운 회사로 매일 아침마다 스탠드업 미팅을 하고 주기적으로 회고를 한다. 개발 회의도 자유로운 분위기에서 밝게 하는 것 같고 코드를 작성하고 Pull Request를 하면 여러 개발자들이 코드 리뷰를 해준다. 코딩을 한 다음 필수적으로 테스트 코드를 작성한다.

1. 현재 작성한 코드가 의도대로 동작하는지 확인하기 위함

2. 이후에 코드가 추가되었을 경우 테스트 코드가 실패하면 어떤 부분을 보완해서 테스트해야 할지 확인하기 위함

 

백엔드 인턴은 나 포함 3명이었다. 한 분은 장고 개발 경험이 좀 있으셔서 잘 하시고, 나는 장고 1도 모르고 다른 분도 마찬가지였다. 학원에서 배운 내용의 대부분이 인턴 프로젝트 때 쓸모가 없었다. 그래서 잘하는 인턴분께서 프로젝트 디렉터리 구조도 잡고 브랜치와 커밋 메시지 네이밍 규칙도 정해주셨다. 역시 잘하신다.

 

인턴 프로젝트의 목표는 이 회사의 서비스를 사용하면서 고객 또는 우리가 필요로 하는 서비스를 구상하고 구현하는 것이었다. 그래서 의견을 나누고 멘토님께서 주제도 던져주시고 다른 팀의 인턴분들께도 질문을 했다.

 

초반에는 일단 장고 웹 프레임워크를 배우기 위해서 강의도 듣고 Two Scoops of Django라는 책도 읽었다.

새 기능을 바로 만들었던 건 아니고 현재 서비스에 있는 기본 기능들을 따라 만든 뒤에 새 기능을 넣기로 했다.

내가 맡은 부분

1. 메인 페이지의 음식 카테고리 출력

2. 특정 카테고리를 클릭하면 식당들 출력

3. 특정 식당 클릭하면 식당 디테일 및 메뉴 리스트 출력

4. 메뉴 클릭 시 메뉴 디테일 출력

초반에는 일단 이 정도만 했다.

쓰고 나니까 간단해보이는데 저런 간단한 걸 하기 위해서 모델 설계, 디자인, url 설계, view함수 및 클래스 view를 작성해야 하고, view에선 값을 받아서 ORM을 작성하고 적절하게 반환해줘야 한다. try except문에서 에러 처리도 해줘야 한다. 그리고 테스트 코드를 짜서 의도대로 값과 응답 코드가 나오는지 봐야 한다. 

프론트 단에선 ajax로 url에 접근하고 응답 성공 또는 실패 시 알맞은 화면을 보여줘야 한다.

커밋을 잘게 나누고 PR을 하면 멘토분들이나 1기 인턴이었다가 정규직 된 분들 그리고 동료 인턴분들이 코드 리뷰를 해주신다. 개발 팁도 나오고 자잘한 수정사항도 나오고 왜 이렇게 짰는지 물어보기도 한다. 피드백 반영을 하고 답변을 한 뒤에 approve가 되면 나의 브랜치는 development 브랜치에 merge가 된다.

 

기본 기능들을 구현하고 이후에는 다음 기능들을 내가 맡아서 개발했다.

1. 날씨별 메뉴

2. 식권 이벤트 하는 레스토랑

3. 메뉴 타임라인

 

날씨별 메뉴

날씨별 메뉴 추천은 사용자 '동' (ex: 서초2동)의 현재 날씨에 잘 팔린 메뉴를 리스팅 해서 보여주는 기능이다.

페이지에 접속하면 상단에 사용자 주소가 뜨고 아래에 날씨, 메뉴가 뜨는데 메뉴는 등수가 매겨져 있다. 그리고 여러 날씨에 거쳐서 잘 팔린 메뉴는 메뉴와 관계가 없다고 판단해서 제외했다는 문구를 띄운다.

여기서 날씨와 메뉴가 뭔 상관이냐는 사람들이 있을텐데 날씨에 따라 호르몬 분비가 변화하고 그에 따라먹고 싶은 음식도 달라진다는 논문이 있다.

이 기능을 만들면서 기상청 API를 써서 현재 사용자 동의 날씨를 받아왔다. 우선 사용자 동에 매칭되는 x, y 좌표를 DB 테이블에 미리 저장해놓는다. 사용자가 페이지에 접속하면 user 정보를 DB에서 찾고 주소에서 정규표현식을 써서 동을 추출한다. 그 동을 좌표 테이블에서 찾고 x, y좌표를 가져온다. 이 좌표들을 기상청 API 호출 시 파라미터로 넘기면 응답 값이 온다. 여기서 원하는 값을 뽑아내야 한다. 값은 숫자로 되어 있다. 1,2,3,4 이런 식인데 각각 맑음, 구름 조금, 구름 많음, 흐림이다. 상세한 날씨는 고려하지 않았다. 어차피 시제품이기 때문에...

날씨를 가져와서 사용자 동에서 주문된 내역을 거른다. 당연히 현재 날씨와 일치하는 주문이어야 한다.

주문 내역들을 메뉴로 group화 한다. 그리고 개수를 센다. 여기서 날씨와 관계없이 잘 팔린 메뉴를 거르는 게 먼저 수행되는 데 흐름은 비슷하다. 이번 달에 잘  팔린 메뉴, 지난달, 지지난달에 잘 팔린 메뉴에 대해 가중치를 부여하고 계산한 다음 가중치 순서대로  dict를 정렬한다.

 

그렇다면 기존의 주문내역엔 날씨가 저장되어 있나? 그렇다. 원래 메뉴 주문과 날씨라는 게 같은 테이블에 있으면 안되고 외래 키로 접근하게 해야 했는데 편의상 이렇게 했다. 불필요하게 join이 증가하는 게 싫었고 성능상 좋지 않다...

주문이 완료된 시점에 사용자 동네의 날씨를 기상청에서 가져와서 같이 삽입하는 간단한 부분이다.

날씨 메뉴 괜히 했다.. ORM 배우고 기상청 API 사용해보고 참.. 좋았다.. 그러나 redis를 써서 더 효율적으로 동작하게 할 수 있었는데 그러지 않고 이후에 있을 새 기능에만 집중해서 개발자로서의 고민이나 노력의 흔적이 덜 묻어났던 것 같다.

 

식권 이벤트 하는 레스토랑

이건 말 그대로 메뉴를 단순히 10개 주문했을 때보다 10개의 식권을 샀을 때 더 저렴하게 살 수 있게 해주는 아이디어에서 나온 것이다. 사장님은 한번에 많은 돈이 꽂혀서 좋고 사용자 또한 저렴한 가격에 식권을 구입해서 두고두고 메뉴를 먹을 수 있어서 좋다.

내가 맡은 부분은 식권 이벤트를 하는 레스토랑의 식권 개수, 세트 식권 개수를 뿌려주는 부분이었다. 단순해 보이는데 코딩할 때는 이걸 어떻게 짜지? 라는 생각을 했다. 하나의 ORM에서 2개의 필드에 대해 집계 함수를 각각 써야 했는데 그건 불가능해 보였다. 그래서 하나의 집계 함수를 쓰고 이후에 나머지 필드를 집계한 뒤 queryset에다가 key, value를 넣어서 해결했다. for문이 레코드만큼 돌아야 해서.. 비효율적이라고 생각했지만 달리 방도가 없었다.

 

메뉴 타임라인

자신이 구독한 레스토랑(생각해보니까 내가 구독하기 기능도 했네)의 신메뉴 출시, 메뉴 변경 사항 등이 한눈에 보이는 기능이다.

사장님 사이트가 별도로 없었으므로 admin 사이트에서 메뉴를 새로 등록하거나 메뉴 이미지, 메뉴 가격등의 정보를 변경하면 타임라인 테이블에 변경 사항이 저장된다. 이 테이블의 필드도 참 막무가내로 짰었는데, 변경 전 값을 저장하는 필드들과 변경 후 값을 저장하는 필드들을 나눠놨다. 그래서 레코드마다 null값이 많다.. 

admin.py에 들어가서 save() 부분을 건드려본 게 참 좋았다. Admin 사이트에서 메뉴 정보를 저장할 때 변경 전 값과 변경 후 값을 집어넣은 뒤 저장했다. 오버 라이딩해서 원하는 코드를 작성했다는 게 뿌듯했다. 변경 전 후 값을 보기 위해서 save() 내에서 브레이크 포인트를 찍고 디버깅을 했다. 프로젝트하면서 디버깅을 하는 습관을 갖게 되었고 디버깅을 하면서 이번엔 어떤 값이 나올까.. 왜 이 값이 안 나오고 엉뚱한 게 나오지??라는 생각과 고민을 했고 재밌으면서 개발에 도움이 되었다.

 

프로젝트 코드는 다행히도 가져가도 된다고 하셔서 나중에 올릴 예정이다.

 

예전에 s전자 수석연구원님께서 학교에 오셔서 git 안쓰면 안된다고 하셨다. 리누스 토발즈님이 리눅스 만들다가 빡쳐서 버전관리 시스템을 만든 거라고 알고 있는데, 당연히 써보긴 했다... CLI가 아닌 GUI sourcetree를... 근데 혼자서 master 브랜치에서 영혼의 쌩쑈를 한 것과 팀원과 함께 협업을 하는 건 천지차이였다. 혼자서 하는 거면 reset, revert도 막 해보고 커밋 메시지도 맘대로 작성하고 그랬다. 물론 내 코드를 봐주는 사람도 없어서 기능별로 브랜치를 만든다거나 버그 수정을 위해 hotfix 브랜치를 만들 일도 없었다. 협업을 하니까 브랜치 네이밍 규칙에 맞게 고민고민해서 네이밍을 하게 되었고 커밋 메시지도 잘게 쪼개고 이해하기 쉽도록 작성해야 했다. 혼자할 때는 PR이라는 것도 몰라서 master에서만 놀았지만 협업 시에는 내가 작업한 브랜치를 development 브랜치에 머지해야 했기 때문에 PR을 날리게 된다. 다른 팀원들은 내가 짠 허접한 코드를 보고 의문을 갖기도 하고 수정을 요청하기도 했다. 피드백을 적절히 반영한 후에 다른 팀원들의 approve가 오면 후다닥 가서 머지 완료를 하게 된다. 이후 fetch해서 원격 저장소의 코드를 새로고침한 뒤에 development 브랜치를 풀한다. Development 브랜치에서 다시 기능 개발을 위한 브랜치를 만들게 된다.

 

물론 순탄하게 진행된 것은 아니었다. 같은 파일의 같은 행을 동시에 건드려서 충돌이 나는 경우도 있었고 DB 스키마를 다루는 migration 파일이 충돌나는 경우도 있었다. 그래서 migration 파일은 반드시 1명이 관리를 하고 변경 사항이 있어서 DB 수정을 해야할 경우에는 1명에게 요청을 해서 그 1명이 models.py 파일을 변경하고 migration 파일을 만든 뒤 development 브랜치에 머지하고 이 브랜치를 풀해서 쓰기로 했었다. 번거롭지만 충돌이 더 무섭기 때문에 이렇게 해결했다.

 

최종 프로젝트 발표를 하고, 질문에 힘겹게 답하고 기술면접, 인성 면접을 봤다.

 

기술 면접은 단골 질문들이 많이 나와서 무난했지만 내가 준비를 평소에 안해서 무안했다.

인성 면접에선 왜 개발자가 되고 싶나, 이 회사에 무슨 기여를 할 것인가 등을 물어봤다.

면접 넘 힘들다

 

떨어진 이유는 일단 질문을 너무 1 기분들에게만 했다는 것이다. 그 결과로 멘토분들, 다른 개발자분들과 교류를 안 했다. 1기 분들이 편해서 질문을 자주 했는데 다른 분들한테도 질문하라는 피드백이 있었다. 공감은 했지만 역시 실행하지 않았다. 3개월이라는 긴 시간 동안 개발에 대한 열정이나 호기심은 새로운 서비스를 구상하고 구현하면서 보여주는 게 아니었다. 사람들과 교류하고 대화하고 질답 하면서 드러났어야 했던 것이다.

 

좋은 문화와 좋은 개발자가 있는 곳에서 결과는 아쉽지만 과정은 괴로우면서 즐거운 경험을 했고 칼퇴와 복지, 사람이 중요하다는 걸 느꼈다.

 

나이 차가 많은 분들이 먼저 식사 제안을 하시고 다른 개발자 분들이 티타임을 제안하셔서 회사 적응하는 데 수월했다.

 

틈틈히 책 읽고 도메인 지식을 쌓고 OS, 자료구조, 알고리즘, 네트워크, DB 공부를 깊게 해야겠다... 좋은 책을 사서 읽음으로써 나에게 투자해야겠다.

 

혼란스럽기도 했지만 좋은 꿈을 꿨다고 생각한다.