파인더유니콘LIVE지원프로그램IR자료구독인사이트엔젤투자
티켓구매
로그인
회원가입
  • 인사이트
  • 첫 회사를 우아한형제들에서 시작한 아가 개발자의 걸음마 떼기

첫 회사를 우아한형제들에서 시작한 아가 개발자의 걸음마 떼기

안녕하세요! 6월 21일 배민주문서비스팀에 서버 개발자로 합류하게 된 김경준입니다.

기술 블로그의 글들을 보면서, 언젠간 사람들에게 도움이 될 수 있는 이야기를 공유해야지 꿈만 꾸던 학생이었는데 지금 우아한형제들에 합류하여 글을 적고 있다니.. 정말 감격스러운 순간입니다.

글을 시작하기에 앞서, 어떻게 하면 도움이 되는 이야기를 담아낼 수 있을까에 대한 고민을 먼저 시작했는데요.

이제 막 걸음마를 시작하는 신규 입사자의 파일럿 프로젝트 글이다 보니, 기술적인 이야기로 가득 채우는 것보단 어떻게 하면 적응을 잘 할 수 있을지에 대한 고민과, 좋은 파일럿 프로젝트를 함께 만들어나가기 위해 했던 저의 작은 노력들을 먼저 전달 드리고, 프로젝트 이후 코드 리뷰에서 있었던 내용을 전달하려 합니다.

‘성공적인’ 파일럿 프로젝트 만들기

좋은 파일럿 프로젝트가 되기 위해선, 신규 입사자인 저 또한 기여할 수 있는 부분이 있으리라 생각합니다. ‘성공적인’ 파일럿 프로젝트를 함께 만들어가기 위해, 먼저 어떤 것이 ‘성공적인’ 것인지를 정의 해야 할 것 같은데요. 파일럿 프로젝트의 목적을 다시 한번 돌아보겠습니다.

팀에서 전달해 주신 파일럿 프로젝트의 목적은,

-대략적인 주문 시스템의 역할을 이해하는 것

-팀 내 업무 방식 경험

그리고 제가 어떤 스타일의 개발자인지, 어떤 생각을 하면서 개발을 하고 있는지를 파일럿 프로젝트를 통해 보여주고 이야기 나누는 것이었습니다.

위의 목적들을 잘 수행하고, 이후 업무를 수행하는 데에 필요한 지식을 파일럿 프로젝트를 통해 최대한 많이 습득한다면 성공적인 파일럿 프로젝트라고 할 수 있겠습니다.

대략적인 주문 시스템의 역할을 이해하는 것

배민주문서비스팀의 파일럿 프로젝트는 고객이 배달의민족에서 메뉴를 장바구니에 담고 사장님에게 접수되어 주문이 완료되는 과정까지의 이야기입니다.

이외에도 사장님 주문 조회, 접수 및 취소 기능, 고객 주문 조회 및 취소 기능의 요구사항이 있었습니다.

실제 서비스는 이보다 훨씬 복잡하겠지만, 주문팀이 어떤 목적을 가진 조직인지, 배달의민족 서비스에서 어떤 역할을 하고 있는지 간략히 파악할 수 있었습니다.

이외에도, 파일럿 프로젝트 기간 중 배달의민족으로 음식을 주문할 때마다 장바구니와 주문지면, 주문 조회와 같은 부분을 유심히 살펴보면서 파일럿 프로젝트 기간 동안 ‘실제 서비스에서는 이런 부분들이 추가로 구현되어야겠구나..’ 와 같은 상상을 하게 되었는데요. 특히, 이 코드가 ‘실제 서비스로의 배포가 된다면’ 와 같은생각들이 주문 시스템이 갖춰야 할 역할에 대해 좀 더 깊게 이해하고 파일럿 프로젝트에 몰입하는 데 큰 도움이 되었습니다. 대량의 트래픽에 따른 동시성 처리를 하는 부분이나 경합이 발생할 가능성이 있는 부분, 외부 시스템의 API를 사용할 때 오류가 발생한다면 그 영향을 어떻게 최소화할 수 있을지에 대한 고민을 할 수 있었습니다.

자신이 좋아하는 서비스를 개발하는 개발자가 누릴 수 있는 특권일지도 모르겠습니다.

팀 내 업무 방식 경험

실제로 업무를 하듯 티켓을 만들고 데일리, 위클리 등을 통하여 파일럿 프로젝트의 진행 상황이나 이슈들을 공유하였습니다. 이외에도 사내에서 사용하는 배포 플랫폼을 사용하여 배포를 진행하기도 하였는데요. 이 과정에서 위키가 정말 큰 도움이 되었습니다. 어디선가 신규 입사자의 중요 업무는 ‘질문’이라는 이야기를 들었었던 기억이 있습니다. 팀에서도 궁금한 게 생기면 바로 질문해달라고 하셨고, 스스로도 질문 많이 해야지! 라는 다짐을 했습니다. 하지만 사내 위키가 많은 궁금증 해소 시켜주었습니다.

