사전 로컬 저장소
용어함정

로컬 저장소

gabury1고친 사람 github-actions[bot]

로컬 저장소는 데이터를 서버가 아닌 내 컴퓨터 안에 두고 바로 꺼내 쓰게 해 줍니다. 같은 이름을 세 분야가 서로 다른 물건에 붙입니다. 버전관리에서는 이력을 담은 내 쪽 저장소입니다. 빌드 도구에서는 내려받은 라이브러리를 모아 둔 폴더입니다. 웹 브라우저에서는 사이트가 값을 적어 두는 공간입니다.

쉽고 빠른 이해

무슨 일을 하는 물건인가 — 필요한 것을 내 컴퓨터 안에 붙잡아 둡니다. Git 으로 받은 프로젝트 안의 .git 폴더, Maven 이 라이브러리를 받아 쌓는 폴더, 브라우저가 사이트마다 값을 남기는 공간이 모두 이 이름으로 불립니다. 세 물건은 이름만 같습니다.

왜 이렇게 하나 — 필요할 때마다 서버에 다녀오면 느립니다. 서버에 못 닿으면 일이 멈춥니다. 내 쪽에 한 벌 두면 변경 기록도, 라이브러리도, 페이지의 설정 값도 네트워크 없이 바로 씁니다.

어떻게 도나

  1. Git 은 저장소 전체를 내 컴퓨터로 받아 옵니다. 새 기록은 먼저 내 쪽에만 쌓습니다
  2. Maven 은 라이브러리가 필요하면 내 쪽 폴더부터 봅니다. 없을 때만 서버에서 받아 와 남겨 둡니다
  3. 브라우저는 사이트마다 칸을 따로 둡니다. 거기 적은 값은 창을 닫아도 남습니다

대가 — 내 쪽 사본은 서버와 어긋날 수 있습니다. Git 의 새 기록은 보내기 전까지 남이 못 봅니다. 내가 직접 만들어 Maven 폴더에만 넣은 라이브러리는 동료 컴퓨터에서 빌드를 깨뜨립니다.

브라우저 공간의 값은 그 페이지에서 도는 스크립트면 누구든 읽습니다. 공격자가 남의 페이지에 몰래 끼워 넣은 스크립트도 읽습니다. 그리고 대화에서 셋을 섞어 부르면 서로 다른 이야기를 하게 됩니다.

상세

이 절은 「로컬 저장소」가 가리키는 세 물건을 봅니다. 먼저 표 하나로 셋을 가릅니다. 그다음 셋을 하나씩 따라갑니다.

끝에서는 대화나 문서에서 어느 뜻인지 알아채는 단서를 모읍니다.

세 뜻

셋은 「서버 말고 내 컴퓨터에 있다」는 점만 같습니다. 무엇을 담는지와 어디에 쓰는지는 다릅니다.

분야 무엇을 담나 영어 이름 예
버전관리 프로젝트 파일과 그 변경 이력 전체 local repository Git 프로젝트 안의 .git 폴더
빌드 도구 내려받은 라이브러리 파일 local repository Maven 이 쓰는 ~/.m2/repository 폴더
웹 브라우저 사이트가 남긴 키와 값 local storage 자바스크립트의 localStorage

앞의 두 줄은 영어 이름까지 같습니다. 둘 다 서버 쪽 상대를 원격 저장소라고 부르는 것도 같습니다. 그래도 담는 것이 달라서 한쪽이 다른 쪽을 대신하지 못합니다.

셋째 줄은 영어 이름부터 다릅니다. 우리말로 옮기면서 앞의 둘과 같은 낱말이 됐습니다.

버전관리의 로컬 저장소

저장소는 프로젝트 파일과 그 파일이 바뀌어 온 기록을 함께 보관하는 곳입니다. 쌓인 기록 전체를 이력이라고 부릅니다. 이력이 있어야 어제의 모습으로 거슬러 갈 수 있습니다.

Git 같은 분산 버전관리 도구는 저장소를 사람마다 하나씩 들게 합니다. 그중 내 컴퓨터에 있는 것이 로컬 저장소입니다. 서버처럼 다른 곳에 있는 상대 저장소는 원격 저장소라고 부릅니다.

