ํ์์ ๊ฐ์ด ์ปคํผ ํ ์๊ณผ ํจ๊ป ๋ชจ๋ํฐ๋ง ๋์๋ณด๋๋ฅผ ํ์ธํ๋ ์ค, ๋ณ ํค๋ ๋ฐค ์๋น์ค์ ์ ์์ด ์ ๋๋ ๊ฒ์ ๋ฐ๊ฒฌํ๋ค. ๋ธ๋ผ์ฐ์ ์๋ ๋ฌด์ ํ๊ฒ๋ ERR_TOO_MANY_REDIRECTS ์ค๋ฅ๋ง ๋ฐ๋ณต๋๊ณ ์์๋ค.
"์ด์ ๊น์ง ์ ๋๋ ์ฌ์ดํธ๊ฐ ๊ฐ์๊ธฐ ์...?"
์ฒ์์๋ ๋น์ฐํ Nginx ์ค์ ๋ฌธ์ ๋ผ๊ณ ์๊ฐํ๋ค. ์ต๊ทผ ๋ฐฐํฌ ๊ณผ์ ์์ ๋ฉ์ธ ์๋ฒ์ ํ๋ก ํธ์๋์ ์๋ nginx.conf ํ์ผ ๋ ๋ค ๋ฆฌ๋ค์ด๋ ํธ ์ฝ๋๊ฐ ์ค๋ณต๋์ด ์์๊ณ , API ํค๋ฅผ ์ฌ๋ฌ ๋ฒ ํธ์ถํด์ผ ํ๋ ์ฐ๋ฆฌ ์น์๋น์ค ํน์ฑ์ ์ด๊ฒ ๊ทผ๋ณธ ์์ธ์ผ ๊ฑฐ๋ผ ํ์ ํ๋ค.
# ๊ธํ๊ฒ Nginx ์ค์ ์์
vim /etc/nginx/nginx.conf
# ์ค๋ณต๋ ๋ฆฌ๋ค์ด๋ ํธ ๊ท์น ์ ๊ฑฐ
sudo systemctl reload nginx
๋คํํ ์์ ํ ์๋น์ค๊ฐ ์ ์ํ๋์๋ค. "์ญ์ Nginx ๋ฌธ์ ์๊ตฌ๋" ํ๋ฉฐ ์๋์ ํ์จ์ ์ฌ์๋ค.
๋ฉฐ์น ํ, ์๋น์ค๊ฐ ์ ๊ตด๋ฌ๊ฐ๊ณ ์๋ค๊ณ ์๊ฐํ๋ฉฐ ์๋ก์ด ๊ธฐ๋ฅ์ ๋ฐฐํฌํ๋ค. ๊ทธ๋ฐ๋ฐ...
๋ ๊ฐ์ ์ด์๊ฐ ๋ฐ์ํ๋ค!
์ด๋ฒ์๋ ๋ธ๋ผ์ฐ์ ์ค๋ฅ๊ฐ ์๋๋ผ ์๋ฒ ๋ก๊ทธ์์ ๋ ์ฌ๊ฐํ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ๋ค:
2025-09-18T07:01:29.821+09:00 ERROR 1 --- [byeolnight] [main]
Caused by: java.lang.IllegalArgumentException:
Could not resolve placeholder 'app.security.jwt.secret' in value "${app.security.jwt.secret}"
"Nginx ๋ฌธ์ ๊ฐ ์๋์๋ค... ์ง์ง ์์ธ์ ๋ฐ๋ก ์์๊ตฌ๋."
๋ก๊ทธ๋ฅผ ์์ธํ ๋ณด๋ ์ด์ํ ์ ์ด ์์๋ค:
โ
Located environment: name=byeolnight, profiles=[prod]
โ
MySQL ๋น๋ฐ๋ฒํธ: ์ ์ ๋ณตํธํ
โ
Redis ๋น๋ฐ๋ฒํธ: ์ ์ ๋ณตํธํ
โ
AWS API ํค๋ค: ์ ์ ๋ณตํธํ
โ JWT ์ํฌ๋ฆฟ: Could not resolve placeholder
"๋ค๋ฅธ ์ํธํ๋ ์ค์ ๋ค์ ๋ฉ์ฉกํ๋ฐ JWT ์ํฌ๋ฆฟ๋ง ์...?"
byeolnight-prod.yml ํ์ผ์ ์ด์ด๋ณด๋ JWT ์ํฌ๋ฆฟ์ด ์ด์ํ๋ค:
# ์ ์์ ์ธ ๋ค๋ฅธ ์ค์ ๋ค
password: '{cipher}4f645acb62e6302d47f02b2d3b88c8cda3c90e64f91d042dc9ff2613955ba***'
# ๋ฌธ์ ์ JWT ์ํฌ๋ฆฟ
jwt:
secret: '{cipher}eaebecbd17000326cf1b0281b5e9b9c905f10300270c747f95207cea0c029d34***'
์ถ๋ฆฌ ๊ฒฐ๊ณผ:
"๋ฒ์ธ์... ์์๋ ์ํธํ ๋ฐ์ดํฐ์๋ค!"
์ด์ ์๋น์ค๊ฐ ๋ค์ด๋ ์ํฉ์์ ์์ธ ๋ถ์๋ณด๋ค๋ ๋น ๋ฅธ ๋ณต๊ตฌ๊ฐ ์ฐ์ ์ด์๋ค.
# ์๊ธ์ฒ์น: JWT ์ํฌ๋ฆฟ์ ํ๋ฌธ์ผ๋ก ๋ณ๊ฒฝ
jwt:
secret: 'byeolnight-jwt-secret-key-2025-very-long-and-secure-key-for-production-use-only'
# ์๋ฒ ์ฌ์์
docker-compose restart app
"ํด... ์ผ๋จ ์๋น์ค๋ ์ด์๋ฌ๋ค. ์ด์ ์ง์ง ํด๊ฒฐ์ฑ ์ ์ฐพ์๋ณด์."
ํ๋ฌธ์ผ๋ก ์์ ํด๊ฒฐํ ํ, ๋ณด์์ ์ํด ์ ๋๋ก ๋ ์ํธํ๋ฅผ ์งํํ๋ค.
# 1๋จ๊ณ: Config Server ์์
cd config-server
gradlew.bat bootRun
# 2๋จ๊ณ: JWT ์ํฌ๋ฆฟ ์ฌ์ํธํ
encrypt-simple.bat "byeolnight-jwt-secret-key-2025-very-long-and-secure-key-for-production-use-only"
ํฐ๋ฏธ๋ ์ถ๋ ฅ:
Encrypting: "byeolnight-jwt-secret-key-2025-very-long-and-secure-key-for-production-use-only"
8bab426a814eb620e297d3a336d22ebf6ede3b285003154b24898d87ba743416***[์๋ก์ด ์ํธํ ํค ์์ฑ๋จ]
"์๋ก์ด ์ํธํ ํค๊ฐ ์์ฑ๋์๋ค! ์ด์ ์ด๊ฑธ๋ก ๊ต์ฒดํ์."
# byeolnight-prod.yml ์ต์ข
์์
jwt:
secret: '{cipher}8bab426a814eb620e297d3a336d22ebf6ede3b285003154b24898d87ba743416***'
# ์๋ฒ ์ฌ์์ ํ ๋ก๊ทธ ํ์ธ
docker logs -f byeolnight-app-1
๊ธฐ๋ค๋ฆฌ๋ ์ฑ๊ณต ๋ก๊ทธ:
โ
JwtAuthenticationFilter: Filter 'jwtAuthenticationFilter' configured for use
โ
TomcatWebServer: Tomcat started on port 8080 (http)
โ
ByeolnightApplication: Started ByeolnightApplication in 28.808 seconds
โ
๋ณ ํค๋ ๋ฐค์ด ๋ค์ ์ด์๋ฌ์ต๋๋ค! ๐
"์ด์ ์ผ ๋ง์ ๋๊ณ ์ปคํผ๋ฅผ ๋ง์ค ์ ์๊ฒ ๋ค... โ"
# Config Server (application.yml)
encrypt:
key: byeolnight-config-encryption-key-2025!@#$%^&*()
fail-on-error: false
@echo off
echo Encrypting: "%1"
curl -u config-admin:config-secret-2024 ^
"http://localhost:8888/encrypt" ^
-d "%1" ^
-H "Content-Type: text/plain"
@Component
public class JwtTokenProvider {
public JwtTokenProvider(@Value("${app.security.jwt.secret}") String secret,
StringRedisTemplate redisTemplate) {
this.key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
this.redisTemplate = redisTemplate;
}
}
# Config Server Health Check
management:
endpoints:
web:
exposure:
include: health,info,decrypt
# ๋ฐฐํฌ ์ ์ํธํ ๊ฒ์ฆ ์คํฌ๋ฆฝํธ
validate-config.sh byeolnight prod
ERR_TOO_MANY_REDIRECTS๋ Nginx ๋ฌธ์ ๋ก ๋ณด์์ง๋ง์ํ๋ก๊ทธ: ๊ทธ๋ ๋ฐค, ๋ณ ํค๋ ๋ฐค ์๋น์ค๋ ๋ค์ ํํ๋กญ๊ฒ ์ฌ์ฉ์๋ค์ ์ฐ์ฃผ ์ด์ผ๊ธฐ๋ฅผ ๋ด์๋ด๊ณ ์์๋ค. ๋๋ก๋ ์์์น ๋ชปํ ๊ณณ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง๋ง, ์ฐจ๊ทผ์ฐจ๊ทผ ์์ธ์ ์ฐพ์ ํด๊ฒฐํ๋ ๊ณผ์ ์ด์ผ๋ง๋ก ๊ฐ๋ฐ์์ ์ง์ง ์ค๋ ฅ์ด ์๋๊น? ๐โจ