Showing Posts From

일상

네트워킹을 해야 하는데 피곤해서 못 할 때

네트워킹을 해야 하는데 피곤해서 못 할 때

네트워킹을 해야 하는데 피곤해서 못 할 때 오늘도 단톡방만 눈팅 슬랙에 알림이 떴다. "이번 주 토요일 스프링 밋업 있는데 누구 갈 사람?" 읽었다. 답 안 했다. 작년부터 똑같은 패턴이다. 개발자 커뮤니티 단톡방이 5개다. "스프링 코리아", "백엔드 개발자 모임", "서울 개발자", 뭐 이런 것들. 가입할 땐 의욕 넘쳤다. "나도 네트워킹 해야지!" 했다. 근데 막상 밋업 공지 뜨면 그냥 넘긴다. 읽씹한다. 가끔 이모지 하나 찍는 게 전부다. 토요일 오후 2시에 강남이래. 2시면 늦잠 자고 일어나서 브런치나 먹을 시간이다. 거기서 강남까지 지하철로 40분. 밋업 끝나면 5시. 집 도착하면 7시. 계산기 두드리면서 한숨 나왔다. 그냥 집에서 넷플릭스 보는 게 낫겠다 싶었다.피곤한 건 진짜다 목요일 밤 9시. 배포 끝났다. 집 도착하니까 10시 반. 씻고 누우니 11시. 핸드폰 보다가 1시. 금요일 아침 8시 알람. 눈 뜨는데 3분 걸렸다. 커피 마셔도 머리가 안 돌아간다. 오전에 PR 리뷰 5개. 점심 먹고 회의 2개. 오후엔 버그 픽스. 퇴근하니까 7시. 이 상태로 토요일 밋업? 웃긴 소리다. 사람들은 말한다. "주말인데 뭐." 주말이라서 더 쉬고 싶은 거다. 평일에 쓴 에너지 회복할 시간이 필요하다. 새로운 사람 만나서 명함 돌리고 스몰토크하는 건 에너지가 더 든다. 내향형이라서 그런가 싶기도 하다. 근데 솔직히 외향형이어도 피곤하면 못 갈 것 같다. 밋업 가는 친구한테 물어봤다. "어떻게 매주 가냐?" "그냥 가요. 가면 재밌어요." 가기 전까지가 문제라는 거다. 나도 안다. 가면 괜찮을 거라는 걸. 근데 그 "가기 전까지"를 못 이긴다.링크드인 구경만 300번 링크드인 켰다. 피드 스크롤했다. "DevFest 2024 다녀왔습니다! 좋은 분들 많이 만났어요 #networking" 사진엔 20명이 웃고 있다. 부럽다. 진짜로. 나도 저렇게 찍고 싶다. "김개발도 네트워킹 하는구나!" 하는 포스팅. 근데 현실은 집 소파다. 치킨 시켜놓고 폰 본다. 링크드인 프로필 업데이트한 게 8개월 전이다. 이력서도 똑같다. 1년 전에 만든 거 그대로다. "언젠간 고쳐야지" 하는데 안 고쳐진다. 이직 준비도 마찬가지다. 알고리즘 문제 풀어야 하는데 안 푼다. "다음 주부터" 가 3개월째다. 네트워킹하면 이직도 쉽다더라. "요즘 개발자는 레퍼럴로 이직해요." 맞는 말이다. 근데 레퍼럴 받으려면 사람을 알아야 한다. 사람을 알려면 밋업을 가야 한다. 밋업 가려면 에너지가 있어야 한다. 무한 루프다. 결국 토요일엔 집에서 유튜브 봤다. "개발자 네트워킹 방법" 영상 3개 봤다. 아이러니하다.온라인도 사실 귀찮다 "오프라인이 부담되면 온라인으로 하세요." 자기계발 아티클에서 봤다. 시도했다. 진짜로. "스프링 디스코드" 들어갔다. "자바 카톡방" 가입했다. "노션 슬랙" 찬 받았다. 3개 다 알림 껐다. 디스코드는 메시지가 너무 많다. 하루 자고 일어나면 300개다. 다 읽으려면 30분 걸린다. 읽어도 맥락을 모르겠다. "아까 그 얘기인데요" 하는데 아까가 언제인지 모른다. 카톡방은 더하다. 새벽 3시에도 울린다. "이거 어떻게 해결하셨어요?" 자고 있는데 폰이 진동한다. 알림 끄면 대화 따라가기 힘들다. 슬랙은 그나마 낫다. 근데 회사 슬랙도 있고 팀 슬랙도 있다. 거기에 커뮤니티 슬랙까지 3개. 어디서 누가 멘션했는지 헷갈린다. 결국 다 눈팅만 한다. 가끔 좋은 정보 올라오면 북마크만 한다. 북마크 폴더엔 안 읽은 링크가 247개다. 온라인 네트워킹도 에너지가 든다는 걸 깨달았다. 대화에 끼려면 맥락을 알아야 한다. 맥락 알려면 계속 봐야 한다. 계속 보려면 시간을 써야 한다. 퇴근하고 그럴 시간 없다. 회사 사람들이랑도 안 어울린다 금요일 저녁 6시. "형 회식 가시죠?" "나 먼저 갈게." 회사 동료들이랑도 안 논다. 팀 회식은 년 2번 의무참석. 그 외엔 핑계 대고 빠진다. "회사 네트워킹이라도 하세요." 선배가 그랬다. "같은 회사 사람이 나중에 다른 회사 가면 레퍼럴 해줘요." 맞는 말이다. 근데 그것도 피곤하다. 팀원 5명이랑은 매일 본다. 스탠드업 미팅에서 본다. 점심 먹을 때 본다. 커피 마실 때 본다. 그 정도면 충분하다고 생각했다. 퇴근해서까지 볼 이유를 모르겠다. 한 달에 한 번 회사 전체 회식이 있다. 100명 넘게 모인다. 인사팀에서 "네트워킹 기회입니다!" 한다. 가면 아는 사람들끼리만 모인다. 모르는 사람한테 말 걸기 어렵다. 명함 주고받는 것도 어색하다. "김개발입니다. 백엔드 하고요." "아 네. 저는 프론트입니다." 이러고 끝난다. 결국 30분 있다가 집 간다. "배 아프다" 핑계 댄다. 거짓말은 아니다. 진짜 배 아프다. 스트레스로. FOMO는 있다 그래도 불안하긴 하다. "다들 네트워킹하는데 나만 안 하면?" "기회를 놓치는 건 아닐까?" FOMO다. Fear of Missing Out. 알면서도 느낀다. 링크드인 보면 심해진다. 동기가 컨퍼런스에서 발표했다. 후배가 밋업 주최했다. 선배가 스타트업 창업했다. 나는? 집에서 넷플릭스 본다. 이력서는 1년째 그대로다. 가끔 생각한다. "5년 뒤에도 이럴까?" "10년 뒤엔?" 무섭다. 솔직히. 개발자는 네트워크가 중요하다고 한다. "요즘 채용은 다 레퍼럴이에요." "좋은 프로젝트는 아는 사람한테 오더라고요." 맞는 말 같다. 근데 당장 내일 밋업 가라고 하면 안 갈 것 같다. 이상과 현실의 괴리다. "해야 한다"와 "할 수 있다"의 차이. 해야 하는 건 안다. 근데 못 한다. 피곤해서. 그냥 쉬고 싶다 결론은 간단하다. 쉬고 싶다. 그냥. 평일엔 회사 일로 에너지 다 쓴다. PR 리뷰하고 회의하고 코드 짠다. 9시간 집중한다. 퇴근하면 탈진 상태다. 주말까지 네트워킹하면? 쉴 시간이 없다. 월요일에 또 출근해야 한다. 그럼 언제 쉬지? "주말에 투자해야 평일이 편해져요." 누가 그랬다. 아니다. 주말에 쉬어야 평일을 버틴다. 재충전이 필요하다. 배터리 0%로는 못 산다. 집에서 뒹굴거리는 것도 생산적인 거다. 아무것도 안 하는 게 나를 회복시킨다. 다음 주를 위한 준비다. 네트워킹은 중요하다. 근데 내 건강도 중요하다. 정신 건강도 포함해서. 번아웃 오면 끝이다. 네트워킹 이전에 일을 못 한다. 우선순위가 있다.회사 일 제대로 하기 건강 챙기기 그 다음에 네트워킹지금은 2번도 제대로 못 한다. 3번은 나중 일이다. 언젠간 하겠지 포기한 건 아니다. 미룬 거다. "지금은 때가 아니다." 스스로 합리화한다. 실제로 그럴 수도 있다. 커리어 초반엔 네트워킹보다 실력이 먼저다. 실력 없으면 네트워크 소용없다. 7년차면 이제 좀 쌓였다. 실력은. 근데 에너지는 줄었다. 아이러니하다. 주니어 때는 에너지 있었는데 자신감이 없었다. 시니어 되니까 자신감 생겼는데 에너지가 없다. 타이밍이 안 맞는다. 언젠간 갈 것 같다. 밋업. "오늘은 좀 괜찮네?" 하는 날. 기분 좋고 날씨 좋고 컨디션 좋은 날. 그런 날이 올까? 잘 모르겠다. 근데 안 와도 괜찮다고 생각한다. 네트워킹이 커리어의 전부는 아니니까. 조용히 일 잘하는 개발자도 있다. 나는 그쪽인 것 같다.토요일 오후 3시. 소파에서 일어났다. 밋업 시간이다. 안 갔다. 대신 커피 내려 마셨다. 이것도 괜찮다.

커피 3잔으로 버티는 하루의 진실

커피 3잔으로 버티는 하루의 진실

커피 3잔으로 버티는 하루의 진실 9시 15분, 첫 번째 아아 지각이다. 14분 59초 지각. 엘리베이터에서 핸드폰으로 슬랙 확인. 긴급한 멘션은 없다. 다행이다. 자리에 앉자마자 가방에서 아이스 아메리카노를 꺼낸다. 편의점에서 2200원짜리. 컵 표면에 물방울이 맺혀있다. 첫 모금을 마신다. 차갑다. 쓰다. 정신이 든다. 모니터를 켠다. 어제 못 끝낸 PR이 3개다. 신입 후배가 올린 코드에 빨간 줄이 보인다. 리뷰를 써야 한다. 근데 아직 머리가 안 돌아간다. 커피를 한 모금 더 마신다. 슬랙에 PM이 메시지를 보냈다. "개발님, 이거 오늘 배포 가능할까요?" 배포 일정표를 확인한다. 오늘은 배포일이 아니다. "확인해보겠습니다"라고 답장한다. 확인할 건 없다. 그냥 시간 버는 답장이다. 커피가 반쯤 줄었다. 손이 차갑다. 키보드를 친다. 손가락이 뻣뻣하다. 아직 몸이 안 깼다.10시쯤 되면 정상이다. 커피 한 잔이 완전히 흡수되는 시간. 그때부터 코드가 읽힌다. 변수명이 눈에 들어온다. 로직이 이해된다. 오전엔 집중이 된다. 아무도 말 안 건다. 회의도 없다. PR 리뷰를 3개 끝낸다. "LGTM" 도장을 찍는다. 신입 후배 코드는 컨벤션이 안 맞아서 코멘트를 7개 단다. 미안하지만 어쩔 수 없다. 첫 번째 커피는 생존용이다. 이게 없으면 오전이 지옥이다. 1시 30분, 두 번째 아아 점심을 먹었다. 김치찌개였다. 항상 김치찌개다. 사장님이 "오늘은 김치가 잘 익었어요"라고 했다. 맛있었다. 근데 배가 부르다. 자리로 돌아온다. 졸음이 온다. 밥 먹고 30분이 가장 위험하다. 모니터만 보면 눈이 감긴다. 코드가 흐려진다. 카페에 간다. 회사 1층 카페. 직원 할인으로 3500원. 아이스 아메리카노 톨 사이즈. 얼음을 가득 채워달라고 한다. 카드를 찍는다. 이번 달 커피값이 얼마나 나올까. 생각하기 싫다.자리에 앉는다. 빨대로 첫 모금. 진하다. 오전보다 진하게 뽑았다. 좋다. 슬랙 알림이 5개다. 다 읽는다. 긴급한 건 없다. 그냥 떠드는 거다. 읽씹한다. 오후 회의가 1시간 후다. 그 전에 이슈 하나를 끝내야 한다. API 응답 속도 개선. 쿼리를 봤는데 N+1이 있다. 수정한다. 테스트를 돌린다. 통과한다. PR을 올린다. 커피를 마신다. 반쯤 남았다. 얼음이 녹아서 연해진다. 그래도 마신다. 안 마시면 회의 중에 잔다. 두 번째 커피는 점심 폭탄 해체용이다. 이게 없으면 오후 2시에 죽는다. 3시 10분, 세 번째 핫아 회의가 끝났다. 2시간 걸렸다. 예상은 1시간이었다. 항상 그렇다. 기획자가 "이건 간단하게 추가할 수 있죠?"라고 물었다. 대답은 "확인해보겠습니다"였다. 간단한 게 없다는 걸 다들 안다. 그래도 묻는다. 피곤하다. 어깨가 무겁다. 눈이 뻑뻑하다. 모니터를 너무 오래 봤다. 카페에 또 간다. 이번엔 핫 아메리카노. 3500원. 같은 가격이다. 근데 핫은 양이 더 많다. 이득이다. 들고 온다. 김이 난다. 한 모금 마신다. 뜨겁다. 혓바닥이 데인다. 그래도 마신다. 입안이 따뜻하다.오후 3시부터 6시까지가 고비다. 가장 졸리고 가장 집중이 안 된다. 근데 일은 가장 많이 들어온다. PM이 "내일까지 되나요?" 하고 묻는다. 기획자가 "급한 건데요" 하고 메시지를 보낸다. 다 급하다. 항상 급하다. 핫아를 마신다. 천천히 마신다. 뜨거워서 빨리 못 마신다. 그게 좋다. 시간이 천천히 간다. 코드를 본다. 레거시다. 주석도 없다. 작성자는 퇴사했다. 이해해야 한다. 수정해야 한다. 한숨이 나온다. 커피를 마신다. 세 번째 커피는 생존 연장용이다. 이게 없으면 오후 4시에 멘탈이 나간다. 6시 17분, 빈 컵 세 개 퇴근 시간이다. 책상 위에 빈 컵이 세 개다. 편의점 플라스틱 컵 하나. 카페 컵 두 개. 다 비었다. 얼음만 남았다. 키보드를 덮는다. 모니터를 끈다. 가방을 챙긴다. 자리에서 일어난다. 허리가 뻐근하다. 하루 종일 앉아있었다. 엘리베이터를 기다린다. 동료가 "오늘 3잔 드셨네요"라고 한다. 책상에 컵 세 개를 봤나 보다. "네"라고 답한다. "매일 3잔이세요?"라고 묻는다. "네"라고 또 답한다. 집에 간다. 지하철에 앉는다. 핸드폰을 본다. 유튜브를 켠다. 아무거나 본다. 내용은 안 들어온다. 그냥 화면만 본다. 손이 떨린다. 미세하게. 카페인 과다다. 알고 있다. 근데 어쩔 수 없다. 커피 없이는 못 버틴다. 반성 같은 건 없다 커피 없이 일할 수 있을까. 생각해봤다. 안 된다. 머리가 안 돌아간다. 코드가 안 읽힌다. 회의 중에 졸음이 쏟아진다. 그럼 줄일 수 있을까. 2잔으로. 생각해봤다. 안 된다. 오전에 한 잔 안 마시면 10시까지 좀비다. 점심 후에 안 마시면 오후 2시에 기절한다. 오후 3시에 안 마시면 퇴근까지 버티지 못한다. 3잔이 적정선이다. 더 마시면 손 떨림이 심해진다. 덜 마시면 일을 못한다. 7년 동안 최적화한 결과다. 건강에 안 좋다는 건 안다. 위장도 안 좋고 수면도 안 좋다. 근데 당장 내일 PR 리뷰를 해야 하고 배포를 해야 한다. 건강은 나중 문제다. 지금은 생존이 먼저다. 동기가 "카페인 끊었다"고 자랑했다. 대단하다고 했다. 진심이었다. 근데 나는 못한다. 안 할 거다. 커피가 내 연료다. 퇴근하고 집에 왔다. 냉장고를 연다. 맥주가 있다. 마실까 말까. 고민한다. 오늘 카페인을 너무 많이 섭취했다. 잠이 안 올 것 같다. 맥주를 마신다. 술로 카페인을 중화시킨다. 건강한 방법은 아니다. 알고 있다. 내일도 아아-아아-핫아다. 모레도 그럴 거다. 다음 주도 마찬가지다. 이게 내 루틴이다. 바꿀 생각은 없다. 바꿀 수도 없다. 커피 3잔으로 버티는 하루. 이게 내 진실이다.내일도 편의점 들러서 아아 사 가야지.