Git 의 로컬 저장소는 프로젝트 폴더 안의 .git 폴더입니다. 원격 저장소를 클론해 오면 이 폴더가 생깁니다. 이때 파일의 지금 모습만이 아니라 지난 모습까지 이력 전체가 들어옵니다.

편집기로 여는 파일은 로컬 저장소가 아닙니다. 저장소에서 한 시점을 꺼내 펼쳐 둔 사본입니다. 이것을 작업 사본이라고 부릅니다.

작업 사본에서 고친 것을 기록 하나로 묶어 저장소에 넣는 일이 커밋입니다. 커밋은 로컬 저장소에만 들어갑니다. 서버에 닿지 않으니 네트워크가 끊겨도 커밋할 수 있습니다.

로컬 저장소가 원격 저장소와 주고받는 방향은 둘입니다. 내 커밋을 원격으로 보내는 일이 푸시입니다. 원격의 새 커밋을 로컬로 받아 오는 일은 페치입니다.

페치는 받아 오기만 합니다. 받아 온 커밋은 내가 편집하는 파일에 아직 반영되지 않습니다. 풀은 페치에 이어 받아 온 커밋을 내 작업에 합치는 데까지 한 번에 하는 명령입니다. 합친다는 것은 양쪽에서 따로 쌓인 커밋을 이어 하나의 이력으로 만든다는 뜻입니다.

flowchart TD
    subgraph PC["내 컴퓨터"]
        W["작업 사본 · 편집하는 파일"]
        L["로컬 저장소 · .git 폴더"]
    end
    R["원격 저장소 · 서버"]
    W -->|"커밋"| L
    L -->|"푸시"| R
    R -->|"페치"| L

커밋은 내 컴퓨터 상자 안에서 끝납니다. 상자 밖으로 나가는 선은 푸시와 페치뿐입니다. 그래서 git commit 만 치고 멈추면 그 커밋은 동료 누구도 못 봅니다.

로컬 저장소에 남는 원격의 모습

로컬 저장소는 원격 저장소의 모습도 한 벌 들고 있습니다. 이것을 보려면 먼저 참조를 알아야 합니다.

참조는 커밋을 가리키는 이름입니다. 커밋마다 긴 식별 값이 붙어 있어서 사람이 외워 부르기 어렵습니다. 그래서 main 같은 읽기 쉬운 이름이 그 커밋을 가리키게 합니다.

브랜치는 참조 가운데 새 커밋을 쌓으면 따라 움직이는 이름입니다. main 브랜치에서 커밋하면 main 은 방금 만든 커밋을 가리키게 바뀝니다. 그래서 브랜치 이름만 알면 그 작업의 가장 최근 커밋을 늘 찾습니다.

클론을 하면 Git 은 가져온 원격 저장소에 origin 이라는 이름을 자동으로 붙입니다. 그 뒤로는 긴 서버 주소 대신 이 이름으로 원격을 부릅니다.

페치를 하면 원격의 브랜치가 어느 커밋을 가리키는지도 받아 옵니다. 로컬 저장소는 이것을 원격 이름과 브랜치 이름을 이은 origin/main 같은 이름으로 따로 적습니다. 이 이름이 원격 추적 브랜치입니다.

원격 추적 브랜치는 마지막으로 페치한 때의 원격 모습입니다. 그 뒤에 동료가 푸시한 커밋은 들어 있지 않습니다. origin/main 을 보고 원격이 이렇다고 믿기 전에 페치부터 하는 까닭입니다.

빌드 도구의 로컬 저장소

빌드 도구 쪽의 로컬 저장소는 이력과 상관이 없습니다. 남이 만든 라이브러리를 받아 두는 폴더입니다.

자바 프로젝트는 대개 라이브러리를 손으로 내려받지 않습니다. 쓸 라이브러리의 이름과 버전을 설정 파일에 적어 두면 빌드 도구가 받아 옵니다. 이렇게 내 코드가 기대는 남의 라이브러리를 의존성이라고 부릅니다.

Maven 은 받아 온 라이브러리 파일을 내 컴퓨터의 한 폴더에 모읍니다. 이 폴더가 Maven 의 로컬 저장소입니다. 따로 정하지 않으면 홈 디렉터리 아래 .m2/repository 폴더를 씁니다.

