문서 읽는 데 61분 · A8

A-8: 어질러진 저장소를 구조하고 졸업하기

목차 29
전체 8강 중 8강 · Git·GitHub
난이도 · 입문

ℹ️코드 버전 관리와 협업의 기본기 — 어떤 트랙을 가든 처음에 익혀두면 좋아요.

안녕하세요, 홍순구 튜터입니다. 드디어 이 과목의 마지막 시간이에요. A-1 에서 검은 터미널 창 앞에서 처음 git init 을 쳤던 게 엊그제 같은데, 어느새 커밋·브랜치·병합·되돌리기·원격·PR·rebase 까지 다 익숙해졌어요. 정말 멀리 왔어요.

마지막 시간인 만큼, 오늘은 새로운 큰 개념을 잔뜩 욱여넣기보다 실전에서 진짜로 막히는 순간들을 함께 빠져나와 볼게요. 현업에 처음 나간 신입들이 식은땀을 흘리는 바로 그 장면들이에요. "HEAD 가 이상해졌어요", "커밋이 사라졌어요", "충돌이 산더미라 손도 못 대겠어요" — 오늘 이 셋을 다 빠져나오고 나면, 어지간한 사고엔 안 무서워져요.

그다음엔 git 을 더 편하게 쓰는 심화 도구를 가볍게 둘러보고, 지난 시간 살짝 예고했던 PR 의 초록 체크 표시의 정체도 직접 만들어 체감해봐요. 그리고 마지막엔, 지금까지 쌓은 8개 모듈이 앞으로 배울 모든 과목의 토대가 된다는 이야기로 졸업해요.

텍스트
   오늘의 여정 — 어질러진 저장소를 구조하고, 다음 여정으로

   ① 길 잃은 HEAD 구하기      — detached HEAD 탈출
   ② 사라진 커밋 되살리기      — reflog 구조
   ③ 충돌 지옥에서 빠져나오기  — --abort 안전망
   ④ 내 Git 길들이기          — 별칭과 유용한 설정
   ⑤ 저장소 안의 저장소        — 서브모듈
   ⑥ 큰 파일은 따로            — Git LFS
   ⑦ 초록 체크의 정체          — GitHub Actions 맛보기
   ⑧ 8개의 모듈, 하나의 토대   — 졸업과 다음 여정

①②③은 실전에서 자주 만나는 사고에서 안전하게 빠져나오는 연습이에요. ④⑤⑥에서 git 을 더 편하게 쓰는 도구들을 둘러보고, ⑦에서 CI 라는 걸 처음 체감해요. 그리고 ⑧에서 8개 모듈을 한 줄기로 돌아보며 다음 여정을 준비해요.

💡 오늘 수업의 핵심 — "실전에서 자주 막히는 세 가지 사고(길 잃은 HEAD·사라진 커밋·충돌 지옥)는 git switch·reflog·--abort 로 안전하게 빠져나올 수 있다. git 에선 어지간한 건 되돌릴 수 있다는 안심을 챙기고, 별칭·서브모듈·LFS 같은 심화 도구와 CI 의 첫 감까지 익히면, 8개 모듈로 쌓은 git 실력으로 어떤 과목이든 자신 있게 따라갈 수 있다."

🎯 학습 목표

  • detached HEAD·사라진 커밋·충돌 지옥 같은 흔한 사고에서 git switch·git reflog·--abort 로 안전하게 빠져나옵니다.
  • 별칭(alias)·서브모듈(submodule)·Git LFS 같은 심화 도구가 각각 왜, 언제 쓰이는지 개념을 잡습니다.
  • CI 가 무엇인지 이해하고, GitHub Actions 로 최소 워크플로 하나를 만들어 push 에 초록 체크가 뜨는 걸 체감합니다.

Step 1: "길 잃은 HEAD 구하기 — detached HEAD 탈출"

지난 시간 rebase 를 하면서 커밋이 하나씩 얹히는 걸 봤죠? 그 과정에서, 또는 특정 옛 커밋을 잠깐 구경하러 들어갔을 때, 가끔 detached HEAD(분리된 HEAD) 라는 낯선 상태를 만나요. 이름부터 무섭게 생겼는데, 알고 보면 별거 아니에요. 오늘 정체를 밝히고 빠져나오는 길을 익혀둬요.

먼저 HEAD 가 뭔지 다시 짚을게요. HEAD 는 "지금 내가 어느 커밋 위에 서 있는지" 를 가리키는 표시예요. 평소엔 HEAD 가 main 이나 feature 같은 브랜치 이름표를 거쳐서 커밋을 가리켜요. 그래서 커밋을 새로 하면 브랜치 이름표가 같이 따라 움직이죠.

텍스트
   평소 상태 — HEAD가 브랜치 이름표를 거쳐 커밋을 가리킨다

   HEAD ─ main ─ A───B───C

그런데 git checkout <커밋 해시>git checkout <태그> 처럼 특정 커밋을 직접 찍어서 그리로 가면, HEAD 가 브랜치를 건너뛰고 그 커밋에 직접 붙어버려요. 이게 detached HEAD 예요. 어느 브랜치에도 매여 있지 않은 상태라 "분리됐다" 고 부르는 거예요.

참고로 A-2 에서 익힌 git switch 로도 git switch --detach <해시> 처럼 같은 상태로 갈 수 있어요. 어느 명령이든 옛 커밋을 직접 찍으면 이렇게 돼요.

텍스트
   detached HEAD — HEAD가 브랜치를 거치지 않고 커밋에 직접 붙었다

           main ─ A───B───C
   HEAD ────────── B
              └ 어느 브랜치에도 매여 있지 않은 상태

이 상태가 되면 git 이 친절하게 안내문을 띄워줘요. 빨간 에러가 아니라 안내예요. 겁먹지 마세요.

Bash
git checkout a1b2c3d
# Note: switching to 'a1b2c3d'.
#
# You are in 'detached HEAD' state. You can look around, make
# experimental changes and commit them, and you can discard any
# commits you make in this state without impacting any branches
# by switching back to a branch.

여기서 진짜 조심할 건 딱 하나예요. 이 상태에서 커밋을 새로 만들면, 그 커밋이 어느 브랜치에도 안 붙어요. 그래서 다른 브랜치로 그냥 휙 옮겨가면 방금 만든 커밋이 길을 잃고 떠돌게 돼요(다행히 바로 다음 Step 의 reflog 로 되살릴 수 있지만요). 그러니 빠져나오는 길을 알아두는 게 중요해요.

빠져나오는 길은 상황에 따라 둘이에요.

Bash
# 그냥 구경만 했고 되돌아가면 될 때 — 원래 있던 브랜치로
git switch -

# 여기서 만든 작업을 살리고 싶을 때 — 새 브랜치로 묶어준다
git switch -c experiment

git switch -- 는 "직전에 있던 브랜치" 를 뜻해요(폴더 이동의 cd - 와 똑같다고 보면 돼요). 그냥 옛 커밋을 구경만 했다면 이걸로 원래 main 등으로 깔끔하게 돌아와요. 반대로 detached 상태에서 뭔가 실험하다 "이거 살리고 싶다" 싶으면, git switch -c experiment 로 그 작업에 새 브랜치 이름표를 붙여주면 떠돌던 커밋이 안전하게 묶여요.

⚠️ detached HEAD 는 신입이 "어, 화면이 이상해졌어요" 하고 가장 자주 당황하는 상태예요. 그런데 보다시피 사고가 아니라 그냥 브랜치 없이 커밋 하나에 서 있는 상태일 뿐이에요. git switch - 한 줄이면 원위치라, 알고 나면 하나도 안 무서워요.

🌟 GUI 로는 — VS Code 의 왼쪽 아래 브랜치 표시를 누르면 브랜치 목록이 뜨고, 거기서 원하는 브랜치를 고르면 git switch 와 같아요. detached 상태면 브랜치 표시 위치에 커밋 해시가 보여서 "아, 지금 브랜치에 안 붙어 있구나" 를 눈으로 알 수 있어요.

💡 한 줄 정리

detached HEAD 는 사고가 아니라 HEAD 가 브랜치를 거치지 않고 커밋에 직접 붙은 상태다. 구경만 했으면 git switch - 로 원래 브랜치로 돌아오고, 거기서 만든 작업을 살리려면 git switch -c 새브랜치 로 새 브랜치에 묶어주면 된다.

🙋 학생 질문 — "튜터님, 그럼 옛날 커밋은 구경하면 안 되는 건가요?"

