SPACE LOGBOOK

OCEAN LOGBOOK

심볼릭 링크와 정크션..

2026.08.22

심볼릭 링크와 정크션..

2026.08.22
🔗 개발 개념 해설

파일 하나를 두 곳에서 동시에 보는 마법
— 정크션과 심볼릭 링크

복사하지 않고도 “같은 파일”을 여러 경로에서 접근하게 만드는 파일시스템의 오래된 트릭

로컬 개발 환경을 손보다가 재미있는 문제에 부딪혔다. 코드는 깔끔하게 Git 저장소 폴더 하나에 모아두고 싶은데, 그 코드를 실행해서 눈으로 확인하려면 워드프레스 프로그램(아파치·DB·PHP가 다 갖춰진)이 요구하는 정해진 폴더 위치에 파일이 있어야 했다. 결국 “파일을 복사하지 않고도, 서로 다른 두 경로에서 같은 파일을 보게 만드는 방법”이 필요했는데 — 그 답이 바로 정크션(Junction)과 심볼릭 링크(Symbolic Link)였다.

💡

한 줄 정의: 정크션과 심볼릭 링크는 “이 경로에 오면 사실 저 경로에 있는 실제 파일을 보여줘라”라고 운영체제(파일시스템)에 등록해두는 표지판이다. 파일을 복제하는 게 아니라, 실제 파일은 딱 한 곳에만 존재한 채로 여러 경로에서 접근 가능하게 만든다.

🚏 흔히 헷갈리는 “바로가기”와는 뭐가 다른가

윈도우를 오래 써본 사람이라면 바탕화면의 “바로가기(.lnk)” 아이콘에 익숙할 것이다. 정크션·심볼릭 링크도 얼핏 비슷해 보이지만, 작동하는 층(layer)이 완전히 다르다.

🖱️ 바로가기 (Shortcut)

탐색기라는 응용 프로그램 수준에서만 인식되는 껍데기 파일(.lnk)이다. 더블클릭하면 탐색기가 “아, 이건 저 경로를 열라는 뜻이구나”하고 해석해줄 뿐, 프로그램(예: 워드프레스 서버)이 그 경로를 직접 파일처럼 읽으려 하면 인식하지 못한다.

🔗 정크션 / 심볼릭 링크

운영체제의 파일시스템 자체에 등록되는 진짜 연결이다. 어떤 프로그램이든 — 워드프레스 서버든, 코드 에디터든 — 이 경로를 열면 실제 파일을 여는 것과 완전히 동일하게 동작한다. 링크를 거친다는 사실조차 눈치채지 못한다.

🏢

비유하자면 바로가기는 “저 건물로 가려면 이 방향으로 가세요”라고 적힌 안내판이고, 정크션·심볼릭 링크는 우체국의 주소 이전 등록에 가깝다. 이 주소로 온 우편물은 사람이 별도로 신경 쓰지 않아도 자동으로 실제 거주지로 배달된다 — 시스템 차원에서 완전히 처리되는 것이다.

🧭 왜 굳이 이런 게 필요한가 — 실제로 부딪힌 문제

워드프레스처럼 아파치·PHP·데이터베이스가 통째로 갖춰져야 돌아가는 프로그램은, 코드 파일 하나만 뚝 떼어서 실행할 수 없다. 반면 코드를 Git으로 버전 관리하려면, DB나 캐시 파일 같은 무거운 데이터와 섞이지 않은 깔끔한 코드 전용 폴더가 필요하다. 이 두 가지 요구가 충돌하는 지점에서 정크션이 해결사로 등장한다.

1

Git 저장소는 코드 전용 폴더에 그대로 둔다

예: C:\site\myproject — 여기엔 테마 코드만 깔끔하게 존재한다.

2

로컬 서버 프로그램이 요구하는 위치는 따로 있다

Local이나 Laragon 같은 도구는 사이트를 만들 때 자기만의 고정된 내부 경로(예: ~/Local Sites/mysite/app/public/wp-content/themes/)를 강제로 사용한다. 이 경로는 임의로 바꿀 수 없다.

3

두 경로를 정크션으로 연결