라이브러리를 내주는 서버 쪽은 원격 저장소라고 부릅니다. 누구나 받아 가는 공용 원격 저장소로 Maven Central 이 있습니다. 회사가 사내에 따로 차리는 원격 저장소도 있습니다.

폴더 안은 라이브러리를 만든 조직 이름, 라이브러리 이름, 버전 순서로 내려갑니다. 조직 이름은 점마다 폴더가 한 층씩 됩니다. 그래서 com.example 은 com/example 두 층이 됩니다.

~/.m2/repository/
└── com/example/order-lib/1.2.0/
    ├── order-lib-1.2.0.jar
    └── order-lib-1.2.0.pom

맨 아래 두 파일이 라이브러리 한 벌입니다. .jar 파일은 컴파일한 코드를 묶은 것입니다. .pom 파일은 그 라이브러리의 이름과 버전과 의존성을 적은 설명서입니다.

빌드가 라이브러리를 찾는 순서는 늘 같습니다. 로컬 저장소를 먼저 보고, 없을 때만 원격 저장소로 갑니다.

flowchart TD
    N["빌드가 라이브러리를 찾는다"] --> Q{"로컬 저장소에 있나"}
    Q -->|"있다"| U["내 컴퓨터의 파일을 쓴다"]
    Q -->|"없다"| D["원격 저장소에서 받는다"]
    D --> S["로컬 저장소에 남긴다"]
    S --> U

한 번 받은 라이브러리는 다음 빌드부터 네트워크를 안 탑니다. 이 폴더는 내 컴퓨터의 모든 프로젝트가 나눠 씁니다. 두 프로젝트가 같은 라이브러리의 같은 버전을 쓰면 파일은 한 벌만 받습니다.

내가 만든 라이브러리도 이 폴더에 넣을 수 있습니다. mvn install 은 빌드한 결과물을 내 로컬 저장소에 넣습니다. 그러면 같은 컴퓨터의 다른 프로젝트가 그 라이브러리를 원격에서 받은 것처럼 씁니다.

대가는 그 결과물이 내 컴퓨터에만 있다는 것입니다. 내 컴퓨터에서는 빌드가 됩니다. 동료 컴퓨터나 빌드 서버에서는 라이브러리를 못 찾아 깨집니다.

모두가 쓰게 하려면 원격 저장소에 올려야 합니다. 그 명령이 mvn deploy 입니다.

받다가 끊겨 망가진 파일이 폴더에 남는 일도 있습니다. 빌드는 그 파일이 있다고 보고 원격에 다시 가지 않습니다. 이럴 때는 그 라이브러리의 폴더를 지워 다시 받게 합니다.

Gradle 도 받은 라이브러리를 내 컴퓨터에 모읍니다. 모으는 곳은 Gradle 자신의 캐시 폴더입니다. 하는 일은 비슷해도 이 편이 말하는 Maven 의 로컬 저장소와는 다른 폴더입니다.

Gradle 은 빌드 설정 파일 build.gradle 에 mavenLocal() 을 적었을 때만 Maven 의 로컬 저장소도 찾아봅니다. mvn install 로 넣은 내 라이브러리를 Gradle 프로젝트에서 쓰려면 이 한 줄이 필요합니다.

Git 의 로컬 저장소와 견주면 차이가 뚜렷합니다. Git 쪽은 프로젝트마다 하나씩 있습니다. 담는 것은 내가 만든 기록입니다. Maven 쪽은 컴퓨터에 하나 있습니다. 담는 것은 남이 만든 결과물입니다.

브라우저의 로컬 저장소

브라우저 쪽 로컬 저장소는 영어 local storage 를 옮긴 말입니다. 대개 자바스크립트의 localStorage 를 가리킵니다. 사이트가 사용자 컴퓨터에 작은 값을 남겨 두는 공간입니다.

값은 키와 값의 짝으로 넣습니다. 키와 값은 둘 다 문자열입니다. 브라우저를 닫았다 열어도 남아 있습니다. 다크 모드 설정처럼 서버에 물을 필요가 없는 값을 흔히 여기에 둡니다.

쓰고 읽는 코드는 두 줄입니다.

JavaScript
localStorage.setItem("theme", "dark");
localStorage.getItem("theme");  // "dark"

둘째 줄은 창을 닫았다 다시 열어도 같은 값을 냅니다.

