2023년 회고 :: 비보(悲報)

임세진·2024년 1월 26일
0

회고

목록 보기
1/1

직장

애자일 방법론은 만능이 아니다

레거시 프로덕트를 교체하는 프로젝트에 참여했다. 전국을 대상으로 십수 년 동안 운영한 사업이다 보니 그 규모가 엄청났다, 그리고 기술부채도 엄청났다. 5개월간 구조를 파악한 것을 바탕으로 악성 채무를 앞으로 1년 동안 변제하는 일이 남았다. 보통 대규모 부채를 변제하기 위해 상환 계획을 세우면서 실패할 것도 동시에 염두에 둬야 한다. 부채 규모와 계획 실패의 대가는 비례하므로 돌발 상황에 유연하게 대처하여 리스크를 줄이는 게 중요하다.

지금까지 워터폴 방식으로 개발하여 이에 대해 염증을 느끼고 있었다. 대기업에서 큰 규모의 프로젝트를 처음 진행하는 거라 프로세스가 어떻게 흘러갈지 궁금해 했고, 리스크에 유연하게 대처하고자 애자일 방식으로 개발하지 않을까 하며 기대했다. 아쉽게도 워터폴 방식을 채택했는데 내 나름대로 원인을 분석하면 다음과 같다.

  • 돈을 지불하여 프로덕트를 기다리는 클라이언트는 퍼포먼스, 개발 사항 준수, 마감기한 준수만을 원한다. 개발 과정이 어떻게 진행되는지, 리소스는 어떻게 사용되는지는 전혀 관심의 대상이 아니다.
  • 애자일 방법론은 모든 구성원의 적극적인 협력에 초점을 두고 있다. 모든 구성원이란 클라이언트를 포함한다. '돈 줬더니 일도 함께하자고? 당신 미쳤어?' 라고 말하면 할 말이 없다. 애초에 애자일 선언문은 고객의 협력을 전제로 하고 있다.
  • 세상은 끊임없이 변화하기에 이에 효과적으로 대응하는 것이 애자일 방법론이 중요하게 여기는 가치 중 하나다. 그런데 클라이언트에게 이 말을 할 수 있을까? '예상보다 시간이 많이 걸리네요. 릴리즈를 미룰 수 있을까요?' 또는 '이 기능은 기한 내에 완성하지 못할 거 같아요. 일단 이건 빼고 나머지 기능으로 오픈할까요?'. 고객 입장에선 화날 일이다. '돈 받고 왜 받은 만큼 일 안해?! 계약한 대로 진행하라고!'. 애초에 전제부터가 잘못되었다.
  • 모든 구성원의 협력을 충족하려면 기획, 디자인, 퍼블리싱, 개발, 테스트를 담당하는 인원들이 한 몸이 되어야 한다. 빅테크 기업은 해당 리소스를 모두 소유했으니 애자일 방법론을 효과적으로 적용할 수 있지만, 내가 속한 프로젝트는 외주 인원이 투입되었다. 기획 인원, 디자인 인원, 개발 인원 등 리소스마다 모두 소속이 다르다. 이는 클라이언트가 각 소속 회사 수만큼 계약을 체결한 것이고, 계약 수만큼 이해관계가 다르다는 걸 의미한다. 외주사도 자기 분야 외에 다른 곳에 힘 빼기 싫어한다. 기획이 끝났으면 바로 계약 종료하는 게 비용을 절감할 수 있으니 고객도 싫어한다.

클라이언트나 외주사가 잘못했다는 게 아니다. 애자일 방법론을 적용하기에 본 프로젝트는 적절하지 않은 것이다. 방법론에 정답은 없고 적재적소에 활용하는 게 가장 중요하지만, 개인적으로 애자일 방법론을 경험하고 싶었던지라 아쉬었다.

실패해야 할 프로젝트가 있다

워터폴 방법론이 나쁜 방식이 아니지만 병목현상이 일어날 수 있다는 단점이 있다. 이 단점이 우리 프로젝트에 방문했다. 외주사가 기획을 담당했는데 계약 종료기간이 다 되어가는데도 결과물이 나오지 않았다. 6개월간 기획 회의에 참여하며 많은 대화가 오고 갔지만 정작 완성된 결과물이 없었다. 외주사는 계약 종료기간이 됐으므로 철수했고 고객과 법적 분쟁이 일어났다. 선행 단계가 지연되면 후행 단계는 손가락만 빨고 있어야 한다는 게 워터폴 방법론의 치명적인 단점이다.

