본문 바로가기

Boostcamp

3주차 후반부

이번 과제는 정말 재밌었는데, 육체적으로 너무너무너무 힘들었다... 허리가 계속 아팠는데, 수요일 저녁부터 앉아있기 힘들 정도로 아팠다. 매주 수요일, 목요일 쯤 컨디션이 급격하게 떨어지는 것 같다. 수면, 운동을 줄이고 앉아있는 시간을 늘리다 보니 당연하긴 한데... 나이를 먹었다는 생각이 든다... 목요일에 과제를 제출하고, 개선을 더 하고싶었는데, 그냥 누워버렸다. 다음주가 지나면 반드시 병원을 가봐야겠다. 일단 이번주 남은 시간 화이팅 ㅠㅠ

 

이번 주제는 Git이다. 정말 거의 매일 쓰는 git이지만 그 내부의 동작 원리는 알지도 못했고, 알아볼 생각도 못한 것 같다. 이번에 공부를 하면서 자세한 동작원리를 알게 되었고, 얼마나 대단한 작품인지 다시 한번 느끼게 되었다. 이러한 Git과 리눅스를 창시하신 리누스 토르발즈님께 경의를 표한다.

 

우선 Git의 기초부터 알아보자. 아래의 내용은 깃의 공식문서를 참고하거나 가져온 내용이다.(https://git-scm.com/)

 


Git의 기초

Git은 파일을 Committed, Modified, Staged 이렇게 세 가지 상태로 관리한다.

- Committed란 데이터가 로컬 데이터베이스에 안전하게 저장됐다는 것을 의미한다.
- Modified는 수정한 파일을 아직 로컬 데이터베이스에 커밋하지 않은 것을 말한다.
- Staged란 현재 수정한 파일을 곧 커밋할 것이라고 표시한 상태를 의미한다.

Git 디렉토리는 Git이 프로젝트의 메타데이터와 객체 데이터베이스를 저장하는 곳을 말한다.
워킹 트리는 프로젝트의 특정 버전을 Checkout 한 것이다.
Staging Area는 Git 디렉토리에 있다. 단순한 파일이고 곧 커밋할 파일에 대한 정보를 저장한다.

Git으로 하는 일은 기본적으로 아래와 같다.

- 워킹 트리에서 파일을 수정한다.
- Staging Area에 파일을 Stage 해서 커밋할 스냅샷을 만든다. 모든 파일을 추가할 수도 있고 선택하여 추가할 수도 있다.
- Staging Area에 있는 파일들을 커밋해서 Git 디렉토리에 영구적인 스냅샷으로 저장한다.

 

 

항상 써왔기에 대충은 알고있는 내용이다. 이제 항상 써왔지만 대충도 알지 못했던 내용들을 공부해보자.

 

 

Git의 내부 - 1

 

git init 명령을 실행하면 Git은 데이터를 저장하고 관리하는 .git 디렉토리를 만든다. 이 디렉토리를 복사하기만 해도 저장소가 백업 된다.

- git 디렉토리 구조

$ ls -F1
config   -> config 파일에는 해당 프로젝트에만 적용되는 설정 옵션
description   ->  GitWeb 프로그램에서만 사용하기 때문에 이 파일은 신경쓰지 않아도 됨
HEAD
hooks/   -> 클라이언트 훅이나 서버 훅이 위치
info/   -> info 디렉토리는 .gitignore 파일처럼 무시할 파일의 패턴을 적어 두는 곳
objects/
refs/



이제 남은 네 가지 항목은 모두 중요한 항목이다. HEAD 파일, index 파일, objects 디렉토리, refs 디렉토리가 남았다. 이 네 항목이 Git의 핵심이다.

- objects: 디렉토리는 모든 컨텐트를 저장하는 데이터베이스
- refs: 디렉토리에는 커밋 개체의 포인터를 저장 (브랜치, 태그, 리모트 등)
- HEAD: 현재 Checkout 한 브랜치를 가리키는 포인터
- index: Staging Area의 정보를 저장

 

 

Git의 내부 - 2

 

Git은 Content-addressable 파일시스템이다. 이게 무슨 말이냐 하면 Git의 핵심은 단순한 Key-Value(역주 - 예, 파일 이름과 파일 데이터) 데이터 저장소라는 것이다. 어떤 형식의 데이터라도 집어넣을 수 있고 해당 Key로 언제든지 데이터를 다시 가져올 수 있다.

 


Blob

파일을 생성 후 `git hash-object`으로 Git 데이터베이스에 새 데이터 개체를 직접 저장하면, Git은 SHA-1 해시를 계산하고 해당 데이터를 저장한다. 그 결과로 나온 해시 값은 파일 이름이 된다. 이렇게 해서 Git은 파일 이름을 SHA-1 해시 값으로 변환하고, 그 해시 값으로 파일을 찾는다. git hash-object 명령이 출력하는 것은 40자 길이의 체크섬 해시다. 해시의 처음 두 글자를 따서 디렉토리 이름에 사용하고 나머지 38글자를 파일 이름에 사용한다.

데이터를 수정 후 다시 `git hash-object`로 저장하면, 데이터베이스에는 데이터가 두 가지 버전으로 저장돼 있다. 앞선 파일과 내용이 완전히 똑같다면, Git은 새로 저장하지 않는다.

파일의 이름은 저장하지도 않고, 단지 파일 내용만 저장한다.

이런 종류의 개체를 Blob이라고 하고, 여기까지가 blob에 대한 설명이다.

 


Tree

파일의 이름은 Tree 개체에 저장한다. 파일 여러 개를 한꺼번에 저장할 수도 있다. Git은 유닉스 파일 시스템과 비슷한 방법으로 저장하지만 좀 더 단순하다. 모든 것을 Tree와 Blob 개체로 저장한다.

Tree는 유닉스의 디렉토리에 대응되고 Blob은 Inode나 일반 파일에 대응된다. Tree 개체는 파일이나 다른 디렉토리에 대한 포인터를 가지고 있고, Blob 개체는 파일의 내용을 가지고 있다.

그러니까, blob은 개별 파일에 대해 저장하고, tree는 디렉토리에 대해 저장한다.

Git은 일반적으로 Staging Area(Index)의 상태대로 Tree 개체를 만들고 기록한다.
그래서 Tree 개체를 만들려면 우선 Staging Area에 파일을 추가해서 Index를 만들어야 한다. -> 우리 과제에선 하나로 통합된 듯?

그럼 JS에서 이 tree 개체를 어떻게 생성할까? 바로 떠오르는 생각은 당연히 js의 object를 이용하는 것이다. 한번 commit을 하면 디렉토리에 있는 모든 blob들을 json tree로 만들고 blob이랑 동일하게 저장하면 될듯?

 


Commit

아직 남은 어려운 점은 여전히 이 스냅샷(tree?)을 불러오려면 SHA-1 값을 기억하고 있어야 한다는 점이다. 스냅샷을 누가, 언제, 왜 저장했는지에 대한 정보는 아예 없다. 이런 정보는 커밋 개체에 저장된다.

commit 객체의 저장경로는 다음과 같다. .mit/index/commits

 

 

사실 이 외에도 더 내용이 많지만, 지금 내가 Git을 사용하는데는 이정도 지식이면 충분 할 것 같다. 이번 기회로 Git의 내부 동작 원리를 자세히 할게되어 만족스럽다.

'Boostcamp' 카테고리의 다른 글

챌린지 마지막 과제  (0) 2023.08.03
마지막주 시작!!  (0) 2023.07.31
3주차 전반부  (0) 2023.07.25
프로세스와 스레드  (0) 2023.07.20
8일차 정리  (0) 2023.07.20