전혀요. 구경은 얼마든지 해도 돼요. detached HEAD 는 "옛 커밋을 들여다보러 들어간" 정상적인 상태예요.

git checkout <해시> 로 옛 커밋에 들어가서 그때의 파일이 어땠는지 둘러보는 건 아주 흔한 일이에요. 예를 들어 "3주 전엔 이 파일이 어떻게 생겼더라?" 를 확인하고 싶을 때 그리로 잠깐 다녀오는 거죠.

조심할 건 딱 하나, 거기서 커밋을 새로 만들지 않는 한 아무 문제 없다는 거예요. 구경이 끝나면 git switch - 로 원래 브랜치에 돌아오면 그만이에요. 혹시 거기서 뭔가 만들었고 살리고 싶다면, 옮겨가기 전에 git switch -c 로 새 브랜치에 묶어두면 되고요.


Step 2: "사라진 커밋 되살리기 — reflog 구조"

이번엔 가장 든든한 안심 장치예요. 지난 시간에 "잘못된 force-push 로 동료 커밋이 사라져도 reflog 로 되살린다" 고 예고했죠? A-3 에서 잠깐 만난 그 reflog 를, 오늘 실제 구조 작업에 써봐요.

흔한 사고 하나를 일부러 만들어볼게요. 커밋을 세 개 올려둔 상태에서, 실수로 git reset --hard HEAD~3 을 쳤다고 해봐요. 최근 커밋 세 개가 통째로 사라진 것처럼 보여요. git log 를 봐도 안 나와요. 신입이라면 여기서 등에 식은땀이 흐르죠.

Bash
git reset --hard HEAD~3
# HEAD is now at 9a8b7c6 프로젝트 초기 설정

git log --oneline
# 9a8b7c6 (HEAD -> main) 프로젝트 초기 설정
#  ← 방금까지 있던 커밋 세 개가 안 보인다!

여기서 안심하세요. git 에선 한 번 커밋한 건 거의 사라지지 않아요. 눈앞의 git log 에서 안 보일 뿐, git 은 여러분의 HEAD 가 지나온 모든 발자국을 따로 기록해둬요. 그 발자국 기록을 보여주는 명령이 바로 git reflog 예요.

Bash
git reflog
# 9a8b7c6 HEAD@{0}: reset: moving to HEAD~3
# e4f5a6b HEAD@{1}: commit: 좋아요 기능 추가      ← 사라진 줄 알았던 커밋
# c3d4e5f HEAD@{2}: commit: 댓글 기능 추가
# b2c3d4e HEAD@{3}: commit: 프로필 화면 추가
# 9a8b7c6 HEAD@{4}: commit: 프로젝트 초기 설정

보이세요? reset 으로 사라진 줄 알았던 커밋들이 HEAD@{1}, HEAD@{2} 에 해시와 함께 멀쩡히 남아 있어요. 이제 사라지기 직전 상태인 HEAD@{1} 의 해시로 되돌리기만 하면 돼요.

Bash
# 사라지기 직전 커밋의 해시로 되돌린다 — 복구 완료!
git reset --hard e4f5a6b

git log --oneline
# e4f5a6b (HEAD -> main) 좋아요 기능 추가   ← 되살아났다
# c3d4e5f 댓글 기능 추가
# b2c3d4e 프로필 화면 추가
# 9a8b7c6 프로젝트 초기 설정

세 커밋이 그대로 돌아왔어요. 혹시 되돌리는 게 부담스러우면, 덮어쓰지 않고 새 브랜치로 따로 빼낼 수도 있어요.

Bash
# 사라진 커밋들을 rescue 라는 새 브랜치로 안전하게 빼낸다
git branch rescue e4f5a6b
텍스트
   git reflog — HEAD가 거쳐온 모든 발자국이 시간순으로 남는다

   HEAD@{0}  reset: moving to HEAD~3    지금 위치(사고 직후)
   HEAD@{1}  commit: 좋아요 기능 추가     여기로 되돌리면 복구
   HEAD@{2}  commit: 댓글 기능 추가
   HEAD@{3}  commit: 프로필 화면 추가
             └ 사라진 게 아니라 발자국에 그대로 남아 있다

그럼 지난 시간 예고한 동료 커밋 복구는요? 원리가 똑같아요. reflog내 컴퓨터에 있는 내 발자국 기록이에요. 그래서 누군가 잘못된 force-push 로 원격의 커밋을 덮어써도, 그 커밋을 받아둔 사람의 로컬 reflog 엔 발자국이 남아 있어서 되살릴 수 있어요. "force-push 한 방에 동료 작업이 영영 날아간다" 는 공포가 생각만큼 절대적이지 않은 이유가 바로 이거예요.

⚠️ 단 reflog 의 발자국도 영원하진 않아요. git 이 한참 지난 발자국은 청소하거든요. 그래도 "방금 사고 친 걸 되살리는" 용도로는 거의 항상 충분해요. 사고 나면 당황하지 말고 가장 먼저 git reflog 를 떠올리세요.

💡 한 줄 정리

reset 이나 잘못된 조작으로 커밋이 사라진 것처럼 보여도, git reflog 는 HEAD 가 지나온 모든 발자국을 해시와 함께 보여준다. 사라지기 직전 해시로 git reset --hard 하거나 git branch 로 빼내면 되살아난다. git 에선 어지간한 건 되돌릴 수 있다.

🙋 학생 질문 — "튜터님, reflog 랑 log 는 뭐가 달라요?"

이름이 비슷해서 헷갈리기 딱 좋아요. 둘은 보여주는 게 완전히 달라요.

git log지금 이 브랜치의 공식 역사를 보여줘요. 커밋들이 부모-자식으로 이어진 족보 같은 거죠. 그래서 reset 으로 커밋을 떼어내면, 그 커밋은 족보에서 빠져서 git log 에 안 나와요.

git reflog내 HEAD 가 언제 어디로 움직였는지의 이동 기록이에요. 커밋했든, 브랜치를 옮겼든, reset 했든, HEAD 가 움직인 모든 순간이 시간순으로 찍혀요. 그래서 족보에서 빠진 커밋이라도 "그때 거기 있었다" 는 발자국이 남아 있는 거예요.

한마디로 log 는 "현재의 공식 역사", reflog 는 "내가 거쳐온 발자국 전부" 예요. 사고 복구엔 reflog 가 생명줄이에요. 그리고 reflog 는 내 컴퓨터에만 있는 기록이라, 다른 사람과 공유되지 않아요.


Step 3: "충돌 지옥에서 빠져나오기 — --abort 안전망"

마지막 트러블슈팅은 충돌(conflict) 이에요. A-2 에서 충돌을 한 줄 한 줄 해결하는 법은 이미 배웠죠. 오늘은 관점이 조금 달라요. "해결" 이 아니라 "탈출" 이에요. 충돌이 너무 많아 손도 못 댈 만큼 꼬였을 때, 안전하게 원점으로 돌아오는 비상구를 알려드릴게요.

먼저 충돌이 왜 무섭게 느껴지는지부터 공감할게요. git mergegit pull 을 했는데 화면 가득 CONFLICT 가 뜨고, 파일마다 <<<<<<< 표시가 들어가 있으면, 어디서부터 손대야 할지 막막하죠. 신입 때 이 화면 보고 얼어붙는 사람 정말 많아요. 그런데 여기 비상구가 있다는 걸 알면 마음이 한결 편해져요.

Bash
git merge feature
# Auto-merging notes.txt
# CONFLICT (content): Merge conflict in notes.txt
# CONFLICT (content): Merge conflict in todo.txt
# Automatic merge failed; fix conflicts and then commit the result.

충돌이 두세 개면 차분히 하나씩 해결하면 돼요(A-2 에서 배운 그대로요). 그런데 충돌이 수십 개라 도저히 감당이 안 되거나, 뭘 잘못 건드린 것 같아 불안하면, --abort 로 병합을 시도하기 직전 상태로 통째로 되돌릴 수 있어요.

Bash
# 병합 도중 — 없던 일로 하고 깨끗한 원점으로
git merge --abort

# rebase 도중이면 (지난 시간에 배운 그 안전장치)
git rebase --abort
텍스트
   충돌 지옥에서 탈출하기

   [충돌 한가운데]  ──  git merge --abort  ──  [병합 시도 직전]
   손도 못 댈 만큼 꼬임                          아무 일 없던 깨끗한 상태

