SVN으로 Spring 프로젝트 하던 시절: 어느 개발팀의 이야기
이 문서는 3명의 개발자가 SVN으로 Spring 프로젝트를 진행하며 겪는 다양한 사건들을 통해 신입 개발자의 성장을 그리고, 개발팀의 협업 문화를 보여주는 이야기입니다.
등장인물
신입 (준호): 이제 막 회사에 입사한 열정 넘치는 신입 개발자. 모든 것이 새롭고 어렵다.
중급 (수진): 3년 차 개발자. 신입을 챙기면서 자기 몫을 해내야 하는 팀의 허리.
고급 (민준): 10년 차 고급 개발자. 팀의 기술적 중심을 잡아주는 해결사.
PM: 프로젝트의 일정과 리소스를 관리하며 고객과 팀 사이의 소통을 담당한다.
고객: 비즈니스 요구사항을 전달하고 결과를 확인하는 최종 사용자.
1장: 신입의 첫 커밋 (feat. Conflict)
어느 화창한 오후, 준호는 첫 번째 업무를 받았다.
PM: "준호 씨, 간단한 작업이에요. 메인 화면의 문구를 '환영합니다'에서 '안녕하세요'로 바꿔주세요."
"네, 알겠습니다!"
준호는 떨리는 마음으로 svn update를 실행하고, 이클립스에서 해당 JSP 파일을 열어 문구를 수정했다. 너무나 간단한 작업. 5분 만에 끝났다.
(타닥... 타닥...) "좋았어! 첫 커밋이다!"
자신감에 찬 목소리로 svn commit -m "메인 화면 문구 수정" 명령을 날리는 순간, 터미널에 빨간 글씨가 나타났다.
codeCode
svn: E155015: Commit failed (details follow):
svn: E155015: Aborting commit: '/path/to/project/src/main/webapp/WEB-INF/views/main.jsp' remains in conflict"어? Conflict? 이게 뭐지?"
준호의 얼굴이 하얗게 질렸다. 파일을 열어보니 생전 처음 보는 <<<<<<< .mine, =======, >>>>>>> .r1234 같은 기호들이 가득했다. 패닉에 빠진 준호의 어깨 위로 수진의 얼굴이 쓱 나타났다.
수진: "준호 씨, 커밋하기 전에 다른 사람이 같은 파일을 수정했나 봐요. 괜찮아요, SVN 쓰다 보면 하루에 열두 번도 더 겪는 일이에요."
수진은 준호의 자리에 앉아 Conflict 해결 방법을 차근차근 설명해주었다. 다른 사람이 수정한 내용을 확인하고, 내가 수정한 부분과 합친 뒤, svn resolved 명령으로 해결 상태를 알려줘야 한다는 것이었다.
수진: "항상 코딩 시작하기 전에 update하고, 커밋하기 직전에도 update해서 충돌을 미리 방지하는 게 좋아요."
준호는 선배의 도움으로 간신히 첫 커밋을 성공시켰다. '안녕하세요'라는 다섯 글자를 올리는 데 한 시간이 걸렸다.
2장: 누가 빌드를 깨트렸는가
어느 월요일 아침, PM이 다급한 목소리로 외쳤다.
PM: "개발팀! 지금 테스트 서버가 안 떠요! 고객사에서 오늘 오전에 확인하기로 했는데 큰일 났어요!"
팀 전체에 비상이 걸렸다. 범인은 금요일 오후 마지막으로 커밋한 사람일 확률이 높다. 고급 개발자 민준이 침착하게 svn log를 찍어봤다. 마지막 커밋은 수진이었다.
민준: "수진 씨, 금요일에 작업한 부분에서 NullPointerException이 나는 것 같은데, 한번 확인해줄래요?"
수진의 얼굴이 빨개졌다. 로컬에서는 잘 돌아갔는데, 테스트 서버의 설정 값 하나를 고려하지 못해 생긴 문제였다. 그녀는 서둘러 코드를 수정하고 다시 커밋했다.
수진: (죄송한 목소리로) "죄송합니다... 제 불찰이에요."
민준: "괜찮아. 누구나 하는 실수야. 대신 앞으로는 커밋하기 전에 동료들한테 어떤 부분을 수정했는지 간단하게라도 공유해주면 이런 실수를 줄일 수 있겠지? 그리고 중요한 로직은 커밋 전에 꼭 한번 더 봐달라고 하고."
이 사건 이후, 팀에는 '중요한 커밋 전 동료에게 코드 리뷰 요청하기'라는 암묵적인 규칙이 생겼다. 준호는 이 과정을 지켜보며 혼자만 잘하는 게 아니라, 팀 전체가 안정적으로 나아가는 것이 중요하다는 것을 깨달았다.
3장: 전설의 svn:ignore
프로젝트가 중반을 넘어가면서 SVN 저장소는 점점 이상한 파일들로 더러워지기 시작했다. 개발자들의 이클립스 설정 파일인 .settings, .project나 컴파일된 .class 파일들이 커밋에 섞여 올라왔다. 특히 준호는 멋모르고 target 폴더 전체를 커밋해버리는 대형 사고를 치기도 했다.
결국 민준이 나섰다.
민준: "다들 잠깐 모여봐요. 우리 저장소가 너무 지저분해졌어요. SVN에도 Git처럼 특정 파일을 무시하는 기능이 있어요. svn:ignore라고."
민준은 svn propset svn:ignore 명령어를 통해 target, .settings, .classpath 같은 파일 및 폴더들을 버전 관리에서 제외하는 방법을 알려주었다. 한번 설정해두니 그 후로는 커밋할 때마다 불필요한 파일들이 목록에 뜨는 일이 사라졌다.
준호: "와... 이런 게 있었다니. 맨날 커밋할 때마다 체크 해제하느라 힘들었는데."
민준: "좋은 툴은 잘 써야 약이 되는 거야. 모르는 게 있으면 부끄러워하지 말고 언제든지 물어봐."
준호는 그날 저녁, SVN의 다른 속성(Property) 기능들에는 무엇이 있는지 찾아보며 밤늦게까지 공부했다.
4장: 고객의 갑작스러운 요구사항 변경
고객: "지금 진행 중인 기능, 방향을 완전히 바꿔야 할 것 같아요. 죄송하지만 내일 오전까지 프로토타입을 볼 수 있을까요?"
PM: (사색이 되며) "네...네?! 알겠습니다. 어떻게든..."
이미 trunk에서 한창 개발이 진행 중이던 기능이었다. 이걸 갑자기 바꾸려면 작업하던 코드를 전부 되돌리거나, 아니면 잠시 다른 곳에 백업해야 했다. 그때 민준이 제안했다.
민준: "이럴 때를 대비해서 브랜치를 쓰는 겁니다. trunk에서 급하게 hotfix 브랜치를 하나 따서 고객 요구사항을 처리하죠. 기존에 작업하던 건 잠시 그대로 두고."
민준의 지휘 아래, 팀은 svn copy 명령으로 hotfix 브랜치를 생성했다. 수진과 민준이 hotfix 브랜치에서 고객의 요구사항을 빠르게 구현하는 동안, 준호는 trunk의 기존 코드가 꼬이지 않도록 조심하며 다른 작은 버그들을 수정했다.
다음 날 아침, 팀은 hotfix 브랜치의 결과물을 성공적으로 고객에게 보여주었고, 위기를 넘겼다. 며칠 뒤, hotfix 브랜치에서 변경된 내용을 다시 trunk로 합치는 svn merge 작업이 진행되었다. 물론, 또 다른 Conflict 파티가 열렸지만 이제 준호는 더 이상 당황하지 않았다.
에필로그
시간이 흘러 준호는 더 이상 신입이 아니었다. 그는 이제 새로 들어온 신입에게 수진이 그랬던 것처럼 Conflict 해결 방법을 알려주고 있었고, 민준이 그랬던 것처럼 커밋 전 코드 리뷰의 중요성을 설명하고 있었다.
SVN은 Git에 비해 불편한 점이 많은 도구였지만, 그 불편함 덕분에 팀원들은 더 많이 소통하고, 서로의 코드를 들여다보고, 실수를 감싸주며 함께 성장할 수 있었다. 어쩌면 개발은 도구가 아니라, 사람이 함께 만들어가는 과정이라는 것을 그들은 SVN과 함께 배우고 있었던 건지도 모른다.
Model
준호가 SVN 충돌을 겪고 수진이 그에게 도움을 주는 모습으로 이야기를 시작해볼까요?
User
옙
Model
알겠습니다! 다음은 준호가 첫 번째 충돌을 겪는 순간을 묘사한 이미지입니다. 수진이 준호의 모니터 너머로 보이는 동안 당황한 준호의 얼굴과 SVN 충돌 메시지가 가득한 화면이 강조됩니다.
