정말 작년말은 하던 일이 모두 잘되던 시기였다. 창업대회들도 많은 일들이 있었지만 결국 좋은 결과를 얻어냈고 소소하게 용돈벌이하려고 썼던 엘리스 스쿨튜터도 붙었다. 하지만 많은 일 중에서도 가장 기뻤던 건 고등학교 때부터 한번쯤 일해보고 싶었던 Lablup에 인턴으로 붙은 것이다. 약간 워커홀릭이라서 복학 전에 할 일들을 찾고 있었는데 이왕이면 내 성장에 도움이 되는 일들 하고 싶었다. 그때 마침 고등학교때부터 일해보고 싶었던 회사인 Lablup에서 인턴을 모집하는 공고를 보고 인턴을 지원하게 되었다.
사실 예전에 정규님께서 인턴 경쟁률이 높다는 글을 쓴 적이 있어서 그런지 지원은 했지만 큰 기대는 하지 않았다. 그리고 나 또한 이제 막 복학한 학부 2학년이 하기에는 난이도가 많이 높은 일이라고 생각해서 '차라리 나중에 할까...' 같은 지원할 때 고민을 하기도 했고...
그렇게 기다리던 중 서류 합격 메일을 받았다! 아직 붙은 건 아니지만 그래도 상당히 기뻤다. 그렇게 면접날을 정하고 면접을 준비해야 했는데... 사실 이런식으로 기술면접을 보는 게 처음이라서 막막했다. 일단은 그래도 내가 제출했던 지원서와 거기에 적어둔 토이프로젝트를 기반으로 준비를 했다. 그리고 종현님한테 면접을 받았는데 생각보다 질문에 대답을 한다는 느낌보다는 내가 했던 토이프로젝트를 설명을 하는 면접에 가까웠다. 궁금하신 부분에 대해서는 날카롭게 질문을 했는데 아마 비동기적 프로그래밍에 대한 질문과 예전에 LOCKA 프로젝트 를 했을 때 쓴 react의 lifecycle에 대해서 질문이 들어왔던걸로 기억한다. 어느정도 예상은 했던 질문이라서 무난하게 넘어가나 싶었는데 react가 화면을 rendering하는 과정에 대해서 깊게 물어보신 건 답변을 잘 못했던 게 기억난다. 그래도 이정도면 무난하게 봤나? 싶을 정도로는 면접을 마쳤고 몇일 뒤에 합격메일을 받을 수 있었다.
아무튼 이제 일에 대한 이야기를 하자면... 우선 계약서를 작성하고 첫주에는 orientation task들이 주어졌다.
1주차에는 총 7개의 task들이 주어졌고 크게 보자면 backend.ai 개발환경을 구축하는 것과 간단한 데이터처리/모델링을 하는 것들이다. 그 중에서 첫 과제인 backend.ai를 설치하는 게 상당히 골치아팠다. 우선 나는 23년동안 거의 윈도우만 써왔는데 개발환경을 맥으로 통일해서 터미널에서 설치가 이루어지는데 이게 상당히 낮설었다. 그리고 VDI 발급이 되고 설치를 할려고 미뤄뒀는데 이게 좀 늦어지다보니 virtualbox에 우분투를 깔아서 진행했다.
그리고 backend.ai를 설치하기 전에 필수적으로 linuxbrew(맥은 homebrew)와 pyenv, docker가 설치되어 있어야 했는데 대부분의 경우 환경변수를 내가 직접 잡아줘야 했다. 그런데 나는 vi같은 편집기들이 낮설어서 좀 해맸다. 그 외에도 한번 설치가 꼬이면 기존 설치과정에서 설치된 자료들을 지우고 다시 설치해야 하는데 그걸 몰라서 environment id는 계속 바뀌는데 manager나 agent 등등을 돌리면 잡아주지 못하는 일이 있었고, 이걸 해결하는데 거의 꼬박 2일정도를 날린 것 같다. 결국은 싹 밀어버리고 다시 설치하는 걸로 해결했지만... 덕분에 터미널 환경에 조금은 적응을 할 수 있었다.
그리고 storage-proxy가 계속 avorted! 라고 뜨면서 돌아가지 않는 문제도 있었는데 netapp 스토리지 호스트를 추가하고 storage-proxy.toml 기본 파일을 sample 파일로부터 복사해오는 과정에서 주석처리하는 부분이 빠져서 그렇다고 지현님께서 알려주셨던 문제였고, 그때 오피스에 같이 있던 동규님께서 도와줘서 해결 할 수 있었다. 그렇게 삽질을 한 끝에 1주차 task를 끝낼 수 있었다.
2주차에는 aiohttp와 aioredis를 활용한 채팅앱을 만드는 것인데 사실 기존에 창업대회에서 node.js로 짰던 적이 있던 내용이라 솔직히 크게 힘들지는 않았지만 아직도 redis를 어떤 식으로 활용해야하는지에 대해서는 고민할 부분이 많은 것 같다.
그렇게 3주차부터는 good first issue를 받아서 진행을 했는데 내가 처음으로 받은 이슈를 간단하게 설명하자면 scaling_group에서 session들을 관리하는데 scaling_group마다 특정한 타입의 session만 실행되도록 제한을 해야 하는 문제다. 사실 이슈에서 적힌 내용이 너무 짤막해서 처음에는 과연 뭘 해야하는지 잘 몰랐다...
그래서 꽤나 추상적으로 질문을 했던 적이 많은데 정말 다들 너무 친절하게 설명을 해주셨다. 아마도 래블업에서 가장 좋았던 점들을 꼽으라면 다른 분들이 정말 질문에 대해서 친절하고 자세하게 설명을 해주신다는 점이라고 생각한다. 그러니까 나중에 혹시라도 lablup에서 인턴을 하시게 된다면 꼭 질문 많이 하는 걸 추천한다!
그래서 이걸 왜 하느냐... 하면은 비싼 GPU 노드들을 묶는 노드는 배치 타입으로 오래 돌아가는 워크로드들만 할당 가능하게 만들고, 싼 GPU 노드들은 주피터나 VSCode 등으로 코딩하게 만드는 식으로 리소스 그룹의 쓰임을 강제하도록 하는 기능을 만들기 위한 전단계인 것 같았다. 사실 구현하는 방법이 꽤 다양해서 그런지 질문을 답변해주시는 분들 사이에서도 의견이 좀 갈린 부분이 있었는데 결국은 준기님 말씀대로 scheduler_opts에 새로운 column type인 StructuredJSONBColumn을 만들어서 option들을 받아주는데 여기에서 인자로 trafaret을 받아와서 들어온 정보들에 대해서 validation check를 해주도록 했다.
그런데 또 문제가 생겼다. 이렇게 방대한 규모의 코드에 기여하는 경우는 처음이라서 이 이슈를 해결하려면 어느 부분의 코드를 수정해야하는지 알기가 너무 어려웠다. 라벨에 manager쪽의 코드를 보라고 되어 있지만 manager의 로직 자체가 워낙에 어렵고 또 코드도 방대해서 해맸다. 중간중간 질문도 자주 하긴 했지만 질문에 대한 답변들조차도 이해가 되지 않을 때가 많았다. 거기다가 내 성격상 이해를 하고 넘어가야 한다는 강박증(?) 이 있어서 그 방대한 코드를 하나씩 읽어가며 이해하려고 했는데... 지금 생각하면 그걸 완전하게 이해할려면 인턴 기간내에는 어림도 없다는 생각이 든다. 아무튼 base에 StructuredJSONBColumn이라는 column type을 만들고 처리를 하는데 막상 test를 해보니 validation check를 하지 않고 값을 넣는대로 다 들어가는 것이다... 알고보니 process_result_value라는 메소드를 쓸 때 column에 들어있는 값을 가져와서 검사를 해줘야 하는거였다... 여튼 사용되는 모듈들이 낮설었던 점도 인턴 난이도를 높이는 큰 요인중에 하나라고 생각한다.
그렇게 StructuredJSONBColumn을 만들고 나서 실제로 scheduler_opts에 들어있는 allowed_session_types의 값을 확인해서 실제로 돌아가지 않도록 만들어줘야 하는데 일단 나는 start_session이라는 함수를 통해 session을 시작하기 전에 DB에 쿼리를 날려 어떤 타입이 허용되어있는지를 확인하고 허용된 타입일경우 start_session을 통해 session이 시작하도록 만들었다. lifecycle로 따지면 SCHEDULED -> PREPARING 단계에서 이걸 확인하는 식으로 작성을 마쳤다.
그리고 드디어 첫번째 PR을 보내고 코드리뷰를 기다렸다.
솔직히 처음 PR 보내서 바로 approval을 받을거라고 기대하지는 않았지만 그래도 생각보다 고칠 점들이 꽤나 있었다. 일단 trafaret object를 class 내부에서 쓴 점에 대해서 이걸 table 선언할 때 받아오라는 지적이 있었다. 사실 원래도 table 선언할 때 받아와서 쓸려고 했지만 막상 오류가 나서 내부에서 선언을 했는데 알고보니까 상속받는 class의 constructor를 안불러와서 생긴 일이었다. 그래서 나중에 보니 준기님이 StructuredJSONBColumn을 수정했는데 음... 기분이 복잡미묘했다. 여튼 그래서 다음 문제인 allowed_session types에 들어가지 않는 session의 경우 PENDING 상태에 머무르게 하는 걸 고쳐보고자 했다. 의외로 내가 작성한 코드의 위치만 바꾸었더니 간단하게 해결되는 문제였다.
그 이후에도 지속적으로 코드 리뷰를 받아서 첫 번째 이슈를 수정을 해야 했는데, 나는 allowed_session_type을 해결하는 과정을 dispatcher에서 진행했는데 이거를 predicate 쪽으로 바꾸자는 이야기였다. 이렇게 하면 세션이 보류 중인 이유를 predicate test 결과의 일부로 기록을 할 수 있기에 이유를 알 수 있었고, 별도의 DB 트랜젝션을 하나 줄일 수 있었다. 그렇기에 이 로직의 위치를 옮겨서 진행했고, 결국 approval을 받고 merge가 되었다!
그리고 원래는 정인님이 맡은 good first issue지만 StructuredJSONBColumn 내부에서 처리해야 하는데 이때 문제가 겹쳐서 내가 받은 이슈가 하나 있다.
간단하게 설명하자면 scheduler_opts에 pending timeout 옵션을 추가해서 (기본값은 0으로 이 경우에는 시간이 지난다고 해서 자동으로 종료되지 않도록 설정) session이 일정 시간이 지나도 pending 상태를 유지하면 자동으로 이 session을 다른 status로 바꾸라는 내용이다.
일단 나는 pending timeout 옵션은 scheduler_opts를 조회해서 가져오고 pendingSession에서 커널의 created_at 값을 조회해서 이 세션이 얼마나 pending 상태에서 머물렀는지 확인했다. 그래서 pending상태에 머무른 시간이 옵션보다 길면 registry의 destroy_session_lowlevel을 통해 이 세션을 종료하는 것으로 처리했고, 테스트 후에 PR을 보낼 생각 었는데...그런데 실제로 테스트를 돌려보니 destroy_session_lowlevel을 돌리기 위해서는 그 세션의 agent 정보들이 있어야 돌릴 수 있는 메소드였는데 PENDING 상태에서는 자원이 할당되지 않다 보니 필요한 정보(예를 들어 agent_addr 같은 것들..)이 부족해 메소드를 돌릴 수 없었다. 그래서 이 문제를 준기님한테 물어보니 바로 DB에 세션의 status를 cancelled로 바꿔주고 status info에 pending_timeout으로 표기하라는 식의 조언을 받고 문제를 해결할 수 있었다.
그렇게 PR을 보내고 지금은 리뷰를 기다리고 있는 상태이다.
그 이후에 설연휴 직전에 세 번째 이슈를 할당받았는데 바로 이 이슈다!
이슈 설명을 하자면 서비스에 vfolder라는 가상 폴더를 지원하고 이에 대한 여러 가지 기능들을 지원하고 있는데 이 폴더를 복사하는 clone이라는 기능이 있다. 그런데 vfolder clone API는 데이터베이스 트랜잭션 블록 내에서 storage-proxy(사용자 웹브라우저 또는 Client SDK가 네트워크 스토리지로부터의 대용량 입출력을 바로 할 수 있도록 해주는 서비스) 쪽의 API를 호출한다. 그런데 기본적으로 SERIALIZABLE isolation level을 기본으로 사용하기 때문에 다른 모든 데이터베이스 트랜잭션을 차단하므로 관리자가 작업 중에 frozen 된 것으로 나타난다.
이게 왜 문제가 되냐면은 사실 간단한 동작들은 금방금방 끝나서 DB 트랜잭션을 오래 물고 있지는 않는다. 그런데 대용량의 vfolder를 복사하는 일은 오래 걸릴 수도 있기 때문에 이때 다른 명령을 manager가 아예 수행하지 못한다. 그렇기 때문에 트랜잭션을 최대한 짧게 만들어줘야 했다.
그래서 내가 해야하는 작업은 vfolder의 생성과 복제 과정이 지금은 트랜잭션 안에 붙어있는데 그걸 분리하고 DB 트랜젝션에서 이들 사이에 대상 vfolder record를 생성하게끔 하고, 복제 작업은 백그라운드 작업으로 실행하고 client쪽에서 이 과정을 tracking 할 수 있도록 vfolder clone API 에서 bgtaskID를 반환하고 여기에 대한 처리를 해야 했다.
근데 지금 와서 이야기하면 처음 이 이슈를 받고 읽어봤을 때 내용이 이해가 되지 않았다. 이때까지 session 쪽 이슈만 맡다가 vfolder 이슈를 맡으니까 어떤 메커니즘으로 돌아가는지 전혀 이해를 할 수 없었고, 내 뇌 속에서 DB에 관련된 지식들은 이미 군대에서 많이 까먹어서...;; 이해를 하기 힘든 부분이 많았다. 거기다가 연휴 때문에 완전히 개발하는 흐름이 끊겨버려서 더 고생했던 것도 있고 지금 생각하면 이 이슈때문에 정말 고생을 많이 했다. 여하튼 이 문제를 해결하기 위해서 또 코드를 열심히 봤다. 이때까지의 issue는 기껏해야 manager 쪽의 코드만 봐도 괜찮았지만, 이번 이슈는 client 쪽과 storage-proxy 쪽의 코드도 연관성이 있기에 어떤 식으로 연결이 되어있는지 확인해야 했다. 그런데 내가 API에 대한 개념이 부족했기에 난이도가 꽤 높았다.
결국 이때도 질문을 통해서 어느 정도 갈피를 잡으려고 했다. 그렇게 해서 이 이슈를 어떻게 접근해야 하는지에 대한 개념을 조금씩 잡을 수 있었다. 우선 storage-proxy로 가는 RPC call이 너무 길어지지 않도록 분리해서 vfolder를 생성하는 과정만 트렌젝션에 집어넣고 그리고 실제로 clone을 거는 과정은 background task를 스폰을 해서 background task라는 프레임워크가 있는데 이친구는 오래 걸리는 작업들을 asyncio 코루틴으로 별도로 스폰을 해놓고 ProgressReporter라는 객체를 가지고 들어가는데 이 친구는 background task가 지금 어떤 식으로 진행되는지를 알려준다. 그래서 이게 필요하다면 구현을 직접 할 수도 있고 이 부분은 Image rescan을 하는 부분에 전부 구현이 되어있으니 참고를 하라고 하셨다. 그리고 이 코루틴이 성공적으로 끝났는지 exception을 뱉었는지에 따라서 background task의 성공여부를 알려주고 bgtask_id를 클라이언트에다가 리턴을 해주면 그 클라이언트는 별도의 bgtask API를 통해서 내가 지금 백그라운드 작업이 끝났는지를 클라이언트가 풀링을 하거나 serversent 라는 표준화된 http 이벤트방식으로 이벤트를 받아볼 수 있다.
뭐 여튼 이런 식으로 문제를 해결을 하는 식으로 방향이 잡혔는데 문제는 또 background task가 어떤 식으로 돌아가는지 나는 전혀 이해하지 못하고 있었기 때문에 Image rescan을 하는 부분을 굉장히 오랫동안 봤었다.
지금 생각하면 이 기간이 가장 내가 인턴기간 중에 쓸모없이 시간만 잡아먹고 있던 것 같다. 삽질을 하기는 했는데 이 삽질이 딱히 나한테 도움이 되는 삽질이라기보다는 그냥 고생을 많이 했던 삽질이었다고 생각한다. 아마 무지에서 오는 혼란스러움 때문에 더욱더 심했던 것 같고... 질문을 하려고 해도 뭔가를 알아야 질문을 할 수 있는데 이 시기에는 그것조차도 아니기에 코드만 하루 종일 보고 '이게 왜 이렇게 돌아가지...?' 생각을 많이 했다. 그런데 결국은 막상 이 내용을 보고 나서 직접 하려고 하니까 이 로직을 다 볼 필요가 전혀 없었고, 그냥 background task를 시작하는 부분과 이걸 client에서 받아와서 처리하는 부분만 봤어도 이 이슈를 해결할 수 있었다고 생각한다.
여튼 이렇게 고생을 하고 나서 clone이 오래 걸려서 원래는 manager 전체가 lock이 되어야 하는 상황을 storage쪽에 asyncio.sleep을 적용해서 기존 코드에서 테스트를 하려고 했다.
매니저가 lock이 걸려서 clone 중에는 다른 명령을 입력해도 실행되지 않아야 하는데 clone작업을 해놓고 backend.ai ps로 세션정보를 조회했는데... 원래는 lock이 걸려서 안돌아가야 하는 쿼리가 실행이 되는것이다... 뭐 사실 이게 된다면 이건 이것대로 좋은 문제이긴 하지만 사실 나는 이렇게 lock이 안 걸린다는 걸 확인했을 때 상당히 허탈했다. 이 이슈 때문에 고생을 많이 하기도 했고 초조한 적도 한두 번이 아닌데 '아무것도 안 해도 이 이슈에 대한 것이 사실 잘 돌아갔어요!' 라는 생각을 하니 뭔가 기분이 찝찝했다. 그래도 이론적으로는 당연히 오래 걸리는 작업을 background task로 돌리는 것이 당연히 좋기에 clone을 background task로 돌리고 이를 client에서 알 수 있도록 작업을 하기는 해야 했다.
그렇게 해서 clone을 background task로 돌리고 이를 client에서 상황을 알 수 있도록 bgtask.listen_events()를 활용해서 event에 대한 처리를 하였다. 그렇게 이 이슈를 해결하기 위해 manager와 client-py 에 PR을 보내 놓은 상황이다.
그리고 딱 저번 주 주말에 내가 맡은 good first issue에 대해서 종현 님이 control-panel 쪽 UI 대응 PR 보다 보니 확인을 하셨는데 사용자의 가용 scaling group 중 하나라도 allowed_session_types가 비어있는 경우에는 무조건 predicate check 실패가 돌아갈 것 같다는 이야기를 하셔서 여기에 대해서 수정을 해서 PR을 보냈다.
그리고 이런저런 이슈들을 처리하고 보니까 막상 맡고 있던 이슈 하나를 거의 방치하게 되었는데...
바로 session의 state가 바뀔 때 커스텀 웹 훅을 호출하도록 하는 이슈인데 문제는 내가 웹훅에 대해서 전혀 모른다는 점이다. session을 다루는 거나 background task를 돌리는 점은 이미 다뤄본 적이 있는 이슈라서 금방 하겠거니 했는데 웹훅 URL을 뭘 써줘야 하나... 외부 서비스로는 테스트 어떻게 해야 하나 등등의 문제가 있어서 일단 JSON 스키마만 만들어 놓은 상태다. 그래도 이 이슈까지는 인턴이 끝나도 해결하고 PR을 보내고 싶다는 생각이 든다.
그래서 내가 Lablup에서 인턴활동을 하면서 느낀 점을 하나씩 이야기해보려고 한다.
우선 Lablup이라는 회사에 대해서 내가 느낀 점을 이야기하자면 이렇게까지 자유로워도 되나? 싶을 정도로 자유롭고 수평적이라는 생각이 들었다.
- 우선 출퇴근 시간에 대한 이야기를 하고 싶은데 보통 오전 10시에 all-hands 미팅이 있는데 이 미팅은 반드시 참석을 해야 하지만 그 외의 출퇴근 시간은 자유롭게 할 수 있다. 8시간 근무만 하면 된다는 느낌이다. 내가 이 기간 중에 건강문제가 많아서 병원을 갈 일이 잦았는데 잠시 자리를 비울 경우 Teams channel에 이야기를 하고 자유롭게 다녀와도 된다. 그리고 나처럼 야행성 인간들이 일하기에는 너무 좋은 환경이었다.
- 그리고 사람들을 직책이 아닌 oo님으로 호칭을 통일해서 부르고 다들 친절하게 잘 대해 주시는 점에 대해서 감사하게 생각한다. 그리고 기본적으로 점심을 같이 먹는데 이런저런 이야기들을 같이 나누면서 편하게 이야기를 했던 것 같다. 능력적으로도 정말 뛰어나지만 인격적으로도 훌륭하신 분들이 많았다.
- 그리고 가장 크게 와닿았던 점은 누구나 질문을 잘 받아주신다! 솔직히 내가 답답한 질문을 하더라도 누구라도 답변을 정말 상세하게 잘해준다. 아마도 인턴기간 중에 이렇게 많은 분들의 답변이 없었더라면 문제를 해결하기 어려웠을 텐데 덕분에 도움이 많이 되었다. 다만 아쉬웠던 건 질문을 할 때 무턱대고 "저 아무것도 모르겠어요..."라고 질문하는 걸 내가 싫어하고 질문받는 입장에서도 좋은 질문이 아니라서 최대한 구체적으로 질문하려고 하다 보니 질문에 신중해지고, 혼자서 끙끙 앓는 경우도 상당히 많긴 했다. 내 문제는 내가 해결해야 한다는 성격 때문이지만 다른 분들은 질문을 더 적극적으로 해도 좋을 것 같다.
- 다만 시기에 따라서 상당히 바쁘신 분들이 있기 마련인데 아무래도 이 경우에는 질문 답변이나 코드 리뷰가 더딘 경우가 있다. 이 점에 대해서는 어쩔 수 없다고 생각은 한다.
그러면 다음으로는 개인적으로 느꼈던 점에 대해서 이야기를 하려고 한다.
일단 내가 무지하다는 점에 대해서 뼈저리게 깨달을 수 있는 기회였다. 내 성격 자체가 내가 하는 일을 잘하고 싶어 하고 여기에 대해서 자존심도 상당히 강한 편인데 인턴 진행하면서 앞으로 갈 길이 많이 멀구나... 라는 걸 느꼈다. 나 같은 경우에는 이슈를 진행할때마다 초반에 상당히 어려움을 겪었는데 항상 해결해야 할 문제에서 전혀 모르는 부분들이 꼭 있어서 여기에 대한 공부를 많이 하고 OKR미팅이나 채널에서 질문을 하고 나서야 문제해결의 방향성을 잡을 수 있었다.
그리고 backend.ai는 상당히 방대한 코드와 복잡한 로직을 가지고 있다. 그래서 그런지 first good issue를 진행하는데도 상당히 오랜 시간이 걸렸고 나 같은 경우에는 manager쪽 코드를 2달째 보고 있는데도 아직까지 잘 모르는 부분이 상당히 많다. 그래서 항상 이슈를 받을때마다 막막하다는 생각이 든다. 설명을 자세하게 들었는데 전혀 이해를 못해서 벙찐적도 있었고 이슈를 끝내고 나서 '이렇게 간단하게 몇줄 추가해서 해결할 문제를 가지고 난 뭘한거지...' 라는 생각도 많이 들었다. 그리고 나같은 경우에는 전역하고 3달 정도 쉬다가 바로 인턴을 했는데 그래서 그런지 실력도 많이 떨어진 상태기도 했고 결정적으로 인공지능이나 시스템 프로그래밍에 대한 전반적인 이해가 없는 상태에서 인턴을 하다 보니 머리부터 들이밀고 본다는 생각이 많이 들었다. 물론 이렇게 배우는 것도 좋지만 1년만 학교를 더 다니고 인턴을 했으면 이슈들을 훨씬 수월하게 해결하지 않았을까 하는 생각도 든다. 결국은 나 스스로에 대한 아쉬움이 많이 남았다는 이야기다.
하지만 2달이 지난 지금 돌이켜보면 나한테 있어서 참 도움이 많이 되었던 것 같다. 코드를 읽는 방법이나 스타일, 코드 리뷰, 그리고 협업하는 것과 더불어서 방대한 오픈소스에 기여하는 경험까지 너무나 좋은 경험을 많이 했다. 다만 2달이라는 기간이 어느 정도 적응되려고 할 때 인턴기간이 끝난다고 느껴서 이 점이 아쉽게 느껴졌다. 그리고 이 기간 동안 다양한 분야를 접해보지 못해서 조금은 아쉽다. 나 같은 경우에는 backend 쪽, 그것도 거의 manager 쪽 코드를 보고 수정했는데, 다른 인턴분들하고 이야기하면서 다른 분야를 했어도 되게 재미있게 했을 것 같다는 생각이 들었다.