git merge --abort 한 줄이면, 충돌 표시가 들어가 있던 파일들이 전부 충돌 전 모습으로 돌아가요. "일단 멈추고 원점에서 다시" 가 되는 거예요. 그래서 충돌이 무서울수록 이 명령을 먼저 떠올리면 좋아요. 망쳐도 되돌아올 곳이 있다는 걸 알면, 오히려 차분하게 해결을 시도하게 되거든요.

그럼 언제 해결하고 언제 abort 할까요? 간단한 기준은 이래요. 충돌이 내가 방금 만진 파일 몇 개에 몰려 있으면 그냥 해결하세요. 반대로 수십 개 파일에 퍼져 있거나, 내가 안 건드린 파일까지 충돌나면, 보통 "오래된 브랜치를 너무 늦게 합치려다" 생긴 일이에요. 이럴 땐 abort 하고, 브랜치를 최신 상태로 맞춘 뒤(git pull 이나 git rebase) 작게 나눠 다시 합치는 게 훨씬 편해요.

사실 가장 좋은 건 충돌을 애초에 작게 만드는 거예요. 현업에서 충돌로 고생하는 사람과 안 하는 사람의 차이는 대부분 습관에서 갈려요.

충돌을 키우는 습관 충돌을 줄이는 습관
브랜치를 몇 주씩 안 합치고 방치 짧게 작업하고 자주 합치기
커밋을 거대하게 한 번에 작게 자주 커밋하기
남이 작업 중인 파일을 같이 건드림 작업 전 팀과 영역 나누기
main 변화를 모르고 오래 떨어져 작업 수시로 git pull최신 맞추기

⚠️ 충돌은 잘못이 아니라, 여럿이 같은 코드를 동시에 고치면 자연스럽게 생기는 일이에요. 협업하는 한 충돌은 계속 만나요. 중요한 건 충돌을 안 만나는 게 아니라, 만났을 때 당황하지 않고 해결하거나(add 후 commit), 안 되면 안전하게 빠져나오는(--abort) 거예요.

🌟 GUI 로는 — VS Code 의 Source Control 패널에서 충돌난 파일을 누르면 "현재 변경 수락 / 들어온 변경 수락 / 둘 다 수락" 버튼이 줄별로 떠서 클릭으로 해결할 수 있어요. 병합을 통째로 취소하는 abort 도 메뉴에 있지만, 이건 git merge --abort 한 줄이 가장 확실하고 빨라요.

💡 한 줄 정리

충돌이 손도 못 댈 만큼 꼬였을 땐 git merge --abort(또는 git rebase --abort)로 시도 직전의 깨끗한 상태로 안전하게 돌아올 수 있다. 충돌은 잘못이 아니라 협업의 자연스러운 일부이며, 작게 자주 커밋하고 자주 합치는 습관이 충돌을 애초에 줄여준다.

🙋 학생 질문 — "튜터님, abort 하면 제가 한 작업도 다 사라지는 거 아니에요?"

좋은 걱정이에요. 결론부터 말하면, abort 는 내 커밋을 지우지 않아요.

git merge --abort 가 되돌리는 건 "방금 시작한 병합 시도" 뿐이에요. 병합을 시작하기 전에 내가 이미 커밋해둔 작업들은 그대로 안전하게 남아 있어요. 즉 "두 브랜치를 합치려던 동작"만 취소되고, 각 브랜치의 커밋은 손대지 않아요.

그러니 충돌 화면에서 막막할 때 abort 하는 걸 두려워하지 마세요. 내가 커밋해둔 작업은 그대로 있고, 단지 합치기 전 상태로 돌아갈 뿐이에요. 다만 충돌난 파일에서 아직 커밋 안 한 채 수동으로 편집하던 내용은 사라질 수 있으니, abort 전에 정말 합칠지만 한 번 더 생각하면 돼요.


Step 4: "내 Git 길들이기 — 별칭과 유용한 설정"

무서운 사고 셋을 빠져나왔으니, 이번엔 잠깐 숨 돌리는 가벼운 시간이에요. 매일 쓰는 git 을 나에게 편하게 길들이는 법을 알려드릴게요. 자주 쓰는 도구일수록 작은 설정 하나로 훨씬 쾌적해지거든요.

먼저 별칭(alias) 이에요. 자주 치는 긴 명령에 짧은 별명을 붙이는 거예요. 예를 들어 커밋 그래프를 보려고 매번 git log --oneline --graph --all 을 치는 건 번거롭죠. 이걸 git lg 한 단어로 줄일 수 있어요.

Bash
# 자주 쓰는 긴 명령에 짧은 별명을 붙인다 (--global 이면 모든 저장소에서)
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --all"

# 이제 짧게 쓸 수 있다
git st          # git status 와 같다
git lg          # git log --oneline --graph --all 과 같다

별칭은 git 명령 자체를 바꾸는 게 아니라 내 컴퓨터에만 추가되는 단축키예요. 그래서 마음껏 만들어도 안전해요. 다만 너무 많이 만들면 다른 사람 컴퓨터(별칭 없는 환경)에서 헤매거나, 시간이 지나 내가 만든 별칭을 잊어버리기도 해요. 그래서 보통은 정말 자주 쓰는 서너 개만 만드는 걸 권해요.

다음은 알아두면 편한 유용한 설정 몇 가지예요. 모두 git config --global 로 한 번만 해두면 쭉 적용돼요.

Bash
# 새 브랜치를 push 할 때 -u 를 매번 안 붙여도 자동으로 연결해준다
git config --global push.autoSetupRemote true

# 기본 에디터를 VS Code 로 (커밋 메시지·rebase 화면이 VS Code 로 열린다)
git config --global core.editor "code --wait"

# 지금까지 한 전역 설정을 한눈에 확인
git config --global --list

특히 첫 줄 push.autoSetupRemote true 는 진짜 편해요. A-4 에서 새 브랜치를 처음 올릴 때 git push -u origin 브랜치명 으로 -u 를 붙였던 거 기억나세요? 이 설정을 켜두면 그냥 git push 만 해도 git 이 알아서 원격 브랜치를 연결해줘요. 매번 -u 를 안 붙여도 되는 거죠.

이 모든 전역 설정은 사실 ~/.gitconfig 라는 파일 하나에 텍스트로 쌓여요. git config 명령이 이 파일을 대신 고쳐주는 거예요. 익숙해지면 이 파일을 직접 열어 편집해도 되고요.

설정 말고, 알아두면 좋은 명령 셋도 여기서 짚고 갈게요. 지금까지 git log 로 역사를 훑어왔다면, 이건 한 걸음 더 들어가 코드의 사연을 추적하는 도구예요. A-1 에서 "이 한 줄을 누가 바꿨는지는 심화에서" 라고 미뤄둔 그 git blame 이 바로 여기 있어요.

Bash
git blame README.md       # 파일의 각 줄을 마지막으로 바꾼 사람·커밋을 줄 단위로
git show a1b2c3d           # 그 커밋 하나가 정확히 무엇을 바꿨는지 펼쳐 보기
git log --grep "로그인"     # 커밋 메시지에 '로그인' 이 든 커밋만 골라 찾기

git blame 은 누구를 탓하려는 게 아니라, "이 줄이 왜 이렇게 됐을까" 의 맥락을 찾는 도구예요. 신입이 낯선 프로젝트에 투입돼 한 줄의 사연이 궁금할 때 가장 먼저 찾게 되는 명령이에요.

🌟 GUI 로는 — 별칭은 터미널 명령을 줄이는 도구라 CLI 전용이에요. GUI 도구(GitHub Desktop·VS Code)는 자체 버튼·단축키가 따로 있어서 별칭이 필요 없어요. 그래서 이 Step 은 GUI 대응 없이 터미널로만 익혀요.

💡 한 줄 정리

git config --global alias.단축어 "긴 명령" 으로 자주 쓰는 명령에 짧은 별명을 붙이고, push.autoSetupRemote·core.editor 같은 유용한 설정으로 git 을 편하게 길들일 수 있다. 모든 전역 설정은 ~/.gitconfig 파일 하나에 쌓이며, git config --global --list 로 확인한다.

🙋 학생 질문 — "튜터님, 별칭을 만들면 다른 사람도 제 저장소에서 쓸 수 있나요?"

아니에요. 별칭은 내 컴퓨터에만 저장돼요(--global 이면 내 계정의 모든 저장소에서, 그 저장소에만 하면 그 저장소에서). 저장소를 누군가에게 push 하거나 공유해도 내 별칭은 따라가지 않아요.

별칭은 ~/.gitconfig(또는 저장소의 .git/config)에 저장되는 개인 환경 설정이거든요. 커밋이나 브랜치처럼 저장소 역사에 들어가는 게 아니에요. 그래서 동료의 컴퓨터엔 동료가 직접 만든 별칭만 있어요.

