버전 관리와 명세서의 중요성
SSAFY_startcamp_team_pjt
Git과 명세서의 중요성 - SSAFY_startcamp_team_pjt
들어가며
학부생 시절에도 팀 프로젝트라는 걸 하긴 했다. 하지만 이름만 팀이었지, 기획도 설계도 코드도 결국 내 몫이었다. 그렇게 늘 혼자 짊어지다 보니 Git은 그냥 "커밋하고 푸시해서 코드를 백업하는 도구"였고, 명세서 같은 문서는 쓸 이유가 없었다. 무엇을 만들지 아는 사람은 나 하나뿐이었으니까.
그래서 이번 팀 프로젝트도 예전 습관 그대로 시작했다. Git은 여전히 "커밋하고 푸시하는 도구" 정도였고, 명세서는 더했다. "어차피 만들면서 정하면 되는데 굳이 문서를 왜 써?" 코드부터 짜고 싶은 마음이 앞섰다.
이번 프로젝트는 딱 3일, 팀원은 나까지 셋이었다. 짧은 만큼 "문서 만들 시간에 코드 한 줄 더 짜자"는 생각이 자연스러웠다. 결론부터 말하면, 그 3일 동안 두 가지를 얕본 대가를 고스란히 시간으로 치렀다. 그리고 그 삽질들이 이번 프로젝트에서 가장 크게 남은 배움이 됐다. 기능 하나 더 구현한 것보다, Git과 명세서에서 데인 경험이 훨씬 오래 갈 것 같다.
이 글은 그 짧고 굵은 삽질의 기록이다.
1부. Git — 편하려고 쓰는 도구에 발목 잡히다
전략 없이 시작한 대가
첫 실수는 시작하자마자 나왔다. 브랜치 전략이라 할 것도 없이, 그냥 구두로 front, BE, lcy 이렇게 나눠서 진행하자고만 했다. 정작 중요한 건 안 정했다. merge는 어떻게 할지, push는 언제 어떻게 할지, pull을 받고 나서는 뭘 확인해야 하는지 — 그런 약속이 하나도 없었다.
사실 우리 셋 다 여럿이 얽혀 쓰는 Git은 처음이었다. 나는 혼자 쓸 때나 편했지 협업 Git은 낯설었고, 팀에는 아직 브랜치 개념부터 익숙하지 않은 팀원도 있었다. 그나마 수업에서 배운 게 있어 master에 바로 작업하진 않았다. dev 브랜치를 하나 파서 거기서 진행한 것이다. 하지만 딱 거기까지였다. 셋이 그 dev 브랜치 하나에 다 같이 매달렸으니, 같은 곳에서 부딪히는 건 시간문제였다. 첫날 오전까진 아무 문제가 없었다. 파일이 몇 개 안 될 땐 뭘 해도 굴러가니까.
pull 한 번 안 받았을 뿐인데
문제는 아주 기본적인 데서 터졌다. 각자 열심히 작업하고 push하려는데 자꾸 거부당하는 것이다. 원격에는 이미 다른 사람이 올린 커밋이 있는데, 나는 그걸 안 받은 채로 밀어넣으려 했으니 당연한 일이었다. 그날은 여기저기서 "어? 왜 안 돼?" 하는 소리가 끊이질 않았다.
그럼 pull을 받으면 되는데, 여기서 두 번째 삽질이 나왔다. 로컬에 커밋하지 않은 변경사항이 있는 채로 pull을 받으려니, Git이 "네 변경사항이 덮어써진다"며 아예 거부해버렸다. 커밋을 먼저 하든 stash를 하든 정리해야 했는데, 그걸 모르니 "왜 안 되지" 하며 한참을 헤맸다.
거기에 .gitignore도 안 만들어둔 게 겹쳤다. node_modules며 각자 환경 설정 파일이며, 굳이 공유할 필요 없는 것들까지 죄다 커밋에 딸려 올라갔다. 그 파일들은 사람마다 내용이 달라서, 그것 때문에 또 충돌이 났다. 정작 우리가 짠 코드가 아니라, 올리지 말았어야 할 파일들이 발목을 잡은 셈이다.
이때 배웠다. push하기 전엔 pull부터, pull받기 전엔 내 변경사항부터 커밋. 그리고 프로젝트를 시작하면 .gitignore부터 만든다. 너무 당연한 순서인데, 그 당연한 걸 안 정해두면 셋이서 반나절을 통째로 날린다.
머지 충돌 지옥
같은 파일을 두세 명이 동시에 건드리자 merge conflict가 쏟아졌다. 충돌 자체는 자연스러운 일인데, 우리는 그걸 해결하는 법을 몰랐다. 겁이 나니까 일단 내 코드로 다 덮어버리는 사람이 생겼고, 그렇게 남의 작업이 조용히 사라졌다.
3일짜리 프로젝트에서 한나절치 작업이 날아가는 건 치명적이었다. 커밋 히스토리를 거슬러 올라가 겨우 복구했지만, 그 시간이면 기능을 하나 더 만들 수 있었다. "Git이 편하려고 쓰는 건데 왜 이렇게 무섭냐"는 말이 절로 나왔다.
커밋 메시지가 곧 협업 언어다
우리 커밋 로그도 처참했다. 수정, ㅇㅇ, asdf, 다시. "그 기능 언제 넣었지?" 하고 로그를 뒤질 때, 이 메시지들은 아무 정보도 주지 못했다. 히스토리는 미래의 나와 팀원에게 보내는 편지인데, 우리는 백지를 보내고 있었던 셈이다.
그래서 바꾼 것
첫날 저녁, 더는 안 되겠다 싶어 셋이 모여 최소한의 규칙을 정했다.
- 덮어쓰기 금지: 충돌 나면 무서워도 확인하고 해결하기 (일단 덮지 않기)
- 작업 순서 약속: 작업 시작 전엔 무조건 pull, push 전에도 pull부터. 그 다음에 꼭 팀원에게 말하기
거창한 브랜치 전략까지 갈 시간은 없었다. 하지만 이 최소한의 약속만으로도 둘째 날부터는 충돌이 무섭지 않았다. 충돌은 "누가 어디를 건드렸는지 알려주는 신호"였고, 규칙이 있으니 어떻게 풀지가 명확해졌다.
2부. 명세서 — 없어서 겪은 통합의 고통
"만들면서 정하자"의 함정
Git 문제가 도구의 문제였다면, 명세서 문제는 훨씬 근본적이었다. 우리는 요구사항을 제대로 문서화하지 않고 바로 코딩에 들어갔다. 역할은 대충 말로 나눴다. "너는 백엔드, 나는 프론트, 다른 한 명은 챗봇." 그 정도면 될 줄 알았다.
프론트와 백이 다른 그림을 그리다
가장 크게 데인 건 프론트엔드와 백엔드 통합 단계였다. 백엔드는 응답을 { userId, userName }으로 내려주고 있었는데, 프론트엔드는 { id, name }으로 받을 거라 믿고 화면을 다 짜뒀다. 필드 이름 하나, 데이터 구조 하나가 서로 달랐다.
이런 게 API마다 쌓여 있었다. 통합하는 날, 우리는 코딩이 아니라 "네가 뭘 보내는데?"를 서로 물어보느라 하루를 다 썼다. 각자 코드는 다 완성됐는데 붙이질 못했다.
애매한 요구사항, 서로 다른 구현
또 하나는 기능 정의가 애매해서 생긴 문제였다. "챗봇이 백엔드에서 데이터를 받아 온다"는 한 줄을 두고, 우리는 각자 알아서 데이터를 다듬었다. 문제는 그 규격이 서로 달랐다는 거다. 백엔드는 백엔드대로 응답 형식을 정해 내려줬고, 챗봇은 챗봇대로 "이런 형태로 오겠지" 기대하며 받을 준비를 했다. 둘 다 열심히 다듬었는데, 맞춰보니 필드 이름도 구조도 어긋나 있었다.
붙여보고 나서야 알았다. 각자 상상한 규격이 달랐으니, 아무리 각자 코드가 완성돼 있어도 연동은 되지 않았다. 결국 서로 뭘 주고받기로 했는지 다시 맞추고, 한쪽 코드를 뜯어고쳐야 했다. 명세가 한 줄이면, 해석은 사람 수만큼 갈린다.
그래서 배운 것: 명세서는 팀의 약속이다
뒤늦게 우리는 API 명세서를 만들었다. 엔드포인트, 요청 형식, 응답 형식, 상태 코드까지 표로 정리했다. 요구사항도 "누가 / 무엇을 / 어떻게"가 드러나게 다시 썼다.
명세서를 먼저 맞추고 나니, 프론트와 백이 각자 작업해도 결과가 딱 맞물렸다. 그제야 깨달았다. 명세서는 문서 작업이 아니라, 코딩하기 전에 팀이 같은 그림을 공유하는 약속이다. 이 약속을 건너뛰면 각자 열심히 만든 조각들이 서로 맞지 않는다.
3부. Git과 명세서, 사실 같은 이야기였다
회고를 쓰면서 깨달은 건, 이 두 삽질이 결국 하나의 뿌리라는 점이다. 둘 다 "혼자였으면 문제없었을 일" 이다.
혼자 개발하면 브랜치 전략이 없어도, 명세서가 없어도 머릿속에 다 있으니 굴러간다. 하지만 사람이 둘만 돼도, 머릿속에 있는 것과 공유된 것 사이의 간극이 곧 버그가 되고 충돌이 된다.
- Git은 "코드를 어떻게 함께 쌓아갈지" 에 대한 약속
- 명세서는 "무엇을 만들지" 에 대한 약속
둘 다 코드를 짜는 기술이 아니라, 함께 일하는 기술이었다. 그리고 협업에서 가장 비싼 비용은 언제나 "말 안 해도 알겠지"라는 가정에서 나왔다.
돌이켜보면 이번엔 운이 좋았다. 3일짜리 스타트 캠프 프로젝트라 다루는 데이터도 얼마 없었고, 주고받는 API도 몇 개 되지 않았다. 그래서 규격이 어긋나도 맞춰보고, 한쪽 코드를 뜯어고치는 걸로 반나절이면 수습이 됐다. 만약 기간이 몇 주씩 가고, 데이터와 백엔드 API가 방대한 프로젝트였다면 어땠을까. 어긋난 규격 하나를 찾아 고치는 데만 며칠이 걸렸을 테고, "말 안 해도 알겠지"의 청구서는 감당 못 할 만큼 불어났을 것이다. 작은 프로젝트에서 이걸 미리 데어본 게 차라리 다행이라는 생각이 든다.
마치며 — 다음 프로젝트에서 바꿀 것
이번 3일이 나에게 남긴 건 결국 "혼자 하던 습관을 버려야 한다"는 한 문장이다. 다음 팀 프로젝트를 시작한다면, 코드를 한 줄 짜기 전에 이것부터 할 것이다.
- Git 워크플로우를 먼저 약속하기 — 브랜치를 어떻게 나눌지, push 전엔 pull부터 받을지, 커밋 메시지는 어떻게 쓸지.
.gitignore도 첫 커밋 전에 만든다. 이번에 반나절씩 날린 삽질들은 대부분 이 약속 하나면 안 생겼을 일이다. - 명세서를 먼저 맞추고 코딩 들어가기 — 주고받을 데이터의 필드 이름, 형식, 누가 어디까지 가공할지. 이걸 한 페이지로라도 합의하고 나서 각자 구현에 들어간다. 각자 열심히 만든 조각이 안 맞는 것만큼 허무한 일이 없다.
- "말로 정한 것"은 반드시 남기기 — 기억은 사람마다 다르게 저장된다. 구두로 "너는 백엔드, 나는 프론트" 하고 넘어간 게 이번 삽질의 시작이었다.
예전엔 이런 걸 "본 작업 전의 귀찮은 절차"라고 생각했다. 코드를 짜는 게 진짜 일이고, 나머지는 곁다리라고. 이번 프로젝트를 지나고 나니, 이게 곧 본 작업이라는 걸 안다. 잘 쌓은 약속 위에서만 코드도 잘 쌓인다. 특히 혼자가 아니라 함께 쌓을 때는 더더욱.
3일은 짧았지만, 덕분에 다음엔 안 할 삽질이 생겼다. 회고의 목적은 그거면 충분하다고 생각한다.