개인적으로 이 프로젝트가 실패로 끝나길 원했다. 실패를 통해 고객에게 충격을 줘 워터폴 방식의 문제점을 인지시키고, 고객 협력을 유도해 애자일 방법론을 채택하길 바라는 큰 그림에서였다. 그러나 회사의 정치적 상황을 고려하면 그렇게 여유롭지 않았다. 그동안의 프로젝트 실패에 대해 임원진은 개발진에게 큰 실망감을 갖고 있었다고 한다. 본 프로젝트는 마지막 기회인 셈이었다. 이번에도 우승하지 못하면 은퇴해야 하는 리오넬 메시의 2022 카타르 월드컵 라스트 댄스처럼.

기술 서적을 보면 대부분 프로젝트를 성공시키는 방법이나 실패를 방지하는 방법에 대해서 설파하고 있다. 내 생각은 다르다. 회생 가능성이 있는 환자라면 마땅히 치료해야겠지만 연명 치료만 남은 상황이라면 치료 거부를 고려해야 한다고 생각한다. 환자는 가족에 대한 미안함과 함께 통증과의 싸워야 하고, 보호자는 죽어가는 환자를 바라보기만 해야 하는 무력감과 함께 경제적 문제를 해결해야 한다. 프로젝트의 성공 가능성과 성공했을 때의 가치 등을 따졌을 때 부정적이라고 판단한다면, 위태로운 프로젝트를 무너뜨리고 새로운 프로젝트를 시작하는 게 기업과 구성원 모두에게 긍정적일 수 있다.

결국 기존 프로젝트를 남은 기간 안에 완료할 수 없다고 판단하여 프로젝트를 변경했다. 비교적 규모가 작은 모바일 프로젝트로 돛대를 틀었고 6개월 안에 오픈하여 성과를 내야 했다.

무엇을, 어떻게 검증할 것인가?

내가 개발한 영역에 다른 레거시 모듈과 EAI로 연동하는 부분이 있었다. 판매 가격을 변경하면 그 가격을 다른 모듈에 전파하여 최종적으로 전사적 동기화를 달성해야 했다. 테스트 코드를 작성하는 프로젝트 룰에는 mock을 이용한 단위 테스트, MockMvc를 이용한 API 테스트가 있었다. 나름대로 테스트 코드를 꼼꼼히 작성했다고 생각했는데 미처 고려하지 못한 부분이 있었다.

다른 모듈에 데이터를 전달했는지가 검증해야 할 핵심 조건인데도 이를 검증하지 않았다. 잘 생각해보면 단위/API 테스트로는 이를 검증할 수 없었는데도, 프로젝트 룰을 맹신하여 사고가 났다. 판매 가격을 변경했는데 다른 모듈에선 반영되지 않았다는 CS를 받았다. 조기에 발견되어 다행이지만 고객에게 금전적으로 피해가 발생했고, 이를 수습하기 위해 여러 사람이 달려들었으며, 팀장님은 시말서를 작성했다. 안일한 태도가 어떤 결과를 불러 오는지 뼈저리게 느꼈다.

얼마나 검증되어 있는지도 중요하지만 무엇을, 어떻게 검증할 것인지는 더욱 중요하다. 스쿠버 다이버에게 완전 방수가 인증된 시계를 판매하려고 하는데, 그 인증 기준이 수심 10cm라면 인증한 의미가 있겠는가? 방수되지 않는 시계보다 못하다.

상대방이 잘 들을 수 있는지를 파악하자

말을 잘 내뱉었다고 끝이 아니라 상대방에게 잘 도달했는지까지 확인해야 한다.

세미나에서 이 말을 들었다면 고개를 끄덕였을 것이다. 일방적인 대화는 상대방에 대한 배려가 없는 거고, 상호 존중하는 대화가 좋은 것임은 알고 있다. 문제는 환경이 직장이라는 점이었다.