그래서 팀에서는 보통 "이런 별칭 쓰면 편하다" 를 문서나 메신저로 공유하고, 각자 자기 컴퓨터에 설정해요. 별칭 자체를 강제로 똑같이 맞출 필요는 없고, 각자 편한 대로 쓰면 돼요.


Step 5: "저장소 안의 저장소 — 서브모듈"

이제 큰 프로젝트에서 가끔 마주치는 도구 둘을 가볍게 둘러볼게요. 깊이 다루진 않고, "이런 게 있구나, 언제 쓰는 거구나" 하는 첫 감만 잡는 시간이에요. 첫 번째는 서브모듈(submodule) 이에요.

서브모듈은 한마디로 내 저장소 안에 다른 git 저장소를 통째로 품는 기능이에요. 이상하게 들리죠? 상황을 하나 그려볼게요. 우리 팀이 여러 프로젝트에서 똑같이 쓰는 공용 코드(예: 로그인 모듈, 공통 디자인 도구 모음) 가 있다고 해봐요. 이걸 프로젝트마다 복사해 붙이면, 공용 코드가 바뀔 때마다 모든 프로젝트를 일일이 고쳐야 해요.

서브모듈을 쓰면, 그 공용 코드를 자기만의 독립된 저장소로 따로 두고, 각 프로젝트는 "그 저장소의 특정 버전을 여기에 끼워 쓴다" 고 연결만 해요.

Bash
# 다른 저장소를 내 프로젝트의 libs/auth 위치에 서브모듈로 끼운다
git submodule add https://github.com/our-team/auth-module libs/auth

여기서 핵심은, 내 저장소가 그 공용 코드의 파일 전부를 복사해 갖는 게 아니라, "그 저장소의 어느 커밋을 쓰는지" 라는 연결 정보(포인터)만 기록한다는 거예요. 그림으로 보면 이래요.

텍스트
   서브모듈 — 내 저장소는 '연결 정보(포인터)'만 갖는다

   [내 프로젝트 저장소]
     ├── src/
     ├── libs/auth  ─────  [auth-module 저장소의 커밋 a1b2c3d]
     └── .gitmodules        └ "이 버전을 쓴다" 는 포인터만 기록

편리한 만큼 조심할 점도 있어요. 서브모듈은 자기만의 커밋 역사를 따로 가져서, 공용 코드를 고치면 그쪽 저장소에서 한 번 커밋하고, 내 프로젝트에서 "새 버전을 쓰겠다" 고 또 커밋해야 해요. 또 이 프로젝트를 clone 하는 동료는 서브모듈 내용까지 받으려면 옵션을 하나 더 붙여야 해요.

Bash
# 서브모듈까지 한 번에 받으며 clone 한다
git clone --recurse-submodules https://github.com/our-team/main-project

이 정도가 서브모듈의 첫 감이에요. "여러 프로젝트가 공유하는 코드를 독립 저장소로 두고 포인터로 연결한다" 만 기억하면 충분해요. 실제로 운영하다 보면 손이 좀 가는 도구라, 깊은 사용법은 정말 필요해질 때 그때 익혀도 늦지 않아요.

💡 한 줄 정리

서브모듈은 내 저장소 안에 다른 git 저장소를 포인터로 연결해 품는 기능이다. 여러 프로젝트가 공유하는 공용 코드를 독립 저장소로 두고 특정 버전만 끼워 쓸 때 유용하며, 파일을 복사하는 게 아니라 "어느 커밋을 쓰는지" 만 기록한다.

🙋 학생 질문 — "튜터님, 그냥 공용 코드를 복사해 붙이면 안 되나요?"

복사해 붙여도 당장은 돌아가요. 다만 시간이 지나면 문제가 생겨요.

공용 코드를 다섯 개 프로젝트에 복사해뒀다고 해봐요. 그 공용 코드에서 버그를 하나 고치면, 똑같은 수정을 다섯 군데에 일일이 다시 붙여야 해요. 빠뜨리는 프로젝트가 생기면, 어떤 곳은 고쳐졌고 어떤 곳은 안 고쳐진 채로 제각각 달라져요.

서브모듈은 공용 코드를 한 곳(독립 저장소)에만 두니까, 거기서 한 번 고치고 각 프로젝트는 "새 버전을 쓰겠다" 고 포인터만 옮기면 돼요. 원본이 하나라 제각각 달라질 일이 없는 거죠. 물론 관리할 게 늘어나는 단점도 있어서, 공유 코드가 정말 많고 자주 바뀔 때 빛을 봐요.


Step 6: "큰 파일은 따로 — Git LFS"

둘러볼 두 번째 도구는 Git LFS 예요. 이걸 이해하려면 먼저 "git 이 어떤 파일에 약한가" 를 알아야 해요. 그 약점을 메우려고 나온 도구거든요.

지금까지 우리가 git 으로 다룬 건 대부분 글자로 된 파일(텍스트) 이었어요. 코드, 메모, 설정 파일 같은 거요. git 은 이런 텍스트 파일에 아주 강해요. 한 글자만 바뀌어도 "어디가 달라졌는지" 를 똑똑하게 가려내서 효율적으로 저장하거든요(git diff 가 그래서 가능했죠).

문제는 큰 이진 파일(binary) 이에요. 영상, 고화질 이미지, 디자인 원본(PSD), 머신러닝 모델 파일 같은 거요. 이런 파일은 git 이 "어디가 달라졌는지" 를 가려낼 수가 없어서, 조금만 바뀌어도 파일 전체를 통째로 새로 저장해요. 100MB 짜리 영상을 열 번 수정하면, 저장소가 1GB 가까이 부풀어 올라요. 그러면 clone 도 한참 걸리고, 저장소가 점점 무거워져요.

텍스트
   큰 이진 파일을 git에 그냥 넣으면 — 수정할 때마다 통째로 쌓인다

   video.mp4 v1 (100MB) ─┐
   video.mp4 v2 (100MB) ─┤
   video.mp4 v3 (100MB) ─┼── 저장소가 300MB+로 부풀어 오른다
   ...                   ─┘

Git LFS(Large File Storage, 대용량 파일 저장소) 가 이걸 풀어줘요. 아이디어는 단순해요. 큰 파일의 실물은 별도의 LFS 저장 공간에 두고, git 저장소엔 "그 파일은 저기 있다" 는 작은 텍스트 포인터만 넣는 거예요. 그러면 git 저장소 자체는 가볍게 유지돼요.

텍스트
   Git LFS — git에는 작은 포인터만, 실물은 LFS 저장소에 따로

   [git 저장소]                    [LFS 저장 공간]
     video.mp4  (포인터, 130바이트) ── 실제 100MB 영상
     └ 저장소는 가볍게 유지된다

쓰는 법도 간단해요. 한 번 설정해두면, 지정한 종류의 파일은 자동으로 LFS 가 처리해요.

Bash
# LFS 를 한 번 켜고 (이 컴퓨터에 한 번)
git lfs install

# 어떤 파일을 LFS로 다룰지 지정한다 (.psd 파일 전부)
git lfs track "*.psd"
# → .gitattributes 파일에 규칙이 기록된다. 이걸 커밋하면 팀 전체에 적용된다

언제 필요하냐면, 디자인 원본을 함께 관리하는 팀, 영상·이미지 같은 미디어가 많은 프로젝트, 큰 데이터셋이나 모델 파일을 다루는 경우예요. 코드만 다루는 프로젝트라면 LFS 없이도 충분하고요. "git 이 큰 이진 파일에 약하고, LFS 가 그 짐을 따로 들어준다" 만 기억하면 돼요.

💡 한 줄 정리

git 은 텍스트엔 강하지만 큰 이진 파일(영상·이미지·모델) 은 수정할 때마다 통째로 저장해 저장소를 무겁게 만든다. Git LFS 는 실물을 별도 저장 공간에 두고 git 엔 작은 포인터만 넣어 저장소를 가볍게 유지한다. git lfs track "*.psd" 로 다룰 파일을 지정한다.

🙋 학생 질문 — "튜터님, 그냥 큰 파일은 git 에 안 올리면 안 되나요?"

그것도 한 가지 방법이고, 실제로 많이 써요. 큰 파일을 .gitignore 로 빼두고 클라우드 드라이브 같은 곳에 따로 두는 거죠. A-3 에서 배운 .gitignore 기억나시죠?