개발자로 34세, 앞으로 뭘 해야 할까

개발자로 34세, 앞으로 뭘 해야 할까

34세, 7년차 어제 생일이었다. 34세. 케이크는 아내가 사 왔다. 초는 안 꽂았다. "축하해" 한마디 듣고 냉장고에 넣었다. 오늘 출근해서 PR 세 개 리뷰했다. 후배가 쓴 코드다. 변수명이 이상하다. "이거 userId로 바꾸는 게 어때요?" 댓글 달고 approve 눌렀다. 그러다 문득 생각했다. 나는 7년차인데 아직도 이런 일을 한다.같은 해 입사한 동기 대학 동기 단톡방이 있다. 요즘은 조용하다. 다들 바쁘다. 얼마 전에 한 명이 썼다. "팀장 됐어요 ㅎㅎ" 축하 이모지가 쏟아졌다. 나도 눌렀다. 엄지 척. 그리고 폰을 내려놨다. 그 친구는 3년차 때 이미 달랐다. 개발보다 기획자랑 얘기하는 게 많았다. "비즈니스를 이해해야 한다"고 했다. 나는 그냥 코드가 좋았다. 지금 그 친구는 팀장이다. 연봉은 모르겠다. 물어볼 수도 없다. 나는 여전히 코드 친다. 이력서의 기술스택 요즘 가끔 이력서를 본다. 이직할 건 아니다. 그냥 본다. [기술스택]Java, Spring Boot MySQL, Redis AWS EC2, RDS Git, Jenkins7년 전이랑 크게 다르지 않다. 버전만 올라갔다. Spring 3.x에서 5.x로. Redis는 그때도 썼다. 새로운 거라곤 Docker 정도. 그것도 배포 스크립트 복붙한 수준이다. 옆 팀 후배는 요즘 Rust 공부한다고 했다. 주말마다 사이드 프로젝트 한다고. "형도 해보세요, 재밌어요" 재밌겠다. 근데 피곤하다. 주말엔 쉬고 싶다.아키텍트라는 단어 회사에 아키텍트가 한 명 있다. 40대 중반. 15년차. 회의 때 화이트보드에 그림 그린다. "이 부분을 MSA로 분리하면..." 다들 고개를 끄덕인다. 나도 끄덕인다. 근데 실제로 코드 짜는 건 나다. 아키텍트는 코드를 안 짠다. 가끔 PR에 댓글 단다. "이 부분 성능 체크 부탁드립니다" 실제로 성능 체크하는 건 나다. JMeter 돌리고, 로그 보고, 튜닝한다. 그러면 아키텍트가 임원한테 보고한다. "성능 30% 개선했습니다" 나도 저렇게 되어야 하나. 그림 그리고 방향 제시하고. 코드는 후배들한테 맡기고. 근데 솔직히 말하면, 그림 그리는 게 재미있을 것 같지 않다. 관리자의 하루 우리 팀 리드가 있다. 나보다 2년 선배. 9년차. 직함은 수석 개발자인데 실제론 팀장이다. 그 사람 하루를 봤다. 아침 9시 출근. 바로 회의. 10시 회의. 11시 회의. 점심 먹고 2시 회의. 회의 끝나면 슬랙 답장. 기획자 질문, 디자이너 질문, 임원 질문. 5시쯤 되면 후배들 진행상황 체크. "이거 일정 괜찮아요?" 코드는 안 짠다. 가끔 PR 보는 게 전부다. 진짜 급한 버그 아니면 직접 안 건드린다. 퇴근은 나보다 늦다. 보고서 쓴다. 다음 분기 계획 짠다. 연봉은 나보다 천만원 많다. 나도 이렇게 되고 싶나. 잘 모르겠다.금요일 저녁의 배포 금요일 오후 4시. 배포 준비한다. 체크리스트 확인.DB 마이그레이션: 완료 API 테스트: 통과 프론트 연동: 확인5시에 배포 시작. Jenkins 빌드 돌린다. 초록불. 성공. 서버 재시작. 헬스체크 확인. 200 OK. 모니터링 본다. 에러율 0%. 응답속도 정상. 6시. 끝났다. "수고하셨습니다" 슬랙 메시지 보낸다. 노트북 덮는다. 이 순간이 좋다. 내가 짠 코드가 돌아간다. 사용자 천 명이 쓴다. 버그 없이 잘 돌아가면 뿌듯하다. 이게 내가 개발자 한 이유다. 근데 34세에도 이러고 있어야 하나. 이력서에 쓸 게 없다 가끔 링크드인 본다. 업데이트는 안 한다. 그냥 본다. 다른 사람들 프로필 구경한다. 똑같은 7년차인데 다르다. "DevOps 파이프라인 구축 리드" "마이크로서비스 아키텍처 전환 주도" "주니어 개발자 3명 멘토링" 나는 뭐라고 쓸까. "레거시 코드 유지보수" "후배 PR 리뷰" "버그 수정" 이게 나쁜 건 아니다. 누군가는 해야 하는 일이다. 회사는 잘 돌아간다. 근데 이력서에 쓰기엔 초라하다. 다음 이직 때 면접관이 물어본다. "7년간 뭐 하셨어요?" "음... 코드 짰습니다" "구체적으로는요?" "여러 가지요..." 대답이 안 나올 것 같다. 금요일 점심의 대화 점심 먹으러 갔다. 김치찌개집. 단골이다. 후배 둘이랑 같이 갔다. 한 명이 물었다. "형은 앞으로 뭐 하실 거예요?" "응? 뭘?" "커리어요. 아키텍트? 관리자?" 대답 못 했다. "아직 모르겠어" "이제 7년차시잖아요" 맞다. 7년차다. 시니어라고 불린다. 근데 아직도 모르겠다. 다른 후배가 말했다. "저는 형처럼 되고 싶어요" "왜?" "코드 잘 짜시잖아요. 부럽습니다" 그 말이 기분 좋으면서도 찝찝했다. 후배는 3년차다. 나도 3년차 때 그렇게 말했다. "저는 시니어처럼 코드 잘 치고 싶어요" 그런데 나는 7년차에도 여전히 코딩이 주 업무다. 집에 가는 지하철 퇴근길 지하철. 폰으로 기술 블로그 본다. 제목들이 비슷하다. "30대 개발자의 커리어 고민" "테크 리드가 되기까지" "관리자 vs 개발자, 나는 어느 쪽?" 다들 고민이 같다. 댓글도 비슷하다. "저도 7년차인데 고민입니다" "결국 관리자 됐는데 코딩이 그립네요" "아키텍트 됐지만 답은 없더라구요" 답이 없다는 말이 많다. 그러면서도 다들 뭔가 선택한다. 나는 아직 선택을 안 했다. 아니, 선택을 미루고 있다. 일단 오늘은 집에 가서 쉰다. 이번 주도 끝났다. 주말의 사이드 프로젝트 토요일 오후. 노트북을 켰다. 3개월 전에 시작한 프로젝트가 있다. 개인 일정 관리 앱. 간단한 거다. React + Spring Boot. README 파일만 있다. 코드는 한 줄도 없다. "일단 DB 스키마부터..." 생각만 한다. 손이 안 간다. 커피 마신다. 유튜브 켠다. "개발자 브이로그" 영상 본다. 30분 지났다. 노트북 덮는다. "다음 주말에 해야지" 벌써 세 번째다. 다음 주말에도 안 할 것 같다. 예전엔 이런 거 재밌었는데. 새 기술 배우고, 뭐라도 만들고. 지금은 그냥 피곤하다. 열정이 식은 건가. 아니면 나이가 든 건가. 아내의 질문 저녁 먹으면서 아내가 물었다. "요즘 고민 있어?" "응?" "요즘 좀 우울해 보여" 대답 안 했다. 그냥 밥 먹었다. "회사 일 힘들어?" "아니, 괜찮아" "그럼 뭔데" 말했다. "나 이대로 괜찮은 것 같아?" "무슨 소리야" 설명했다. 7년차인데 코딩만 한다. 동기들은 팀장 되고 아키텍트 된다. 나는 뭐 하는 건지 모르겠다. 아내가 말했다. "너 코딩 좋아하잖아" "응..." "그럼 계속 하면 되지" 간단한 말이었다. 근데 뭔가 찝찝했다. "그래도 발전이 없잖아" "발전은 무슨. 7년 전보다 훨씬 잘하잖아" "근데 이력서엔..." 말을 멈췄다. 이력서가 뭐가 중요한가. 나는 왜 이력서 걱정을 하는가. 이직할 것도 아닌데. 월요일 아침 회의 월요일 오전 10시. 팀 회의다. 팀장이 말한다. "이번 분기 목표입니다" 슬라이드를 넘긴다. "신규 기능 3개 런칭" "레거시 마이그레이션 완료" "성능 20% 개선" 다들 고개 끄덕인다. 나도 끄덕인다. "개발님이 마이그레이션 리드 맡아주세요" 팀장이 나를 본다. "네" 회의 끝났다. 내 책상으로 돌아왔다. Jira 티켓 30개가 보인다. 다 나한테 할당된 거다. 레거시 마이그레이션. 버그 수정. 신규 API. 한숨 나왔다. 커피 마셨다. 그리고 IDE를 켰다. 코드를 봤다. public class UserService { // 이 코드는 5년 됐다 // 내가 짠 건 아니다 // 근데 내가 고친다 }마우스를 움직였다. 리팩토링 시작했다. 이게 내 일이다. 아키텍트도 아니고. 관리자도 아니고. 그냥 코드 짜는 사람. 점심시간의 깨달음 김치찌개집에서 혼자 밥 먹었다. 후배들은 회의 중이다. 사장님이 물었다. "오늘 혼자?" "네" "김치찌개 드시죠?" "네" 7년 왔다. 메뉴는 항상 김치찌개다. 사장님은 내 이름 안다. 밥 먹으면서 생각했다. 나는 왜 이렇게 고민하는가. 7년차면 시니어다. 시니어는 뭘 해야 하는가. 아키텍트? 관리자? 그게 정답인가. 옆 테이블 사람들 대화가 들렸다. "우리 팀 시니어는 진짜..." "응?" "코드 하나하나 다 봐줘. 꼼꼼해" 부러웠다. 그 팀 시니어. 코드 하나하나 봐주는 사람. 나도 그런 사람이고 싶다. 아키텍트 아니어도. 관리자 아니어도. 그냥 코드 잘 짜는 시니어. 후배들한테 도움 되는 사람. 그게 나쁜 건 아니잖아. 오후 3시의 PR 리뷰 슬랙 알림이 떴다. "PR 올렸습니다. 리뷰 부탁드려요" 후배가 올린 코드다. API 하나 추가했다. 코드 봤다. 200줄 정도. 로직은 괜찮다. 근데 몇 개 보였다. 변수명이 애매하다. 예외 처리가 없다. 테스트 케이스가 부족하다. 댓글 달았다. "userId 대신 id는 어떨까요?" "NullPointerException 처리 필요할 것 같아요" "edge case 테스트 추가 부탁드립니다" 10분 뒤 답장 왔다. "오 감사합니다!" "수정했습니다" "다시 봐주세요" 다시 봤다. 깔끔해졌다. approve 눌렀다. "고생하셨습니다" "형 덕분에 배웠습니다" 기분이 좋았다. 이게 내가 할 수 있는 거다. 아키텍트는 큰 그림 그린다. 관리자는 일정 관리한다. 나는 코드 리뷰 잘한다. 이것도 가치 있는 일이다. 퇴근길의 결론 6시 퇴근. 지하철 탔다. 오늘 하루 생각해봤다. 아침엔 고민했다. 점심엔 생각했다. 오후엔 일했다. 그리고 알았다. 답은 하나가 아니다. 아키텍트가 되는 게 정답인 사람도 있다. 관리자가 되는 게 맞는 사람도 있다. 계속 코딩하는 게 좋은 사람도 있다. 나는 아직 모른다. 34세에도 모른다. 7년차에도 모른다. 근데 괜찮다. 지금 당장 정할 필요 없다. 내년에 생각이 바뀔 수도 있다. 관리자 해보고 싶어질 수도. 아키텍트 공부하고 싶어질 수도. 아니면 10년차까지 코딩할 수도. 중요한 건 지금이다. 지금 내가 잘하는 거. 지금 내가 해야 하는 거. 코드 잘 짜기. 후배 잘 가르치기. 레거시 잘 고치기. 이게 나다. 34세 7년차 개발자. 집에 와서 집 도착했다. 현관문 열었다. 아내가 물었다. "오늘은 어때?" "괜찮았어" "고민 좀 풀렸어?" 고개 끄덕였다. "응. 좀" 노트북 꺼냈다. 주말의 사이드 프로젝트. README만 있는 그 프로젝트. 열었다. DB 스키마 작성했다. 간단한 거다. 테이블 세 개. 한 시간 작업했다. 첫 커밋 했다. "Initial database schema" 많이 한 건 아니다. 근데 시작했다. 커피 마셨다. 오늘 다섯 번째다. 아내가 말했다. "뭐해?" "코딩" "또?" 웃었다. "응. 좋아서" 그게 답인 것 같다. 아직도 좋아서 한다. 7년 했는데도. 34세인데도.34세. 7년차. 아직도 코딩한다. 그리고 그게 괜찮다.

버전 관리 충돌: Git merge의 악몽

버전 관리 충돌: Git merge의 악몽

버전 관리 충돌: Git merge의 악몽 월요일 오전 10시 출근했다. 슬랙을 켰다. 빨간 알림 37개. "김개발님, UserService.java 머지 부탁드립니다 ㅎㅎ" 후배 박주니어가 올린 PR이다. 코드 확인했다. 내가 금요일에 수정한 파일이랑 겹친다. 아뿔싸. 금요일 저녁 7시. 급하게 hotfix 커밋하고 튀었다. push는 했는데 PR은 안 올렸다. 주말 내내 까먹었다. 박주니어는 금요일 오후에 브랜치 땄다. 내 hotfix 이전 버전에서. "충돌 날 거 같은데요." 답장을 보냈다. 3분 후. "어? 진짜네요. 어떻게 하죠?"충돌 파일 열어보기 <<<<<<< HEAD public void updateUser(Long userId, UserDto dto) { User user = userRepository.findById(userId) .orElseThrow(() -> new UserNotFoundException()); user.update(dto); cacheManager.evict("users", userId); // 내가 추가한 캐시 처리 ======= public void updateUser(Long userId, UserDto dto) { User user = userRepository.findById(userId) .orElseThrow(() -> new UserNotFoundException()); validateUserStatus(user); // 박주니어가 추가한 검증 로직 user.update(dto); >>>>>>> feature/user-validation둘 다 필요하다. 내 코드는 캐시 버그 수정이다. 프로덕션에서 유저 정보가 안 갱신되던 문제. 급해서 금요일에 핫픽스했다. 박주니어 코드는 기획에서 요청한 기능이다. 탈퇴 유저 업데이트 방지. 월요일 배포 예정이었다. 둘 다 놓치면 안 된다. 전화했다. "주니어님, 잠깐 통화 가능하세요?" "네 형님!" 형님 소리는 별로다. 나이 차이 4살인데. 협상 시작 "제 코드랑 주니어님 코드 둘 다 살려야 할 것 같은데요." "아 네! 그럼 제가 다시 짤까요?" 착한 후배다. 근데 시간이 아깝다. "아니요. 제가 해볼게요. 근데 validateUserStatus 메서드 어디 있어요?" "아 그거요. UserValidator 클래스 새로 만들었어요. src/main/java/validators 폴더에요." validators 폴더? 처음 듣는다. "그 폴더 언제 만드셨어요?" "이번 주에요! 검증 로직 분리하려고요. 클린 코드 책에서 봤는데..." 좋은 의도다. 근데 팀원들한테 얘기했어야지. 폴더 구조 바꾸는 건 함께 논의한다. 우리 팀 룰이다. 주니어는 아직 모른다. "아 그거 좋은데요. 근데 다음엔 먼저 얘기해주세요. 폴더 구조 바뀌면 다른 분들도 헷갈려하거든요." "아... 죄송해요." 목소리가 풀 죽었다. 기분 상한 것 같다. "아니 괜찮아요. 좋은 시도예요. 나중에 팀 회의 때 같이 정리해봅시다." "네!" 목소리가 다시 밝아졌다. 다행이다.코드 합치기 시작 일단 pull 받는다. git pull origin develop예상대로 conflict 발생. CONFLICT (content): Merge conflict in src/main/java/service/UserService.java CONFLICT (content): Merge conflict in src/test/java/service/UserServiceTest.java테스트 코드도 충돌이다. 예상 못 했다. 테스트 파일 열었다. <<<<<<< HEAD @Test void updateUser_캐시_삭제_확인() { // given Long userId = 1L; UserDto dto = createUserDto(); // when userService.updateUser(userId, dto); // then verify(cacheManager).evict("users", userId); ======= @Test void updateUser_탈퇴유저_검증() { // given Long userId = 1L; User withdrawnUser = createWithdrawnUser(); when(userRepository.findById(userId)).thenReturn(Optional.of(withdrawnUser)); // then assertThrows(UserStatusException.class, () -> userService.updateUser(userId, createUserDto())); >>>>>>> feature/user-validation둘 다 다른 테스트다. 근데 같은 위치에 넣었다. 이건 둘 다 남겨야 한다. 순서만 정리하면 된다. 합치는 중 UserService.java부터 정리했다. public void updateUser(Long userId, UserDto dto) { User user = userRepository.findById(userId) .orElseThrow(() -> new UserNotFoundException()); // 박주니어 코드 validateUserStatus(user); // 내 코드 user.update(dto); cacheManager.evict("users", userId); }깔끔하다. 검증 먼저, 업데이트 다음, 캐시 삭제 마지막. 근데 생각해보니 validateUserStatus는 private 메서드로 만들어야 한다. 외부에서 부를 필요 없다. 박주니어 코드 확인했다. public으로 되어 있다. 고쳤다. private void validateUserStatus(User user) { if (user.isWithdrawn()) { throw new UserStatusException("탈퇴한 회원입니다."); } }테스트는 더 간단했다. 두 테스트 메서드 순서만 정리. @Test void updateUser_정상동작() { // 기존 테스트 }@Test void updateUser_탈퇴유저_검증() { // 박주니어 테스트 }@Test void updateUser_캐시_삭제_확인() { // 내 테스트 }저장했다. 빌드 돌려보기 ./gradlew clean build기도했다. 제발 한 번에 성공해라. 30초 후. BUILD SUCCESSFUL in 28s됐다! 근데 테스트 결과 확인해야 한다. ./gradlew test --tests UserServiceTest전부 통과했다. 124개 테스트 모두 초록불. 안심이다.푸시하기 전 확인 박주니어한테 메시지 보냈다. "주니어님, 코드 합쳤어요. 제가 좀 수정한 게 있는데 괜찮을까요?" "뭐 수정하셨어요?" "validateUserStatus를 private으로 바꿨어요. 이 메서드는 UserService 내부에서만 쓰니까요." "아 맞네요! 그게 맞는 것 같아요." "그리고 validators 패키지는 일단 안 만들었어요. 나중에 검증 로직이 더 많아지면 그때 분리하는 게 좋을 것 같아서요." 잠시 답이 없었다. 3분쯤 지났다. "네 알겠습니다. 그게 나을 것 같네요." 목소리가 조금 아쉬운 것 같다. 그래도 이해는 하는 것 같다. "주니어님 코드 아이디어는 좋았어요. 검증 로직 분리하는 거. 나중에 꼭 해봅시다. 지금은 검증이 하나뿐이라 오버 엔지니어링일 수 있어서요." "아 네! 감사합니다 형님!" 다시 밝아졌다. 푸시와 PR git add . git commit -m "Merge: user validation + cache eviction" git push origin develop푸시했다. 슬랙에 알림이 떴다. GitHub Actions 돌아간다. CI 파이프라인이 돌아간다. 빌드, 테스트, 린트 체크. 2분 후. 초록불. 박주니어 PR에 코멘트 남겼다. "LGTM. 제 hotfix랑 합쳤습니다. 확인 부탁드려요." 1분 후. 박주니어가 approve 했다. "확인했습니다! 감사합니다 형님!" 머지 버튼 눌렀다. develop 브랜치에 합쳐졌다. 끝났다. 오후 3시, 후속 작업 근데 문제가 또 있다. 이찬민 팀장이 슬랙 메시지 보냈다. "김개발님, user 관련 코드 왜 두 번 커밋됐어요? 금요일이랑 오늘이랑." 아차. PR 안 올리고 바로 푸시한 거 들켰다. "금요일에 긴급 버그 수정이었습니다. PR 올릴 시간이 없어서..." "그래도 PR은 올려야죠. 팀 룰이잖아요." 맞는 말이다. "죄송합니다. 다음부터 조심하겠습니다." "알겠습니다. 근데 주니어님이랑 충돌 안 났어요?" "났습니다. 제가 합쳤어요." "수고하셨어요." 휴. 팀장은 착하다. 다른 회사 동기들 얘기 들으면 우리 팀장은 천사다. 회고 merge conflict는 피할 수 없다. 팀 프로젝트니까. 중요한 건 충돌을 어떻게 해결하느냐다. 오늘 배운 것들:hotfix도 PR 올리기: 급해도 기록은 남겨야 한다. 나중에 누가 왜 고쳤는지 알아야 한다.폴더 구조 변경은 함께: 좋은 의도라도 혼자 결정하면 안 된다. 팀원들이 헷갈린다.conflict 해결은 소통으로: 내 코드가 맞다고 우기지 말기. 상대방 코드 의도 먼저 이해하기.테스트는 꼭 돌리기: 합쳤다고 끝이 아니다. 빌드 성공해도 테스트 실패할 수 있다.후배 기분 챙기기: 코드 리뷰는 코드만 보는 게 아니다. 사람도 봐야 한다.박주니어는 좋은 개발자가 될 것 같다. 의욕도 있고 배우려고 한다. 나도 저랬다. 7년 전에. 그때 선배들이 잘 가르쳐줬다. 지금 내가 그 역할이다. 책임감이 든다. 무겁다. 퇴근길 6시 15분에 나왔다. 평소보다 늦었다. conflict 해결하느라. 지하철에서 폰 봤다. 슬랙 알림 3개. "김개발님 내일 회의 때 validators 패키지 건 같이 얘기해봐요!" 박주니어다. "네 좋습니다." 답장 보냈다. 집에 도착했다. 7시 10분. 아내가 저녁 만들고 있다. 김치찌개 냄새가 난다. "오빠 늦었네?" "응. merge conflict." "뭐 그게 뭐야?" 설명 안 했다. 길다. "그냥 코드 충돌." "힘들었겠다." "응." 밥 먹었다. 맛있다. 넷플릭스 틀었다. 아무 생각 없이 봤다. 10시에 잤다. 내일 또 회의다.충돌은 일상이다. 해결하면 된다.

새 팀원이 실수할 때마다 드는 생각

새 팀원이 실수할 때마다 드는 생각

새 팀원이 실수할 때마다 드는 생각 오늘도 PR이 날아왔다 알림이 울렸다. 신입 민수의 PR이다. 제목부터 불안하다. "로그인 기능 수정". 뭘 수정했길래. 코드를 열었다. 첫 줄부터 눈에 띈다. if (password == user.getPassword())문자열 비교를 ==로 했다. 자바 기본 중의 기본이다. 한숨이 나온다. 근데 참는다. 스크롤을 내린다. 더 있다. try { // 200줄의 로직 } catch (Exception e) { System.out.println("에러남"); }Exception을 그냥 잡아서 출력만 한다. 로그도 없다. 키보드에 손을 올렸다가 뗀다. 뭐라고 써야 하나. "이건 왜 이렇게 하셨나요?"는 너무 공격적이다. "equals() 써야 합니다"는 너무 교과서적이다. 결국 이렇게 쓴다. "문자열 비교는 equals() 메서드를 사용해주세요. == 연산자는 객체 참조를 비교해서 예상과 다르게 동작할 수 있습니다." 친절하게 썼다고 생각한다. 근데 속으로는 욕이 나온다. 이건 3년 차면 당연히 알아야 하는 거다. 아니, 신입도 알아야 한다.3년 전 내 코드가 떠오른다 근데 코멘트를 달다가 멈췄다. 문득 3년 전 내가 쓴 코드가 생각났다. 당시 팀장님이 내 PR에 코멘트를 달았었다. "N+1 쿼리 문제가 있을 것 같은데요. fetch join 고려해보시겠어요?" 그때 난 몰랐다. N+1이 뭔지도. 검색해서 알았다. 창피했다. 이런 기초도 모르고 있었다니. 근데 팀장님은 그냥 "고려해보시겠어요?"라고 물었다. 명령이 아니었다. 그래서 나도 찾아봤다. 공부했다. 고쳤다. 만약 팀장님이 "이것도 모르세요?"라고 했으면 어땠을까. 아마 위축됐을 거다. 질문도 못 했을 거다. 민수의 코드를 다시 본다. 완벽하진 않다. 근데 노력은 보인다. 변수명도 신경 썼고, 주석도 달았다. 틀렸지만. 코멘트를 수정한다. "equals()를 쓰면 더 안전합니다. 참고: [자바 문자열 비교 docs 링크]" 이 정도면 될 거다.당연한 게 어디 있나 점심시간이다. 민수가 옆자리에 온다. "형, 코멘트 확인했어요. 제가 equals()를 써야 하는 이유를 몰랐네요." 솔직하다. 좋다. "응, == 연산자는 객체 주소를 비교하거든. 그래서 내용이 같아도 false가 나올 수 있어." "아... 그럼 항상 equals()를 써야 하나요?" 질문이 나왔다. 좋은 신호다. "문자열은 그래. 근데 equals()도 null 체크를 해야 해. 아니면 Objects.equals()를 쓰거나." 민수가 고개를 끄덕인다. 노트에 적는다. 예전엔 이런 게 답답했다. '이 정도는 당연한 거 아닌가?' 근데 지금은 안다. 당연한 게 없다는 걸. 나도 7년 차지만 모르는 게 수두룩하다. 어제도 코틀린 코루틴 관련해서 검색했다. 3시간 걸렸다. 리액트 개발자한테 물어봤다. "이거 당연한 건가요?" 했더니 웃었다. "저도 처음엔 헷갈렸어요. 당연한 거 없어요." 그 말이 위로가 됐다. 민수한테도 그래야겠다고 생각한다. "당연한 거 없어. 다 배우는 거야."실수를 바라보는 법 민수의 두 번째 PR이 왔다. 이번엔 equals()를 썼다. 그런데. if (user.getName().equals(null))null을 뒤에 뒀어야 했는데 앞에 뒀다. NPE 터진다. 또 한숨이 나온다. 근데 참는다. 코멘트를 단다. "null 체크는 null을 뒤에 두면 안전합니다. 혹은 Objects.equals() 추천드려요." 이번엔 왜냐고 안 물었다. 예시 코드를 같이 올렸다. // NPE 위험 if (user.getName().equals(null))// 안전 if (null == user.getName()) if (Objects.equals(user.getName(), null))30분 뒤에 답이 왔다. "아 이런 방법이! 감사합니다!" 수정 커밋이 올라왔다. Objects.equals()를 썼다. approve를 눌렀다. 실수는 반복된다. 어쩔 수 없다. 나도 지금 실수한다. 어제 배포에서 env 파일 빠뜨렸다. 30분 롤백했다. 팀장님이 뭐라고 했나. "괜찮아요. 다음엔 체크리스트 만들어봐요." 혼내지 않았다. 해결 방법을 알려줬다. 그래서 나도 민수한테 그렇게 한다. "틀렸네요"가 아니라 "이렇게 하면 더 좋아요"로. "이것도 몰라요?"가 아니라 "저도 헷갈렸어요"로. 시간이 오래 걸린다. 설명하는 게 직접 고치는 것보다 3배는 느리다. 근데 이게 맞는 거 같다. 민수가 스스로 고치고, 이해하고, 다음엔 안 틀리는 게 낫다. 내가 고쳐주면 당장은 빠르다. 근데 민수는 배우지 못한다. 그럼 똑같은 실수를 반복한다. 결국 더 느리다. 가르치는 게 배우는 거다 리뷰를 하다 보니 내가 더 배운다. 왜 equals()를 써야 하는지 설명하려면 내부 동작을 알아야 한다. 그래서 다시 찾아봤다. String pool이랑 intern() 메서드까지. 7년 차인데 제대로 몰랐다. 그냥 쓰기만 했다. 민수한테 설명하려고 정리했다. 내가 더 명확해졌다. null 체크도 그렇다. "왜 null을 뒤에 둬요?" 물어봤을 때 대답을 못 했다. 그냥 그렇게 하라고 배웠으니까. 이유는 몰랐다. 찾아봤다. Yoda notation이라는 게 있었다. 스타워즈 요다에서 따온 이름이다. "null is name" 이런 식으로 읽힌다고. 재밌다. 근데 요즘엔 Objects.equals()를 더 권장한다는 것도 알았다. 민수 덕분에 배웠다. 예전 팀장님 말이 생각난다. "가르치는 게 제일 공부 많이 돼요." 맞는 말이다. 혼자 코드 짤 땐 대충 넘어간다. '일단 되네, 됐어.' 근데 누군가한테 설명하려면 제대로 알아야 한다. 그래서 찾아본다. 정리한다. 내 것이 된다. 민수가 물어볼 때마다 귀찮다. 솔직히 그렇다. 근데 동시에 고맙다. 내가 더 성장한다. 인내심이 필요하다 오늘 민수가 세 번째 실수를 했다. git commit에 node_modules를 올렸다. 200MB다. 한숨이 나온다. 또. ".gitignore에 추가해주세요"라고 썼다. 근데 민수가 ".gitignore가 뭐예요?"라고 물었다. 순간 멈췄다. 이것까지 모르나. 화가 났다. 솔직히 말하면. '깃도 제대로 모르고 어떻게 입사했지?' 근데 참았다. 심호흡했다. 예전 내가 생각났다. 첫 회사 들어가서 깃 쓸 줄 몰랐다. SVN만 써봤다. merge conflict 나면 패닉했다. 선배가 옆에 앉아서 30분 동안 알려줬다. 짜증 한 번 안 냈다. 그 선배 덕분에 깃을 배웠다. 지금도 감사하다. 그래서 민수한테 답했다. ".gitignore는 git에 올리지 않을 파일을 정의하는 거예요. 같이 볼까요?" 화면 공유했다. 10분 설명했다. "아~ 이래서 템플릿이 있었구나. 감사합니다!" 민수가 이해했다. 다음 커밋엔 제대로 했다. 인내심이 필요하다. 매일. 실수는 반복된다. 다른 실수지만. 그때마다 설명한다. 참는다. 기다린다. 3개월 뒤면 민수도 달라질 거다. 6개월 뒤면 더. 1년 뒤엔 혼자 할 수 있을 거다. 그럼 나도 편해진다. 지금 투자하는 시간이 나중을 위한 거다. 그렇게 생각하면 견딜 만하다. 완벽한 사람은 없다 퇴근 전에 슬랙 메시지가 왔다. 팀장님이다. "개발님, 오늘 배포 건 확인 부탁드려요." 내가 짠 코드다. 테스트 다 통과했다. 배포했다. 10분 뒤에 알림이 울렸다. 에러다. 로그를 봤다. NullPointerException. 내 코드에서 났다. null 체크를 안 했다. 아까 민수한테 null 체크하라고 했는데. 나도 안 했다. 창피했다. 얼굴이 뜨겁다. 급하게 고쳤다. 롤백하고 재배포했다. 팀장님한테 보고했다. "제가 null 체크를 빠뜨렸습니다. 죄송합니다." "괜찮아요. 급한 건 아니었으니까. 다음부턴 조심하시면 돼요." 혼나지 않았다. 오히려 위로받았다. 그제야 깨달았다. 나도 실수한다. 매일. 7년 차도 이런데 3개월 차는 오죽할까. 민수의 실수가 이해됐다. 완전히. 당연한 게 없다. 누구한테도. 시니어도 틀린다. 주니어는 더 틀린다. 당연하다. 그래서 서로 봐줘야 한다. 코드 리뷰로. 페어 프로그래밍으로. 혼자선 못 본다. 같이 봐야 한다. 결국 팀이다 민수가 한 달 지났다. 실수는 여전히 한다. 근데 줄었다. 같은 실수는 안 한다. 새로운 실수를 한다. 그게 성장이다. 어제 민수가 내 코드에 코멘트를 달았다. "형, 이 부분 Optional 쓰면 더 안전할 것 같아요." 맞는 말이다. 내가 놓쳤다. approve 눌렀다. "좋은 지적이에요. 고맙습니다." 민수가 웃는 이모지를 보냈다. 이게 팀이다. 서로 실수하고, 서로 고쳐주고, 서로 배운다. 완벽한 사람은 없다. 완벽한 코드도 없다. 그래서 같이 한다. 리뷰하고, 논의하고, 개선한다. 민수의 실수를 볼 때마다 짜증났다. 솔직히. 근데 지금은 안다. 그게 과정이라는 걸. 나도 그 과정을 거쳤다. 지금도 거치고 있다. 앞으로도 실수할 거다. 민수도, 나도. 그때마다 서로 알려주면 된다. "이렇게 하면 더 좋아요." "저도 헷갈렸어요." "같이 볼까요?" 그게 시니어가 하는 일이다. 코드를 잘 짜는 것만이 아니다. 팀을 키우는 것도. 민수가 1년 뒤엔 또 달라질 거다. 2년 뒤엔 더. 그럼 나도 편해진다. 민수한테 맡길 수 있다. 그리고 민수도 후배를 가르칠 거다. "당연한 거 없어. 다 배우는 거야." 내가 했던 말을.내일도 민수의 PR이 올 거다. 또 실수가 있을 거다. 그래도 괜찮다. 인내심 가지고 본다.

대학 동기들 단톡방: 1년에 한 번 보는 우리의 현재

대학 동기들 단톡방: 1년에 한 번 보는 우리의 현재

대학 동기들 단톡방: 1년에 한 번 보는 우리의 현재 스탠프만 남기는 채팅창 단톡방 알림. 어제 온 거 같은데 이제 봤다. '안녕하세요 ^^' 누구지? 이름이 안 띄어 있다. 멤버 목록을 본다. 13명. 왜 13명이지? 졸업 당시엔 11명이었는데. 아, 누군가의 남편. 아니면 여자친구. 이제 그 정도 사이가 됐구나. 'ㅇㅈㅇㅇ님이 입장했습니다.' '어어어 환영한다 형!!' 이 문장 뒤에 슬랙 이모지가 3개 따라붙는다. 너희도 개발자네. 그 느낌 안다. 회사에서 슬랙에 이모지 스팸하는 그 문화. 여기까진 따라온 거다. 대학 때는 달랐다. 2020년. 코로나 이전. 우리는 학년 올라가면서 자연스럽게 모였다. 학식, 도서관 앞 벤치, 밤새 과제 하는 호실. 2시간마다 카톡으로 '뭐해?' 쓰고, 1분 안에 답장 왔다. 지금은 이거다. 스탠프.'언제 봐?'만 오고 가다 단톡방 검색. 지난 6개월. '언제 봐?' '진짜 봐야겠다' '시간 되면 봐요!' '언제 모여?' '다음 달?' '그 다음 달?' 이 대사들만 15개. 실제로 만난 적? 없다. 작년 명절. 누군가가 '내려간다' 했다. 아, 그때 한 명 봤나? 아니. 그건 전전년도다. 우리는 시간이 없다. 모두가. 금요일 밤. 그게 유일한 기회다. 근데 누구는 배포를 해야 한다고 했다. 누구는 주말에 고쳐야 할 버그가 있다고. 누구는 신입이라 휴가를 못 낸다고. '다음에 진짜 봐' 다음은 언제지? 리더보드를 본다. 채팅 횟수로 순위를 매기는 개발자들만의 오만한 작은 게임이 우리에게도 있었나? 없다. 근데 누가 말을 많이 하는지 본다. 'ㅇㅇ' - 어제 온 스탠프 3개 'ㅈㅇ' - 한 달 전 '안녕' 'ㅎㅅ' - 3개월 전 '요즘 뭐해' 스탠프만 남기는 애들도 있다. 이제 감정 표현도 패킹하는 거네. 최적화. 우리가 배운 게 단톡방까지 왔다. 회사에서 9시부터 6시까지 벨이 9시에 울린다. 9시가 아니라 8시 50분에 나가기 시작한다. '출근한다' 이 한 단어를 누구에게 건넬까? 아내? 아내도 같은 시간에 나간다. 엄마? 엄마는 딸은 신경 쓰고 아들은 알아서 한다고 생각한다. 대학 동기? 아, 그들도 지금 자신의 회사에서 로그인하고 있을 거다. 2023년. 우리는 학교를 나왔다. 그 다음부터가 다항식이었다. 누군가는 대기업 들어갔다. 근데 스트레스 받다가 작년에 스타트업 갔다. 단톡방에 '이직했어요'라고만 적었다. 누군가는 프리랜서가 됐다. '자유롭다'고 했는데, 3개월 뒤에는 '부스러기처럼 산다'고 했다. 누군가는 공무원 된다고 했는데 지금도 시험 치고 있다. 나? 난 동기들보다 좀 더 일찍 들어갔다. 지금 테크 리드다. 직책은 아니지만.공통분모는 한 가지 더 이상 공통분모가 없다. 학교 있을 때 공통분모는 뭐였나. 과제. 시험. 축제. 밥 먹을 때 갈 식당. 서로의 로맨틱한 관심사. 프로젝트 팀. 동아리. 다 외부 강제였다. 제도가 우릴 한곳에 모았다. 지금 공통분모는? "우린 다 개발자야." 그게 다다. 근데 그 안에서도 나뉜다. 프론트엔드 vs 백엔드. Java vs JavaScript. 대기업 vs 스타트업. 계약직 vs 정규직. 우리가 대학에 갔을 때 배운 게 뭔지 생각해본다. 자료구조? 알고리즘? 네트워크? 잘못 배웠다. 우리가 배워야 했던 건 이거다. '떨어져 나가는 방법'. 그래도 가끔 미안한 마음 '형 생일 축하해!' 단톡방에 올라온다. 누가 사실 봤을까? 한 3명. 알람 설정 안 했으니까. 'ㅇㅇ님이 이모지를 보냈습니다' 이모지면 충분하다. 충분해야 한다. 근데 왜 미안한 마음이 생길까. 마치 우리가 함께 늙어가는 게 아니라 각자 다른 타임라인으로 살아가고 있다는 생각이 들 때. 한 명은 서울에서 일하고, 한 명은 경주로 내려가고, 한 명은 리모트다. 한 명은 결혼했다. 한 명은 결혼할 생각이 없다. 한 명은 고민 중이다. 한 명은 승진했다. 한 명은 계약 끝났다. 한 명은 유학 간다고 했는데 아직 가지 않았다. 우린 같은 시간에 태어났다. 같은 학교에 갔다. 근데 시간이 더 이상 같지 않다. 네트워크 에러다. 패킷이 너무 멀리 떨어져 있다. '언제 봐?' 그 이후 어제 카톡이 울렸다. '모임 가능한 사람?' 이 문장이 올 때마다 우리의 심장이 철렁 내려간다. '언제?' '이번 달 25일?' 계산한다. 이번 달. 지금 8월이니까. 8월 25일은? 금요일이다. 그 금요일에 배포가 있나? 없나? 구글 캘린더를 본다. 팀 회의. 스프린트 플래닝. 1:1 미팅. 백로그 정제. '그 날 좀 바쁠 거 같은데...' 누군가는 이미 같은 답을 보냈다. '다음 달?' 대화는 여기서 끝난다. 다음 달은 다음 달이니까. 지금은 생각하지 않는다.그런데도 누구는 왔다 작년 가을. 누군가는 정말 왔다. 단톡방에 사진 올렸다. 우리가 다니던 학교. 정문 앞. '돌아왔다' 그 사진 밑에 반응이 확 달라붙었다. '오오오!!' '어디?? 갈께!!' '너 미쳤나? 왜 와??' 반가운 거였다. 정말로. 그 사람은 미국 출장 갔다가 서울 들었다고 했다. 이틀밖에 없다고 했다. 우리는 만났다. 진짜로. 밥 먹으면서 5년을 말했다. 5시간에 5년을 압축했다. 누가 떠나갔고, 누가 들어갔고, 누가 계속 같은 자리 있고, 누가 변했고, 누가 안 변했고. 그리고 그 사람이 떠날 때 우리는 일렬로 버스 정거장까지 따라갔다. 아무말도 하지 않고. 버스가 떠났다. 그 다음 날 단톡방에 사진이 올라왔다. 비행기 창밖이었다. '또 언제 봐?' 아, 그거요 아, 그거요. 시간이 없어서가 아니다. 시간은 있다. 부족하지 않다. 우리가 두려워하는 건 다른 거다. 만나면 뭘 말해야 하지? 하는 두려움. 회사 얘기만 할 수도 없고. 그 얘기 하면 한 명은 스트레스 받고, 한 명은 자존심 상하고. 연봉이 나올까봐. 직급이 나올까봐. 결혼 얘기가 나올까봐. 아이 얘기가 나올까봐. 전월세 얘기가 나올까봐. 부모님이 아직 돈 달라고 하냐는 얘기가 나올까봐. 우린 모두가 어쨌든 조금씩 불안하다. 그래서 스탠프만 남긴다. 스탠프는 거짓말을 하지 않는다. 미소. 엄지. 불꽃. 더 이상 말할 게 없으니까. 근데 나는 가끔 생각해 만약 우리가 아직도 같은 학교에 있었다면? 과제 같이 하고, 밥 같이 먹고, 밤 10시에 갑자기 누구 기숙사로 모였을 거다. 그런데 우린 여기 있다. 나는 서울에서, 누군가는 대구에서, 누군가는 싱가포르에서, 누군가는 여전히 "취직할 거예요"라고 말하고 있고. 단톡방은 여전히 켜져 있다. 알림은 여전히 울린다. 근데 우린 누구도 댓글을 달지 않는다. 웃음이라도 표현하고 싶을 땐 스탠프를 남긴다. 이게 우리 세대의 우정인가? 아니면 이게 수도권 백엔드 개발자들의 현실인가? 아마도 둘 다. 내일도 같은 알림 내일도 같은 시간에 알림이 울릴 거다. 혹은 주말에. 누군가가 '요즘 뭐해?'라고 쓸 거다. 난 커피를 마시면서 생각할 거다. 뭐라고 답해야 할까? '일해요' 이것만 쓸 거다. 스탠프 하나 붙이고. '다음에 봐' 이렇게 닫을 거다.언제 봐? 모르겠다. 모두가 바쁘니까.

결혼 2년차, 아내와의 개발자 부부 생활

결혼 2년차, 아내와의 개발자 부부 생활

결혼 2년차, 아내와의 개발자 부부 생활 그렇게 야근은 만난다 퇴근 시간이 따로 없다는 건 뭐 하는 말인가. 회사에 나가기 전부터 이미 결정되어 있다. 아내 이수진은 UI 디자이너고, 나 김개발은 백엔드 개발자다. 둘 다 IT 회사. 둘 다 서로 다른 회사. 그런데 오늘따라 야근 문화는 똑같다. 결혼 2년 차가 되니까 알게 된 게 있다. 지인들한테 "아, 개발자랑 디자이너 부부 축하해요"라고 들을 때 정말 감동했는데, 3개월 정도 지나니까 '아, 이게 축하할 일만은 아니구나' 싶었다.월요일 오전 10시. "어제 몇 시까지 있었어?" 하는 인사말로 날이 시작된다. 나는 배포 건으로 10시까지 있었다고 했고, 아내는 "어? 나 11시까진 있었는데?"라고 대답한다. 이게 우리의 일상 인사다. 어떻게 된 일인지 모르겠지만, 한 사람이 퇴근할 때쯤이면 다른 한 사람이 야근 전화를 받는다. 처음 이 생활이 반복되고 1년이 지났을 때, 나는 정말 미칠 뻔했다. 회사에서 스트레스를 받고 집에 와서도 쉬지 못하는 거다. 아내도 디자인 피드백으로 예민하고 있고, 나도 레거시 코드 때문에 모니터를 노려보고 있다. 저녁 8시, 집에는 침묵만 흐른다. 각자 슬랙을 본다. 각자 메일을 확인한다. "밥 먹었어?" "응, 너도?" 이런 식의 대화가 하루의 전부다. 라면 냄새가 나는 밤 아내가 야근이 예정되어 있다고 했던 어느 날. 나는 혼자 집에 남았다. 회사 근처 김치찌개집에서 퇴근한 지 1시간이 안 되는데, 벌써 배가 고팠다. 이쯤 되면 밥을 먹으러 나가는 게 아니라 시간을 보내러 나가는 건 같다. 일단 냉장고를 열었다. 계란 두 개, 파 한 단, 라면 3개. 그리고 나머지는 아내가 아직 손도 못 댄 반찬들. 아내가 주말에 만들어두는 반찬은 나를 위한 배려인데, 정작 함께 먹을 시간이 없어서 냉장고에 처박혀만 있다. 라면을 끓으면서 계란을 풀고 파를 썬다. 냄비에서 치직거리는 소리, 몬순이 올라오는 소리. 이게 내 저녁이다. 맛있는 요리도, 함께할 누군가도 없이 그냥 배를 채우기 위한 밤의 의식.그런데 신기한 거, 아내가 집에 와서 그 라면을 마주칠 때마다 웃는다. "또 라면이야?" 라고 묻지만 웃고 있다. 내가 "그래, 또 라면이야"라고 대답해도 웃는다. 이 웃음이 뭔지 알게 된 건 이제다. 고독하지만, 그 고독 속에서도 누군가를 생각하고 있다는 그 감정이다. 내가 먼저 집에 있을 때는 좀 다르다. 나는 집에 와서 TV를 켜고 누워 있다. 넷플릭스 화면이 보조 모니터처럼 변해버린 지는 언제였을까. 퇴근해서 이것도, 퇴근해서 저것도 하고 싶지 않은데 시간은 자꾸 흘러간다. 그럼 아내가 들어온다. "밥 먹었어?" "냉장고 밥 있잖아." "아, 반찬도 남아있고..." 이런 대화를 나누면서도, 아내는 나를 휙 지나간다. 자기 가방을 던지고, 신발을 벗고, 휴대폰을 본다. 업무 슬랙이 얼마나 쌓였나. 요청 건은 몇 개나 들어왔나. 내일 아침 회의 준비는 되어 있나. 그런 아내의 모습을 보면서 이상하게도 나는 덜 외로워진다. 서로 알기 때문에 나약해질 수 있다 일반인 부부들이 부러워하는 말을 들은 적이 있다. "개발자랑 디자이너라니, 쟤들은 서로의 일을 이해할 수 있겠네"라는 둥, "일이 많으면 서로 도와줄 수 있고 좋겠다"는 둥 말이다. 반은 맞고 반은 틀렸다. 아내가 야근하는 날, 나는 그 이유를 안다. 클라이언트가 갑자기 UI를 바꿔달고 했거나, 디자인 시스템 문서를 다시 정리해야 했거나, 개발팀과의 협의가 자꾸 꼬인 거거나. 나는 이런 상황들을 정확히 안다. 내 직업에서도 매일 일어나니까. "어? 나도 이런 일을 당하잖아" 이렇게 생각하면서 아내에게 공감을 건넨다. 그냥 말로만 하는 공감이 아니다. 피부로 느끼는 공감이다. 그런데 문제는, 이 공감이 때로는 둘 다를 나약하게 만든다는 것이다. "이거 봐, 기획자가 또 마지막 날에 요구사항을 바꿨어." "어? 우리 PM도 그랬거든. 완성했다고 생각했는데 '아, 그런데 이것도 해야겠는데?'라고." 이런 식으로 불만을 나누다 보면, 그게 위로가 되는 동시에 서로의 스트레스를 증폭시킨다. 공감이 공명이 되는 거다. 우리 둘 다 최악의 상황을 경험하고 있다는 확인이 오히려 답답함을 키운다. 그럼 이건 뭐할까? 쿠션처럼 작동해야 할 배우자가 같은 난로에 있는 불장난이 되어버리는 거다.그런데 웃긴 일이 생겼다. 2년 차에 접어들면서, 우리는 어떤 방식을 터득했다. "야, 오늘 하루는 그냥 아무 말도 하지 말자." 이 말이 나올 때마다 우리는 웃는다. 웃고 있지만 진지하다. 업무 얘기는 하지 말고, 서로가 일으킨 스트레스에 대해 공명하지 말고, 그냥 침묵 속에서 함께 있자는 뜻이다. 그리고 가끔, 정말 가끔 아내가 나를 본다. "개발자 공부하는 거 봤어. 좋아 보이더라." 이렇게 나의 사이드 프로젝트를 먼저 챙기거나, 나도 그렇게 한다. "그 디자인 포트폴리오 사이트, 예뻤어." 이런 식으로 서로의 작은 노력을 본다. 누군가는 이걸 당연하다고 할지도 모르지만, 둘 다 출장지에서 야근하는 생활을 하는 입장에선, 상대방의 사이드 프로젝트를 봐줄 여유가 생긴다는 것만으로도 고마운 일이다. 결국은 옆에 있다는 것 나는 솔직하게 말할 거다. 개발자 부부 생활이 로맨틱한 건 아니다. 집에 와서도 각자의 모니터를 본다. 침실에서 자기 전까지도 휴대폰 화면을 본다. 주말에는 늦잠을 자지만, 평일에는 서로 다른 시간에 출근하고 다른 시간에 퇴근한다. 만약 모두가 9시 출근 6시 퇴근이라면, 주말에 함께할 시간도 많겠지만, 우리는 그렇지 않다. 그렇지만 남은 것이 있다. 라면을 끓을 때, 아내가 온다는 걸 알고 있어서, 나는 두 그릇을 준비한다. 한 그릇은 내 것이고, 한 그릇은 그 언젠가 아내가 늦게 와서 먹을 것이다. 그러다가 아내가 집에 일찍 온 날이면, 그 라면이 두 사람이 먹는 대신 냉장고에 들어간다. 그것도 좋다. 왜냐하면 아내가 이제 있을 거니까. 기획자가 또 마지막 날에 요구사항을 바꾸면, 나는 한숨을 쉰다. 그리고 아내가 같은 한숨을 쉬고 있다는 걸 느낀다. 그럼 우리는 침묵한다. 말이 필요 없다. 그 침묵 속에서도 '난 너를 알아'라는 신호가 오간다. 주말에 치킨을 시킬 때, 나는 한 마리를 시키지 않는다. 아내가 조각을 집어갈 걸 알고 있으니까. 아내는 "야, 너 혼자 다 먹어도 돼"라고 말하지만, 우리는 모두 알고 있다. 그 말은 표면의 말일 뿐이다. 이게 개발자 부부 생활의 핵심이다. 일이 많고, 야근이 많고, 때론 침묵이 집을 채운다. 하지만 그 모든 것을 견딜 수 있는 건, 상대방이 나와 같은 고민을 하고 있다는 걸 알고, 그래도 옆에 있다는 걸 느끼기 때문이다. 나는 출장 가는 날, 아내에게 슬랙을 보낸다. "야, 밥은 먹어?" 아내도 답한다. "응, 너도 뭐 좀 먹고 자." 이 메시지는 8글자도 안 되지만, 이건 '난 네가 어디에 있든 너를 생각하고 있어'라는 뜻이다. 우리의 사랑의 언어는 업무 얘기가 아니라, 끼니를 챙기는 것이다. 개발자 부부 생활? 별로 로맨틱하지 않다. 하지만 누구보다 솔직하고, 누구보다 따뜻하다. 우리는 밤 11시에 집에 도착해서, 난로 옆에 앉은 것처럼 서로를 데운다. 전자기기의 불빛 속에서 말이다. 그리고 내일도 또 다시, 각자의 야근 문화는 만난다. 결국 가장 좋은 건, 누가 먼저 오든 라면을 함께 끓일 수 있다는 거 아닐까.

아내가 야근하는 밤, 혼자 라면을 끓이며 생각한 것

아내가 야근하는 밤, 혼자 라면을 끓이며 생각한 것

아내가 야근하는 밤, 혼자 라면을 끓이며 생각한 것 저녁 8시 47분. 슬랙 메시지가 울렸다. 아내였다. "디자인 수정 요청 또 들어왔어. 늦을 것 같아 :(" 아. 또 그 시간이구나. 휴. 나는 모니터를 꺼고 의자에서 일어났다. 회사 근처 편의점 가면서 휴대폰으로 "밥 뭐 먹을까" 검색해봤는데, 깊은 밤에 나 혼자 밥을 챙겨먹는다는 게 좀 이상했다. 미안한 마음도 들었고. 그냥 라면 사 왔다. 신라면과 진라면 중에 고민하다가 신라면으로. 아내는 매운 거 잘 못 먹으니까, 이건 순전히 내 선택이다.혼자가 된 주방의 감정 기복 집에 돌아와서 냄비에 물을 부었다. 가스불을 켰다. 이 순간이 가장 낯설다. 보통 우리는 함께 집에 들어온다. 아내가 "오늘 뭐 먹을까?" 하고, 나는 "뭐든 좋아" 하고, 그러면 아내가 "좀 구체적으로 말해" 한다. 그 루프. 근데 오늘은 그 대화가 없다. 물이 끓으면서 김이 피어오르는데, 혼자 서 있는 주방이 유독 크게 느껴진다. 냄비 옆에 아내의 멀티탭 정리기 같은 거 보이고, 냉장고 문에 붙은 우리 둘이 찍은 사진 보인다. 여행 가서 찍은 거였나. 1년 전? 2년 전? 기억이 안 난다. 라면을 끓이면서 생각한 것들: "밥을 해야 하나?" - 라면만 먹어도 괜찮지 않나? 밥까지 하면 너무 번거롭지 않나? 근데 밥 없이 라면만 먹는 게 좀 이상하지 않나? 아내 귀가했을 때 "저 혼자 라면만 먹었어" 라고 말하면 뭐라고 할까? "야근이 많은 아내가 나한테서 뭘 기대하나?" - 내가 밥을 해놓고 있었으면 좋았을 텐데. 근데 오늘 배포일이었잖아. 코드 리뷰도 많았고. 내가 야근하는 날은 아내가 라면을 끓이는데, 그럼 아내가 야근하는 날은... 나도 뭔가를 챙겨야 하는 건 아닐까? "우리가 이렇게 살기로 한 건가?" - 신혼집에 와서 가장 많이 들은 말이 "집을 좀 챙겨야 하지 않나?" 였는데, 난 여전히 회사만 챙기고 있다. 아내의 야근이 길어질수록, 내가 라면을 끓일 때마다 이 질문이 자꾸 떠오른다.슬로우 라이프는 꿈이고, 우린 패스트푸드의 주인 라면이 끓는 동안 나는 생각했다. 요즘 유튜브에 자주 떠오는 영상들 말이다. "조용하고 평화로운 일상" 이런 거. 영상 속 주인공은 보통 시골에 작은 집을 짓고, 정성스럽게 밥을 짓고, 밤에는 촛불 아래 책을 읽는다. 가끔 그런 삶에 끌려본다. 심지어 댓글도 "이런 삶을 살고 싶어요" 로 가득 찬다. 근데 현실은 어떤가. 난 7년 차 백엔드 개발자고, 아내는 UI 디자이너다. 우린 서울에 작은 전세를 얻고 살고 있다. 그 전세금도 부모님 도움으로 겨우 마련했다. 정성스러운 밥은커녕, 우리 저녁의 대부분은 "이거 간단하게 먹을까?" 로 시작된다. 화요일 점심? 회사 근처 김치찌개집. 목요일? 배달음식. 금요일? "아 오늘은 치킨 시킬까" 가 뭔가 특별한 일처럼 느껴진다. 주말 아침? 늦잠 자고 두 시간 뒤에 치킨. 이게 우리의 삶이다. 그런데 문제는, 이게 싫다고 느껴지면서도 바꿀 에너지가 없다는 거다. 후배 PR 리뷰하고, 슬랙 알림에 정신없고, 주말에도 "혹시 모르니까" 노트북을 켜둔다. 아내는? 밤 11시에 "마진 수정이 또 나왔대" 하고, 자정이 넘어서 "이제 끝났어" 한다. 우린 정성스러운 밥을 지을 여유가 없는 사람들이다. 그래서 라면이다. 라면은 8분이면 된다. 신라면이 끓는 동안 나는 다른 생각을 할 수 있다. 예를 들면, "내가 이렇게 살아도 되나?" 이런 생각들. 밥 대신 라면을 선택하는 순간, 그게 책임감인가 미안함인가 물론 나도 안다. 아내가 들어왔을 때 밥이 있으면 좋겠다는 걸. 따뜻한 국과 반찬이 있으면, 아내가 "오, 고마워" 하면서 얼굴이 부드러워질 거 같다. 근데... "근데"가 문제다. 회사에서 배포일이었다. 배포일은 언제나 예측 불가능이다. 8시에 끝날 줄 알았는데 9시까지 간다. 이틀 전부터 "내일 배포 있으니까 좀 일찍 집에 갈게" 라고 말해놓고도, 정작 배포날 오전 9시에 "어? 이게 왜 이래?" 하면서 시작된다. 그 와중에 아내는 밥 준비할 생각을 해야 하나? 아니다. 그 정도의 여유는 없다. 그래서 라면이 합리적인 선택지가 된다. 아내가 야근하는 걸 어쩔 수 없으니까, 나도 자기 밥이라도 챙기자는 마음으로. 근데 이게 정말 책임감일까? 아니면 그냥 무책임함의 다른 표현일까? 가끔 생각해본다. "밥을 해야 하나?" 라는 질문은 사실 "내가 가정에 대해 뭘 해야 하나?" 라는 더 큰 질문의 축소판인 거 같다. 밥 하나 못 하면서 무슨 남편이냐고 생각할 때도 있다. 근데 또 다시 생각해보면, 난 지금 이 순간도 피곤하다. 일도 많고, 머리도 복잡하고, 뭔가를 결정할 에너지가 남아있지 않다.결국 우린 서로에게 미안해하는 사람들이다 밤 11시 32분. 아내가 집에 들어왔다. "오..." 하면서 신발을 벗었다. 피곤한 목소리였다. "라면 먹었어?" 라고 물었다. "응. 너는?" 이라고 대답했다. 아내는 "회사에서 라면 먹었어" 라고 했다. 둘 다 라면이었다. 그 순간, 정말 이상한 감정이 들었다. 미안했다. 왜? 정확하게는 모르겠다. 아내가 회사에서 라면을 먹으면서까지 일을 했을 거고, 나도 집에서 라면을 먹으면서 자기 자신을 챙겼고 (라고 생각했고), 우리 둘 다 피곤해서 아무것도 제대로 챙길 수 없었다는 게 미안했던 것 같다. "내일 좀 일찍 들어올 수 있어?" 라고 아내가 물었다. 내일도 배포가 있나? 아. 없긴 한데, 후배 오인턴이 새로운 모듈을 올렸고, 코드 리뷰를 해야 한다. "아마도?" 라고 대답했다. 아내는 웃었다. "뭐 하나 제대로 안 되네" 라고. 그건 우리 둘 다를 비난하는 게 아니었다. 우린 이런 사람들이니까. 계획해도 안 되는 사람들. 라면 끓일 때마다 "밥도 해야 하지 않을까?" 고민하는 사람들. 내가 "밥 먹을래?" 라고 물었다. 아내는 "그냥 좀 누워있고 싶어" 라고 했다. 나도 알겠다. 그 피곤함. 밥을 해야 하는데, 밥을 하려면 장을 봐야 하고, 준비를 해야 하고, 씻어야 하고... 그 모든 과정이 산처럼 느껴지는 그 피곤함. 라면 한 그릇의 철학 결국 이거다. 우리는 라면 끓이는 수준의 인생을 사는 사람들이다. 8분이면 된다. 깊이 생각할 필요가 없다. 물 끓이고, 면 넣고, 스프 넣고, 계란 삶은 거 넣고, 파 올리고, 먹는다. 그게 끝이다. 반대로 밥은 복잡하다. 밥을 준비하려면 마음가짐부터 다르다. "오늘 뭘 할까" "반찬은 뭐로 할까" "누가 먹을까" 이런 식으로. 밥은 누군가를 생각하는 음식이다. 라면은 나를 생각하는 음식이다. 근데 결혼했으니까, 밥을 해야 하는 거 아닐까? 난 계속 이 질문의 루프에 빠진다. 매번 아내가 야근하는 밤, 라면을 끓이면서. "좀 더 성숙해져야 하나?" 라는 생각도 든다. 다른 남편들은 어떻게 할까? 아내가 야근하는 밤, 밥을 해두고 반찬까지 챙기고 있을까? 난 못하는 게 당연한가? 아니면 나만 못하는 걸까? 혼자가 아니라는 확인 그런데 아내가 "고마워" 라고 했다. 왜 감사의 말을 했을까? 나는 뭘 한 거도 아닌데. 그냥 라면을 끓였을 뿐인데. "뭐가?" 라고 물었다. 아내는 "뭐든. 혼자가 아니라서. 함께 있어서" 라고 했다. 아. 그게 그 말이었구나. 우리는 둘 다 바쁘다. 우리는 둘 다 피곤하다. 우린 둘 다 밥을 챙길 여유가 없다. 그래서 둘 다 라면을 먹는다. 회사에서 하나, 집에서 하나. 하지만 적어도 우린 같은 시간대에, 같은 음식을 먹고 있었다. 그리고 그 사실만으로도, 혼자가 아니라는 걸 확인하는 거였다. 밥을 해야 한다는 미안함과 라면을 끓여야 한다는 현실 사이에서, 우린 그렇게 함께하고 있었다. 완벽하지는 않지만, 그래도 옆에 있다는 것. 그 밤, 나는 라면 국물을 마시면서 생각했다. "내일은 밥을 해야겠다" 고. 하지만 그 생각도 마음속 어딘가에서는 알고 있었다. 내일도 무언가는 일어날 거고, 내일도 우린 바쁠 거고, 내일도 라면을 끓일 수도 있다는 걸. 그래도 괜찮을 거라는 걸. 왜냐하면, 우린 함께니까.결국 밥인지 라면인지는 중요하지 않았다, 옆에 있다는 것 하나면 충분했다.

회의 중에 노트북으로 딴 짓하는 척 코드 보는 기술

회의 중에 노트북으로 딴 짓하는 척 코드 보는 기술

회의 중 노트북으로 딴 짓하는 척 코드 보는 기술: 개발자의 이중생활 가이드 프롤로그: 슬랙 알림과 함께 시작되는 악몽 월요일 오전 10시, 평화로운 개발 시간이 끝난다. 슬랙에 떴다. "다들 회의실로 모여주세요. 분기별 로드맵 공유 회의입니다." 심장이 철렁 내려앉는다. 로드맵 공유? 1시간은 족히 걸린다. 기획자는 항상 '이건 빠르게 끝낼 거예요'라고 하지만, 실제로는 파워포인트의 각 슬라이드마다 10분씩 설명한다. 그사이 서버에서는 뭔가 돌아가고 있다. 어제 배포한 API의 응답 시간이 괜찮은지, Redis 캐시가 제대로 워밍업됐는지, 에러 로그에 뭔가 쌓여있지 않은지. 회의실에 들어가는 순간, 그 모든 게 나를 부르고 있는 것 같다. 아, 그래서 우리는 이 기술을 터득했다. 회의 중에 노트북으로 딴 짓하는 척 코드 보는 기술. 7년 경력 개발자인 나도 처음엔 서툴렀다. 회의 중 슬랙을 봤다가 팀장한테 "김개발, 뭐 하냐?"라고 들었다. 기획자 앞에서 IDE 창을 켜려다가 키보드 백라이트가 반짝여서 눈에 띴다. 하지만 지금은 다르다. 이건 단순한 기술이 아니라, 생존 기술이다.회의의 정체: 우리가 피할 수 없는 현실 먼저 인정해야 할 것이 있다. 모든 회의가 쓸모없진 않다. 그런데 우리가 참석하는 대부분의 회의는... 음, 쓸모없다. 우리 회사 달력을 보면 이해할 수 있다:월요일 조회: "이번 주 계획을 얘기하는" 회의인데, 결국 지난주 결과를 재탕한다 수요일 동기화: "크로스펑셔널 커뮤니케이션"이라는 명목의 30명 대회의, 내가 할 말은 없다 목요일 회고: 아직도 회고가 끝나지 않았다는 게 신기하다 금요일 플래닝: 점심 때문에 자리를 비운 사람이 반 이상이다그리고 여기 추가로, 갑자기 소집되는 기획 회의들. "개발팀이 빨리 끝낼 수 있을 것 같아서요"라는 말과 함께. 요청사항은 언제나 간단해 보인다. "그냥 이거 버튼 추가해 주시고, 데이터베이스에 컬럼 하나만 더하면 되겠네요?" 그런데 나는 안다. 그 "버튼 하나"가 얼마나 많은 것들을 건드리는지. 마이그레이션, 롤백 전략, 캐시 무효화, 테스트 케이스... 아무도 이걸 모른다. 그래서 회의 중에 나는 코드를 본다. 실제로 그 "버튼 하나"를 어디에 어떻게 붙일지 생각하면서, 동시에 기획자의 말을 들었다는 척한다. 이건 이중생활이 아니라 생존 기술이다. 기본기: 외적 완벽성의 추구 이 기술의 핵심은 한 가지다. 보이는 것이 전부다. 처음 시작할 때 실수하기 쉬운 부분부터 말하자면: 1단계: 각도 조절의 중요성 노트북 화면을 옆 사람이 볼 수 없도록 해야 한다. 각도는 약 45도가 최적이다. 정면에 가까워지면 정신을 차리고 있는 것처럼 보이고, 너무 누우면 진짜 딴짓하는 것처럼 보인다. 45도에서는 "열심히 정리하고 있는 척"하는 완벽한 각도가 된다. 내 팀의 시니어 개발자 이준호는 이걸 마스터한 사람이다. 그의 노트북은 항상 기울어져 있고, 카메라가 정면을 향하고 있으며, 그의 손은 언제나 마우스패드나 트랙패드 근처에 있다. 누군가 다가올 때면 갑자기 손을 이동시켜서 "아 이거요"라고 대응할 수 있는 준비 자세를 유지한다. 2단계: 표정과 제스처 코드를 보면서 이 표정을 지켜야 한다:미간에 조금의 주름이 있어야 한다 (생각하는 모습) 눈은 화면에 집중하되, 2분마다 한 번씩 회의 진행자를 본다 마우스를 매 30초마다 움직인다 (살아있는 커서) 가끔 고개를 끄덕인다이건 마치 배우가 역할을 하는 것처럼 보일 수도 있지만, 실제로는 우리 뇌의 일부가 진짜 회의를 듣고 있다. 기획자가 "이 기능의 우선순위는?"이라고 나에게 질문을 던지면, 우리의 뇌는 동시에 여러 스레드를 실행한다: Thread 1: Redis 응답 시간 분석 Thread 2: 기획자의 말 파싱 Thread 3: "아 그거요"라는 말이 자연스러울지 판단 Thread 4: 다음 슬라이드 준비다중 작업 처리 능력이 정말로 개발됐다. 3단계: 음성 신호 "음", "네", "맞아", "그렇네" 같은 짧은 음성 신호를 정기적으로 발생시킨다. 이건 피드백이다. 아무말도 하지 않으면 이상하다. 하지만 너무 자주 말하면, 회의에 다른 사람들이 자신에게 말을 걸어야겠다는 신호가 된다. 최적의 주기는 약 1분 30초에 한 번. 회의가 진행되고 있고 누군가 발표하고 있을 때, 나는 코드 리뷰를 열어본다. 어제 PR에서 한 후배가 올린 커밋을 본다. "왜 이 부분에서 Optional을 사용했지? NPE 가능성이 있는데..."라고 생각하면서 동시에 "정확해요"라고 중얼거린다. 이건 회의에도 참여하는 것처럼 보이고, 실제로는 기술 부채를 갚고 있는 중이다.심화 기술: 다양한 회의 상황별 가이드 모든 회의가 같지는 않다. 각 상황에 맞는 전략이 필요하다. 기획 회의 (위협 레벨: 매우 높음) 기획자가 발표하는 회의는 가장 위험하다. 자신이 준비한 것을 보여주는 상황이기 때문에, 기획자는 누가 집중하고 있는지 본능적으로 감지한다. 마치 고양이가 움직임을 감지하듯이. 이때는 깊은 참여가 필요하다. 노트북을 너무 많이 사용할 수 없다. 대신 그림을 그려야 한다. 종이에, 기획 내용을 다이어그램으로 그린다. 이건 매우 영리한 방법이다. 왜냐하면:기획자 입장에서 보면 "오, 이 개발자는 내 말을 정말 진지하게 받아들이고 있네?"라고 생각한다 실제로는 우리는 그리면서 기술적 구현 방법을 생각하고 있다 나중에 "여기 이 부분은 기술적으로..."라고 말할 때 그림이 있으니까 권위 있어 보인다내 노트북 옆에는 항상 A4 종이와 펜이 있다. 기획 회의 직후 휴지통에 들어가는 그 다이어그램들. 하지만 그건 훌륭한 투자다. 기획자의 신뢰를 얻고, 동시에 기술 분석까지 하는 일석이조의 효과. 스탠드업 회의 (위협 레벨: 낮음) 스탠드업은 가장 쉽다. 왜냐하면 다들 서 있기 때문이다. 앉아서 노트북을 할 수 없다. 이때는 진짜로 슬랙을 본다. 아무도 상관하지 않는다. 회고 회의 (위협 레벨: 중간) 여기는 감정이 섞여있다. 좋은 것도 있고, 개선해야 할 것도 있다. 이때 노트북을 사용하면 "저 사람 이미 다음 스프린트 생각해?"라는 인상을 줄 수 있다. 좋은 인상이다. 실제로 나는 항상 회고 회의 중에 다음 스프린트 백로그를 정리한다. 이건 회의의 목적과도 맞는다. CEO 타운홀 (위협 레벨: 극도로 높음) 모든 직원이 참석하는 회의다. CEO가 발표한다. 이때는 절대 노트북을 켤 수 없다. 왜냐하면 회의실 전면의 스크린에 참석자 명단이 떠 있거나, 누군가가 녹화를 하고 있기 때문이다. 이때는 핸드폰을 본다. 그리고 손에는 메모지를 든다. 메모지에는 아무것도 쓰지 않는다. CEO 발표는 항상 비슷하다. "올해는 AI 기술에 집중합니다", "고객 만족도를 높여야 합니다", "비용 절감을 목표로 합니다". 우리 개발팀은 안다. 이게 뭘 의미하는지. 더 짧은 마감시간으로 더 많은 기능을 만들라는 뜻이다. 도구와 준비물: 프로 설정 이 기술을 제대로 하려면 환경 설정이 중요하다. 노트북 세팅 내 MacBook Pro는 전술적으로 배치되어 있다:배경화면: 회사 프로젝트 이름이 있는 네이비 + 회사 로고. 너무 개인적이면 의심받는다 독(Dock): 일 관련 앱만 보이도록. Slack, IDE, 브라우저, 노션 데스크탑: 깔끔하게. 파일이 많으면 산만해 보인다 키바인딩: 빠른 전환을 위해 커맨드+탭을 마스터해야 한다회의 5분 전에, 나는 이 루틴을 한다:IDE 열기 → 어제 작업하던 브랜치 열기 Datadog 또는 NewRelic 열기 (서버 모니터링) 슬랙 음소거 (슬랙 핑 소리만 들으면 회의 집중력이 떨어진다) 밝기 조절 (너무 밝으면 눈에 띈다)추가 도구외장 마우스: 트랙패드보다 자연스럽다. 손가락으로 탭탭 거리는 것보다 마우스를 들었다 놨다 하는 게 더 "일하는 느낌"을 준다 종이와 펜: 위에서 언급했듯이, 기획 회의에서 필수 헤드폰: 회의 직후 슬랙 메시지를 받을 때 사용. 회의 중에는 안 쓴다. 회의에 참여하지 않는 것처럼 보인다 커피/물: 들었다 놨다를 반복하면 "바쁜 사람" 이미지를 준다윤리적 경계선: 우리는 완전히 나쁘지만은 않다 여기서 중요한 걸 말해야 한다. 이 기술은 악의는 아니다. 예를 들어, 내가 어제 배포한 마이크로서비스의 응답 시간이 평소보다 300ms 높아졌다면? 나는 회의 중에 그걸 봐야 한다. 왜냐하면 사용자가 경험하는 시간이 증가하고 있기 때문이다. 이건 긴급하다. 회의보다 우선순위가 높다. 또는 후배가 올린 PR에서 심각한 SQL injection 취약점을 발견했다면? 나는 회의 중에 코멘트를 남겨야 한다. 왜냐하면 그게 프로덕션에 들어가면 회사 데이터가 위험해지기 때문이다. 그런데 그게 아니라면? 예를 들어, 회의는 진짜 중요하고, 내 의견이 필요한 상황이라면? 그럼 노트북을 덮어야 한다. 이건 기술의 올바른 사용법이다. 내 경험상, 회의의 80%는 정말로 불필요하고, 20%는 정말로 중요하다. 문제는, 시작할 때 어느 것인지 모른다는 것이다. 그래서 우리는 이 기술을 개발했다. 처음 10분은 준비 자세를 유지하다가, 정말로 불필요하다는 것을 확인한 후에 코드를 본다.실제 상황: 회의 중 코드로 문제를 푼 날들 이 기술이 정말로 가치를 발휘한 순간들이 있다. 사건 1: 쿼리 최적화가 필요했던 날 분기 기획 회의 중이었다. 기획자가 새로운 대시보드 기능에 대해 설명하고 있었다. "사용자별 통계를 실시간으로 볼 수 있는 기능입니다." 내 뇌는 두 가지를 동시에 생각했다:기획 내용 파싱: "리얼타임 대시보드, 차트 표시, 필터링" 기술 부채 감지: "어제 배포한 사용자 통계 쿼리가 30초 걸렸는데..."그래서 나는 조용히 IDE에서 그 쿼리를 열었다. 회의가 진행되는 동안, 내 손은 인덱스를 추가하고 있었다. 그리고 로컬에서 다시 실행했다. 3초. 회의가 끝났을 때, 기획자가 물었다. "김개발, 이 기능 구현 난이도는?" 나는 대답했다. "쿼리 최적화가 필요한데, 제가 이미 일부를 테스트했습니다. 내일까지 프로토타입을 만들 수 있을 것 같아요." 기획자의 표정이 밝아졌다. 나는 "진짜로 집중하고 있었나봐"라는 인상을 주었다. 실제로는 회의 중 거의 모든 개발을 끝낸 것이다. 사건 2: 후배의 실수를 회의 중에 발견 월요일 회의에서, 지난주 배포 리뷰를 하고 있었다. 팀장이 "배포가 순조롭게 진행되었다"고 얘기했다. 나는 슬랙에서 배포 로그를 봤다. 그리고 발견했다. 후배가 올린 코드에서 트랜잭션 롤백이 제대로 설정되지 않았다. 데이터베이스 연결이 끊기면 부분 처리된 데이터가 남아있을 수 있는 상황이다. 나는 회의가 끝나고 즉시 PR을 닫고, 후배를 불러서 설명했다. "다음 배포에서 이 부분을 수정해야 해. 지금은 문제 없지만, 트래픽이 증가하면 이슈가 터질 거야." 후배는 고마워했다. 만약 회의 중에 코드를 보지 않았다면, 이 버그는 한두 달 뒤에 프로덕션에서 터졌을 것이다. 사건 3: 기획자의 불가능한 요청을 기술적으로 거절하기 "이 기능 이번 스프린트에 가능할까요?" 기획자의 질문에, 나는 노트북으로 현재 진행 중인 작업들을 확인했다. 동시에 기획자가 설명하는 새 기능의 복잡도를 머릿속으로 계산했다. 스토리 포인트: 13 (충분히 크다) 현재 용량: 32 포인트 (이미 꽉 참) 남은 포인트: 5 "아, 이번 스프린트에는 용량이 부족할 것 같습니다. 다음 스프린트는 어떨까요?" 기획자는 동의했다. 왜냐하면 나는 "아무래도 어려울 것 같은데"가 아니라, 구체적인 포인트와 이유로 설명했기 때문이다. 회의 중에 노트북으로 정보를 수집했기에 가능했던 일이다. 주의할 점: 들킬 수도 있다 사실 이 기술에도 리스크가 있다. 리스크 1: 카메라 요즘은 온라인 회의가 많다. 화상 회의에서는 카메라가 활성화되어 있다. 내 화면이 보이지는 않지만, 내 손과 시선이 보인다. 이때는 매우 조심해야 한다. 눈이 화면을 본다면, 사람들은 내가 뭘 보고 있는지 궁금해한다. 해결책: 화상 회의 중에는 덜 한다. 또는 화면을 공유하는 사람의 스크린을 보는 척하면서 동시에 폰으로 슬랙을 본다. 리스크 2: 팀장 우리 팀장은 "이 회의 필요해?"라는 타입이다. 즉, 회의를 싫어한다. 그런데 회의는 여전히 많다. 회의 중에 내가 코드를 본다는 것을 알지만, 팀장은 나한테 뭐라고 하지 않는다. 왜냐하면 팀장도 회의 중에 이메일을 본다. 우리 회사 문화는 "정직한 불만족"을 허용한다. 일이 불가능하면 불가능하다고 말한다. 회의가 불필요하면 불필요하다고 말한다. 그 대신 권장사항은, 회의를 최대한 짧게 만드는 것이다. 리스크 3: 진짜로 필요한 의견이 필요할 때 가끔 기획자가 정말로 기술 의견이 필요한데, 나는 화면만 보고 있다. 이때 순간적인 반응 시간이 0.5초 길어진다. 이건 매우 어색해 보인다. "어라, 왜 대답이 없지? 아, 화면 보고 있구나" 이런 생각을 하게 된다. 그래서 나는 중요한 회의는 정말로 집중한다. 처음부터 끝까지. 이건 신뢰 관계다. 더 깊은 고민: 이게 맞는 걸까? 요즘 들어 이런 생각이 든다. 정말로 회의가 필요 없는 걸까, 아니면 내가 회의 문화에 적응하지 못하는 걸까? 아니다. 회의는 정말로 필요 없다. 우리 회사는 3일마다 "동기화" 회의를 한다. 동기화? 우리는 슬랙에서 이미 동기화되어 있다. 하지만 인간관계가 필요하다고 생각한다. 그래서 회의가 있다. 인간관계를 원하면서, 동시에 "회의는 쓸모없다"고 느끼는 우리의 이중성. 이건 현대 업무 문화의 모순이다. 하지만 현실은 현실이다. 그래서 우리는 이 기술을 계속 사용할 것이다. 회의 중에 코드를 본다. 동시에 회의에 참여하는 척한다. 이건 악의 없는 생존 전략이다. 그리고 언젠가, 누군가가 "회의 시간을 50% 줄여봅시다"라고 제안할 때, 우리는 손을 들고 동의할 것이다. 하지만 그때까지는, 우리의 이중생활이 계속된다. 에필로그: 내일도 같은 방식으로 오늘 오후에도 "긴급 기획 회의"가 있다. 새로운 스타트업 파트너의 API 연동에 대한 것이다. 기획자는 "30분만 할 거예요"라고 했다. 30분. 나는 이 말을 이제 믿지 않는다. 그래서 노트북을 준비했다. IDE도, 모니터링 대시보드도, PR 리스트도 모두 준비했다. 그리고 준비했다. "이거 구현할 때 이쪽에서 이렇게 해야겠네"라는 생각을 하면서, 동시에 기획자의 말을 듣는 준비를. 이건 개발자의 숙명이다. 우리는 이런 회의들과 함께 살아간다. 그리고 우리는 이렇게 생존해왔다. 내일 또 다른 회의가 있을 것이다. 그리고 나는 또 다시 노트북으로 코드를 볼 것이다. 외적으로는 회의에 참여하면서, 내적으로는 코드와 함께. 이게 우리의 이중생활이다. 그리고 이제는 이것이 자연스럽다.결국 회의는 피할 수 없지만, 회의 중 코드는 피할 수 있다는 게 우리의 비밀이다.

레거시 코드와의 전쟁: 언제까지 봐줘야 하나

레거시 코드와의 전쟁: 언제까지 봐줘야 하나

레거시 코드와의 전쟁: 언제까지 봐줘야 하나 월요일 아침, 또 시작된다 월요일 9시. 커피를 마시며 슬랙을 확인하는 순간, 그 메시지가 떴다. "개발팀, 어제 결제 모듈에서 버그 발생. 긴급 조치 필요!" 한숨을 쉬며 코드베이스로 향한다. 이미 알고 있다. 이 버그는 5년 전 누군가가 만들어놓은 레거시 코드 속에 깊이 박혀있을 것이다. 급히 작성되었을 거다. 커밋 메시지는 아마 "fix: payment bug" 정도. 당시 개발자는 이미 떠났고, 남은 건 주석 없는 코드 덩어리뿐이다.나는 7년을 이 회사에서 보냈다. 그 세월이 얼마나 길었는지는 내가 얼마나 많은 다른 사람의 코드를 봤는가로 측정된다. 입사했을 때 이미 레거시였던 것들, 3년 전에 다시 레거시가 된 것들, 내가 작성했다가 이제는 남이 보기엔 레거시인 것들... 이 모든 게 뒤섞여 있다. "김개발님, 이거 어디 고쳐야 해요?" 후배 정호가 물어본다. 나는 모니터를 보면서 펜을 돌린다. 그 동작은 이미 무의식적이다. 생각할 시간이 필요하다. 코드를 이해할 시간이 아니라, '이 코드를 어떻게 설명할 것인가'에 대한 시간이다. 레거시 코드란 무엇인가 정확히 말하면, 레거시 코드는 "이전 개발자가 작성한 코드"를 뜻하지 않는다. 사실 더 정확한 정의는 "테스트되지 않은 코드"이다. 그리고 대부분의 경우, 그 코드가 작성된 배경을 알 수 없는 코드다. 우리 회사의 결제 모듈은 2017년에 작성되었다. 당시 개발자는 신입이었을 거다. 마감이 촉박했을 거고, 리뷰는 제대로 안 됐을 거다. 그렇게 탄생한 코드가 이제 회사의 심장 부분이 되어버렸다. // payment_module_2017.java - 이런 식의 주석뿐 public class PaymentProcessor { public void processPayment(String userId, String amount, String type) { // TODO: refactor this later if(type.equals("CARD")) { // ... 50줄의 복잡한 로직 } else if(type.equals("ACCOUNT")) { // ... 30줄의 비슷한 로직 } else { // ??? } } }이런 코드를 보면 정말 묘한 감정이 든다. 분노? 아니다. 그것보다는... 안타까움? 아니, 동정심인가? 저 코드를 쓴 사람도, 나처럼 야근하고 있었을 거다. 그 사람도 "나중에 리팩토링하겠지" 하고 있었을 거다. 하지만 "나중"은 절대 오지 않는다. 긴급 이슈의 악순환 "긴급"이라는 단어만큼 개발자를 좌절시키는 단어가 있을까. 지난 3개월간 나의 캘린더를 보면, 내 일정의 60%는 긴급 이슈였다. 긴급하지 않은 계획된 작업은 20%. 나머지 20%는 회의와 리뷰다. 계산이 맞지 않는다고? 응, 내가 초과근무하는 시간이 20%라는 뜻이다. 우리 팀장은 좋은 사람이다. 나쁜 사람이 아니다. 다만 마케팅 부서의 압박을 받고 있고, 나는 그의 압박을 받고 있다. 기획팀은 "이거 간단하죠?"라고 묻는데, 그들이 모르는 건 그 "간단한" 기능이 엄청나게 복잡한 레거시 코드에 짜여있다는 거다. 지난달의 예를 들어보자. 월요일: 새로운 결제 게이트웨이 연동 요청. 마감은 금요일. "간단한 연동이니까 3일이면 되겠지?" 화요일: 기존 결제 모듈의 구조를 파악하려고 시도. 결제 처리 로직이 3개 파일에 흩어져 있음을 발견. 데이터베이스 스키마도 난장판. "누가 이렇게..." 수요일: 기존 로직을 수정하면서 다른 부분에서 버그 발생. 결제 조회 기능이 깨짐. 긴급 회의. 목요일: 야근. 밤 11시, 결국 새로운 연동을 추가했는데 테스트를 다 못 함. 금요일: 아침 10시 배포. 오후 2시 고객 불만 접수. "결제가 안 돼요." 다시 파악 중... 이게 내 리얼 스토리다. 이게 나만의 이야기는 아니겠지만.기술 부채는 이자가 붙는다 경제학에 "복리"라는 개념이 있다. 돈은 시간이 지날수록 기하급수적으로 늘어난다. 기술 부채도 마찬가지다. 초기에 시간을 들여 제대로 작성하지 않은 코드는 나중에 수십 배의 시간을 빼앗는다. 내가 개발한 기능을 테스트하는 데 3시간이 소요된다는 건, 아마 그 아래 있는 레거시 코드가 너무 뒤엉켜서일 거다. 우리 팀에서 일반적인 버그 수정 시간:새로운 기능 버그: 1-2시간 레거시 버그: 4-8시간왜일까? 왜냐하면 레거시 코드의 버그는 단순히 그 부분만 고치는 게 아니기 때문이다. 그 부분이 어디와 연결되어 있는지 파악해야 한다. 그 파악 과정이 90%의 시간을 먹는다. 한 번은 이런 일도 있었다. 아주 간단한 버그였다. 특정 상황에서 결제 시간이 잘못 저장되는 거. 나는 "이거 5분이면 끝나겠네" 했다. 한 시간 반 후, 나는 발견했다. 이 버그는 실제로는 3개의 서로 다른 부분에서 발생하고 있었고, 각각 다른 개발자가 만든 거였으며, 심지어 일부는 데이터베이스 레벨의 문제였다. 최종적으로 3시간이 걸렸다. 그리고 수정한 지 2주 후, 또 다른 버그가 터졌다. 내가 수정한 부분이 다른 모듈과 충돌했기 때문이다. 다시 2시간. 이게 기술 부채의 복리 효과다. 처음엔 5분이 3시간이 되고, 3시간이 나중엔 5시간이 된다. 리팩토링의 꿈 나는 리팩토링을 꿈꾼다. 이 모든 레거시 코드를 들어내고 깨끗하게 다시 짜는 거. 정말 깔끔한 구조. 적절한 디자인 패턴. 완벽한 테스트 커버리지. 그걸 내 팀장에게 제안했던 게 6개월 전이다. "팀장님, 결제 모듈 리팩토링 프로젝트 시작하면 좋을 것 같아요. 지금 이대로면..." 팀장: "알지. 근데 요즘 릴리즈 스케줄이 타이트해서... 나중에 이야기하자." 3개월 후에 다시 제안했다. 팀장: "그러고 싶은데 마케팅에서 새 기능 요청이 들어와서... 지금은 어렵다." 지금은? 지금도 다를 게 없다. 지금도 "긴급"이다. 이게 대부분의 회사에서 일어나는 현실이다. 리팩토링의 중요성을 아무도 부인하지 않는다. 하지만 모두가 현재의 긴급한 일에 밀린다. 그리고 몇 년이 지나면, 레거시가 더 심해진다. 나는 왜 고칠 수 없을까 가장 정직한 대답은: "시간이 없어서" 하지만 더 정직한 대답은: "우선순위가 없어서" 내가 할 수 있는 리팩토링:결제 모듈 전면 개편: 3-4주 필요 사용자 관리 모듈 정리: 2주 필요 로깅 시스템 개선: 1주 필요 에러 핸들링 통일: 3-4일 필요할 수 있는 일들은 많다. 하지만 이 중 어느 것도 직접적인 매출과 연결되지 않는다. 그래서 우선순위가 낮다. 기획팀이 "새로운 결제 수단 추가해요"라고 하면, 그건 매출과 직접 연결된다. 고객이 더 많은 결제 수단을 원하면, 그걸 만들어야 한다. 기획팀의 입장도 이해한다. 하지만 개발자의 입장에서 보면, 그 "새로운 기능"은 이미 망가진 기초 위에 또 다른 벽돌을 얹는 거다.그래도 계속하는 이유 그럼 왜 나는 여전히 여기에 있을까? 더 나은 회사로 이직하면 되지 않을까? 이 질문은 매달 한 번씩 떠오른다. 특히 야근할 때. 특히 주말에 슬랙 알림이 울릴 때. 진짜 이유는 몇 가지다. 첫째, 익숙함 이 회사의 모든 레거시 코드를 내가 안다. 5년 전 누군가가 작성한 코드의 의도를 안다. 왜 이런 식으로 짰는지 알 수 있다 (물론 여전히 이해 불가능한 부분도 많지만). 새로운 회사가면 또 다른 레거시를 만나야 한다. 차라리 이미 알고 있는 악을 택하는 게 낫다. 둘째, 내가 할 수 있는 영향력 내가 여기를 떠나면, 이 레거시 코드는 누가 고칠까? 아마 후배들이 더 힘들어할 거다. 내가 지금 할 수 있는 작은 개선들, 새로운 코드에서는 레거시를 안 만드는 것, 후배들에게 좋은 예시를 보여주는 것... 이런 게 의미 있다고 생각한다. 셋째, 충성심? 아니, 관성 더 솔직하게 말하면, 이직은 너무 힘들다. 이력서 쓰고, 포트폴리오 정리하고, 면접 봐야 한다. 지금의 피로감 속에서는 그 모든 게 산처럼 보인다. 작은 개선들의 누적 하지만 포기하지는 않았다. 대신 접근 방식을 바꿨다. 큰 리팩토링 대신 작은 개선 일주일에 한두 시간, 뭔가 하나씩 정리한다. 기능을 추가할 때마다 그 주변의 코드를 조금씩 개선한다. 이런 식의 "보이 스카우트 룰" - 도착했을 때보다 떠날 때 더 깨끗하게 - 을 적용한다. 문서화 레거시 코드의 가장 큰 문제는 "왜 이렇게 만들었는가"를 모른다는 거다. 그래서 나는 중요한 로직에 대해 몇 줄의 설명을 남기기 시작했다. 코드 리뷰할 때도 후배들에게 "왜"를 설명하려고 한다. 테스트 추가 모든 레거시 코드를 리팩토링할 수는 없지만, 테스트는 추가할 수 있다. 테스트가 있으면, 나중에 누군가 이 코드를 수정할 때 훨씬 안전하다. 기술 부채 추적 우리 팀은 이제 매달 "기술 부채" 미팅을 한다. 여기서 가장 시급한 레거시 코드들을 정리하고, 가능하면 작은 것부터 개선한다. 한 번에 다 고칠 수는 없지만, 계속 움직이면 언젠가는... 깨달음과 수용 7년을 거쳐 내가 배운 것 중 가장 중요한 건, 완벽한 코드는 존재하지 않다는 거다. 아니, 더 정확하게는: "완벽한 코드는 존재하지 않지만, 나아지는 코드는 존재한다"는 거다. 레거시 코드는 악이 아니다. 그건 과거의 결정이 현재에 남긴 흔적이다. 그 개발자가 나쁜 사람이라서 그렇게 작성한 게 아니다. 그는 당시 조건 하에서 할 수 있는 최선을 했을 거다. 마감이 촉박했고, 이해도 낮았고, 테스트할 시간이 없었을 거다. 지금의 나도 마찬가지다. 내가 지금 작성하는 코드가, 10년 후에 누군가에겐 "왜 이렇게 만들었어?"라는 질문을 받을 거다. 그건 피할 수 없는 운명이다. 그래서 내