Configuration management (CM)
변하는 소프트웨어를 관리하는 모든 프로세스와 툴을 CM이라고 한다.
파일을 사람이 직접 복사하고 옮기고 하는 걸로는 전체를 관리하기 힘들기에 소프트웨어를 관리하는 소프트웨어를 통하여 전체를 관리한다.
System building
다 모아서 하나의 통합된 시스템을 만드는 것을 말한다.
모든 컴포넌트를 모아서 최종적인 바이너리 코드가 나오면 된다.
Change management
버그 제거와 같은 요청들을 추적하고 관리한다.
Release management
외부에다가 출시하는 것을 말한다.
버전이 여러개 나오는데 그걸 다 출시 하진 않고, 그 중에서 무엇을 출시 할 지를 정한다.
아래의 과정 전체가 CM이다. ▼
Multi-version systems
큰 시스템에서는 버전이 하나만 있지 않다.
큰 시스템일 수록 참여하는 사람이 많은데, 각 사람들이 만든 버전들을 일일히 관리하는 것은 무리가 있다.
게다가 요즘에는 대규모 시스템이 아니더라도 iOS, AOS, WEB 까지 3개의 버전을 만들게 된다.
이렇게 버전이 많아질 수록 직접 버전 관리를 하는 것은 어려워지기에 버전 컨트롤 시스템(version control system)을 써야한다.
이는 팀 단위가 아닌 혼자 개발할 때도 해야하는 중요한 것이다.
버전 컨트롤 시스템에는 두 개의 타입이 있다.
하나는 Centralized Systems로 하나의 레포지토리를 이용하는 방식이고, 다른 하나는 Distributed Systems으로 여러 개의 레포지토리를 이용하는 방식이다.
참고로 Git은 Distributed Systems로 레포지토리 여러 개를 사용하는 방식이다.
각 타입에 대해서 한 번 살펴보자.
Centralized Version Control Systems
CVC(Centralized Version Control)는 모든 컴포넌트의 Master 버전을 포함하는 시스템이다.
그러면 개발자들은 이 시스템에서 개발을 어떻게 할까?
Check-Out과 Check-In
각 개발자들은 Check-Out과 Check-In을 통해 버전 관리를 한다.
In과 Out의 기준은 레포지토리라고 생각하면 쉽다.
Check-Out
데이터가 나가는 것을 말하며, 개발자의 PC로 카피한다는 의미이다.
개발자는 원본이 아닌 카피를 가지고 작업을 한다.
Check-In
변경된 데이터가 들어오는것을 말한다.
변경된 데이터를 레포지토리에 들여와 덮어씌우는 것을 말한다.
"그런데 여러 명이서 모두 작업을 하게 되면 어떻게 될까?"
충돌(Conflict)
일단 위에서 말한대로 작업을 하면, 전부 다 체크 아웃을 통해 복사본을 갖게 된다.
그리고 각자의 기기에서 수정을 하게되는데, 이를 동시에 체크인 하게되면 충돌이 생겨버린다.
"그렇다면 이를 어떻게 해결할까? 자동으로 해결할 수 있을까?"
같은 파일을 수정한 것이라도 같은 파일의 100번째 라인과 300번째 라인을 수정한 거면 큰 문제없이 합칠 수도 있을 것이다.
그런데 같은 파일의 같은 라인을 수정하게 되면 답이 없어진다.
그래서 체크아웃할 때 이야기를 해준다.
‘나 이거 어디 고쳐야해서 체크아웃 좀 할게’ ▼
이렇게 미리 고지 받으면 충돌에 대해 예측이 가능해진다.
CVC 사용 흐름
고라니가 A 1.0, B 1.0 C 1.0을 체크아웃하고, 거위가 C 1.0, X 1.0, Y 1.0을 체크아웃한다. ▼
각자 알아서 수정해서 새로운 버전이 나오게 된다. ▼
그리고 고라니가 먼저 체크인을 하여 고라니가 작업한 것들이 마스터 버전에 반영이 된다. ▼
그 다음에 거위가 체크인하려고하는데, X와 Y에 대해서는 충돌이 생기지 않지만 C에서는 충돌 문제가 생기게 된다. ▼
거위가 만든 C 1.1은 고라니가 만든 C 1.1과는 다르니 새로운 버전으로 취급되어 C 1.2로 들어가게 된다. ▼
이후에는 두 가지 옵션이 생기게 된다.
'고라니 너 코딩 개못하잖아ㅋㅋ' 하고 거위가 작업한 내용을 그대로 C 1.1에 덮어씌우는 것이 첫번째. ▼
두번째는 고라니가 한 것도 나쁘지 않아 보여, 고라니가 한 거를 받아와서 내가 수정한 부분을 첨부하고 덮어씌울 수 있다. ▼
둘 중 무엇을 선택하는지는 개발자의 선택이다.
Distributed Version Control Systems
DVC(Distributed Version Control)에도 마스터 레포지토리가 하나 있다.
CVC에서는 작업하려면 Check-Out을 해야했는데, 여기서는 그렇게 하지않고 Clone을 만들어온다.
퍼블릭 레포지토리에 있는거랑 똑같은 파일을 내 PC로 가져온다.
그러면 Clone해서 가져온 레포지토리를 Private 혹은 Local 레포지토리라고 한다.
Clone한 레포지토리는 특정 시간의 마스터 레포의 스냅샷이라고 할 수 도 있다.
Commit과 Push
Commit
개발자는 Private 레포지토리에 Commit이라는 것을 할 수 있다.
Commit을 하게 되면 private 레포지토리에 새로운 버전이 만들어진다.
지금 한 행동은 Clone된 레포지토리에 한 것이기 때문에 Public 레포지토리에 반영이 안된다.
Push
Commit은 public 레포지토리에 반영되지 않기에 그동안 Commit한 내용들을 public 레포지토리에 반영을 시켜야한다.
그동안 Commit한 내용들을 반영하는 동작을 push라고 한다.
앞에서 본 CVC는 레포지토리 입장에서의 버전 컨트롤인데, DVC는 개발자 입장에서의 버전 컨트롤이다.
충돌(Conflict)
DVC라고 해서 충돌에서 자유로운 것은 아니다.
두 기기에서 같은 파일을 수정하고, 동시에 Commit과 Push를 하게 되면 충돌이 발생한다.
이 부분 역시도 CVC와 같이 사전 소통을 통해 해결할 수 있다.
DVC를 한 번에 설명해주는 그림
Remote를 Public 레포지토리라고 생각하고 들어가자.
엄밀하게 따지자면 둘은 다르긴 하지만, DVC의 동작 흐름을 봤을 때는 이렇게 생각해도 다르지 않다.
그래서 왼쪽의 Local Repository는 나의 기기에 있는 것이고, 오른쪽에 있는 Remote는 서버에 있는 것이다.
git clone
Remote 레포지토리에 있는 내용을 Local 레포지토리로 복제하는 것을 말한다.
맨 처음에 git clone해서 내 PC에 전체를 복제한다.
Clone을 하게 되면 로컬의 Private 레포지토리(Head)에 저장이 된다.
헤드가 전체 레포지토리가 되고, 작업하기에 위해 작업 디렉토리(Working directory)로 가져온다.
git add
git add는 작업 디렉토리상의 변경 내용을 스테이징 영역(Staging area)에 추가하는 것을 말한다.
작업이 다 끝나면 git add를 통해 Staging Area(임시 저장소)에 저장하게 된다.
git commit
스테이징 영역에 있는 변경 내용을 확정시키는 것을 말한다.
내가 지금까지 add로 올려놓은 것들로 새 버전을 만들겠다고 하면 git commit을 통해 확정할 수 있다.
그러면 로컬에 새로운 버전이 생성된다.
git push
지금까지 Commit 된 내용들을 모두 Remote 레포지토리에 보내는 것을 말한다.
우리의 목표는 Public(Remote) 레포지토리에 저장하는 것이다.
Commit 명령어로는 로컬에만 저장이 되기 때문에 Public 레포지토리에 넣기 위해서는 Push를 해야한다.
git pull
Remote 레포지토리의 내용을 받아오는 것을 말하는데, Clone과는 다른 점은 내가 변경한 내용들은 유지한 채로 받아오는 것을 말한다.
Remote 레포지토리와 Private 레포가 다른 팀원들의 Push로 인해 같지 않게 될 수 있는데, 그 때 Pull을 통해 둘을 같게 만들 수 있다.
팀원의 코드를 살리면서 넣고 싶으면 Pull을 받고 내용을 고치고 Push하면 된다.
DVC 사용 흐름
처음에는 Clone으로 레포지토리를 복제하는 것으로 시작한다.
고라니와 거위는 레포지토리를 복제하여 가져가는데, CVC와는 다른 점은 필요한 컴포넌트만 복제하는 것이 아니라 레포지토리 전체를 복제해서 가져간다. ▼
그 다음 각자의 로컬 레포지토리에서 새 버전을 만든다.
고라니는 A, B, C의 새 버전을 만들고, 거위는 C, X, Y의 새 버전을 만든다. ▼
어느정도 개발이 되었을 때 백업 차원이든 개발이 끝나서든 레포지토리에 반영하기 위해 Push를 해야한다.
그래서 고라니가 먼저 A, B, C의 새 버전을 푸쉬한다. ▼
그리고 개발을 마친 거위도 C, X, Y를 Push하려고 하는데 고라니가 먼저 Push한 C버전으로 인해 충돌이 나게 된다.
이렇게 되면 거위는 충돌난 부분을 해결하기 전에는 개발한 새 버전을 올릴 수 없다. ▼
이후에는 두 가지 옵션이 생기게 된다.
‘고라니 너 코딩 자꾸 거지같이 할래?’ 하고 그냥 덮어 씌워버리는 것이 첫번째. ▼
두번째는 고라니가 한 내용을 Pull 받고 거위가 한 내용들을 첨부하고, 다시 Push 하는 방법이다.
DVC의 장점
오프라인 작업
DVC는 오프라인에서 작업을 할 수 있다.
네트워크가 필요할 때는 Clone, Push, Pull의 3가지이다.
Clone의 경우엔 처음 한 번만 하는 것이기에 걸림돌이 되지 않으며, Push와 Pull은 전체 버전 컨트롤에서 찰나의 순간이기에 사실상 대부분의 작업은 오프라인에서 진행이 된다.
Master 레포지토리 안전성
CVC의 경우 컴포넌트 단위로 복제하기 때문에, Master 레포지토리에서 내가 복제한 컴포넌트 외의 것들이 망가지면 큰일이 나게 된다.
하지만 DVC는 그런 문제에서 조금 더 자유롭다.
레포지토리 전체를 복제하기 때문에 개인 기기에 있는 복제본이 많다.
Master 레포지토리가 망가져도 복구할 기회가 남아있다.
또한 Public, Private 레포지토리가 독립적으로 관리될 수 있어 자기 자신만의 Commit history와 Versioning을 할 수 있다.
CVC에는 잘못 된 코드가 있는데 체크인 해버리면 모든 사람에게 영향이 가게 되어 조심을 해야하지만, DVC의 경우 똑같이 그럴 수 있지만 Push 전까지는 영향이 가지 않기에 그런 문제에서 조금 자유롭다. (물론 조심은 해야한다.)
오픈 소스 개발
오픈 소스에서는 DVC가 거의 필수적으로 필요하다.
오픈 소스 개발은 서로가 서로를 잘 모르거나 물리적으로 떨어져있는 사람들과 하게 되는 경우가 많다.
소통이 원할하지 않은 상황에서는 얼마든지 Public 레포가 손상될 수 있다.
게다가 그런 개발상황에서 의도적이든 의도적이 아니었든 개발을 방해하는 사람이 한 명쯤은 있을 수 있다.
"그런데 이 사람이 계속해서 Push를 하게 되면 어떨까?"
당연히 프로젝트는 나락으로 가버린다.
그렇기에 이를 막기 위한 매니저라는 존재가 필요하다.
오픈 소스 매니저는 최종적인 시스템의 어떤 것을 Pull 할지를 고를 수 있다.
그러면 개발을 방해하는 사람의 버전은 무시하고 프로젝트에 도움을 주는 사람들의 버전만 골라서 받아올 수 있고, 그렇게 취합한 것을 Public 레포에 Push하는 것으로 버전 관리를 할 수 있따.
이런 측면에서 오픈 소스 개발에서는 DVC가 필요하다.
Branching and merging
버전은 가지를 치면서 진행이 된다.
1.1, 1.2, 1.3 … 과 같이 직선적으로 진행이 안되는 편이다.
이렇게 직선이 아니라 여러 가지를 치면서 나아가는 것을 브랜칭(Branching)이라고 한다.
그런데 가지가 뻗어져 나아가는것 까지는 좋지만, 버전을 무수히 많이 둘 수는 없기에 합치는 과정이 필요할 수 있다.
브랜치를 합치는거를 병합(Merging)한다고 한다.
1.0부터 시작해서 1.1로 간다음에 브랜칭한다.
나중에 2.1.2와 2.3을 합치고 싶다하면 병합해서 2.4를 만든다.
파일이 다르면 합치는게 어렵지 않지만, 같은 파일에 같은 줄의 코드면 어려울 수 있다.
마치며
git과 git hub 사용법에 대해서 모르는 것은 아니었지만, 항상 팀 개발에 대해 의문이 조금 있었다.
개발을 언제까지 혼자할 수는 없다. 언젠가는 다른 사람들과 같이 개발을 해야할 때가 오는데, 그런 측면에서 이런 CVC나 DVC에 대한 이야기는 팀 개발에 대한 기반을 다지기 좋은거 같다.
추가로 git 명령어에 대해서도 조금 자세하게 알게 되어 도움이 많이 되었다.
'CS > 소프트웨어 공학' 카테고리의 다른 글
14. Sequence Diagram (작성중) (0) | 2024.02.03 |
---|---|
13. Use Case Realization (0) | 2024.01.31 |
11. 다형성(Polymorphism) 예제 (0) | 2024.01.31 |
10. 객체 지향 프로그래밍 (Object-Orientation Programming) (0) | 2024.01.31 |
9. 요구사항 문서화 (0) | 2024.01.29 |