개발팀 팀장 회고 (전 회사)
2025년 12월 14일 -
Table of Contents
들어가며
전 회사에서 개발팀 팀장으로 근무했었다. 20년 넘는 오래된 레거시 시스템을 유지보수하면서 동시에 신규 프로젝트를 진행해야 하는 팀을 맡는다는 건, 시작부터 쉽지 않은 과제였다.
안정성을 해치지 않으면서 변화를 만들어야 했고, 변화가 필요하다는 사실을 팀 모두가 뿐만 아니라 관련 부서들도 납득해야 했다.
이 글은 그런 상황에서 개발팀 팀장으로서 무엇을 우선순위로 두었고, 어떤 판단과 선택을 했는지에 대한 기록이다.
팀 파악
이미 팀원으로 근무했던 팀이었기 때문에 팀 파악 자체에는 큰 어려움이 없었다. 당시 팀의 상황을 정리해보면 아래와 같았다.
- 20개 이상의 레거시 서비스 유지보수 중심
- 모든 서비스가 상시 이슈를 일으키는 것은 아니었지만, 오래된 문제일수록 원인 파악과 해결에 많은 시간이 소요됨
- 단기 해결에 익숙해지며 이른바 ‘땜빵식 처리’가 반복되었고, 그 결과 코드 품질 저하와 동일 이슈의 재발이 계속됨
- 신규 서비스조차 레거시화
- Laravel, Vue 기반의 신규 서비스가 존재했으나 구조와 구현 방식이 레거시와 크게 다르지 않아 사실상 유지보수가 불가능한 상태
- 개발 프로세스 부재
- 공통된 개발 규칙, 리뷰 문화, 배포 기준 등이 정리되어 있지 않음
- 인력 유지의 악순환
- 새로 합류한 개발자들이 팀의 기술적 상태와 업무 방식을 보고 의욕을 잃고 퇴사하는 일이 발생
이 모든 문제의 근본에는 레거시에 익숙해진 문화가 자리 잡고 있다고 판단했다.
다만 매출과 직결된 레거시 업무를 무시할 수는 없었기 때문에, 레거시와 신규 개발을 분리된 축으로 바라보고 단계적으로 개선해 나가는 방향을 선택했다.
레거시 유지보수 및 개선
매출과 직결된 레거시 시스템의 유지보수 및 개선 방향은, 큰 틀에서는 기존 방식을 유지했다. 대신 동일한 이슈 재발 등을 방지하기 위한 코드 품질 개선에 집중했다.
구체적으로는 코드 리뷰를 도입했고, 담당자 단독 배포가 아니라 리뷰 후 승인된 변경만 운영 서버에 반영하도록 프로세스를 변경했다.
물론 근본적인 문제는 따로 있었다. 레거시 시스템은 여전히 FTP를 통해 담당자가 직접 운영 서버에 배포하고 있었고, 이는 명백히 위험한 구조였다. 반드시 개선해야 할 지점이었지만, 당시 상황에서는 즉시 손대기 어려운 영역이기도 했다.
- 레거시 전체 코드베이스에는 각종 리소스까지 포함되어 있었고, 규모가 지나치게 컸음
- 필요한 코드만 Git으로 관리하고 git pull 기반 배포로 전환은 단기간 시도하기에는 리스크가 매우 큼
결국 이 시점에서는 완전한 구조 개선보다는, 현실적으로 사고 가능성을 줄이는 방향의 점진적 개선을 선택할 수밖에 없었다.
신규 프로젝트
팀은 레거시 유지보수 뿐만 아니라 신규 프로젝트도 진행해야 했다. 다만 팀 내 신규 프로젝트에 대한 경험이 많지 않았기에, 프로젝트 시작할 때 마다 기술스택을 직접 선정하고 적용하는 역할이 필요했다.
신규 프로젝트는 성격에 따라 두 가지 유형으로 나누어 진행했다.
- 기존 레거시 시스템 내부에서 동작하는 신규 기능 개발
- 기존 시스템과 분리된 완전히 새로운 서비스 개발
각 유형의 특성과 리스크를 고려해 접근 방식과 기술 스택을 달리 선택했다.
레거시 내부에서 동작하는 신규 기능 개발
기존에도 레거시 시스템 내부에서 신규 기능 개발이 이루어지고 있었지만, 대부분은 기존 레거시 코드 스타일을 그대로 따르는 방식이었다. 그 결과 신규 기능임에도 불구하고 코드 품질은 레거시와 크게 다르지 않았고, 구조적인 개선 효과를 기대하기 어려운 상태였다.
이러한 방식이 반복된다면 장기적으로 확장성과 유지보수성을 확보할 수 없다고 판단했다. 이에 따라 신규 기능을 레거시와 동일한 방식으로 개발하는 접근을 중단하고, 코드 구조와 개발 방식을 근본적으로 변경했다. 레거시 환경 안에서 동작하더라도, 신규 기능만큼은 명확한 구조와 기준을 갖춘 형태로 개발하는 것을 원칙으로 삼았다.
Frontend는 Vue를 기반으로 개발을 진행했으며, TypeScript를 기본으로 사용했다. Backend는 Laravel을 활용해 API를 구현해 연동하거나, 레거시 시스템에서 데이터를 정리한 뒤 Vue 컴포넌트에 파라미터 형태로 전달하는 방식으로 구성했다. 레거시와의 공존을 고려해, 다음과 같은 방식으로 점진적인 적용을 시도했다.
- 레거시 내 신규 페이지 개발
- Frontend: Vite의 MPA 구성을 활용해 페이지 단위로 개발한 후 레거시 시스템에 적용
- Backend: Laravel로 API를 구현해 연동
- 레거시 일부 영역 교체 (GNB, Footer 등)
- Frontend: Vite Module 방식을 이용해 특정 영역만 분리 개발 후 레거시 시스템에 적용
- Backend: 빌드 결과를 레거시 시스템에 반영한 뒤, 컴포넌트에 가공된 데이터를 직접 파라미터로 전달하거나 Laravel로 구현한 API를 활용
이 과정에서 이후에 서술할 코드 표준, 정적 분석 도구, 포매팅 규칙, Docker 기반 개발 환경 등을 함께 도입했다. 이를 통해 팀 내부에서 반드시 지켜야 할 개발 기준을 명확히 했고, 시간이 지날수록 레거시 코드 내부에서도 점진적인 개선 효과가 나타나기 시작했다.
이러한 변화는 타 부서에도 긍정적으로 인식되었으며, 다른 서비스에서도 동일한 방식으로 개발해달라는 요청이 이어졌다. 더 나아가, 이 접근 방식은 향후 다른 레거시 시스템에도 적용할 수 있도록 사업 계획에 반영되기도 했었다.
완전 새로운 서비스 개발
완전히 새로운 서비스 개발의 경우 기술 스택과 개발 방식은 비교적 자유롭게 선택할 수 있었다. 다만 팀 전체의 업무량이 많은 상황이었기 때문에, 업무 전환(Context Switching)에 드는 비용을 최소화하는 것이 가장 중요한 기준이었다.
예를 들어 PHP 환경에서 Java나 Node.js와 같은 다른 언어로 전환하는 것과, PHP 기반에서 동일한 언어와 생태계를 유지하며 개발하는 것은 전환 속도와 안정성 측면에서 큰 차이가 있었다. 이러한 이유로, 팀이 이미 경험했던 Laravel을 신규 서비스의 기반 기술로 사용했다.
신규 서비스 개발 시에는 다음과 같은 기준으로 진행했다.
- API 설계
- Laravel 기반 API 개발
- Route 규칙 내 버전 관리(V1, V2) 적용
- API Key 필수 적용
- 신규 서비스
- 모놀리식(Monolithic) 구조로 개발
- Laravel에 Inertia.js 기반 Vue (Typescript) 적용 - Frontend와 Backend를 하나의 프로젝트로 구성
특히 서비스 전체를 개발·운영하는 과정에서 관리 복잡도를 줄이기 위해, Frontend와 Backend를 물리적으로 분리하지 않고 하나의 프로젝트 내에서 동작할 수 있도록 하였다. 서비스 규모가 커지는 경우에는 Controller에 로직을 집중시키지 않고, Repository–Service–DTO 계층으로 분리해 개발함으로써 재사용성과 유지보수성을 확보했다.
또한 팀 내부에서 반드시 지켜야 할 개발 기준을 명확히 하기 위해, 이후에 서술할 코드 표준, 정적 분석 도구, 포매팅 규칙, Docker 기반 개발 환경을 함께 도입했다. 이를 통해 신규 서비스 개발에는 표준을 지켜 개발할 수 있었다.
개발 규칙
팀에는 명확한 개발 규칙이 존재하지 않았다. Git을 사용하고는 있었지만 도입된 지 오래되지 않았고, 사실상 파일 백업 용도에 가까운 수준으로만 활용되고 있었다. 이 상태에서는 코드 품질 관리나 협업, 이력 추적이 어렵다고 판단했고, 개발 규칙을 정립하는 것을 가장 우선 과제로 설정했다.
이에 따라 다음과 같은 기준과 도구를 단계적으로 도입했다.
버전 관리 도구(Git) 운영 규칙 정립
- Pull Request 및 코드 리뷰 프로세스 도입
- Issue 및 Pull Request 템플릿(Markdown) 적용
- Pull Request 승인(Merge Complete) 후 배포 진행
- 브랜치 생성 자동화
- 사내 관리자 > 업무 협조 프로세스에서 담당자가 요청 접수 시 Git 브랜치가 자동으로 생성되도록 기능 추가
- 브랜치 네이밍 규칙을 고정해 개발자가 브랜치 생성 시 고민하지 않도록 개선
신규 프로젝트 기준 코드 규칙 적용
Conventional Commit 규칙 적용 & 커밋 시 커밋 메시지 검사하는 Commitlint 도입
커밋 시 정적 코드 검사 도입
- 커밋 대상 소스코드 검사 실패 시 커밋이 되지 않도록 설정
- Frontend(Vue): ESLint / Backend(Laravel): PHPStan 적용 / SCSS: Stylelint 도입
개발 환경 표준화
- Docker 기반 개발 환경 도입
- Windows 환경은 WSL2 기반, macOS 환경은 colima 사용
에디터 설정 통일
- .editorconfig 적용
- 개발 도구와 상관없이 동일한 코드 포맷을 유지하도록 설정
이러한 규칙을 통해 개인별 개발 스타일 차이로 발생하던 문제를 줄이고, 팀 전체가 공통된 기준 위에서 개발할 수 있는 환경을 마련했다. 결과적으로 코드 품질과 협업 효율이 함께 개선되었고, 이는 신규 인원이 합류하더라도 빠르게 팀의 개발 방식에 적응할 수 있는 기반이 되었다.
커뮤니케이션
커뮤니케이션은 단순한 대화 수단이 아니라, 팀이 현재 무엇을 하고 있는지 서로 인지하고 있는 상태를 만드는 것이라고 생각했다. 이를 위해 팀 내에서 누가 어떤 업무를 하고 있으며, 작업이 어떻게 진행되고 있는지를 자연스럽게 공유할 수 있도록 커뮤니케이션 방식을 개선했다.
사내 정책상 Slack과 같은 메신저를 사용할 수 없는 환경이었기 때문에, 개발팀 내부 커뮤니케이션 도구로 Google Chat을 사용했다. 제한된 환경 안에서도 최대한 실시간성과 가시성을 확보하는 것을 목표로 했다.
- 기존 메신저 대신 Google Chat을 개발팀 메인 커뮤니케이션 채널로 사용
- Google Chat 내 개발 이벤트 자동 공유
- GitLab Hook을 Google Chat에 연동, Merge Request 생성, 코드 리뷰 댓글 등 주요 이벤트를 Google Chat으로 자동 전송
- 업무 인지 개선
- Google Apps Script + Naver API를 활용해 업계 뉴스 및 참고 자료를 매일 아침 Google Chat으로 공유
추가로, 서비스 운영 안정성을 높이기 위해 사이트 오류 발생 시 즉시 팀에 공유되도록 했다. 레거시와 신규 서비스 구분 없이 오류가 발생하면 Google Chat으로 알림이 전송되도록 구성했으며, 이를 통해 팀원들이 빠르게 상황을 인지하고 원인을 파악해 조치할 수 있도록 했다.
이러한 커뮤니케이션 개선을 통해 팀 내 정보 비대칭을 줄이고, 문제 발생 시 대응 속도를 눈에 띄게 개선할 수 있었다.
업무 분배
팀은 7~9명 규모로 구성되어 있었지만, 각 팀원의 강점과 성향은 모두 달랐다. 레거시 시스템에 강점이 있는 팀원, 신규 개발에 잠재력이 있는 팀원, 그리고 하나의 도메인에 집중할 때 가장 좋은 성과를 내는 팀원 등 다양한 특성이 존재했다.
레거시 유지보수와 신규 개발을 동시에 수행해야 하는 팀 특성상, 기본적으로는 각자의 강점에 맞는 업무를 우선 배정했다. 다만 특정 업무에만 고착되는 것을 방지하기 위해, 역할을 유연하게 조정했다.
- 레거시 유지보수를 주로 담당하는 팀원에게도 신규 개발에 참여할 기회를 제공해 업무 편중에 따른 불만을 최소화하려고 노력
- 신규 개발을 중심으로 일하는 팀원에게는, 신규 기능 개발을 위해 반드시 필요한 도메인 이해를 위해 레거시 개발을 병행하도록 구성
이를 통해 특정 인력이 레거시 또는 신규 개발에만 고정되지 않도록 하고, 팀원 모두가 레거시와 신규 개발을 모두 경험할 수 있는 구조를 지향했다. 이러한 업무 분배 방식은 개인의 성장과 팀 전체의 리스크 분산을 동시에 고려한 선택이었다.
마치며
돌이켜보면 2년이 조금 넘는 기간 동안 팀장으로서 레거시 위주의 팀에 변화를 시도해 온 시간이었다. 누군가는 이를 “달리는 기차의 바퀴를 갈아끼우는 일”에 비유했는데, 실제로도 그에 가까운 작업이었다. 운영을 멈출 수 없는 상황 속에서 레거시의 기술 부채를 하나씩 정리해 나갔고, 그 과정에서 레거시 환경에서도 충분히 개선이 가능하다는 자신감을 팀과 함께 만들어갈 수 있었다.
물론 아쉬운 점도 몇 가지 있었다.
- 배포 과정 자동화를 충분히 완성하지 못한 점
- Jenkins를 활용해 Git Pull 기반의 배포 환경을 구성했지만, 일부 플러그인의 보안 취약성 문제로 사용 빈도를 낮출 수밖에 없었음
- 개인적인 업무 상황으로 인해 더 깊이 파고들지 못한 부분도 있어, 지금 돌아보면 가장 아쉬움
- 클라우드 플랫폼을 사용할 수 없어 도움받아 제대로 만들 수 있는 것도 만들지 못한 점
- 사용했다면 이미지와 동영상 처리 영역에서 더 나은 구조를 만들 수 있었을 것 같음
- 이미지: AWS S3, Lambda, CloudFront를 이용해 On-Demand Image Resizing을 활용한 포맷 및 사이즈 동적 처리
- 동영상: AWS S3, Lambda, Cloudfront, MediaConvert를 이용해 MP4를 스트리밍(HLS) 형태 변환 후 활용
- 컨테이너(Container) 기반 개발/운영 환경 구축: AWS ECS(Elastic Container Service) 사용
- 사용했다면 이미지와 동영상 처리 영역에서 더 나은 구조를 만들 수 있었을 것 같음
무엇보다 이 모든 변화는 내 윗분이자 실장님의 지속적인 지원과 이해가 있었기에 가능했다. 기술적인 시도와 방향성에 대해 믿고 맡겨주지 않았다면, 레거시 환경에서 이 정도의 변화조차 시도하기 어려웠을 것이다.
마지막으로, 위에서 서술한 변화와 개선의 내용들은 이미 많은 회사에서 보편적으로 수행하고 있는 것들이기도 하다. 그렇기 때문에 이 글을 읽는 분들 중에는 “특별할 것 없는 이야기”라고 느끼실 수도 있을 것이다.
다만 나에게 이 경험은, 레거시 위주로 운영되며 익숙해진 틀을 깨고 새로운 방식을 시도해 본 과정 그 자체에 의미가 있었다. 당연하게 여겨지던 관성과 한계를 넘어서기 위해 고민하고, 작은 것부터 순차적으로 도입해 나갔던 이 시간들은 앞으로 내가 더 나은 선택을 하고, 더 단단한 판단을 내릴 수 있게 해주는 중요한 밑바탕이 될 것이라 믿는다.
이 경험은 분명 미래의 나를 성장시키는 데 있어 매우 값진 자산이 될 것이다.