# πŸƒ ν€΅μŠ€νƒ€νŠΈ 이 νŽ˜μ΄μ§€λŠ” μ„€μΉ˜κ°€ λλ‚œ ν˜ΈμŠ€νŠΈμ—μ„œ 직접 μ œμ–΄ν•˜λŠ” μ„œλ²„κΉŒμ§€ μ§„ν–‰ν•©λ‹ˆλ‹€. λ””μŠ€ν¬ μœ„μ˜ μ„€μ •, κ²€μ¦λœ 컴파일, μ‹œμž‘Β·μ€‘μ§€Β·κ°μ‹œν•  수 μžˆλŠ” μ„œλ²„, 그리고 파일 μ„œλ²„κ°€ μ‘λ‹΅ν–ˆλ‹€λŠ” ν™•μΈμž…λ‹ˆλ‹€. [μ„€μΉ˜](/ko/start/install/)κ°€ 끝났닀고 κ°€μ •ν•©λ‹ˆλ‹€. ## 🧾 μ‹œμž‘ν•˜κΈ° 전에 μ„€μΉ˜ ν”„λ‘œκ·Έλž¨μ€ 80 ν¬νŠΈμ—μ„œ μ„œλΉ„μŠ€λ₯Ό 돌린 μ±„λ‘œ 남겨 λ‘μ—ˆκ³ , κ·Έ μ„œλΉ„μŠ€κ°€ `/etc/Pingclair/Pingclairfile` 섀정을 μ₯κ³  μžˆμŠ΅λ‹ˆλ‹€. μ‹€ν—˜ν•˜λŠ” λ™μ•ˆμ—λŠ” μ€‘μ§€ν•΄μ„œ 포트λ₯Ό λΉ„μ›λ‹ˆλ‹€. ```bash sudo pc service stop ``` ```bash mkdir -p ~/demo/public cd ~/demo echo '

hello from ~/demo/public