다만 그러면 그 파일의 버전 역사가 사라져요. "지난주 디자인 원본으로 되돌리고 싶다" 거나 "이 영상이 언제 누구에 의해 어떻게 바뀌었나" 를 git 으로 추적할 수 없게 돼요. 코드와 디자인 원본의 버전이 따로 놀게 되고요.

Git LFS 는 "큰 파일도 git 의 버전 관리 안에 두되, 저장소는 무겁지 않게" 라는 절충안이에요. 그래서 큰 파일도 버전을 함께 추적해야 할 때 LFS 를 쓰고, 그냥 보관만 하면 되는 파일은 .gitignore 로 빼는 식으로 나눠요.


Step 7: "초록 체크의 정체 — GitHub Actions 맛보기"

드디어 지난 시간에 살짝 설레게 예고했던 그것이에요. A-5 에서 PR 을 올리면 초록색 체크 표시가 뜨는 걸 봤죠? 그게 대체 뭐고 어떻게 동작하는지, 오늘 아주 간단한 걸 직접 만들어 체감해봐요.

먼저 그 바탕에 깔린 CI 라는 개념부터 짚을게요. CI 는 Continuous Integration(지속적 통합)의 줄임말인데, 어려운 말 같지만 뜻은 단순해요. 코드를 올릴 때마다(push 할 때마다), 자동으로 검사를 돌려서 문제를 일찍 잡는 것이에요. 사람이 매번 "테스트 돌렸나? 빌드 되나?" 를 손으로 확인하는 대신, 기계가 자동으로 해주는 거죠.

왜 필요할까요? 팀으로 일하면 누군가 깨진 코드를 main 에 올릴 수 있어요. 그걸 다음 날 다른 사람이 받아서 한참 헤매다 발견하면 너무 늦죠. CI 는 코드가 올라오는 그 순간 자동으로 검사해서, 깨진 코드가 합쳐지기 전에 빨간불을 켜줘요. PR 의 그 초록 체크가 바로 "자동 검사를 통과했다" 는 신호예요.

GitHub 에서 이 자동 검사를 돌려주는 기능이 GitHub Actions 예요. 사용법의 핵심은 이거예요. 저장소 안 .github/workflows/ 라는 폴더에 워크플로(workflow) 파일 을 하나 두면, 정해둔 사건(예: push)이 일어날 때마다 GitHub 이 깨끗한 가상 컴퓨터를 하나 띄워서 내가 적어둔 작업을 자동으로 실행해줘요.

말로만 들으면 막연하니, 세상에서 가장 간단한 워크플로를 하나 만들어볼게요.

YAML
# .github/workflows/ci.yml
name: CI
on: push
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - run: echo "검사 통과! 🟢"

한 줄씩 읽어볼게요. on: push 는 "push 가 일어나면 실행해라", runs-on: ubuntu-latest 는 "우분투 리눅스 컴퓨터를 하나 띄워서", stepsrun 은 "이 명령을 실행해라" 예요. 지금은 그냥 메시지 하나 출력하는 게 전부지만, 이걸 저장소에 commit 하고 push 하면 마법 같은 일이 벌어져요.

Bash
git add .github/workflows/ci.yml
git commit -m "CI: 첫 워크플로 추가"
git push

push 하고 나서 GitHub 저장소의 Actions 탭에 들어가 보면, 방금 그 워크플로가 자동으로 돌아간 기록이 보여요. 그리고 커밋 옆, PR 을 올리면 그 안에 초록색 체크 표시가 떠요. 우리가 늘 보던 그 초록 체크가, 바로 이렇게 만들어지는 거였어요.

팀에선 이 초록 체크를 "통과해야만 합치기 버튼이 열리게"(필수 상태 체크) 보호 브랜치에 걸어두기도 해요. A-5 에서 본 "승인을 받아야 합칠 수 있다" 는 보호 장치 위에, "자동 검사까지 통과해야 한다" 는 조건이 하나 더 얹히는 거죠. 그 본격 설정도 인프라 과목의 몫이에요.

텍스트
   push 하면 — GitHub Actions가 자동으로 워크플로를 돌린다

   git push ── [GitHub] ── 가상 컴퓨터에서 워크플로 실행
                                      │
                                      ├ 통과  🟢 초록 체크
                                      └ 실패  🔴 빨간 X (합치기 전에 경고)

자, 여기서 딱 멈출게요. 지금 우리가 만든 건 "메시지 하나 출력하는" 장난감이지만, 실제 현업의 워크플로는 여기서 코드를 받아(checkout) 빌드하고, 테스트를 전부 돌리고, 통과하면 서버에 자동 배포까지 해요. 그 본격적인 자동화 파이프라인을 만드는 법은 이 과목의 범위를 넘어서, 인프라 과목에서 제대로 배워요. 오늘은 "아, 초록 체크가 이렇게 뜨는 거구나" 하는 첫 감까지만이에요.

한 가지 용어만 더 얹고 넘어갈게요. 한 발 더 나가면 GitOps 라는 방식도 있어요. "git 에 합쳐진 내용(main)을 유일한 기준으로 삼아, 서버의 상태를 그 git 내용에 자동으로 맞추는" 배포 방식이에요. 이름만 기억해두세요. 이것도 자동 배포의 영역이라 인프라 과목의 몫이에요.

⚠️ Actions 와 CI/CD 는 그 자체로 거대한 세계라, 깊이 들어가면 끝이 없어요. 이 과목에서는 "코드의 역사를 다루고 사람이 협업하는 법" 까지가 우리 몫이에요. 그 협업 결과를 받아 자동으로 빌드·테스트·배포하는 기계 파이프라인은 다음 과목들의 주제예요. 오늘은 그 입구를 살짝 들여다본 것만으로 충분해요.

🌟 GUI 로는 — GitHub 저장소의 Actions 탭에서 "set up a workflow yourself" 를 누르면 웹 화면에서 바로 워크플로 파일을 만들 수 있어요. 다만 결국 이 파일도 저장소에 commit 되는 텍스트라, 우리가 한 것처럼 직접 만들어 push 하는 흐름을 알아두는 게 좋아요.

💡 한 줄 정리

CI 는 push 할 때마다 자동으로 검사를 돌려 문제를 일찍 잡는 방식이고, GitHub Actions 는 .github/workflows/ 의 워크플로 파일로 이를 실행한다. PR 의 초록 체크가 바로 그 자동 검사 통과 신호다. 단 본격적인 빌드·테스트·배포 파이프라인과 GitOps 는 인프라 과목의 영역이다.

🙋 학생 질문 — "튜터님, 이 가상 컴퓨터는 누가 띄워주고, 돈이 드나요?"

좋은 현실적인 질문이에요. 그 가상 컴퓨터(러너, runner)는 GitHub 이 알아서 띄워주고 검사 끝나면 없애요. 내가 서버를 따로 준비할 필요가 없어요.

비용은, 공개(public) 저장소는 기본적으로 무료예요. 그래서 오픈소스 프로젝트들이 마음껏 자동 검사를 돌려요. 비공개(private) 저장소는 매달 일정량까지 무료고, 그 이상 쓰면 사용한 시간만큼 과금돼요. 학습용 연습 저장소 수준에서는 거의 무료 범위 안에서 충분히 다 써볼 수 있어요.

그래서 부담 없이 한번 만들어보세요. 워크플로 파일 하나 push 하고 Actions 탭에서 초록 체크가 뜨는 걸 직접 보면, "CI 가 이런 거구나" 가 확 와닿아요.


Step 8: "8개의 모듈, 하나의 토대 — 졸업과 다음 여정"

자, 이제 정말 마지막이에요. 새 명령은 없어요. 지금까지 우리가 함께 걸어온 8개 모듈을 한 줄기로 돌아보고, 여기서 어디로 가는지를 짚을게요.

처음 A-1 에서 우리는 검은 터미널 창 앞에서 git init 으로 빈 폴더를 저장소로 만들고, addcommit 으로 내 코드의 첫 역사를 남겼어요. A-2 에서 브랜치라는 평행 우주로 가지를 쳐서 실험하고 다시 합치는 법을, A-3 에서 .gitignore 와 되돌리기로 실수를 안전하게 수습하는 법을 익혔죠. 여기까지가 내 컴퓨터 안에서 혼자 git 을 다루는 힘이었어요.

그다음 A-4 에서 GitHub 라는 원격으로 나가 내 코드를 세상에 올리고, A-5 에서 Pull Request 와 코드 리뷰로 여럿이 함께 코드를 모으는 법을, A-6 에서 GitHub Flow 같은 팀의 협업 약속을 배웠어요. 그리고 A-7 에서 rebase 로 역사를 깔끔하게 정리하는 고급 기술까지 손에 넣었죠. 오늘 A-8 에선 실전에서 막히는 사고를 빠져나오고, 심화 도구와 CI 의 첫 감까지 챙겼고요.

