P4 Stream 을 사용하는 이유 ( 퍼포스 스트림 )

2020. 3. 11. 04:35개발환경

P4 란 Perforce 라는 형상관리툴의 별칭 이다.

Perforce 는 형상관리툴 중에서도 비싼 상용화 툴인지라,

널리 쓰이는 svn, git 보다 정보가 부족한 것 같다.

 

이 포스트에서는 형상관리툴에 대해선 따로 다루지 않고 Perforce 의 depot 종류 중 하나인 stream 에 대해서

개인적으로 학습한 것들을 정리하였다.

 

기본적인 Perforce 용어와 사용법에 대해서도 따로 다루지 않았다.

 

정리한 목적은 이렇다.

  1. 왜 stream 을 사용하는가?
  2. 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 브랜치로 merge ( Merge Down ) )
( merge 확인창 )
( merge 대상 파일들이 pending list 에 잡힘 )

위 캡쳐를 보면 main -> dev2.3 으로 향하는 화살표가 '초록색' 이다. main 에서 dev2.3 브랜치로 merge 할 내용이 있다는 뜻이다. 

main 과 동기화가 끝나면 아래처럼 '회색' 화살표로 바뀐다.

'회색' 화살표 - 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 기능은 다른 글에서 다뤄야겠다.

 

 

 

 

 

개인적으로 학습한 내용이므로 틀린 부분이 있을 수 있습니다. 잘못된 내용이 있다면 공유 부탁드립니다 :)