궁금증은 위키로 해결하였지만 그렇다고 질문을 안 하는 건 좋지 않다고 생각했습니다. 질문은 단순히 모르는 것을 알게 해주는 것 뿐만 아니라 서로의 유대감 형성에도 큰 영향을 준다고 생각합니다.

잡담이 경쟁력인 것처럼요.

위키에서 알게 된 것도, 위키에서 이렇게 확인했는데 그대로 참고해서 진행하면 될지에 대해 짧게 질문을 하면서 소통을 하기도 하고 잡담 역시 빠짐없이 참여하려고 노력했습니다.

치열한 15절 제창 현장

내가 어떤 개발자인지 전달하기

어떤 개발자인지 전달하기 위해선, 먼저 어떤 개발자인지 스스로 인지하고 있어야 할 것 같습니다. 주관적인 평가이지만, 스스로 어떤 개발자인지 생각해봅니다.

저는 문제가 생기면 해결하려는 욕구가 강하고, 상황에 따른 최적, 최선의 방법을 찾는 과정을 좋아합니다. 은탄환은 없다고 하지만, 적어도 이 상황에서의 은탄환은 무엇일까에 대해 고민하고, 상황마다의 탄환들을 모아 두려는 습성이 있습니다. (탄피받이..?)

개발자와 협업을 하는 데에 있어선 제가 좋다고 생각하는 부분들이 상대방이 공감하지 않는다면 강요가 될 수 있다는 생각에, 의견 개진에 조심스러울 때가 많습니다. 하지만 보통 그런 상황에서 혼자 끙끙대다 결국 말하게 됩니다. 이야기 나누다 보면 은탄환인 줄 알았던 생각이 구리탄환이었다는 것을 알게 될 때도 많습니다.

마지막으로 기록하는 습관을 가지지 못했습니다. 생각들을 기록하기보단 머리에 적립해놓는 게 익숙합니다. 체화가 되지 않은 부분은 까먹는 경우가 많아서 체화시키기 위한 연습을 할 때도 있지만, 그냥 까먹어 버리는 경우가 부지기수입니다.

다음은 프로젝트를 구현하면서 했던 고민을 코드 리뷰 과정 중에 빼먹지 않고 전달하기 위해, 중간중간 위키에 기록하면서 진행하였습니다.

슬쩍 보시면 아시겠지만, 해당 글은 독자를 고려하지 못했습니다. 저만 해석할 수 있는 언어로 적혀있는 부분이 많습니다. 말씀드렸던 대로 원래 의도는 코드 리뷰 때 위키를 보면서 파일럿 과정 중에서 했던 고민을 전달하겠다는 생각이었으나, 차라리 시간을 좀 투자해서 리뷰를 해주실 때 글을 보고도 파악할 수 있게끔 다듬어 두는게 더 좋았겠는 아쉬움이 있습니다. 저만 보기 위한 글이라면 굳이 위키에 적을 이유도 없었겠다는 생각도 듭니다.

일정 추산하기

처음 파일럿 프로젝트의 설명과 요구 사항을 말씀해주시고, 진행하기 전 일정 추산을 먼저 한 뒤, 공유해달라고 말씀해주셨습니다. 이때 해주신 조언도 정말 큰 도움이 되었는데요.

일정 추산에 관해 느낀 점

학생에서 개발자가 되고, 최근 느끼고 있는 가장 큰 차이점이기도 합니다. 공부를 할 땐 딱히 시간을 정해놓지 않았고 계획을 세우면서 공부하는 스타일도 아니었습니다. 해야 하는 일이나 하고 싶은 일이 있을 땐 밤을 세기도 하면서 항상 하고 싶은 만큼, 그리고 할 수 있는 만큼 자유롭게 살아왔던 것 같은데요. 그러다 보니 일정 추산에 미숙할 수밖에 없었던 것 같습니다. ‘이 정도면 일주일 정도 걸리겠다.’ 생각했던 일주일은, 주말도 포함하고 있었고 마지막 날 여차하면 밤을 새울 각오도 되어있는 일주일이었습니다.

처음 생각했던 일정보다 좀 더 현실적인 계획을 세웠습니다. 다행히 큰 무리 없이 일정 내에 파일럿 프로젝트를 마칠 수 있었습니다. 아마도 처음의 계획으로 진행했었다면, 주말에도 작업했었을 것 같네요.

이러한 과정을 거쳐 아래와 같은 결과물을 만들었습니다.