나는 공과 사를 구분하는 것을 중요하게 생각한다. 철천지원수가 있어도 공적인 일이라면 개인적인 원한으로 그에게 불이익을 주지 않을 것이다. 회사 일은 돈 받고 하는 것이니 프로 의식이 필요하다고 생각했다. 동료가 바쁘거나 업무로 인해 스트레스가 쌓여 있다는 걸 알았지만, 우리는 프로라는 생각에 이를 무시하고 냉정하게 업무를 맡겼다.

한계에 다다른 동료가 언성이 높아지자 주변 동료들이 나서서 과열된 분위기를 식혀줬다. 당시에 나는 업무적으로 논쟁했을 뿐인데 이게 싸우는 것처럼 보였나? 라고 생각했다. 얼떨결에 사과를 했지만 조금 시간이 지나고 보니 내 잣대를 상대한테 들이댔 거였다. 지금도 나는 프로 의식이 필요하다는 생각엔 변함 없지만, 이는 내 생각이지 다른 이가 이를 수용해야 할 의무는 없다. '내 자신에게 엄하게, 상대에게 관대하게'라는 좌우명이 흐릿해지는 순간이었다. 회사 일이지만 사람은 감정 없는 기계가 아니라는 걸 명심하자.

개인

증명은 말로 하는 게 아니다

나는 고졸이다. 정보처리기사 자격증을 취득해야 중급 개발자가 빨리 될 수 있다는 말을 예전부터 들었지만 관심의 대상이 아니었다. 시험 수준은 실무 능력 향상은커녕 수박 겉 핥기 정도였고, 소를 도축하여 고기의 급을 나누듯 개발자를 합리적이지 않은 기준으로 급을 나누는 데에 반발심이 들었기 때문이었다.

입사 4년 후 갑자기 생각이 달라졌다. 나는 말만 번지르르한 빛 좋은 개살구를 좋아하지 않는다. '정보처리기사 자격증이 필요없어서 응시하지 않았을 뿐이지 맘만 먹으면 충분히 따~.' 이제까지 이런 생각으로 기고만장해 있었다. 어느새 내가 원하지 않는 모습이 됐다. 내가 개살구라는 의심을 없애고 나에게 스스로를 증명하기 위해, 공부를 시작했다.

프로젝트 매니지먼트 관련 지식이 생소했다. 프로젝트라는 거대한 배를 이끌어 가는 선장의 역할 및 요구 역량에 대해 알 수 있었다. 그간 선원으로서 어떻게 하면 노를 잘 저을지만 고민했었는데 덕분에 시야가 넓어졌다. 나중에 알게 된 사실인데, 외주 계약 특성상 인력 단가를 급수로 책정할 수밖에 없다. 높은 급의 인력이 많을 수록 회사의 이윤이 늘어나고 이는 연봉, 복지 등 어떠한 형태로든 회사 전체에 플러스 요인이 된다. 자격증 취득이 자신의 역량을 증명하는 것뿐 아니라 동료 모두에게 도움된다는 사실. 역시 사람은 항상 겸손해야 한다.

실기 시험 접수일 첫 날에 회사 일이 바빠 까먹고 있다가 밤에 접수하려고 했더니 재앙을 보았다. 나는 서울에 사는데 서울, 경기도, 인천 모두 자리가 꽉 찼다. 수도권에서 시험을 보기 위해 며칠 동안 필사적으로 노력했지만 나보다 더 필사적인 사람들이 많은 거 같았다. 자리 하나가 생겨서 수초 안에 결제 버튼을 눌러도 다른 사람이 이미 결제했다는 팝업을 몇 번을 본 건지 모르겠다. 보험으로 서대전역 배재대학교를 염두하고 있었는데 오전에 150 자리가 오후엔 90 자리로 줄어 들었다. 이러다 전라도나 경상도로 가겠다는 생각에 배재대학교로 자리를 잡았다. 자격증 시험을 보기 위해 새벽 4시에 일어나 KTX 타고 지방에 내려가는 신선한 경험을 했다.

