git
git의 전체적인 개념에 대해 설명해보겠다.
- git이란?
git은 소프트웨어 개발 및 유지보수 과정에서 발생하는 소스코드나 문서 등의 생성, 수정, 삭제 등의 이력을 관리하는 VSC(Version Control System)의 하나이다.
git은 버전 관리 시스템 중에서도 분산형 VSC이다. 분산형 VSC는 중앙에서 관리하고 있는 모든 버전들을 가지는 저장소(Remote Repository) 전체를 복사하여 사용자의 컴퓨터로 가져와 사용한다. 분산형 외에도 개인 컴퓨에 관리할 버전을 저장하고 관리하는 로컬형, 여러 사용자의 버전 관리 내용을 중앙 서버에서 관리하는 중앙형 VSC도 존재한다.
그렇다면 이런 다양한 VSC의 종류 중 왜 특히 git이 대중적으로 쓰이는 것일까?
git의 장점이 협업에 매우 용이하게 사용될 수 있기 때문이다.
- 수정된 코드의 내용을 개발자 간에 주고받을 필요 없이 여러 명의 개발자가 프로젝트 개발에 동시에 참여 할 수 있음(동시성)
- 기능를 작성하다가 오류가 발생하는 경우나 기획자가 특정 기능을 취소할 경우와 같이 작업하던 코드를 과거로 돌려야할 때에 이전 코드로 복구할 수 있음(가역성)
- 과거에 작성한 코드의 내용과 수정된 내용이 저장되기에 오류의 추적이 용이(기록성)
- git은 무료 오픈 소스임
- 컴퓨터에 문제가 생기면 복구가 어려운 로컬형, 서버에 문제가 생기면 복구가 어려운 중앙형과는 다르게 git은 로컬 컴퓨터와 서버 상에 모두 git Repository를 가지고 있기에 프로젝트에 대한 정보가 날아갈 가능성이 낮음
- 국내적, 국제적으로 git의 위상이 타 VSC에 비해 압도적이기에 사용자가 많음
위와 같은 장점들이 있기에 현재 많은 개발자들이 git을 사용하여 협업을 통해 프로젝트를 진행한다.
- Github
Github는 소프트웨어 개발자를 위한 웹 기반 버전 제어 및 협업 플랫폼이다.
git으로 관리 중인 프로젝트들을 온라인 상에 올려둘 수 있는 git 호스팅 사이트 중 대표격이라고 생각하면 되겠다.
Github에 개인 또는 단체 Repository를 만들고, 여기에 git으로 관리 중인 프로젝트를 올려두면 다른 개발자들이 이를 clone 또는 fork를 통해 개인 Repository로 옮김으로써 개별 개발을 가능하게 할 수 있다.
또한 개인적으로 작업한 내용을 다시 push나 pull request를 통해 Github 상의 Remote Repository에도 반영할 수 있기에 유용한 협업 관리 도구로 쓰일 수 있다.
GitHub는 협업을 위한 관리 도구뿐 아니라 개발자를 위한 일종의 소셜 네트워킹 사이트로도 생각할 수 있다. 팔로우 기능을 제공하기에 회원끼리 서로를 팔로우하여 서로의 코드를 보거나 평가할 수 있으며, 특정 오픈 소스 프로젝트의 업데이트 내용들을 Github에서 확인할 수도 있다.
- git의 작동 방식
위의 그림은 git의 작동 방식을 보여준다. git이 어떤 과정을 거침으로써 파일의 버전을 관리할 수 있는지 확인할 수 있다.
작동 방식을 알아보기 위해 git의 세 가지 영역에 대해 알아야 한다.
- Working Directory
Working Directory는 작업할 파일이 있는 디렉토리를 의미한다. git init 명령어를 통해 git이 관리하도록 지정된 디렉토리로, 쉽게 말해 현재 우리가 파일을 작업하며 저장하고 있는 디렉토리라고 생각하면 되겠다.
- Staging Area
Staging Area는 commit을 진행할 파일들이 올라가 있는 영역을 말한다. Working Directory에서 작업한 파일들 중 버전으로 만들고자 하는 파일들을 git add 명령어를 통해 Staging Area로 올린다.
- Repository
Repository는 commit이 완료된 파일들로, git에 의해 버전 관리가 되는 파일들이 위치한다. commit이 완료되어 Repository에 위치하는 파일들은 버전 관리가 되기에 이후 상황에 따라 복구도 가능하다.
그리고 로컬 Repository에 존재하는 내용들은 git push를 통해 원격 Repository(GitHub 등)에 버전들을 올려 둘수도 있으며, git pull(fetch+merge)를 통해 원격 Repository의 내용을 Working Directory에 반영할 수도 있다.
위의 세 가지 영역을 거치면서 git은 파일들의 버전을 관리할 수 있는 것이다.
- git 파일의 3가지 상태 & git 파일의 라이프 사이클
git이 관리하는 파일들은 3가지 상태를 가진다.
- Modified : 수정된 파일들을 commit 하지 않은 상태
- Staged: 수정한 파일들 중 commit 할 것이라고 표시한 상태
- Commited: Staged 상태의 파일들이 Repository에 commit 된 상태
마지막으로 git 파일의 라이프 사이클을 알아보겠다.
- Untracked: Working Directory에 파일이 존재하긴 하지만, git이 해당 파일을 관리하지 않는 상태
- Unmodified: git에 의해 관리되는 파일이지만, 수정을 하지 않은 파일 상태
- Modified: Unmodified 상태의 파일에 수정을 가한 상태
- Staged: commit하고자 하는 파일의 상태, 커밋을 하면 Unmodified 상태로 돌아감
※ 2,3,4의 경우는 Tracked의 세부 분류이다.
SHA와 git
- SHA 해시 함수
SHA 해시 함수에 대해 알아보기 전에 먼저 해시 함수에 대해 알아보자.
해시 함수는 임의의 길이 데이터를 고정된 길이의 데이터로 매핑하는 함수로, 이로 인해 얻어지는 값을 해시값, 해시 체크섬 등으로 부른다. 이번 미션 구현 시에 commit, tree, blob의 해시값을 각자 규칙에 맞게 설정해야 했으므로 해시 함수에 대한 이해가 필수적이었다.
해시 함수는 결과값을 가지고 원래의 원본 데이터를 알아내기 힘들다는 특징이 있어서 암호화를 위해 주로 사용한다.
그럼 SHA 해시 함수는 무엇일까?
SHA는 미국국가안보국, 미국국립표준기술연구원에서 발표한 암호화 해시 함수의 집합이다.
SHA-0부터 현재 SHA-3까지 발표되어 있으며, 점차 버전이 올라갈 수록 이전 버전의 보안 취약점과 수학적 오류를 해결해냈다.
예를 들어 SHA-1은 현재 가장 많이 사용되는 SHA 해시 함수인데, 이는 264bit의 메시지로부터 160bit의 해시값을 만들어내는 해시 함수들이다.
- git에서의 해시 함수
git에서도 위에서 알아본 해시 함수를 사용한다!
해시 함수는 위에서 언급했듯이 암호화를 위해 주로 사용된다. 그렇다면 보안과는 크게 연관이 없는 git에서 굳이 해시 함수를 사용하는 이유는 무엇일까? 크게 두 가지 이유로 해시값을 사용한다고 한다.
- git이 오프라인 상태에서도 작동해야 하기 때문에
git은 온라인 상황이 아니더라도 작동을 보장한다.
그런데 만약 인터넷에 연결 할 수 없는 상황에서 git에 commit을 진행하려고 한다면 이전에 사용한 commit ID와 겹치지 않는다는 것을 온라인에서의 확인 작업 없이 어떻게 보장할 수 있을까?
위와 같은 상황을 위해서 SHA 해시 함수를 사용하는 것이다. 해시 함수값을 사용하면 중복이 발생할 가능성이 없다고 볼 수 있다.
그렇기에 온라인 상에서 최신 번호를 확인할 필요도 없고, 중복이 없음을 보장할 수 있는 SHA 해시 함수를 git에 적용했다.
- 자료의 신뢰성과 일관성 체크를 위함
위의 이유는 git의 개발자이신 리누스 토발즈님께서 직접 설명하신 내용이다.
SHA 함수를 보안적인 이유라기 보단 자료의 신뢰성 및 일관성 체크를 위해 사용한다고 한다.
예를 들어보자. 특정 데이터를 git에 올려두고 다른 컴퓨터로 이동하기도 하고, 몇 년이 지나서야 데이터를 꺼내고자 할 때 그 데이터가 정말로 내가 올린 데이터라는 것을 신뢰할 수 있을까? 누군가가 나쁜 마음을 먹고 글자 하나만 딱 바꿔서 그 자리에 그대로 둔 것인지 확인할 수가 없다.
하지만 SHA 해시 함수를 사용할 때, 한 글자라도 바뀌면 해시값이 달라지기 때문에 해시값만 알고 있으면 데이터의 무결성이 보장된다는 의미로 생각할 수 있겠다.
git 내부 객체
이제 git을 가능하게 하는, 프로젝트 관련 데이터들을 가지고 있는 git 내부의 객체들을 한 번 알아보겠다.
git의 내부 구조를 이루는 데이터 파일을 Object라고 하고, Object에는 Blob, Tree, Commit, Tag이 있다. 그리고 이 Object들은 미션에서 구현한 바와 마찬가지로 .git/object(Object Database)에 저장하고 zlib으로 압축하며, SHA-1 해시값으로 저장한다.
그럼 이제 각 객체에 대해 간단하게 알아보겠다.
- Blob
Blob 객체는 Working Directory 내의 파일 각각에 대응되는 내용을 저장하는 객체이다.
Blob에는 파일의 확장자나 파일명은 저장되지 않고, 오로지 파일의 내용만 저장하기 때문에 다른 이름을 가진 같은 내용의 파일들이 많이 존재하더라도 저장되는 Blob 객체는 단 하나이다.
기존 파일을 수정하고, git add를 통해 스테이징 영역에 파일을 올릴 때 생성되는 객체이다.
- Tree
Tree 객체는 Working Directory의 디렉토리에 대응되어 만들어지는 객체이다.
Tree의 내용은 해당하는 디렉토리의 내부 파일에 대한 정보와 디렉토리 자체에 대한 정보(해시값, 파일명, 파일 확장자 등)를 담은 객체이다.
디렉토리 내부에 디렉토리가 존재할 수 있기에 Tree 객체는 Blob 객체와 내부의 디렉토리에 대응하는 Tree 객체를 모두 포함한다.
git commit을 통해 스테이징 영역에 존재하는 파일들을 commit할 때 생성되는 객체이다.
- Commit
Commit 객체는 Commit History를 저장하는 객체이다. Author(작성자/해당 Commit을 최초로 작성한 사람), Committer(적용자/해당 Commit을 실제로 저장소에 push나 merge를 통해 적용한 사람), Commit Message애 대한 내용을 담고 있다. 즉 Commit과 관련된 정보들을 담고 있다고 생각하면 되겠다. 또한 Commit 객체는 해당 Commit의 스냅샷의 최상단 트리를 가리키는 Tree 포인터와 바로 직전 Commit의 해시값을 가리키는 포인터를 가진다. 이를 통해 이전 Commit에 대해서도 쉽게 참조할 수 있다. Tree와 마찬가지로 git commit을 통해 commit을 진행할 때 생성되는 객체이다.
- Tag
마지막으로 Tag는 미션에서 구현한 객체는 아니고, 중요도가 그렇게 크지도 않은 것 같다. git의 특정 Commit에 tag를 달 경우에 생성되는 객체로, Lightweight와 Annotated 태그로 나뉜다. Lightweight는 특정 commit에 대한 단순한 포인터 역할을 하고, Annotated는 태그의 작성자, 이메일, 날짜, 메시지 등도 포함할 수 있다고 한다. git tag 명령으로 Tag를 Commit에 달아줄 때 생성되는 객체이다.
'개발 > CS' 카테고리의 다른 글
(CS) 트리 & 트라이 (0) | 2023.12.25 |
---|---|
(CS) 객체와 객체지향이란? (0) | 2023.12.19 |
(CS) HTTP Request/Response/Method, CORS, 서브넷 (0) | 2023.05.27 |
(CS) HTTP, HTTPS, TCP (0) | 2023.05.19 |
(CS) OSI, TCP/IP Layer, TCP vs UDP (1) | 2023.05.12 |