텍스트
   8개 모듈, 하나의 토대

   로컬 (혼자)        원격 (협업)         심화 (실무)
   A-1 ─ A-2 ─ A-3 ─ A-4 ─ A-5 ─ A-6 ─ A-7 ─ A-8
    │                                          │
    └─────────── 코드의 역사 + 협업 ───────────┘
                        │
                        
         앞으로 배울 모든 과목의 실습이
         이 git 위에서 굴러간다

여기서 가장 중요한 한마디를 할게요. 이제 여러분은 어떤 언어, 어떤 프레임워크를 배우든 든든해요. 왜냐하면 자바를 배우든 파이썬을 배우든, 리액트로 화면을 만들든 서버를 만들든, 커밋하고 브랜치를 따고 PR 을 올리는 방법은 똑같기 때문이에요. git 은 모든 개발 과목의 밑에 깔리는 토대예요.

앞으로 다른 과목에서 코드를 작성하면, 오늘까지 배운 그대로 하면 돼요. 연습한 내용을 브랜치에서 작업하고, 커밋으로 역사를 남기고, GitHub 에 올려 PR 로 정리하세요. 처음 A-1 에서 식은땀의 주인공이던 git 이, 이제는 여러분의 가장 든든한 동료가 됐어요. 정말 수고 많았어요.

💡 한 줄 정리

A-1 부터 A-8 까지, 로컬에서 혼자 다루는 힘(A-1~A-3)·원격 협업(A-4~A-6)·실무 심화(A-7~A-8)를 한 줄기로 익혔다. 어떤 언어·프레임워크를 배우든 커밋·브랜치·PR 은 똑같으니, 앞으로 모든 과목의 실습을 이 git 위에서 자신 있게 진행할 수 있다.

🙋 학생 질문 — "튜터님, 이제 git 은 다 배운 건가요? 더 공부할 게 있을까요?"

이 과목에서 다룬 걸로 실무에서 매일 쓰는 git 의 90% 이상을 손에 넣었어요. 커밋·브랜치·병합·되돌리기·원격·PR·rebase·트러블슈팅까지 왔으니, 어떤 팀에 가도 git 때문에 막히는 일은 거의 없을 거예요.

더 깊이 가고 싶다면, 오늘 맛본 것들의 본격편이 기다려요. GitHub Actions 로 진짜 빌드·테스트·배포 파이프라인을 짜는 건 인프라 과목에서, 서브모듈·LFS 의 깊은 운용은 정말 필요해질 때 그때 찾아보면 돼요. git 의 내부 동작 원리(객체·해시 구조)가 궁금해지면 그것도 좋은 다음 공부고요.

하지만 지금 당장은, 배운 걸 실제로 많이 써보는 게 최고의 공부예요. 다음 과목에서 코드를 짤 때마다 커밋하고 push 하다 보면, 오늘 배운 게 진짜 손에 붙어요. 축하해요, 졸업이에요!


마무리

8개 모듈의 여정이 여기서 끝나요. 오늘은 실전에서 만나는 사고를 빠져나오는 법, git 을 편하게 길들이는 도구들, 그리고 CI 의 첫 감까지 챙겼어요. 무엇보다 "git 에선 어지간한 건 되돌릴 수 있다" 는 안심을, 이제 명령으로 증명할 수 있게 됐어요. 처음의 그 막막함에서 정말 멀리 왔어요.

오늘 배운 핵심 세 가지

  • 💡 하나 — 흔한 사고는 안전하게 빠져나올 수 있다. 길 잃은 HEAD 는 git switch -, 사라진 커밋은 git reflog, 손 못 댈 충돌은 --abort 로 원점으로. git 에선 어지간한 건 되돌릴 수 있다는 안심이 가장 큰 무기다.
  • 💡 둘 — git 을 내게 맞게 길들이고, 심화 도구를 안다. 별칭과 유용한 설정으로 매일의 git 을 편하게 만들고, 서브모듈(저장소 안의 저장소)·Git LFS(큰 파일 따로)가 언제 쓰이는지 개념을 잡았다.
  • 💡 셋 — PR 의 초록 체크는 CI 가 만든다. GitHub Actions 로 push 마다 자동 검사를 돌릴 수 있다. 단 본격적인 빌드·배포 파이프라인은 다음 과목의 몫이다.

다음 여정 예고

이 과목은 여기서 졸업이지만, 사실 진짜 여정은 지금부터예요. 앞으로 어떤 과목을 배우든, 그 코드는 전부 오늘까지 익힌 git 위에서 굴러가요. 자바·파이썬으로 첫 프로그램을 만들 때도, 리액트로 화면을 그릴 때도, 서버와 데이터베이스를 다룰 때도, 여러분은 자연스럽게 브랜치를 따고 커밋을 남기고 PR 을 올리게 될 거예요.

그러니 다음 과목으로 갈 때, 오늘 만든 연습 저장소를 졸업장처럼 간직하세요. 그리고 새 과목의 첫 코드를 짜는 순간, 망설이지 말고 git init 부터 쳐보세요. 그게 여러분이 진짜 개발자의 길에 올라선 신호예요. 그동안 정말 고생 많았고, 다음 여정에서 또 만나요.


과제

오늘 배운 트러블슈팅은 직접 사고를 내보고 빠져나와 봐야 진짜 안 무서워져요. 연습 저장소는 망쳐도 아무 일 없으니, 마음 편히 일부러 망쳐보세요.

[기초] detached HEAD 에 일부러 빠졌다가 빠져나오기

연습 저장소에서 detached HEAD 상태를 직접 만들고 안전하게 돌아와 보세요.

먼저 커밋을 두세 개 만든 뒤 git log --oneline 으로 옛 커밋의 해시를 확인하세요. 그 해시로 git checkout <해시> 를 쳐서 detached HEAD 안내문이 뜨는 걸 직접 보고, git status 로 지금 어떤 상태인지 읽어보세요. 그다음 git switch - 로 원래 브랜치에 무사히 돌아오면 성공이에요. 마지막으로 "detached HEAD 가 뭐고 왜 안 무서운지" 를 한 문장으로 적어보세요.

[응용] 커밋을 날려보고 reflog 로 되살리기

가장 든든한 안전망인 reflog 를 손으로 직접 써보는 과제예요.

연습 저장소에 의미 있는 커밋을 세 개쯤 만든 뒤, git reset --hard HEAD~2 로 최근 두 커밋을 일부러 날려보세요. git log 에서 사라진 걸 확인하면 잠깐 식은땀이 날 텐데(괜찮아요!), 바로 git reflog 를 쳐서 사라진 커밋의 해시를 찾으세요.

그 해시로 git reset --hard <해시> 해서 커밋을 되살리고, git log 로 복구됐는지 확인하세요. "사고가 났을 때 가장 먼저 떠올려야 할 명령이 무엇인지" 도 한 줄로 적어보세요.

상상해보세요. 입사 첫 주에 reset 을 잘못 쳐서 작업이 사라진 것 같을 때, 옆자리 선배에게 묻기 전에 여러분이 직접 git reflog 로 되살릴 수 있다면 어떨까요? 오늘 이 연습이 바로 그 상황이에요.

[심화] 나의 첫 GitHub Actions — 초록 체크 띄우기

지난 시간 설레게 예고했던 그 초록 체크를, 직접 만들어 띄워보세요.

GitHub 에 연습 저장소를 하나 두고(없으면 새로 만들어 push 하고), 그 안에 .github/workflows/ci.yml 파일을 만들어 교안의 최소 워크플로를 그대로 적으세요. 그걸 commit 하고 push 한 뒤, GitHub 저장소의 Actions 탭에서 워크플로가 돌아간 기록과 커밋 옆의 초록 체크 표시를 직접 확인하세요.

마지막으로 "지금 이 워크플로는 메시지만 출력하는데, 진짜 현업의 CI 라면 여기서 무엇을 더 할까" 를 한두 문장으로 상상해 적어보세요. (정답을 맞히는 게 아니라, 다음 과목으로 가는 호기심을 적는 거예요.)


생각해볼 주제

1. "되돌릴 수 있다" 는 안심에도 한계가 있을까

오늘 우리는 reflog 덕분에 "git 에선 어지간한 건 되돌릴 수 있다" 는 든든함을 얻었어요. 그런데 그 안전망에도 빈틈이 있어요. reflog 는 내 컴퓨터에만 있는 기록이고, 오래된 발자국은 git 이 청소한다고 했죠.