C언어에 대해 아는 게 없었는데 회사 동료가 흥달쌤을 추천했다. 내 생각엔 정보처리기사의 바이블이다. 이 선생님 아니었으면 합격하지 못했다! 정보처리기사를 준비하는 수험생이라면 무조건 추천한다. SQL-D 자격증의 시험 범위가 정보처리기사의 데이터베이스 과목과 겹치는 게 많아 쉽게 합격할 수 있었다. 정보처리기사 데이터베이스 문제보다 난도가 높지만 실무자라면 기출 문제 조금 풀고 금방 합격할 수 있다. 할 수 있으면 같이 응시하는 걸 추천한다.

비법거래소

내 이력서를 살펴 보니 프로젝트 이력이 취약했다. 회사에서도 소규모로 진행한 프로젝트뿐이고 개인적으로도 혼자서 진행한 프로젝트밖에 없었다. 부족한 협업 경험을 채우기 위해 사이드 프로젝트를 찾으러 발품 팔다가 렛플에서 '비법거래소'를 알게 됐다.

자신이 알고 있는 지식을 공유하고 여러 사람의 지지를 받으면 유료화가 된다. 이를 게시글이 상장됐다고 한다. 주식 시장을 모티브로 하여 수요와 공급에 따라 게시글 열람 비용이 변화한다. 주식이 상장폐지되는 것처럼 상장된 게시글이 호응 받지 못하면 폐지된다. 게시글 구매 비용을 작성자와 플랫폼이 나눠 가지는 수익 구조를 갖고 있다.

내가 생각하는 비법거래소 프로젝트의 장점은 다음과 같았다.

  1. 시장조사를 사전에 진행하여 서비스를 긍정적으로 생각하는 비율이 높은 걸 알아낸 점.
  2. 컨텐츠 구매자가 언제든지 판매자가 될 수 있고, 그 반대도 가능한 점.
  3. 기획, 디자인, 프론트, 백엔드까지 소수지만 분야별 인원이 모두 모인 점.
  4. 프로젝트 기여율에 따라 수익을 배분하는 점.

단점은 이랬다.

  1. 시장조사의 표본집단이 제한적이고 인원 수가 너무 적은 점.
  2. 투기로 변질될 수 있는 주식을 통제하기 위해 많은 장치가 마련되어 있지만 게시글을 통제하는 장치를 마련되어 있지도, 정부처럼 강력하게 통제할 수도 없는 점.
  3. 분야별 인원이 소수라 업무 부담이 과할 수 있는 점.

면접 합격 후 백엔드팀의 결제 파트를 맡았다. 비법거래소의 핵심 서비스 '거래' 로직을 구현하는 게 대단히 중요했다. 결제 연동은 포트원 결제 API 서비스를 사용했다. 회사에서 PG사와 직접 연동했던 적이 있었는데 샘플 코드는 JSP에 API 문서는 hwp로 되어 있는 걸 보고 충격 받았었다. 수수료 더 내더라도 API 서비스를 이용하는 게 정신 건강에도 좋고, 관리자 콘솔도 잘 되어 있어 사후 관리에도 좋다.

첫 PR

코드도, 리뷰 받는 것도 익숙하지 않아 첫 PR은 일반적인 것을 올렸다. 스프링 빈 선언부는 롬복 애노테이션을 붙여서 생성자 주입을 받고 있는 것과 @Bean 메서드 2가지였다. 생성자와 메서드의 접근 레벨을 package-private으로 변경했다. 스프링 프레임워크를 사용한다면 그럴 일은 없겠지만 외부에서 직접 호출하여 빈의 인스턴스를 생성하지 못하게 하려는 의도였다. 단위 테스트 때 예외적으로 생성자를 직접 생성할 수 있도록 접근 레벨을 고려했다.

리뷰어: 몰랐던 사실 감사합니다. DI/빈 생성에 대해 reflection과 proxy를 사용하는 걸 몰라, 관용적으로 public으로 사용하고 있었어요. 외부에서 호출하는 일은 적을 거 같지만, 옳은 방향으로의 수정이라고 생각해서 좋습니다.

