# ๐Ÿ”€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋ก์‹œํ•˜๊ธฐ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ์ด ์ฒ˜์Œ ์ฐพ๋Š” ๊ตฌ์„ฑ์ž…๋‹ˆ๋‹ค. ๊ณต๊ฐœ ์ฃผ์†Œ ํ•˜๋‚˜, ๊ทธ ๋’ค์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธ์Šคํ„ด์Šค ํ•˜๋‚˜ ์ด์ƒ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์†๋Œ€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ํŽ˜์ด์ง€๋Š” ๋‹จ์ผ ์—…์ŠคํŠธ๋ฆผ์—์„œ ์‹œ์ž‘ํ•ด ํ—ฌ์Šค ์ฒดํฌ, ํƒ€์ž„์•„์›ƒ, ๋ฐฑ์—…์„ ๊ฐ–์ถ˜ ํ’€๊นŒ์ง€ ๋งŒ๋“ค์–ด ๋ณด๊ณ , ๋ฐ˜๋Œ€ํŽธ์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ฌด์—‡์„ ๋ณด๋Š”์ง€ ๋ณด์—ฌ ์ค๋‹ˆ๋‹ค. ## ๐Ÿงพ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— - Pingclair๊ฐ€ ์„ค์น˜๋˜์–ด ์‹คํ–‰ ์ค‘์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค([์„ค์น˜](/ko/start/install/)). ์‹คํ—˜ํ•˜๋Š” ๋™์•ˆ์—๋Š” ์„œ๋น„์Šค๋ฅผ ๋ฉˆ์ถฅ๋‹ˆ๋‹ค: `sudo pc service stop`. - ๋กœ์ปฌ ํฌํŠธ์—์„œ ๋“ฃ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜. ์˜ˆ์ œ๋Š” `127.0.0.1:3000`์„ ์”๋‹ˆ๋‹ค. - ํ”„๋ก์‹œ ์ž์‹ ์˜ ํฌํŠธ. ์˜ˆ์ œ๋Š” `:8080`. ## ๐Ÿ”€ ์—…์ŠคํŠธ๋ฆผ ํ•˜๋‚˜ ```caddyfile { admin 127.0.0.1:2019 } http://:8080 { reverse_proxy 127.0.0.1:3000 } ``` ```bash sudo cp Pingclairfile /etc/Pingclair/Pingclairfile sudo pingclair validate /etc/Pingclair/Pingclairfile sudo kill -USR1 "$(systemctl show -p MainPID --value pingclair)" curl -i http://localhost:8080/ ``` ์‘๋‹ต์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฒƒ์ด๊ณ  ๊ทธ ํ—ค๋”๋„ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. `admin`์€ `pingclair reload`๊ฐ€ ์‹คํ–‰ ์ค‘์ธ ์„œ๋ฒ„์— ๋‹ฟ๊ธฐ ์œ„ํ•œ ๊ฒƒ์ด๋ฉฐ `SIGUSR1`์—๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค([์žฌ์ ์šฉ์˜ ์˜๋ฏธ](/ko/start/service/#-์žฌ์ ์šฉ์˜-์˜๋ฏธ)). ## โš–๏ธ ์—…์ŠคํŠธ๋ฆผ ์—ฌ๋Ÿฌ ๊ฐœ `to`๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ๋‚˜์—ดํ•˜๊ณ  ๋ถ„๋ฐฐ ๋ฐฉ์‹์„ ๊ณ ๋ฆ…๋‹ˆ๋‹ค. ```caddyfile http://:8080 { reverse_proxy { to 127.0.0.1:3000 to 127.0.0.1:3001 lb_policy round_robin } } ``` ์‚ด์•„ ์žˆ๋Š” ๋‘ ๋Œ€๋กœ ๊ฐ„ 6๋ฒˆ์˜ ์š”์ฒญ์€ ๋ฒˆ๊ฐˆ์•„ ๊ฐ‘๋‹ˆ๋‹ค. ์–ด๋А ํฌํŠธ๊ฐ€ ์‘๋‹ตํ–ˆ๋Š”์ง€ ์•Œ๋ ค ์ฃผ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์ธก์ •ํ•œ ๊ฐ’์ž…๋‹ˆ๋‹ค. ```text 3000 3001 3000 3001 3000 3001 ``` | `lb_policy` | ๋™์ž‘ | | --- | --- | | `round_robin` | ์ˆœ์„œ๋Œ€๋กœ ์—…์ŠคํŠธ๋ฆผ๋งˆ๋‹ค ํ•˜๋‚˜์”ฉ. ๊ธฐ๋ณธ๊ฐ’. | | `random` | ์ž„์˜์˜ ์—…์ŠคํŠธ๋ฆผ. | | `least_conn` | ์ง„ํ–‰ ์ค‘์ธ ์—ฐ๊ฒฐ์ด ๊ฐ€์žฅ ์ ์€ ์—…์ŠคํŠธ๋ฆผ. | | `ip_hash` | ๊ฐ™์€ ํด๋ผ์ด์–ธํŠธ ์ฃผ์†Œ๋Š” ํ•ญ์ƒ ๊ฐ™์€ ์—…์ŠคํŠธ๋ฆผ์œผ๋กœ. | | `first` | ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ฒซ ์—…์ŠคํŠธ๋ฆผ. | | `header <์ด๋ฆ„>`, `cookie <์ด๋ฆ„>`, `query <์ด๋ฆ„>` | ๊ทธ ํ•„๋“œ๋กœ ํ•ด์‹œํ•ด ์„ธ์…˜์„ ํ•œ ์ธ์Šคํ„ด์Šค์— ๊ณ ์ •. | | `weighted_round_robin <๊ฐ€์ค‘์น˜> โ€ฆ` | ๊ฐ™์€ ์ค„์— ์—…์ŠคํŠธ๋ฆผ๋ณ„ ๊ฐ€์ค‘์น˜. | ๊ฐ€์ค‘์น˜๋Š” ์—…์ŠคํŠธ๋ฆผ๋งˆ๋‹ค ์“ธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์œ ๊ฐ€ ์ธ์Šคํ„ด์Šค๋งˆ๋‹ค ๋‹ค๋ฅผ ๋•Œ ๋” ์ฝ๊ธฐ ์ข‹์Šต๋‹ˆ๋‹ค. ```caddyfile http://:8080 { reverse_proxy { to 127.0.0.1:3000 { weight 3 } to 127.0.0.1:3001 } } ``` โš ๏ธ `lb_policy weighted_round_robin 3 1`์€ ์ด๋ฏธ ์“ฐ์ธ ์—…์ŠคํŠธ๋ฆผ์„ ์„ธ๋ฏ€๋กœ `to` ์ค„์ด **๋จผ์ €** ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ˆœ์„œ๋ฅผ ๋’ค์ง‘์œผ๋ฉด `validate`๊ฐ€ `2 weights were given for 0 upstreams`๋กœ ๊ฑฐ๋ถ€ํ•ฉ๋‹ˆ๋‹ค. `backup`์œผ๋กœ ํ‘œ์‹œํ•œ ์—…์ŠคํŠธ๋ฆผ์€ ๋‹ค๋ฅธ ๋ชจ๋“  ์—…์ŠคํŠธ๋ฆผ์„ ์“ธ ์ˆ˜ ์—†์„ ๋•Œ๋งŒ ์“ฐ์ž…๋‹ˆ๋‹ค. ```caddyfile http://:8080 { reverse_proxy { to 127.0.0.1:3000 to 127.0.0.1:3001 { backup } } } ``` ๋‘˜ ๋‹ค ์‚ด์•„ ์žˆ์œผ๋ฉด ๋ชจ๋“  ์š”์ฒญ์ด `3000`์œผ๋กœ ๊ฐ‘๋‹ˆ๋‹ค. ๊ทธ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ฉˆ์ถ”๋ฉด ๋‹ค์Œ ์š”์ฒญ์€ `3001`์ด ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค. ## ๐Ÿฉบ ํ—ฌ์Šค ์ฒดํฌ ์ฒดํฌ๊ฐ€ ์—†์œผ๋ฉด ์—…์ŠคํŠธ๋ฆผ์€ ์š”์ฒญ์ด ์‹คํŒจํ•œ ๋’ค์—์•ผ ๋น ์ง‘๋‹ˆ๋‹ค. ์ฒดํฌ๊ฐ€ ์žˆ์œผ๋ฉด ๋จผ์ € ๋น ์ง‘๋‹ˆ๋‹ค. ```caddyfile http://:8080 { reverse_proxy { to 127.0.0.1:3000 to 127.0.0.1:3001 health_check { path /health interval 2s timeout 1s status 200 consecutive_failure 2 consecutive_success 1 } } } ``` ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—๋Š” ๊ฐ’์‹ธ๊ฒŒ ์‘๋‹ตํ•˜๋Š” ์—”๋“œํฌ์ธํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค(์—ฌ๊ธฐ์„œ๋Š” `/health`). ์ƒํƒœ ๋ณ€ํ™”๋Š” ๋กœ๊ทธ์— ๋‚จ์œผ๋ฏ€๋กœ ์™œ ๋กœํ…Œ์ด์…˜์—์„œ ๋น ์กŒ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ```text INFO pingclair_proxy::health_check: ๐Ÿฉบ Active upstream health changed backend=Inet(127.0.0.1:3001) healthy=false INFO pingclair_proxy::health_check: ๐Ÿฉบ Active upstream health changed backend=Inet(127.0.0.1:3001) healthy=true ``` ์ด ๊ตฌ์„ฑ์—์„œ ์ธก์ •: ๋‘ ๋ฒˆ์งธ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฃฝ์ด๋ฉด ๋ชจ๋“  ํŠธ๋ž˜ํ”ฝ์ด ์ฒซ ๋ฒˆ์งธ๋กœ ๊ฐ”๊ณ , ๋˜์‚ด๋ฆฌ๋ฉด `consecutive_success`๋ฒˆ์˜ ์„ฑ๊ณต ๋’ค์— ๋กœํ…Œ์ด์…˜์œผ๋กœ ๋Œ์•„์™”์Šต๋‹ˆ๋‹ค. ์‹ค์ œ Caddyfile์ด ์“ฐ๋Š” ํ‰ํ‰ํ•œ ํ‘œ๊ธฐ(`health_uri`, `health_interval`, `health_timeout`, `health_status`, `health_fails`, `health_passes`)๋„ ๊ฐ™์€ ์ฒดํฌ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ## โฑ๏ธ ํƒ€์ž„์•„์›ƒ ํƒ€์ž„์•„์›ƒ์€ `reverse_proxy` ๋ฐ”๋กœ ์•„๋ž˜๊ฐ€ ์•„๋‹ˆ๋ผ ๊ทธ ์•ˆ์˜ `transport http` ๋ธ”๋ก์— ์žˆ์Šต๋‹ˆ๋‹ค. ```caddyfile http://:8080 { reverse_proxy { to 127.0.0.1:3099 to 127.0.0.1:3000 transport http { connect_timeout 1s first_byte_timeout 1s read_timeout 30s write_timeout 30s } } } ``` ์ธก์ •: `127.0.0.1:3099`๊ฐ€ ์•„๋ฌด๊ฒƒ๋„ ๋ฐ›์ง€ ์•Š์œผ๋ฉด `connect_timeout 1s`๋กœ 1์ดˆ๋ฅผ ์“ฐ๊ณ  ์š”์ฒญ์€ ๋‘ ๋ฒˆ์งธ ์—…์ŠคํŠธ๋ฆผ์œผ๋กœ ์žฌ์‹œ๋„๋˜์–ด `200`์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์—ฐ๊ฒฐ๋งŒ ๋ฐ›๊ณ  ๋ณธ๋ฌธ์„ 3์ดˆ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—๋Š” `first_byte_timeout 1s`๊ฐ€ ์ ์šฉ๋˜์–ด ํด๋ผ์ด์–ธํŠธ๋Š” `504`๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. `dial_timeout`์€ `reverse_proxy`์˜ ์˜ต์…˜์ด ์•„๋‹™๋‹ˆ๋‹ค. ๊ฑฐ๊ธฐ ์“ฐ๋ฉด `validate`๊ฐ€ `Unknown directive 'reverse_proxy: dial_timeout'`์œผ๋กœ ๊ฑฐ๋ถ€ํ•ฉ๋‹ˆ๋‹ค. `transport http` ์•ˆ์—์„œ์˜ ์ด๋ฆ„์€ `connect_timeout`์ž…๋‹ˆ๋‹ค. ## ๐Ÿ” ์ด๋ฆ„์œผ๋กœ ์ง€์ •ํ•˜๋Š” ์—…์ŠคํŠธ๋ฆผ ์—…์ŠคํŠธ๋ฆผ์€ ์ฃผ์†Œ ๋Œ€์‹  ์ด๋ฆ„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒˆ IP๋กœ ๋‹ค์‹œ ๋œจ๋Š” ์ปจํ…Œ์ด๋„ˆ์— ํ•„์š”ํ•œ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค. ```caddyfile { dns_refresh 5s } http://:8080 { reverse_proxy { to api.internal:3000 } } ``` ๊ทธ ๊ฐ„๊ฒฉ๋งˆ๋‹ค ์ด๋ฆ„์„ ๋‹ค์‹œ ํ•ด์„ํ•˜๊ณ , ๋ณ€๊ฒฝ์€ ๋กœ๊ทธ์— ๋‚จ์Šต๋‹ˆ๋‹ค. ```text INFO pingclair_proxy::dns: ๐Ÿ”„ Upstream DNS scheduler enabled interval_secs=5 pools=1 INFO pingclair_proxy::dns: ๐Ÿ”„ Upstream DNS refresh changed=1 adopted=0 kept_stale=0 unresolved=0 ``` `/etc/hosts`๋ฅผ ์œ ์ผํ•œ ์ •๋ณด์›์œผ๋กœ ํ•œ ์ธก์ •: `api.internal`์„ `127.0.0.1`๋กœ ๋‘๋ฉด ์ฒซ ์ธ์Šคํ„ด์Šค๊ฐ€ ์‘๋‹ตํ–ˆ๊ณ , `127.0.0.2`๋กœ ๊ณ ์น˜๋ฉด ๊ฐ„๊ฒฉ ์•ˆ์— ๋‘ ๋ฒˆ์งธ๊ฐ€ ์‘๋‹ตํ–ˆ์Šต๋‹ˆ๋‹ค. ์žฌ์‹œ์ž‘๋„ ์‹คํŒจํ•œ ์š”์ฒญ๋„ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ด์„์— ์‹คํŒจํ•˜๋ฉด ์ด์ „ ์ฃผ์†Œ๊ฐ€ ๋กœํ…Œ์ด์…˜์— ๋‚จ์Šต๋‹ˆ๋‹ค. ## ๐Ÿ“จ ์—…์ŠคํŠธ๋ฆผ์ด ๋ณด๋Š” ๊ฒƒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์›๋ž˜์˜ `Host`์™€ ๋Š˜ ์“ฐ๋Š” ํ—ค๋”์— ๋‹ด๊ธด ํด๋ผ์ด์–ธํŠธ ์ฃผ์†Œ๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. ```text { "host": "127.0.0.1:8080", "x_forwarded_for": "127.0.0.1", "x_forwarded_proto": "http", "x_real_ip": "127.0.0.1" } ``` ๋‹ค๋ฅธ ํ”„๋ก์‹œ ๋’ค์—์„œ๋Š” ๊ทธ ํ”„๋ก์‹œ๊ฐ€ `trusted_proxies`์— ์—†์œผ๋ฉด ์ด ํ—ค๋”์˜ ์ฃผ์†Œ๋Š” ๊ทธ ํ”„๋ก์‹œ์˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค([Cloudflare Tunnel ๊ฐ€์ด๋“œ](/ko/guides/cloudflare-tunnel/)). ## โš ๏ธ ์ž˜ ๋˜์ง€ ์•Š์„ ๋•Œ - **ํ”„๋ก์‹œ์˜ `502`.** ์–ด๋–ค ์—…์ŠคํŠธ๋ฆผ๋„ ์‘๋‹ตํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋“ฃ๊ณ  ์žˆ๋Š”์ง€(`sudo ss -ltnp | grep :3000`)์™€ ์ฃผ์†Œ๊ฐ€ ๋งž๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. - **์ž ์‹œ ๋’ค `504`.** ํƒ€์ž„์•„์›ƒ์ด ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค. ๋А๋ฆฐ ๋ฐฑ์—”๋“œ๋ฉด `first_byte_timeout`, ๋А๋ฆฐ ๋ณธ๋ฌธ์ด๋ฉด `read_timeout`, ๊ฒฐ์ฝ” ๋ฐ›์ง€ ์•Š๋Š” ์ƒ๋Œ€๋ฉด `connect_timeout`์ž…๋‹ˆ๋‹ค. - **`Unknown directive 'reverse_proxy: โ€ฆ'`.** ๊ทธ ์˜ต์…˜์€ ์ค‘์ฒฉ ๋ธ”๋ก์— ์†ํ•ฉ๋‹ˆ๋‹ค (ํƒ€์ž„์•„์›ƒ์€ `transport http`, ์ฒดํฌ๋Š” `health_check`). `validate`๊ฐ€ ๊ฑฐ๋ถ€ํ•œ ์ฒ ์ž๋ฅผ ๊ทธ๋Œ€๋กœ ์•Œ๋ ค ์ค๋‹ˆ๋‹ค. - **์„ค์ • ๋ณ€๊ฒฝ์ด ๋ฐ˜์˜๋˜์ง€ ์•Š์Œ.** ์žฌ์ ์šฉ์ด ์ ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ •์ฑ…์ด์ง€ ์ƒˆ ๋ฆฌ์Šค๋„ˆ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์žฌ์ ์šฉ์ด ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์˜ฎ๊ฒผ๋‹ค๋ฉด ์œ ๋‹›์˜ status line์ด ๋ฐ”๋€ ์ฃผ์†Œ๋ฅผ ์•Œ๋ ค ์ฃผ๊ณ , `sudo pc service restart`๊ฐ€ ๊ทธ๊ฒƒ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค ([์„œ๋น„์Šค๋กœ ์‹คํ–‰](/ko/start/service/#-์žฌ์ ์šฉ์˜-์˜๋ฏธ)). - **๋ชจ๋“  ์š”์ฒญ์ด ํ•œ ์ธ์Šคํ„ด์Šค๋กœ ๊ฐ.** ๊ทธ๊ฒƒ์ด ์œ ์ผํ•˜๊ฒŒ ๊ฑด๊ฐ•ํ•œ ์—…์ŠคํŠธ๋ฆผ์ž…๋‹ˆ๋‹ค. ํ—ฌ์Šค ์ฒดํฌ ๋กœ๊ทธ๊ฐ€ ์–ธ์ œ ์–ด๋–ค ์ด์œ ๋กœ ๋‚˜๋จธ์ง€๊ฐ€ ๋น ์กŒ๋Š”์ง€ ์•Œ๋ ค ์ค๋‹ˆ๋‹ค(`ConnectRefused`, `failure_statuses` ๋“ฑ). ## ๐Ÿงญ ๋‹ค์Œ ๋‹จ๊ณ„ - [์ •์  ์‚ฌ์ดํŠธ ์„œ๋น„์Šค](/ko/guides/static-site/): ์••์ถ•, ์บ์‹œ, ๋‹จ์ผ ํŽ˜์ด์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํด๋ฐฑ. - [`reverse_proxy`](/ko/reference/directives/#reverse_proxy): ์ง€์‹œ์–ด ๋ ˆํผ๋Ÿฐ์Šค. - [์„œ๋น„์Šค๋กœ ์‹คํ–‰](/ko/start/service/): ์žฌ์ ์šฉ, ์žฌ์‹œ์ž‘, ๋กœ๊ทธ.