서버가 요구하는 그 위치에 정크션을 하나 만들어, 실제로는 Git 저장소 폴더를 가리키게 한다.

4

결과 — 파일을 복사할 필요가 완전히 사라진다

Git 저장소에서 코드를 수정하면, 그 즉시 로컬 서버가 보는 화면에도 반영된다. 파일은 하나뿐이고, 두 경로는 그 하나를 바라보는 창문일 뿐이니까.

🔬 손에 잡히도록 — 그림과 실험으로 확인하기

여기까지가 개념이라면, 이제 “복사했을 때”와 “링크했을 때”가 실제로 어떻게 다르게 움직이는지 그림과 눈에 보이는 예시로 확인해보자.

① 복사 vs 링크 — 수정했을 때 무슨 일이 벌어지나

원본 폴더 style.css 복사 복사본 폴더 style.css 여기만 수정 원본 폴더 style.css (v2) 복사본 폴더 style.css (v1) ✕ 내용이 어긋난다 둘 다 일일이 수정해야 함

📁 복사 — 서로 다른 파일 2개

경로 A Git 저장소 경로 B Local 사이트 실제 파일 style.css (딱 1개) ✓ 항상 같은 내용 한 곳만 고치면 끝

🔗 링크 — 진짜 파일은 1개뿐

② 지금까지 다뤘던 실제 사례를 그림으로

실제 데이터가 있는 곳 C:\site\myproject 📄 index.php 📄 style.css 📄 functions.php 📁 assets/ 정크션 (링크일 뿐) …Local Sites\mysite\…\mytheme 열어보면 — 📄 index.php 📄 style.css 가 그대로 똑같이 보인다 정크션

두 경로는 이름만 다를 뿐, 디스크에는 파일이 왼쪽 자리 딱 하나만 존재한다

③ 실험 — 링크 전후를 명령어로 직접 비교

같은 파일을 고쳤을 때, 정크션이 없을 때(=단순 복사본)와 있을 때(=링크) 결과가 어떻게 갈리는지 터미널로 재현하면 다음과 같다.

❌ 정크션 없이 — 그냥 복사만 해둔 경우

# 저장소에서 색상을 빨강으로 수정 echo “body{color:red}” > C:\site\myproject\style.css # Local 사이트 쪽 파일을 열어보면… type “…\themes\mytheme\style.css” → body{color:blue} # 예전 그대로! 반영 안 됨

✅ 정크션 연결 후

# 저장소에서 색상을 빨강으로 수정 echo “body{color:red}” > C:\site\myproject\style.css # Local 사이트 쪽 파일을 열어보면… type “…\themes\mytheme\style.css” → body{color:red} # 즉시 반영됨!
📮

비유를 하나 더 보태면 — 같은 사람이 “본명”과 “별명” 두 개로 불리는 것과 같다. 별명으로 불러도 대답하는 건 결국 같은 한 사람이듯, 어느 경로(이름)로 접근하든 열리는 건 디스크 위의 같은 한 파일이다.

🛠️ 직접 만들어보기

윈도우에서는 “정크션”, 맥·리눅스에서는 “심볼릭 링크”라는 이름으로 부르지만 개념은 동일하다. 서버 관리를 해본 사람이라면 ln -s 명령을 한 번쯤 마주쳤을 텐데, 바로 이것과 같은 원리다.

방법 ① PowerShell — New-Item

# 문법: New-Item -ItemType Junction -Path “링크를 만들 위치” -Target “실제 파일이 있는 위치” New-Item -ItemType Junction ` -Path “C:\Users\user\Local Sites\mysite\app\public\wp-content\themes\mytheme” ` -Target “C:\site\myproject”

방법 ② 명령 프롬프트 — mklink

:: 문법: mklink /J “링크경로” “실제경로” mklink /J “C:\Users\user\Local Sites\mysite\app\public\wp-content\themes\mytheme” “C:\site\myproject”
✅

정크션(/J)은 관리자 권한 없이도 만들 수 있고 폴더 전용이다. 반면 같은 mklink에서 /D 옵션(심볼릭 링크)을 쓰면 관리자 권한이 필요하다 — 윈도우 10 이상에서는 “개발자 모드”를 켜두면 이 제약이 풀린다.