코드 하나하나 부검하면서 왜 이런 코드를 작성했는지 설명해야 했다. 법원으로 치자면 내 코드는 피의자, 리뷰어는 검사, 나는 변호사 같은 느낌이었다. 내 코드는 문제가 없고 합리적으로 작성됐다는 걸 변론하는 시간이었다. 그런데 이건 방어적으로 생각했을 때 이야기고, 열린 마음으로 보면 다르다. 하나의 프로덕트가 성공하기 위한 내 의견(코드)에 대해 구성원들을 설득하는 일이었다. 공격적으로 말할 필요가 없다.

롬복의 var, val을 사용하지 못하게 설정 파일을 생성했다. 단순히 사용하지 말자고 구두로 얘기하는 것과 문서로 남기는 것은 다르다고 생각했고, 이러한 준수 사항을 컴파일 레벨에서 잡을 수 있다면 코드 리뷰 리소스를 줄일 수 있다는 근거에서였다.

리뷰어: 동의합니다. 지금까지 코딩 컨벤션이 없었는데 같이 만들어나가면 좋을 것 같네요. 이 내용은 다음 회의 때 같이 논의해보면 좋을 것 같습니다.

그동안 리뷰 없이 코드를 작성하다가 첫 리뷰를 받으니 느낌이 새로웠다. 열심히 하여 프로덕트를 성공적으로 런칭해도 '야근 많이 한 거 안다', '이 모듈을 구현하느라 고생했다' 등 추상적으로 인정 받았었다. 리뷰를 통해 코드를 직접 보면서 나의 노고를 인정해주니, 구체적으로 칭찬 받은 것 같았다.

무엇을 암시하는 것이지?

리뷰 받으면서 알 수 없는 용어들을 마주했다. 리뷰어가 어떤 사항을 지적했고 다른 소스도 동일한 문제가 있어서, ditto라는 답글을 달았다. 갑자기 뜬금없이 뉴진스? 뉴진스 팬이신가? 다른 사람에게 보낼 걸 나한테 잘못 보낸 건가?

다른 리뷰에선 또 다른 용어를 만났다.

nit) typo

오타를 수정하라는 건 알겠지만 앞에 붙은 nit가 무엇인지 알 수가 없었다. 니트족의 니트를 말하는 것인가? 사전에서 찾아보니 '멍청이'라던데 오타 때문에 멍청이라고 하는 건가? 이게 애교 섞인 장난으로 '멍청이'라고 하는 건가? 그런데 우리가 장난칠 정도로 친한 건 아닌데..?

  • DITTO (The same as before): 전에 말한 것과 같다는 의미로 사용한다.
  • NIT (Need improvement or suggestion): 개선 또는 제안할 사항을 말하며 보통 사소한 문제에 대해 사용한다.

리뷰 관련 줄임말이 자연스럽게 나오는 걸 보니, 평소에 리뷰를 많이 하는 분이라는 걸 간접적으로 느낄 수 있었다. 그러려니 하고 넘길 수 있겠지만 난 다르게 생각했다. 자신이 리뷰 경험 없다는 걸 환경을 탓하며 합리화하지 말고, 시간을 짬 내서 간단하게라도 동료의 코드를 리뷰해주자고. 큰 프로젝트는 혼자서 완성할 수 있는 게 아니다. 내 리뷰로 인해 프로젝트 릴리즈에 차질이 없도록 도움이 되었다면 결국 내게도 이익인 것이다, 동료의 신뢰와 함께. 내 할 일을 얼른 완료하고 리뷰해줄 수 있도록 꾸준히 역량을 키워야겠다.

비보(悲報)

2023년 12월 31일 일요일 아침, 달콤한 늦잠을 자다가 낯선 번호로 전화가 왔다. 느닷없이 형의 이름과 함께 보호자가 맞냐는 다급한 말. 잠결에 전화를 받아 몽롱하고 느긋한 말과 대비를 이루고 있었지만, 그 대비가 깨지는 데는 몇 초 안 걸렸다.

여기 경찰관입니다. 형 분이 심정지가 왔어요. 지금 119가 CPR 중입니다.

'어' 소리와 함께 폐 속 공기가 빠져 나갔다. 무의식적인 반응이었다. 이 사실을 아빠에게 알리고 엄마에게 알리려던 순간 멈칫했다. 엄마는 몸이 불편하여 병원에 갈 수 없는데 심정지라고 말하고 집을 나서면, 안 그래도 유약한 엄마가 더 불안해 할 거 같았다. 들은 정보가 부족하기도 해서 형이 쓰러져 병원에 갔다라고 말했다.