' > public/index.html ``` ## 1. ✍️ μ„€μ • μž‘μ„±ν•˜κΈ° `~/demo/Pingclairfile`을 λ§Œλ“­λ‹ˆλ‹€. ```caddyfile { admin 127.0.0.1:2019 } http://localhost:8080 { file_server ./public } ``` μ„Έ κ°€μ§€λ§Œ μ§šμ–΄ λ‘‘λ‹ˆλ‹€. 맨 μœ„μ˜ 이름 μ—†λŠ” 블둝은 μ „μ—­ μ˜΅μ…˜μ΄κ³ , `admin`이 있으면 `pingclair start`, `stop`, `reload`κ°€ μ‹€ν–‰ 쀑인 μ„œλ²„μ™€ 톡신할 수 μžˆμŠ΅λ‹ˆλ‹€. μ‚¬μ΄νŠΈ μ£Όμ†Œμ—λŠ” μŠ€ν‚΄μ΄ λ“€μ–΄κ°€κ³ , `http://`κ°€ 평문을 κ°•μ œν•©λ‹ˆλ‹€. 이게 μ—†μœΌλ©΄ PingclairλŠ” `localhost`λ₯Ό μ΄λ¦„μœΌλ‘œ μ·¨κΈ‰ν•΄ 자체 인증 κΈ°κ΄€μœΌλ‘œ HTTPSλ₯Ό μ œκ³΅ν•˜λ©°, 평문 HTTP ν΄λΌμ΄μ–ΈνŠΈμ—κ²ŒλŠ” 빈 μ‘λ‹΅μœΌλ‘œ λ³΄μž…λ‹ˆλ‹€([HTTPS](/ko/start/https/)). `file_server`의 λ£¨νŠΈλŠ” μž‘μ—… 디렉터리 κΈ°μ€€ μƒλŒ€ κ²½λ‘œμž…λ‹ˆλ‹€. ## 2. βœ… μ‹€ν–‰ 전에 κ²€μ¦ν•˜κΈ° ```bash pingclair validate ``` ```text βœ… Configuration 'Pingclairfile' is valid! ``` `validate`λŠ” 기본적으둜 `./Pingclairfile`을 읽고 `./Caddyfile`도 κ°μ§€ν•©λ‹ˆλ‹€. 섀정을 μ»΄νŒŒμΌν•˜κ³  μΈμ¦μ„œ 경둜 쑴재 μ—¬λΆ€ 같은 의미 검사λ₯Ό μ μš©ν•©λ‹ˆλ‹€. 검증은 κΆŒκ³ κ°€ μ•„λ‹™λ‹ˆλ‹€. μ‹€νŒ¨ν•œ 섀정은 μ‹€ν–‰λ˜μ§€ μ•Šκ³ , λ§ˆμ§€λ§‰ 쀄에 μ΄μœ κ°€ λ‚˜μ˜΅λ‹ˆλ‹€. ## 3. 🧭 섀정이 무엇이 λ˜λŠ”μ§€ 보기 ```bash pingclair adapt --pretty ``` ```text { "debug": false, "servers": [ { "name": "localhost", "names": [ "localhost" ], "listen": [ "[::]:8080" ], ``` 컴파일된 JSON은 μ„œλ²„κ°€ μ‹€μ œλ‘œ μ‹€ν–‰ν•˜λŠ” ν˜•νƒœμž…λ‹ˆλ‹€. μ§€μ‹œμ–΄κ°€ λ¬Έμ„œλŒ€λ‘œ λ™μž‘ν•˜μ§€ μ•Šμ„ λ•Œ κ°€μž₯ λ¨Όμ € λ³Ό κ³³μž…λ‹ˆλ‹€. λŒ€μ‹  `pingclair fmt`κ°€ νŒŒμΌμ— κ°€ν•  변경을 보렀면 λ‹€μŒκ³Ό 같이 ν•©λ‹ˆλ‹€. ```bash pingclair fmt --diff ``` ```text - file_server ./public + file_server ./public ``` `fmt`λŠ” μ •κ·œν˜•μ„ 좜λ ₯ν•˜λ©°, λ“€μ—¬μ“°κΈ°λŠ” 두 칸이 λ©λ‹ˆλ‹€. ## 4. πŸš€ μ‹€ν–‰ν•˜κΈ° λ‘œκ·Έκ°€ 터미널에 λ‚¨λŠ” ν¬κ·ΈλΌμš΄λ“œλ‘œ μ‹€ν–‰ν•©λ‹ˆλ‹€. ```bash pingclair run Pingclairfile ``` ```text πŸš€ Starting Pingclair with config: Pingclairfile πŸš€ Starting Pingclair v0.2.0-rc.3 πŸ“„ Loaded configuration from: Pingclairfile πŸ”§ Configured 1 server(s) πŸ” Auto HTTPS: enabled ``` `--watch`λ₯Ό 뢙이면 μ €μž₯ν•  λ•Œλ§ˆλ‹€ 섀정이 λ‹€μ‹œ μ½ν˜€ 개발 루프가 λ©λ‹ˆλ‹€. ```bash pingclair run --watch Pingclairfile ``` ```text ♻️ Configuration reloaded successfully βœ… Configuration reloaded completed successfully in 2.478622ms ``` μ…Έμ—μ„œ 뢄리해 λ°±κ·ΈλΌμš΄λ“œλ‘œ 돌릴 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. ```bash pingclair start -c Pingclairfile ``` ```text βœ… Pingclair started in the background (pid 4432) ``` `pingclair start`, `stop`, `reload`λŠ” Admin APIλ₯Ό 톡해 μ‹€ν–‰ 쀑인 μ„œλ²„μ— λ„λ‹¬ν•©λ‹ˆλ‹€. μœ„ 섀정에 `admin`이 μžˆλŠ” μ΄μœ μž…λ‹ˆλ‹€. `pingclair run`μ—λŠ” ν•„μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ## 5. πŸ” ν™•μΈν•˜κΈ° ```bash curl -i http://localhost:8080/ ``` ```text HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 34 Last-Modified: Tue, 22 Sep 2026 03:26:39 GMT ETag: "22-6ab1f56f" Vary: Accept-Encoding Accept-Ranges: bytes server: Pingclair ``` `ETag`와 `Last-Modified`λŠ” 파일 μ„œλ²„κ°€ λ””μŠ€ν¬μ—μ„œ μ½μ—ˆλ‹€λŠ” μ¦κ±°μž…λ‹ˆλ‹€. 본문은 `public/index.html`μž…λ‹ˆλ‹€. λ°±κ·ΈλΌμš΄λ“œ μ„œλ²„λ₯Ό λ©ˆμΆ”λ €λ©΄ λ‹€μŒκ³Ό 같이 ν•©λ‹ˆλ‹€. ```bash pingclair stop ``` ```text βœ… Pingclair stopped ``` ## ⚑ λͺ…λ Ή ν•˜λ‚˜λ‘œ λ„μš°λŠ” μ„œλ²„ μ„Έ ν•˜μœ„ λͺ…령은 μ„€μ • 파일 없이 μ„œλΉ„μŠ€ν•©λ‹ˆλ‹€. μ‹œν—˜ν•΄ λ³΄κ±°λ‚˜ μΌνšŒμ„± ν˜ΈμŠ€νŠΈμ—μ„œ μœ μš©ν•©λ‹ˆλ‹€. ```bash pingclair file-server --listen :8081 --root ./public pingclair reverse-proxy --from :8082 --to 127.0.0.1:8081 pingclair respond --listen :8083 -s 200 -b "hello from respond" ``` 각각 μ‹œμž‘ν•  λ•Œ λ¦¬μŠ€λ„ˆλ₯Ό 좜λ ₯ν•©λ‹ˆλ‹€. ```text πŸš€ Starting file server on :8081 serving ./public (browse: false) πŸš€ Starting reverse proxy: :8082 -> ["127.0.0.1:8081"] Server address: [::]:8083 ``` `:8082`둜 온 μš”μ²­μ€ `:8081`의 파일 μ„œλ²„λ‘œ μ „λ‹¬λ˜κ³ , `:8083`은 λ„˜κΈ΄ 본문을 κ·ΈλŒ€λ‘œ λŒλ €μ€λ‹ˆλ‹€. `respond`λŠ” 개발 μ „μš©μž…λ‹ˆλ‹€. ## πŸ” μ„œλΉ„μŠ€μ— λ§‘κΈ°κΈ° μ„œλΉ„μŠ€λŠ” `/etc/Pingclair/Pingclairfile`을 μ‹€ν–‰ν•˜λ―€λ‘œ, 그곳에 두어야 μž¬λΆ€νŒ… 후에도 μ‚΄μ•„λ‚¨μŠ΅λ‹ˆλ‹€. ```bash sudo cp Pingclairfile /etc/Pingclair/Pingclairfile sudo pingclair validate /etc/Pingclair/Pingclairfile sudo pc service reload curl -i http://localhost/ ``` `pc service reload`λŠ” μ‹€ν–‰ 쀑인 μ„œλ²„μ— νŒŒμΌμ„ λ‹€μ‹œ 읽으라고 μš”μ²­ν•˜λ©°, μœ λ‹›μ€ 그것을 `SIGUSR1`둜 ν•©λ‹ˆλ‹€. `pingclair reload`λŠ” Admin APIλ₯Ό 거쳐 같은 μ½”λ“œμ— λ„λ‹¬ν•˜κ³  μ„œλ²„κ°€ κ·Έ νŒŒμΌμ„ μ–΄λ–»κ²Œ λ΄€λŠ”μ§€λ„ λ³΄κ³ ν•©λ‹ˆλ‹€(μ „μ—­ μ˜΅μ…˜ λΈ”λ‘μ˜ `admin`이 ν•„μš”ν•©λ‹ˆλ‹€). `sudo kill -USR1 "$(systemctl show -p MainPID --value pingclair)"`λŠ” λ‘˜ λ‹€ 없이 같은 일을 ν•©λ‹ˆλ‹€. μ–΄λŠ μͺ½μ΄λ“  λ¨Όμ € κ²€μ¦ν•˜κ³ , κ·Έλ‹€μŒ 닡을 μ½μœΌμ‹­μ‹œμ˜€. `systemctl reload`κ°€ 보고할 수 μžˆλŠ” 것은 μ‹ ν˜Έκ°€ μ „λ‹¬λ˜μ—ˆλ‹€λŠ” μ‚¬μ‹€λΏμ΄λ―€λ‘œ, μ„œλ²„μ˜ νŒλ‹¨ β€” μ μš©λ˜μ—ˆλŠ”μ§€, μ΄μœ μ™€ ν•¨κ»˜ κ±°λΆ€λ˜μ—ˆλŠ”μ§€ β€” 은 μœ λ‹›μ˜ status lineκ³Ό 저널에 λ‚¨μŠ΅λ‹ˆλ‹€. κ±°λΆ€λœ μž¬μ μš©μ€ 이전 섀정을 계속 μ„œλΉ„μŠ€ν•©λ‹ˆλ‹€. 그것이 κ±°λΆ€μ˜ λͺ©μ μž…λ‹ˆλ‹€. [μ„œλΉ„μŠ€λ‘œ μ‹€ν–‰](/ko/start/service/#-재적용의-의미)에 μžμ„Έν•œ μ„€λͺ…이 μžˆμŠ΅λ‹ˆλ‹€. ## ⚠️ 잘 λ˜μ§€ μ•Šμ„ λ•Œ - **`Address already in use`.** μ„€μΉ˜ ν”„λ‘œκ·Έλž¨μ˜ μ„œλΉ„μŠ€κ°€ 아직 `:80`을 작고 μžˆκ±°λ‚˜ λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€κ°€ κ·Έ 포트λ₯Ό 작고 μžˆμŠ΅λ‹ˆλ‹€. `sudo ss -ltnp | grep :80`이 주인을 보여 μ£Όκ³ , `sudo pc service stop`이 κΈ°λ³Έ μ„œλΉ„μŠ€λ₯Ό ν’€μ–΄ μ€λ‹ˆλ‹€. - **`http://localhost:8080`μ—μ„œ `Empty reply from server`.** ν‰λ¬ΈμœΌλ‘œ TLS λ¦¬μŠ€λ„ˆμ— λ§ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ‚¬μ΄νŠΈ μ£Όμ†Œμ— `http://`λ₯Ό λΆ™μ΄κ±°λ‚˜, λ‚΄λΆ€ μΈμ¦μ„œλ₯Ό μ‹ λ’°ν•œ λ’€ `https://`둜 ν†΅μ‹ ν•˜μ‹­μ‹œμ˜€. - **`Cannot reach admin API at 127.0.0.1:2019`.** 섀정에 `admin`이 μ—†μ–΄ `pingclair stop`κ³Ό `pingclair reload`λ₯Ό λ°›μ•„ 쀄 λŒ€μƒμ΄ μ—†μŠ΅λ‹ˆλ‹€. μ „μ—­ μ˜΅μ…˜ 블둝에 μΆ”κ°€ν•˜κ±°λ‚˜ ν¬κ·ΈλΌμš΄λ“œ ν”„λ‘œμ„ΈμŠ€λ₯Ό Ctrl-C둜 λ©ˆμΆ”μ‹­μ‹œμ˜€. - **`curl`이 λ£¨ν”„λ°±μ—μ„œ 멈좀.** μ‹œμŠ€ν…œ ν”„λ‘μ‹œκ°€ μš”μ²­μ„ κ°€λ‘œμ±„κ³  μžˆμŠ΅λ‹ˆλ‹€. `curl --noproxy '*'`둜 λ‹€μ‹œ μ‹€ν–‰ν•˜μ‹­μ‹œμ˜€. - **검증이 `Unsupported feature`둜 μ‹€νŒ¨.** μ§€μ‹œμ–΄λŠ” μΈμ‹λ˜μ§€λ§Œ κ΅¬ν˜„μ΄ μ—†κ³ , λ©”μ‹œμ§€κ°€ λŒ€μ•ˆμ„ μ•Œλ € μ€λ‹ˆλ‹€. `encode br`의 경우 ν”„λ‘μ‹œ 응닡에 Brotliκ°€ κ΅¬ν˜„λ˜μ–΄ μžˆμ§€ μ•Šμ•„ `encode zstd gzip`을 κ°€λ¦¬ν‚΅λ‹ˆλ‹€. ## 🧭 λ‹€μŒ 단계 - [HTTPS](/ko/start/https/): 곡개 이름을 μœ„ν•œ μΈμ¦μ„œλ₯Ό Let's Encrypt λ˜λŠ” λ‚΄λΆ€ 인증 κΈ°κ΄€μ—μ„œ. - [μ„œλΉ„μŠ€λ‘œ μ‹€ν–‰](/ko/start/service/): μœ λ‹›, 재적용의 의미, 둜그. - [Pingclairfile](/ko/reference/pingclairfile/): μ–Έμ–΄ 자체. 맀처, μŠ€λ‹ˆνŽ«, μž„ν¬νŠΈ.