그렇다면 "어떤 상황에서는 정말로 되돌릴 수 없는지" 를 떠올려보세요. 동료의 사고를 내가 되살려줄 수 있는 경우와 없는 경우는 무엇이 다를까요? 이 한계를 알면, 왜 "중요한 작업은 자주 push 해서 원격에도 올려두라" 고 하는지가 보일 거예요.

2. 표준 명령 먼저일까, 편한 별칭 먼저일까

별칭과 자동 설정은 git 을 훨씬 편하게 만들어줘요. 그런데 입문자가 처음부터 별칭만 쓰면, 정작 별칭이 없는 동료의 컴퓨터나 서버 터미널에서 막힐 수 있어요.

여러분이 후배에게 git 을 가르친다면, 표준 명령(git status·git log)을 충분히 익숙해진 뒤에 별칭을 권하겠어요, 아니면 처음부터 편한 별칭으로 시작하게 하겠어요? "편리함" 과 "어디서나 통하는 기본기" 사이에서 무엇을 먼저 둘지 여러분의 기준을 정리해보세요.

3. 기계가 검사를 대신하면, 사람의 역할은 어떻게 바뀔까

CI 가 push 마다 자동으로 검사를 돌려주면, 사람이 일일이 "빌드 되나, 테스트 통과하나" 를 확인하던 수고가 사라져요. 분명 큰 이득이죠. 그런데 자동 검사에만 의존하면 놓치는 것은 없을까요? 기계가 통과시킨 코드라도 사람이 꼭 봐야 하는 부분(예: 코드 리뷰에서 사람이 보는 것)은 무엇일까요? "기계가 잘하는 검사" 와 "사람만 할 수 있는 판단" 의 경계를, A-5 에서 배운 코드 리뷰와 묶어 생각해보세요.

✅ 예시 답안정답 보기

이 문서는 A-8 「실전과 심화」의 과제와 생각해볼 주제에 대한 예시답안입니다. 정답을 외우는 용도가 아니라, 직접 손으로 해본 결과를 어떻게 정리하고 설명하는지 흐름을 참고하는 용도로 보세요. 특히 오늘 배운 트러블슈팅은 연습 저장소에서 일부러 사고를 내보고 빠져나와 봐야 진짜 안 무서워집니다. 답안을 보기 전에 꼭 먼저 직접 쳐보세요. 망쳐도 reflog 라는 안전망이 있으니 안심하고요.


과제 예시답안

🎯 [과제 1 예시답안] detached HEAD 에 일부러 빠졌다가 빠져나오기

채점 포인트

항목 배점 기준
커밋·해시 확인 20% 커밋을 만들고 git log 로 옛 해시를 확인했는가
detached 진입 30% git checkout <해시> 로 안내문이 뜨는 걸 직접 봤는가
상태 읽기 20% git status 로 지금 상태를 확인했는가
안전한 복귀 30% git switch - 로 원래 브랜치에 돌아오고 한 문장으로 정리했는가

풀이 예시

먼저 커밋을 두세 개 만들고, 옛 커밋의 해시를 확인해요.

Bash
echo "첫 줄" >> diary.txt
git add diary.txt
git commit -m "일기 시작"

echo "둘째 줄" >> diary.txt
git add diary.txt
git commit -m "둘째 날"

git log --oneline
# b2c3d4e (HEAD -> main) 둘째 날
# 9a8b7c6 일기 시작        ← 이 옛 커밋으로 가본다

이제 옛 커밋의 해시로 checkout 해서 detached HEAD 에 일부러 들어가 봐요.

Bash
git checkout 9a8b7c6
# Note: switching to '9a8b7c6'.
# You are in 'detached HEAD' state. ...

git status
# HEAD detached at 9a8b7c6      ← 브랜치에 안 붙어 있다는 신호

안내문과 git status 로 지금 브랜치에 매여 있지 않다는 걸 확인했으면, 안전하게 원래 브랜치로 돌아와요.

Bash
git switch -
# Previous HEAD position was 9a8b7c6 일기 시작
# Switched to branch 'main'

한 문장 정리 예시: "detached HEAD 는 HEAD 가 브랜치를 거치지 않고 특정 커밋에 직접 붙은 상태일 뿐이라, git switch - 한 줄이면 원래 브랜치로 무사히 돌아오니 안 무섭다."

💡 튜터의 한마디 — 이 과제의 진짜 목적은 "낯선 화면을 일부러 만들어보고 빠져나와 보는" 경험이에요. 한 번 직접 들어갔다 나오면, 나중에 진짜로 detached HEAD 를 만나도 "아, 그거" 하고 침착하게 git switch - 를 칠 수 있어요. 신입 때 이 화면 보고 당황하는 사람과, 웃으며 빠져나오는 사람의 차이는 딱 이 연습 한 번이에요.

🎯 [과제 2 예시답안] 커밋을 날려보고 reflog 로 되살리기

채점 포인트

항목 배점 기준
커밋 쌓기 20% 의미 있는 커밋을 세 개쯤 만들었는가
일부러 날리기 25% git reset --hard HEAD~2 로 커밋을 날리고 사라진 걸 확인했는가
reflog 로 찾기 30% git reflog 로 사라진 커밋의 해시를 찾았는가
복구·정리 25% 해시로 되살리고 "가장 먼저 떠올릴 명령" 을 적었는가

풀이 예시

먼저 커밋 세 개를 만든 뒤, 최근 두 개를 일부러 날려요.

Bash
git log --oneline
# c3d4e5f (HEAD -> main) 좋아요 기능
# b2c3d4e 댓글 기능
# 9a8b7c6 프로젝트 시작

git reset --hard HEAD~2
# HEAD is now at 9a8b7c6 프로젝트 시작

git log --oneline
# 9a8b7c6 (HEAD -> main) 프로젝트 시작
#  ← 최근 두 커밋이 사라졌다! (잠깐 식은땀)

이제 reflog 로 사라진 커밋의 발자국을 찾아 되살려요.

Bash
git reflog
# 9a8b7c6 HEAD@{0}: reset: moving to HEAD~2
# c3d4e5f HEAD@{1}: commit: 좋아요 기능   ← 사라지기 직전 상태
# b2c3d4e HEAD@{2}: commit: 댓글 기능

git reset --hard c3d4e5f
# HEAD is now at c3d4e5f 좋아요 기능

git log --oneline
# c3d4e5f (HEAD -> main) 좋아요 기능   ← 되살아났다!
# b2c3d4e 댓글 기능
# 9a8b7c6 프로젝트 시작

한 줄 정리 예시: "커밋이 사라진 것 같을 때 가장 먼저 떠올릴 명령은 git reflog 다 — HEAD 의 발자국에서 사라진 해시를 찾아 되살릴 수 있다."

💡 튜터의 한마디 — 이 한 번의 경험이 git 에 대한 두려움을 크게 줄여줘요. "reset 을 잘못해도 reflog 로 돌아올 수 있다" 를 머리로 아는 것과, 직접 날렸다가 살려본 것은 안심의 크기가 달라요. 입사 첫 주에 비슷한 사고가 나도, 선배에게 묻기 전에 여러분이 먼저 git reflog 를 떠올릴 수 있게 돼요.

🎯 [과제 3 예시답안] 나의 첫 GitHub Actions — 초록 체크 띄우기

채점 포인트

항목 배점 기준
워크플로 파일 35% .github/workflows/ci.yml 을 올바른 위치에 만들었는가
push·실행 30% commit 후 push 해서 워크플로가 돌아갔는가
초록 체크 확인 20% Actions 탭과 초록 체크 표시를 직접 확인했는가
상상 적기 15% 진짜 CI 라면 무엇을 더 할지 한두 문장 적었는가

풀이 예시

저장소 안에 워크플로 파일을 만들어요. 폴더 경로가 정확해야 GitHub 이 알아봐요.

Bash
mkdir -p .github/workflows

.github/workflows/ci.yml 파일에 교안의 최소 워크플로를 그대로 적어요.

YAML
# .github/workflows/ci.yml
name: CI
on: push
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - run: echo "검사 통과! 🟢"

이제 commit 하고 push 하면, GitHub 이 자동으로 워크플로를 돌려요.

Bash
git add .github/workflows/ci.yml
git commit -m "CI: 첫 워크플로 추가"
git push