나는 형이 이미 죽었다고 생각하며 병원으로 이동했다. 심장이 멈췄다는 건 사실상 죽은 상태고 앞으로 닥칠 일을 어떻게 처리해야 하나 고민했다. 집에서 병원까지 30분 이상 걸리는데 체감상 30초가 걸린 것 같았다. 대학병원 응급실에 도착하니 보호자는 1명만 들어갈 수 있다고 보안요원이 제지했다. 가족이 응급실에 실려갔다는 말을 들으면 대부분 모든 가족이 뛰쳐 나갈 텐데, 이리 야박하다니.

아빠보다 내가 의료진과 대화하는 게 좋을 거 같다고 판단해서, 나는 들어가고 아빠는 밖에서 기다렸다. 보호자 대기실에서 몇 분 정도 대기하자 의사 선생님이 형 이름을 부르며 보호자를 찾았다. 사건의 경위는 이러했다.

  1. 09:32 눈 뜬 채 쓰러져 있는 형을 행인이 발견했다. 당시 입김이 보였다고 했다.
  2. 09:43 구급대원이 도착했다. 호흡이 없고 심장이 정지된 상태였다.
  3. 10:07 대학병원 응급실에 도착했다. 리듬은 있으나 맥박이 없어 심폐소생술 시행했고, 4분 후에 호흡이 돌아왔다.

대기실에 있어도 내가 할 수 있는 건 없었다. 형이 지금 회복되고 있는지 죽어가고 있는지 모른 채, 기약없이 의료진을 기다려야 했다. 한참 뒤 의사 선생님이 오셔서 검사 결과를 설명해줬다.

폐렴과 패혈증이 심각해요. 산증이 있는데 피가 끈적해진 상태라고 보면 돼요.

평소에 의학 웹툰을 즐겨 봐서 패혈증의 위험성을 알고 있었다. 세균이 혈관을 타고 온 몸을 돌아 다니면서 여러 장기를 감염시키고 있는 것이다. 형은 세균과의 전쟁을 치르고 있었다. 이 질병은 사망률이 20% ~ 35% 정도로 대단히 높은 편이다.

내가 병원에 있어도 도와줄 수 있는 게 없었다. 형을 보고 싶었지만 심정지가 왔던 환자를 치료하는 건 대단히 바쁠 텐데 오히려 치료에 방해될까봐 면회를 요청하지 않았다. 그저 의료진들이 최선을 다하길 기도할 뿐...

저녁이 다 돼도 의료진이 보호자를 찾지 않아서 응급실 비용을 결제하려고 원무과에 갔다. 8시간 동안 응급실에서 치료받은 비용 180만원. 하루만에 이 금액이면 일주일이면 대략 천만원...?

저쪽에선 세균과의 전쟁, 이쪽에선 돈과의 전쟁이 벌어지고 있었다.

profile
러닝 포인트를 찾는 개발자

2개의 댓글

comment-user-thumbnail
2024년 1월 26일

느끼고 생각하신 바를 이렇게 나누어 주셔서 감사합니다. 한 해 동안 회사에서 직간접적으로 경험한 것(ex. ‘병목 현상’)에 대해 막연한 인상만 있었는데, 분석적으로 접근한 글을 읽으니 좋았습니다. ‘실패해야 할 프로젝트가 있다’는 관점도 파격적이고 재밌었습니다.ㅎㅎ
선임님과의 대화는 항상 재밌어서 기대하게 되는데 평소 생각이 치열하고 깊으신 덕분인 것 같아요.

비보에 대해서는 겪으신 상실에 비한다면 어떠한 말도 궁색하고 부적절할 것 같습니다. 상심이 크신 와중에도 일할 때, 휴식할 때 보여주시는 모습에 저는 죄송하면서도 고마운 마음을 갖고 있어요. 그저 선임님이 맛있는 것 많이 드시고 충분한 수면 취하면서 안온한 매일을 보내면 좋겠습니다.

다음 글도 기다릴게요!

1개의 답글