웹 프론트

  • 서버 모듈 구성

두근 두근 코드리뷰 !

간단한 시연 이후, 인텔리제이의 Code With Me 플러그인을 활용하여 약 2시간에 걸친 코드 리뷰를 진행하였습니다. 그중에서도 가장 핫한 (?) 주제였던 모듈에 관한 내용을 공유해 드리려 합니다

모듈을 나눈 기준

프로젝트 초반, 헥사고날 아키텍처 스타일을 따라 패키지를 구성하여 단일 모듈로 프로젝트를 진행했습니다.

이후, 배치 애플리케이션이 생겨나면서 핵심적인 비즈니스 로직을 수행하는 도메인 모델을 공유하여 사용해야 할 필요성이 생겼고, 도메인 모듈을 분리하였습니다. 분리 이후엔 의존의 방향은 사용하는 애플리케이션이나 다른 모듈들이 도메인을 바라보도록 하고, 도메인 모듈은 다른 모듈에 의존하지 않도록 하였습니다. 많은 모듈이 의존하게 될 도메인 모듈이 다른 모듈을 의존하게 된다면, 그 영향이 대부분의 모듈에 전파가 될 것이기 때문에 격리가 필요하다고 생각하였습니다.

이벤트 처리에 대한 요구사항이 생기면서, 이 부분 역시 api와 batch 모듈이 같이 사용해야 할 필요성이 생겼습니다. 만약, 도메인 모듈이 이벤트 처리에 관한 부분을 담당하게 된다면, api 모듈과 batch 모듈엔 변경이 필요하지 않았을 것입니다. 하지만, 도메인 모듈의 책임은 이벤트를 발생시키는 것까지이고, 그 처리를 어떻게 할 것이냐는 별도의 관심사라고 생각하였고 event-listener 모듈로 분리하였습니다.

이밖에 외부 API를 호출하는 모듈은 이후에 여러 모듈에서 사용할 가능성이 높다고 판단하였고, 핵심 도메인인 주문을 보조하는 하위 도메인으로 취급하여 sub-domain 모듈로 분리하였습니다.

모듈 내부 구성

모듈을 사용하는 쪽에선 해당 모듈이 적절한 행동을 하기를 기대할 것입니다. 반면, 그 행동을 ‘어떻게’ 수행하는지는 관심사가 아니라고 생각하였습니다. 때문에, 모듈의 행동을 인터페이스로 공개하고, 구체적인 내용을 담고 있는 구현 클래스는 package-private으로 외부 모듈에서의 접근을 제한하였습니다.

더 나아가, 만약 구현체가 여러 개가 된다면 사용하는 모듈에서 환경 변수 주입과 같은 방법으로 구현체를 선택하여 사용할 수도 있으리라 생각하고 있습니다.

인터페이스에선 구현 내용을 알 수 없기 때문에, 해당 메소드에서 발생시킬 수 있는 예외를 표시하는게 도움이 될 것이라 생각하였습니다.

구현 내용을 담고 있는 package-private 클래스 입니다.

실제 요청을 보내는 클래스이기 때문에, 테스트에선 DI를 할 수 없게 하였습니다.

테스트에선 시나리오에 맞는 Mock 객체를 테스트 패키지에 구현하여 사용하였습니다.

모듈은 얼마만큼 행동해야 하는가

외부 요청하는 모듈이 어디까지 행동하는 게 좋다고 생각하는지에 대한 질문도 받았습니다. 위에서 보여드린 BillingService에서 결제수단을 검증하는 기능을 예로 들어보겠습니다.

-시나리오

-고객이 주문을 결제할 때, 요청에는 결제 수단에 대한 정보가 담겨 있습니다. 결제를 수행하기 전, 요청한 결제 수단이 유효한지에 대한 검증이 선행되어야 합니다.

이에 대한 구현 방법은 다양하겠지만, 결제 수단의 검증까지 수행하는 방법과 유효한 결제 수단을 응답하는 방법이 있을 것 같습니다.

파라미터로 넘긴 결제수단이 유효한지 검증하고, 유효하지 않을땐 IllegalArgumentException을 발생시킵니다.

현재 유효한 결제 수단을 조회하고, 이에 대한 검증은 요청한 애플리케이션 (OrderService) 에서 진행합니다.

저는 첫 번째 방법으로 구현하였습니다. 객체 지향에서 자율적으로 행동하는 객체를 만드는 것이 더 좋다고 말하는 것이 지금의 상황과 맞아떨어진다고 생각했기 때문입니다. 좀 더 구체적인 예로 들자면, 결제 수단이 유효한지에 대한 검증을 여러 객체에서 사용한다고 했을 때, 유효한 결제 수단을 반환findAvailablePayMethods() 경우에는 검증 작업을 하는 코드가 중복으로 생겨날 것이고, 만약 검증에 대한 기준이 바뀌는 경우 코드 수정은 여러 곳에서 발생하리라 생각하였습니다.