연결 확인하는 법

# 링크인지, 실제 폴더인지, 어디를 가리키는지 확인 Get-Item “C:\Users\user\Local Sites\mysite\app\public\wp-content\themes\mytheme” | Select-Object LinkType, Target

결과에 LinkType: Junction과 실제 대상 경로가 표시되면 정상적으로 연결된 것이다.

ln 명령으로 심볼릭 링크 생성

# 문법: ln -s [실제 원본 경로] [새로 만들 링크 경로] ln -s /home/user/site/myproject /var/www/mysite/wp-content/themes/mytheme

유닉스 계열(맥·리눅스)에는 애초에 “정크션”이라는 별도 개념이 따로 없다 — 심볼릭 링크 하나로 파일과 폴더를 전부 처리한다. 윈도우의 정크션은 이 심볼릭 링크 개념 중 “폴더 전용, 관리자 권한 불필요” 버전만 별도로 떼어낸 것에 가깝다.

연결 확인하는 법

# -l 옵션을 붙이면 링크는 화살표(->)로 실제 경로를 보여준다 ls -l /var/www/mysite/wp-content/themes/ # 결과 예시: # lrwxrwxrwx mytheme -> /home/user/site/myproject

링크 삭제 시 주의

# 반드시 이렇게 — 마지막에 / 를 붙이지 않는다 rm mytheme # 절대 이렇게 하면 안 됨 — 원본 폴더 내용까지 통째로 삭제될 위험 rm -rf mytheme/

🌐 Windows vs Mac/Linux — 개념 비교표

구분바로가기(Shortcut)정크션(Junction)심볼릭 링크(Symbolic Link)
작동 계층응용 프로그램(탐색기) 수준파일시스템(NTFS) 수준파일시스템 수준
연결 대상파일 · 폴더 모두폴더만파일 · 폴더 모두
관리자 권한불필요불필요필요 (개발자 모드 시 예외)
지원 운영체제Windows 전용Windows(NTFS) 전용Windows / Mac / Linux 공통
프로그램의 인식대부분 인식 못함실제 폴더처럼 인식실제 파일 · 폴더처럼 인식

🚀 실무에서 심볼릭 링크가 자주 쓰이는 곳

지금까지 다룬 “로컬 개발 환경 연결”은 사실 심볼릭 링크·정크션이 쓰이는 여러 상황 중 하나일 뿐이다. 유닉스 계열 파일시스템은 애초에 “파일”과 “그 파일을 부르는 이름(경로)”을 분리해서 다루는 걸 기본 철학으로 삼고 있어서, 서버 운영·개발 곳곳에서 계속 마주치게 된다.

1. 무중단 배포(Zero-downtime deploy) — current 링크

새 버전을 별도 폴더에 통째로 새로 올려두고, 서버는 항상 current라는 고정된 이름만 바라보게 해둔다. 배포 순간엔 이 링크가 가리키는 대상만 바꿔치기한다.

2. 런타임 버전 전환 — PHP·Node 등

/usr/bin/php → /etc/alternatives/php → php8.2 처럼, 여러 버전을 서버에 깔아두고 링크만 바꿔서 “현재 쓰는 버전”을 스위칭한다. nvm의 버전 전환도 같은 원리다.

3. 웹서버 설정 활성화 — nginx의 sites-enabled

설정 파일 실체는 sites-available에 두고, sites-enabled에는 그걸 가리키는 링크만 걸거나 지워서 사이트를 켜고 끈다.

4. 컨테이너 로그를 표준출력으로 연결

/var/log/nginx/access.log → /dev/stdout — Docker 환경에서 로그 파일 대신 컨테이너 표준출력으로 연결해, docker logs로 바로 확인하게 만드는 트릭.

5. 설정 파일(dotfiles) 동기화

~/.bashrc → ~/dotfiles/bashrc 처럼, 여러 설정 파일을 Git 저장소 하나에 모아두고 홈 디렉터리엔 링크만 심어둔다. 새 컴퓨터 세팅 시 저장소만 클론하면 끝.