push 한 뒤 GitHub 저장소의 Actions 탭에 들어가면 워크플로가 실행된 기록이 보이고, 커밋 옆(또는 PR 안)에 초록색 체크 표시가 떠요. 우리가 늘 보던 그 초록 체크를 직접 만든 거예요.

상상 적기 예시: "지금은 메시지만 출력하지만, 진짜 CI 라면 여기서 코드를 받아 빌드가 되는지 확인하고, 자동으로 테스트를 전부 돌려서 하나라도 실패하면 빨간 X 를 띄울 것 같다. 통과하면 서버에 자동 배포까지 할 수도 있겠다."

💡 튜터의 한마디 — 이 작은 워크플로 하나로 "CI 가 이런 거구나" 가 확 와닿았을 거예요. 그동안 PR 에서 보던 초록 체크가 더 이상 마법이 아니라, 내가 만들 수 있는 무언가가 된 거죠. 진짜 빌드·테스트·배포 파이프라인을 짜는 건 인프라 과목에서 제대로 배워요. 오늘은 그 입구를 직접 열어본 것만으로 충분해요.


생각해볼 주제 예시답안

🤔 [생각해볼 주제 1] "되돌릴 수 있다" 는 안심에도 한계가 있을까

문제 상황 요약

reflog 덕분에 "git 에선 어지간한 건 되돌릴 수 있다" 는 든든함을 얻었어요. 하지만 그 안전망은 내 컴퓨터에만 있고, 오래된 발자국은 청소돼요. 정말로 되돌릴 수 없는 경우가 무엇인지, 동료의 사고는 언제 살려줄 수 있는지 따져보는 문제예요.

튜터의 가이드 및 해설

reflog 는 강력하지만 만능은 아니에요. 되돌릴 수 없는 경우부터 짚어볼게요.

정말로 되돌리기 어려운 경우: 한 번도 커밋하지 않은 변경(작업 폴더에만 있던 수정)을 reset --hard 로 날리면, 애초에 git 에 기록된 적이 없어서 되살릴 수 없어요. 또 reflog 의 발자국은 한참 지나면 청소되고, 발자국은 그 컴퓨터에만 있어요. 즉 다른 사람의 컴퓨터나 내가 접근할 수 없는 곳의 기록은 내 reflog 로 못 살려요.

동료의 사고를 살릴 수 있느냐는 "그 커밋을 누가 갖고 있느냐" 에 달렸어요. 동료가 잘못된 force-push 로 원격을 덮었어도, 그 커밋을 이미 받아둔 사람의 로컬 reflog 엔 남아 있어서 거기서 살릴 수 있어요. 반대로 그 커밋이 오직 force-push 당한 원격에만 있었고 아무도 받지 않았다면, 살릴 길이 막막해져요.

여기서 중요한 교훈이 나와요. "되돌릴 수 있다" 는 결국 "어딘가에 사본이 남아 있을 때" 의 이야기예요. 그래서 중요한 작업일수록 자주 커밋하고, 자주 push 해서 원격에도 사본을 둬야 해요. 안전망은 사본의 개수만큼 두꺼워져요.

💡 핵심을 한마디로

"reflog 는 강력하지만, 커밋된 적 없는 변경이나 다른 사람 컴퓨터의 기록까지 살려주진 못해요. '되돌릴 수 있다' 는 결국 어딘가에 사본이 남아 있을 때의 이야기죠. 그래서 중요한 작업은 자주 커밋하고 자주 push 해서 원격에도 사본을 둬요. 안전망의 두께는 사본의 개수가 정해요."

🤔 [생각해볼 주제 2] 표준 명령 먼저일까, 편한 별칭 먼저일까

문제 상황 요약

별칭과 자동 설정은 git 을 편하게 만들어줘요. 그런데 입문자가 처음부터 별칭만 쓰면, 별칭이 없는 동료의 컴퓨터나 서버에서 막힐 수 있어요. 후배를 가르친다면 표준 명령을 충분히 익힌 뒤 별칭을 권할지, 처음부터 편한 별칭으로 시작하게 할지 정하는 문제예요.

튜터의 가이드 및 해설

이건 "편리함" 과 "어디서나 통하는 기본기" 사이의 선택이에요. 양쪽을 견줘볼게요.

표준 명령 먼저 쪽의 논리는 이래요. git status·git commit·git log 같은 표준 명령은 세상 어떤 컴퓨터, 어떤 서버 터미널에서도 똑같이 통해요. 입문자가 이걸 충분히 익히면 머릿속에 git 의 정확한 모형이 생겨요. 별칭은 그저 그 명령의 단축키라, 기본기가 있으면 별칭은 나중에 얼마든지 얹을 수 있어요.

별칭 먼저 쪽의 논리도 있어요. 입문자가 긴 명령을 매번 치는 건 부담이고, 그 부담 때문에 git 자체를 멀리하게 될 수도 있어요. 편한 별칭으로 일단 자주 쓰게 만들면, 손이 git 에 익숙해지는 게 먼저라는 거죠.

대체로 권하는 균형은 "표준 명령으로 충분히 익숙해진 뒤 별칭을 얹기" 예요. 이유는, 별칭에만 의존하면 정작 별칭 없는 서버에 접속했을 때(현업에선 흔해요) 손이 멈추기 때문이에요. 기본기가 단단하면 어디서든 안 막히고, 별칭은 그 위에서 속도만 더해줘요. 그래서 "기본기 먼저, 편의는 그 위에" 가 입문자에겐 더 안전한 순서예요.

💡 핵심을 한마디로

"별칭은 표준 명령의 단축키일 뿐이라, 기본기 위에 얹어야 안전해요. 별칭에만 익숙해지면 별칭 없는 서버 터미널에서 손이 멈추거든요. 그래서 입문자에겐 '표준 명령으로 먼저 단단해진 뒤, 편의를 그 위에 얹는' 순서를 권해요. 어디서나 통하는 기본기가 먼저예요."

🤔 [생각해볼 주제 3] 기계가 검사를 대신하면, 사람의 역할은 어떻게 바뀔까

문제 상황 요약

CI 가 push 마다 자동으로 검사를 돌려주면, 사람이 일일이 빌드·테스트를 확인하던 수고가 사라져요. 분명 큰 이득이죠. 그런데 자동 검사에만 의존하면 놓치는 건 없을지, 기계가 통과시킨 코드라도 사람이 꼭 봐야 할 부분은 무엇인지를 A-5 의 코드 리뷰와 묶어 생각하는 문제예요.

튜터의 가이드 및 해설

핵심은 기계가 잘하는 검사사람만 할 수 있는 판단이 다르다는 거예요. 둘을 나눠볼게요.

기계(CI)가 잘하는 것은 "정해진 기준에 맞나" 를 빠르고 지치지 않게 확인하는 일이에요. 빌드가 되는지, 테스트가 다 통과하는지, 코드 형식(들여쓰기·스타일)이 규칙에 맞는지 같은 거죠. 이런 건 사람이 매번 손으로 확인하면 느리고 실수도 하지만, 기계는 매 push 마다 완벽하게 같은 검사를 반복해요.

사람만 할 수 있는 판단은 "이 코드가 과연 좋은가" 예요. 테스트는 다 통과해도, 코드가 읽기 쉬운지, 애초에 맞는 문제를 풀고 있는지, 설계가 합리적인지, 더 간단한 방법은 없는지는 기계가 못 봐요. 이게 바로 A-5 에서 배운 코드 리뷰에서 사람이 보는 부분이에요. CI 가 초록불을 켜도, 동료의 리뷰 승인이 따로 필요한 이유가 여기 있어요.

그래서 둘은 경쟁 관계가 아니라 역할 분담이에요. 기계가 기계적인 검사를 떠맡아준 덕분에, 사람은 그 시간을 아껴 "이 코드가 정말 좋은 방향인가" 라는 더 가치 있는 판단에 집중할 수 있어요. 자동화의 진짜 이득은 사람을 대체하는 게 아니라, 사람을 더 중요한 일에 쓰게 해주는 거예요.

💡 핵심을 한마디로

"CI 는 '정해진 기준에 맞나'(빌드·테스트·형식)를 지치지 않고 검사하고, 사람은 '이 코드가 좋은가'(가독성·설계·맞는 문제를 푸는가)를 판단해요. 그래서 초록불이 떠도 코드 리뷰 승인이 따로 필요하죠. 자동화의 진짜 이득은 사람을 대체하는 게 아니라, 사람을 더 가치 있는 판단에 쓰게 해주는 거예요."

전체 목록 Git·GitHub
이 토픽을 끝까지 봤어요 🎉 다음은 리눅스 →