위 질문에 대한 저의 생각을 답변하고 나니, BillingService의 billing 메소드도 void 메소드가 되는 것이 더 좋았을 것 같았다고 생각하게 되었습니다. billing 메소드를 사용하는 OrderService도 BillingResponse 를 사용하지 않고 있었습니다.

AS IS

TO BE

이런 방식으로 모듈을 나누는 것이 좋은 방법인지에 대해선 아직도 의문을 갖고 있습니다. 모듈의 경계를 정하고, 나누는 것은 정말 정답이 없는 것 같습니다.

이 부분에 있어선,

The hardest part of splitting a program into modules is just deciding on what the module boundaries should be. There’s no easy guidelines to follow for this, indeed a major theme of my life’s work is to try and understand what good module boundaries will look like. Perhaps the most important part of drawing good module boundaries is paying attention to the changes you make and refactoring your code so that code that changes together is in the same or nearby modules.

프로그램을 모듈로 분할할 때 가장 어려운 부분은 모듈 경계를 결정하는 것입니다. 이를 위해 따라야 할 쉬운 지침은 없습니다. 실제로 제 인생의 주요 주제는 좋은 모듈 경계가 어떤 모양일지에 대해 이해하는 것 입니다. 좋은 모듈 경계를 만드는 데 있어 가장 중요한 부분은 변경사항에 주의를 기울이고 함께 변경되는 코드가 동일하거나 가까운 모듈에 있도록 코드를 리팩터링하는 것입니다.

– Martin Fowler, Refactoring Module Dependencies

마틴 파울러도 어렵다 하고,

선 긋기의 달인 기철이도

잘하고 있는 것 같진 않네요..

최근에도 팀에선 모듈을 어떻게 구성하는 게 좋을까에 대한 토론이 이어지곤 합니다. 항상 더 나은 방법을 같이 고민하는, 최고의 팀에 온 것 같습니다. (주문팀 짱!)

우아한 개발자가 되었습니다 !

도움이 되는 이야기를 전해드리고 싶었는데, 도움이 되셨을지 모르겠습니다.

처음으로 일을 시작한 쮸니어는 (주니어에 주니어를 더해서.. 쮸니어..) 이런 고민을 하고 있구나 정도로 봐주셨으면 좋겠습니다.

짧은 시간이지만 회사에서 만난 분들 다 너무 좋으신 분들이었고 배울 점이 많았었습니다.

너무 좋은 회사, 너무 좋은 팀에 합류하게 된 것 같아 정말 행복합니다

주문팀은 요새 게더타운에 푹 빠져 있습니다

저도 얼른 성장해서 기여할 수 있도록 하겠습니다!

앞으로 잘 부탁드리겠습니다. 배민주문서비스팀 김경준입니다.

긴 글 읽어주셔서 감사합니다.

출처 : techblog.woowahan.com [우아한형제들 기술 블로그]

https://contents.nextunicorn.kr/company/1fe09f6393338275/profile-2d2017a53cb39f9da94bdac5954040fb2c9c.png?s=200x&t=cover

(주)우아한형제들

에디터

김경준

우아한형제들은 배달의민족의 운영사로 '좋은 음식을 먹고 싶은 곳에서'라는 비전을 가지고 음식 배달 업계를 혁신 중입니다.

회사
회사 소개인재 채용팀 블로그
서비스
파인더
유니콘LIVE
지원프로그램
IR자료구독
인사이트
엔젤투자
서비스 안내
스타트업 서비스
전문투자자 서비스
유니콘LIVE 서비스
티켓구매
티켓구매
주식회사 넥스트유니콘 l 대표자 장재용
l
개인정보책임관리자 장재용(nextunicorn@nextunicorn.kr)
사업자 등록 번호 139-87-00196
l
통신 판매 신고 번호제 2017-서울강남-04053 호
서울특별시 강남구 테헤란로 427, 8층 101호
l
nextunicorn@nextunicorn.kr l 070-8884-3333
|
©nextunicorn Inc. All rights reserved.
넥스트유니콘 서비스는 전문투자자와 스타트업이 자율적으로 서로에 대한 IR정보 등을 확인할 수 있는 플랫폼 서비스로,
주식회사 넥스트유니콘은 이를 중개하거나 자문하는 투자중개업 및 투자자문업을 영위하지 않습니다.
따라서 실제 투자계약, 투자손실의 위험 등에 대한 책임은 계약 당사자 각자에게 있습니다.