Mac 환경에서 Pull Request(PR)을 하는 방법에 대해서 알아보겠습니다.
먼저 원격 저장소를 들고 올 폴더로 이동을 해야합니다.
// Terminal
cd 폴더주소
여기서 Mac에서 간단히 폴더 주소를 가져올 수 있는데 터미널에서 cd
를 입력 후에 원하는 폴더를 드래그하여서 터미널에 넣으면 간단히 해당 폴더로 이동할 수 있습니다.
이제 로컬 저장소에 원격 저장소를 추가하는 작업을 진행 하면 됩니다.
git clone repository주소
위와 같이 작성을 해주면 깃허브 아이디와 토큰을 입력하라고 뜨는데 맞게 입력해주면 됩니다. 만약 토큰을 설정을 해야 한다면, 이 링크 로 들어가면 됩니다.
입력을 끝냈다면 다음 명령어로 잘 연결이 되어있는지 확인합니다.
git remote -v
다음과 같이 뜬다면 원격저장소가 제대로 연결이 된 것입니다.
이제 Pull Request를 하기 위해 새로운 브랜치를 생성해야 합니다.
git switch -c newbranch
위의 명령어로 브랜치를 만들고 바로 현재 브랜치로 바꿀 수 있습니다.
이제 해당 브랜치에서 작업을 끝냈다면 add
를 사용하여서 변경사항을 저장하고 commit
으로 커밋 메시지를 남긴다음 push
하면 됩니다. 이 때, 해당 브랜치에서 push
해야한다는 것의 주의해야 합니다.
// 변경사항 전부를 add
git add .
git commit -m "first commit"
git push origin newbranch
이제 push
를 하였기 때문에, 깃허브에 들어가보면 새로운 버튼이 활성화가 되어 있습니다.
Compare & pull request
버튼을 눌러 주고, 내용을 작성이 가능합니다.
레포지토리 담당자가 자신일 경우에는 충돌 되는 코드가 없는지 확인하고, merge
하면 됩니다. 만약 자신이 관리하는 경우가 아닐 경우에(팀 프로젝트, 회사 등) PR을 받은 담당자가 코드 내역을 확인하고 merge
여부를 확인하여서 병합합니다.
이제 원격저장소에 올렸으므로, 작업 브랜치는 삭제를 하고, 로컬 저장소에서는 동기화를 시켜 줍니다.
git branch -D newbranch
git pull remote-name
pull
을 사용하지 않고 push
를 하려고 하면, 에러가 나는 경우가 있으니 올리기 전에 pull
을 하는 편이 좋습니다.
git pull origin master = git pull [원격저장소 이름][원격 저잦오세엇 받아오고자 하는 브랜치 이름] 이라는 의미이다. git pull 만 입력하면 해당 저장소에 내용을 현재 브랜치에 들고온다고 생각하면 된다.
여기까지 PR을 하는 방법에 대해서 알아보았습니다. 이번에 살펴 본 부분은, Fork
를 사용하지 않았는데 이 부분은 단순히 다른 사람의 저장소를 자기 깃허브에 복사한다는 차이가 있다는 것 외에는 위의 과정이랑 전부 동일하므로 쉽게 할 수 있을거라 생각합니다.
이번에는 SwiftUI가 어떤 방식으로 레이아웃을 그리는지에 대해서 알아보겠습니다.
만약 파란색 배경의 원 안에 텍스트가 존재하는 뷰를 만든다고 할 때, 이를 코드로 구현을 해본다면,
Text("Reset")
.background(
Circle()
.fill(Color.blue)
)
위 코드로는 다음 사진과 같은 화면으로 나올 것입니다
이렇게 나오게 되는 이유는 SwiftUI의 레이아웃 알고리즘에 대해 알고 있어야 합니다. SwiftUI의 모든 레이아웃은 다음 4가지 단계를 통해 그려집니다.
이 절차와 뷰 디버깅을 통해 그려진 뷰의 계층을 보면서, 위의 코드를 분석해보겠습니다.
루트 뷰가 화면 전체 사이즈를 background
에게 제안합니다. 그리고 background
는 다시 Text
에게 전달합니다. (Modifier
는 새로운 뷰를 만들고 이전 뷰를 감싸서 반환한다는 것을 기억한다면, background
가 Text
를 감싸고 있다는 것을 이해 할 수 있습니다.)
하지만, Text
는 자신이 담고 있는 내용만큼만 필요하기 떄문에 콘텐츠의 내용 만큼만 사용할 것을 background
에게 알립니다.
다시 background
는 이를 하위 뷰인 ShapeView
에 알리고 ShapeView
는 이를 Circle
에게 알립니다.(ShapeView
와 Text
는 형제-자매 관계 입니다.) Circle
은 받은 크기를 그대로 사용하여 해당 크기에 딱 맞는 원을 그립니다.
그리고 이를 background
에 전달하고 background
는 다시 이 크기를 루트 뷰에 전달하고 루트 뷰는 해당 뷰를 가운데 정렬 합니다.
이제 우리가 원하는 레이아웃을 그리기 위해서는 어떤 방식이 있을지 알아보겠습니다.
UIKit에서는 크기를 사용할 때 객체에 직접 접근을 하여 값을 가져올 수 있었지만, SwiftUI에서는 불가능하므로, 이 문제를 GeometryReader
로 해결하려고 합니다.
이는 컨테이너 뷰의 한 종류로, 자신의 바로 위에 있는 상위 뷰의 기하학 정보를 자신이 포함하는 자식 뷰에게 제공하는 역할을 합니다.
사용 예시는 다음과 같습니다.
Text("hi~~")
.padding()
.fixedSize() // Text에만 존재하는 수정자로, 아무리 문자열이 길어도 한줄에 보여줍니다.
.background(
// 이때, proxy의 너비는 Text의 너비와 같습니다.
GeometryReader { proxy in
self.width = proxy.size.width // error
// 생성자로 ViewBuilder를 받기 때문에, 해당 할당식은 작성이 불가능
}
)
.frame(width: self.width, height: self.width)
.background(
Circle()
.fill(Color.blue)
)
이 시점에서 proxy
의 정보를 width
에 할당을 하려면 이 정보를 뷰 계층 위로 전달을 해야합니다. 이럴 때 사용하는것이 Preference
입니다.
이는 키-값 메커니즘으로 하위 뷰 정보를 상위 뷰에 전달할 수 있는 수단입니다. 이를 위해선 먼저 Preferencekey
프로토콜을 따르는 키를 정의해야합니다.
struct SizeKey: PreferenceKey {
static func reduce(value: inout CGFloat?, nextValue: () -> CGFloat?) {
value = nextValue()
}
}
간단하게 설명하자면, reduce
메소드는 SizeKey
를 사용하는 하위 뷰들을 순회하면서 상위 뷰가 접근할 수 있는 값을 만들기 위해 이들의 값을 취합하는 역할을 합니다.
struct ContentView: View {
@State private var width: CGFloat? = nil
var body: some View {
Text("Reset")
.padding()
.fixedSize()
.background(
GeometryReader { proxy in
Color.clear.preference(key: SizeKey.self, value: proxy.size.width)
}
)
.frame(width: self.width, height: self.width)
.background(
Circle()
.fill(Color.blue)
)
.onPreferenceChange(SizeKey.self) { value in
self.width = value
}
}
}
위와 같이 간단하게 트릭을 사용하여서 proxy
정보를 전달 할 수 있습니다.
Color
도 View
프로토콜을 따릅니다. 때문에, 사용자는 볼 수 없는 Color.clear
에 preference
를 통해 proxy.size.width
를 전달하고 있습니다.
상위 뷰(Text
)에선 하위 뷰에서 전달한 정보를 onPreferenceChange
를 통해서 받을 수 있습니다.
이런식으로, 원하던 레이아웃을 구현할 수 있습니다.
참조
https://zeddios.tistory.com/27