2020. 3. 11. 04:35ㆍ개발환경
P4 란 Perforce 라는 형상관리툴의 별칭 이다.
Perforce 는 형상관리툴 중에서도 비싼 상용화 툴인지라,
널리 쓰이는 svn, git 보다 정보가 부족한 것 같다.
이 포스트에서는 형상관리툴에 대해선 따로 다루지 않고 Perforce 의 depot 종류 중 하나인 stream 에 대해서
개인적으로 학습한 것들을 정리하였다.
기본적인 Perforce 용어와 사용법에 대해서도 따로 다루지 않았다.
정리한 목적은 이렇다.
- 왜 stream 을 사용하는가?
- stream 에서 사용하는 기능들은 무엇인가?
이전 팀에서도 Perforce 를 사용했었는데, local 타입의 depot 만 사용했었다.
그래서 들게 된 의문은 local 타입이 아니라 stream 타입을 사용했을 때 취할 수 있는 이점이 무엇인가? 였다.
local, stream 타입 외에도 Perforce 에는 여러가지 depot 타입이 존재한다.
캡쳐를 보면 remote, spec, archive 타입이 보이는데 어떤 경우에 사용해야하는지 아직 잘 모르겠다.
이런 타입들도 있다는 정도로 인지하고 넘어가려 한다.
그럼 다시 본론으로 넘어와서,
왜 local 타입을 두고 stream 을 사용하는가? 에 대해 얘기해보자.
형상관리툴의 주 사용목적 중 하나는, 브랜칭 전략이라고 생각한다.
게임이든 소프트웨어든 실제로 유저에게 배포하는 과정에서 수많은 버전 들이 존재하게 되고
이 버전들을 여러 사람이 동시에 개발하게 된다.
1. 먼저 수많은 버전 에 대해 얘기해보자.
버전은 브랜치라고 생각하면 된다. 이후부턴 브랜치라고 지칭하겠다.
이해를 돕기 위해서 다음 상황을 가정한다.
1. 원빌드
( 즉, 중심이 되는 main 버전이 있고, 파생되는 브랜치들은 모두 파생 시점의 main 을 복사하면서 분기된다. )
2. 파생된 브랜치에서 어떤 피처를 개발하고, 다시 main 으로 역머지한다.
위 상황일 때 local 타입과 stream 타입이 역머지 하는 과정은 다음과 같다.
-local 타입
파생된 브랜치에서 submit 한 모든 changelist 들을 개별로 한땀한땀 머지 해주어야한다.
위 캡쳐에서 빨간 박스 안에 있는 changelist 들을 main 으로 머지해주기 위해선, 8번의 머지 작업이 필요하다.
브랜치에서 submit 한 내용이 많을 수록 이 main 으로 역머지하는 작업 시간은 증가하게 된다.
changelist 마다 머지해줘야하기 때문에 실수하기도 쉽다.
-stream 타입
위 캡쳐에서 dev2.3 이 파생된 브랜치이다. dev2.3 에서 main 으로 역머지하는 작업은
빨간 박스의 'Merge/Integrate to main' 한 번의 클릭으로 끝난다.
클릭하게 되면 pending list 가 생성되고, 파일별 resolve 작업을 해준 후에 submit 하면 끝.
추가적으로, Merge 가 아닌 통복사 시키는 방법도 있다.
위 캡쳐에서 'Copy to main' 을 클릭하면, 브랜치 리소스를 main 으로 통복사 하게 되는데
이게 가능한 이유는 stream 은 원할 때 마다 main 변경점을 브랜치로 merge (동기화) 할 수 있기 때문이다. Perforce 에서는 이 작업을 'Merge down' 이라고 부른다.
'Merge down' 과정은 다음과 같다.
위 캡쳐를 보면 main -> dev2.3 으로 향하는 화살표가 '초록색' 이다. main 에서 dev2.3 브랜치로 merge 할 내용이 있다는 뜻이다.
main 과 동기화가 끝나면 아래처럼 '회색' 화살표로 바뀐다.
브랜치 리소스를 main 으로 통복사 하는 방식을 풀어 설명하면
'Merge down' 을 하고 난 후 ( main 변경점들을 브랜치에 동기화 시키고 ), 브랜치 리소스를 main 에 덮어씌워 버리는 거라고 보면 될 것 같다.
그런데 통복사 한다는 얘기를 들으면 아마도 이런 걱정이 들 것이다.
브랜치를 main 에 통복사하다가 main 변경점들을 날리면 어떡하지 ?
이 문제는 앞서 얘기한 화살표 색깔을 보고 예방 할 수 있다. 아래 그림을 보자.
main -> dev2.3 으로 향하는 화살표는 '초록색' 이고,
dev2.3 -> main 으로 향하는 화살표가 '빨간색' 이다.
main -> dev2.3 으로 향하는 '초록색' 화살표 : main 과 동기화 할 내용이 있다.
dev2.3 -> main 으로 향하는 '빨간색' 화살표 : 브랜치를 main 으로 머지하는 작업은 불안정한 상태이다.
이 상황에서 main 으로 'Copy' 를 시도하면 경고창이 뜬다고 한다. ( 아직 실제로 해보진 못했다. )
( 실제로 해보니, main 과 브랜치 내용이 다른데 정말로 Copy 하겠어? (잘못하면 사유서 쓸 수 있어) 라고 물어보며 Merge 는 어때? 라고 경고창이 제안한다. 원한다면 Copy 를 그대로 진행 할 수 있다. )
'Merge Down' 을 한 후에는 아래처럼 dev2.3 -> main 으로 향하는 화살표가 '초록색' 으로 바뀐다.
즉, 브랜치를 main 에 머지하거나 복사해도 안전하다는 뜻이다.
설명이 길었는데 local 타입과 stream 타입의 머지 과정을 비교해보면
stream 타입이 압도적으로 빠르고 간편한 걸 알 수 있다.
Perforce 에서 stream 을 설명 할 때 빼놓지 않고 얘기하는 점이 빠르게, 쉽게 머지 가능! 이였는데 이런 점 때문에 자랑한 것 같다.
설명하는 과정에서 Stream Graph 의 화살표 얘기를 많이 했는데, 이 부분도 stream 의 장점 중 하나이다. ( 직관성 )
Stream Graph 를 통해 변경점들이 브랜치 간에 어떻게 이동했는지 빠르게 파악하거나, 브랜치 간의 종속성도 한눈에 파악 할 수 있는 장점이 있다고 한다.
나중에 시간이 되면 Stream Graph 에 대해서도 정리해보면 좋을 것 같다.
2. 여러 개발자가 동시에 개발 할 때
마찬가지로 원빌드 정책이라고 가정해보자.
1인 개발이 아닌 이상 여러 개발자가 각자의 작업물을 서버에 ( 여기서는 p4 server ) submit 하게 될 것이고
원빌드이므로 submit 된 작업물들은 즉각 다른 개발자들의 개발환경에 영향을 미치게 된다.
극단적인 예로, 내가 submit 한 변경점으로 인해서 크래시가 발생한다면 다른 개발자분들이 이 변경점을 갱신 받는 순간 크래시로 고통을 받게되는 슬픈 현실이 초래한다.
이런 슬픈 현실을 막기 위해서, 문제 발생 소지가 높은 피처이거나 장기간 마이그레이션이 필요한 작업인 경우에는 전용 브랜치를 생성하고 이 브랜치에서만 작업 ( submit ) 한 후에 어느정도 안정화가 되었다고 판단되면 main 으로 merge 시키는 전략을 취한다. (그런다고 크래시가 발생 안한다고는 읍 )
그럼 여기서 전용브랜치를 어떤 타입으로 생성할 것인지 따져보자.
전용브랜치를 생성한 이유는, 작업물이 main 에서 안정적으로 돌아가기 위함이다.
그러려면 전용브랜치 환경이 main 과 동일한 상태에서 작업 해야한다.
( 그래야 실제로 main 에 머지했을 때 발생하는 문제들을 전용브랜치에서 캐치 할 수 있기 때문에 )
전용브랜치를 main 과 동일한 환경으로 만들려면 어떻게 해야 할까?
main 에 sumbit 되는 변경점들을, 지속적으로 전용브랜치에 적용 ( merge ) 하면 된다.
좋다. 그럼 local 타입과 stream 타입이 main 변경점들을 어떻게 merge 해오는지 보면 되겠다.
이미 위에 1번 항목에서 다 살펴본 내용들이다.
-local 타입
오늘 출근하고 보니 main 에 submit 된 변경점들이 8개다.
8개의 변경점을 모두 전용브랜치에 merge 해주어야 한다. 1번 항목에서 살펴봤듯이 변경점 하나하나 한땀한땀.
점심을 먹고 오후에 main 환경이랑 동일하게 놓고 테스트 해야 하는 상황이 왔다.
그 사이에 main 에 변경점 10개가 submit 되었다. 다시 한번 변경점 10개를 전용브랜치에 merge 해주자.
흑흑. 울고 싶다.
-stream 타입
'Merge Down' !
'Merge Down' !
'Merge Down' !
끝.
StreamGraph 의 '회색 화살표' 를 통해서 전용브랜치가 main 과 동일한 환경인지도 알 수 있다.
-마치며
브랜치 분기 후에 main 에 역머지해야하는 상황이라면, stream 타입을 두고 local 타입을 써야하는 이유가 마땅히 떠오르지 않는다.
local 타입으로 할 수 있는건 stream 타입으로 커버가 가능하지만, 이 반대는 성립하지 않는 것 같다.
p.s.
이 글을 정리하며 발견한 p4 의 merge 기능이 있는데,
바로 특정 changelist 구간을 묶어서 통으로 merge 할 수 있는 것이다.
local 타입도 변경점 한땀한땀 merge 해야하는 상황은 피할 수 있겠다.
p.s.2
글이 너무 길어져서 p4 stream 기능은 다른 글에서 다뤄야겠다.
개인적으로 학습한 내용이므로 틀린 부분이 있을 수 있습니다. 잘못된 내용이 있다면 공유 부탁드립니다 :)