6. 패키지 캐시 공유 — node_modules

여러 프로젝트가 같은 라이브러리를 쓸 때, 실제 파일은 전역 캐시에 한 번만 두고 각 프로젝트엔 링크만 걸어 디스크 용량을 절약한다 (pnpm, Yarn PnP 등).

💡 1번을 좀 더 깊게 — 왜 “순간적으로” 전환되는가

무중단 배포가 신뢰받는 이유는 링크를 바꾸는 연산 자체가 원자적(atomic)이기 때문이다. “바꾸는 중간 상태”라는 게 존재하지 않고, 어떤 요청이 들어와도 버전1 완결본이거나 버전2 완결본 둘 중 하나만 보게 된다 — 파일이 절반씩 뒤섞인 상태를 볼 방법이 없다.

# 배포: current 링크를 새 버전으로 재지정 (한 순간에 전환) ln -sfn /var/www/releases/2026-08-22-0930 /var/www/current # 롤백: 다시 이전 버전 폴더로 되돌리기만 하면 즉시 원상복구 ln -sfn /var/www/releases/2026-08-20-1400 /var/www/current
🧠

PHP-FPM opcache 주의. PHP-FPM은 파일 경로 기준으로 컴파일된 코드를 캐싱해두는데, 링크가 가리키는 대상이 바뀌어도 opcache가 예전 코드를 그대로 물고 있는 경우가 있다. 그래서 배포 스크립트에는 링크 전환 직후 php-fpm 재시작(또는 opcache reset) 단계를 함께 넣는 게 안전하다.

⚠️ 실무에서 주의할 점

🗑️

삭제 명령에 특히 주의. 정크션·심볼릭 링크가 있는 폴더를 지울 때 잘못된 방식(예: 끝에 슬래시를 붙이거나 재귀 삭제 옵션을 잘못 조합)으로 지우면, 링크만 지워지는 게 아니라 실제 원본 폴더 내용까지 통째로 삭제될 수 있다. 링크를 만들기 전 원본은 반드시 별도로 백업해두는 습관이 안전하다.

📦

백업·압축 프로그램과의 충돌. 일부 백업 도구나 압축 프로그램은 링크를 “실제 파일”로 착각해 원본 내용을 통째로 복사하려 든다. 이 경우 용량이 예상보다 커지거나 중복 백업이 생길 수 있어, 백업 대상에서 링크 폴더를 제외하는 설정이 필요할 때가 있다.

🔍

Git과의 궁합은 좋다. Git 저장소 자체가 정크션 대상(원본)이라면, Git 입장에서는 자신이 링크를 통해 접근되고 있다는 사실을 신경 쓸 필요가 없다 — 원본 경로에서 평소처럼 commit·push 하면 그만이다.

정리하면, 정크션과 심볼릭 링크는 “파일은 한 곳에, 접근 경로는 여러 곳에”라는 아주 단순한 아이디어다. 서버 운영에서 흔히 쓰이는 ln -s도, 로컬 개발 환경에서 쓰는 mklink /J도, 무중단 배포의 current 링크도 결국 같은 철학을 각자의 상황에 맞게 구현한 것뿐이다.

처음엔 로컬 개발 환경 문제 하나를 풀려고 알게 된 개념이었는데, 파고들다 보니 배포 자동화·버전 전환·설정 관리처럼 완전히 다른 문제들이 전부 같은 도구 하나로 풀리는 걸 보고 나니 생각이 좀 바뀌었다. 유닉스 파일시스템이 애초에 “파일”과 “그 파일을 부르는 이름”을 분리해서 설계된 덕분에 가능한 일인데, 이 감각 한 번 잡히고 나면 여기저기서 “아, 이것도 링크로 풀 수 있겠는데” 싶은 지점이 계속 눈에 밟히기 시작한다. 몰랐을 땐 그냥 지나쳤을 자리들인데, 알고 나니 활용할 구석이 의외로 많았다.

댓글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

이 기록은 여기까지지만,
생각은 아직 이동 중이다