앞에서 브라우저가 사이트마다 칸을 따로 둔다고 했습니다. 그 칸을 가르는 단위가 출처입니다. 출처는 주소 앞머리의 https 같은 스킴, 호스트, 포트 셋을 묶은 것입니다. 셋 중 하나만 달라도 다른 출처가 됩니다.

한 출처가 남긴 값을 다른 출처의 스크립트는 못 읽습니다. 이 규칙이 동일 출처 정책입니다.

거꾸로 말하면 같은 출처에서 도는 스크립트는 전부 읽을 수 있습니다. 공격자가 남의 사이트 페이지에 자기 스크립트를 끼워 넣는 공격을 교차 사이트 스크립팅(Cross-Site Scripting, XSS)이라고 부릅니다. 이 공격이 성공하면 끼워 넣은 스크립트도 그 페이지와 같은 출처에서 돕니다. 그러면 로컬 저장소의 값을 다 읽습니다.

그래서 로그인한 사용자임을 증명하는 액세스 토큰처럼 새면 곤란한 값을 로컬 저장소에 두면 위험합니다. XSS 한 번이면 그 값이 공격자 손에 넘어갑니다.

스크립트가 아예 못 읽는 곳에 두려면 쿠키를 씁니다. 쿠키는 브라우저가 그 사이트로 요청을 보낼 때마다 함께 실어 보내는 작은 값입니다. 서버가 쿠키에 HttpOnly 표시를 붙이면 페이지의 스크립트는 그 쿠키를 읽지 못합니다.

어느 뜻인지 가르는 단서

대화나 문서에서 「로컬 저장소」가 나오면 함께 나오는 낱말을 봅니다. 대개 그것만으로 어느 뜻인지 갈립니다.

함께 나오는 말 뜻
커밋 · 푸시 · 브랜치 · .git 버전관리
의존성 · .m2 · mvn install · 라이브러리를 못 찾는다 빌드 도구
자바스크립트 · 토큰 · 새로고침 · XSS 웹 브라우저
스레드 · 변수 이름만 비슷한 다른 말인 스레드 로컬 저장소

마지막 줄의 스레드 로컬 저장소는 스레드마다 따로 갖는 변수 공간입니다. 이 편의 세 뜻 어느 것과도 관계가 없습니다.

세 뜻 밖에서도 「로컬 저장소」는 흔히 「그 기기 자신의 디스크」라는 평범한 뜻으로 쓰입니다. 모바일 앱이 폰 안에 데이터를 둘 때나, 분산 시스템의 한 노드가 자기 디스크에 쓸 때가 그렇습니다. 이때는 특정 물건이 아니라 「서버나 다른 노드가 아닌 이 기기」를 말합니다.

관련 항목

버전관리 로컬 저장소와 짝을 이루는 저장소

저장소 · 원격 저장소 · 작업 사본 · 베어 저장소 · 중앙 저장소

로컬 저장소와 원격 저장소를 잇는 Git 명령

클론 · 커밋 · 푸시 · 페치 · 풀 · 머지

Git 로컬 저장소가 담는 참조와 기록

참조 · 브랜치 · 태그 · HEAD · 원격 추적 브랜치 · origin · 스테이징 영역

로컬 저장소를 만드는 도구와 그 분류

Git · 버전관리 · 분산 버전관리 · Maven · Gradle

빌드 도구 로컬 저장소에 쌓이는 라이브러리와 그 공급원

의존성 · 전이 의존성 · 아티팩트 · Maven Central · 아티팩트 저장소 · 패키지 저장소

브라우저가 사이트 값을 남기는 저장 공간

localStorage · 웹 스토리지 · 세션 스토리지 · IndexedDB · 쿠키 · 캐시 스토리지

브라우저 로컬 저장소를 노리는 공격과 막는 규칙

교차 사이트 스크립팅 · 동일 출처 정책 · 출처 · 콘텐츠 보안 정책 · 액세스 토큰

로컬 저장소와 헷갈리는 이웃

스레드 로컬 저장소 · 로컬 캐시 · 캐싱

기기 자신의 디스크라는 일반 뜻으로 로컬 저장소를 쓰는 분야

모바일 개발 · 분산 시스템 · 오프라인 우선 · 엣지 컴퓨팅

다른 이름: local repository · 로컬 리포지토리 · 로컬 레포