๐Ÿ’ป PROJECT/[Spring Boot, React] ๋…์„œ ์Šต๊ด€ ๊ด€๋ฆฌ ์„œ๋น„์Šค

[ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…] JWT secret ํ‚ค ๊ธธ์ด ๋ถ€์กฑ์œผ๋กœ ์ธํ•œ WeakKeyException

devCloud 2026. 5. 7. 21:49
728x90
TROUBLESHOOTING

JWT secret ํ‚ค ๊ธธ์ด ๋ถ€์กฑ์œผ๋กœ ์ธํ•œ WeakKeyException ํ•ด๊ฒฐ

1. ๊ตฌํ˜„ ๋ฐฐ๊ฒฝ

JWT ๊ธฐ๋ฐ˜ ์ธ์ฆ ์‹œ์Šคํ…œ์„ ๊ตฌํ˜„ํ–ˆ๋‹ค. JwtProvider์— @PostConstruct๋กœ init() ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ์‹œ secret ํ‚ค๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋„๋ก ํ–ˆ๊ณ , application.yml์— jwt.secret ๊ฐ’์„ ์„ค์ •ํ–ˆ๋‹ค.

JWT ์„œ๋ช…์—๋Š” secret ํ‚ค๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค. ์ด ํ‚ค๋Š” ํ† ํฐ์ด ๋ณ€์กฐ๋˜์ง€ ์•Š์•˜๋Š”์ง€ ๊ฒ€์ฆํ•˜๋Š” ๊ธฐ์ค€์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์‚ฌ์šฉํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์š”๊ตฌํ•˜๋Š” ์ตœ์†Œ ๊ธธ์ด๋ฅผ ๋งŒ์กฑํ•ด์•ผ ํ•œ๋‹ค.

2. ๋ฌธ์ œ ์ƒํ™ฉ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜์ž๋งˆ์ž ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋˜์ง€ ์•Š์•˜๊ณ , jwtProvider ๋นˆ ์ƒ์„ฑ ๊ณผ์ •์—์„œ ์ดˆ๊ธฐํ™” ๋ฉ”์„œ๋“œ ์‹คํ–‰์— ์‹คํŒจํ–ˆ๋‹ค.

Error creating bean with name 'jwtProvider': Invocation of init method failed

์Šคํƒ ํŠธ๋ ˆ์ด์Šค๋ฅผ ๋”ฐ๋ผ๊ฐ€๋ณด๋‹ˆ ๊ทผ๋ณธ ์›์ธ์€ WeakKeyException์ด์—ˆ๋‹ค. ์ง€์ •ํ•œ secret ํ‚ค์˜ ๊ธธ์ด๊ฐ€ JWT HMAC-SHA ์•Œ๊ณ ๋ฆฌ์ฆ˜์—์„œ ์š”๊ตฌํ•˜๋Š” ๋ณด์•ˆ ๊ธฐ์ค€์„ ์ถฉ์กฑํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.

io.jsonwebtoken.security.WeakKeyException: The specified key byte array is 152 bits
which is not secure enough for any JWT HMAC-SHA algorithm.


3. ์›์ธ

์›์ธ์€ application.yml์— ์„ค์ •ํ•œ jwt.secret ๊ธฐ๋ณธ๊ฐ’์ด ๋„ˆ๋ฌด ์งง์•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

app.jwt.secret=${JWT_SECRET:change-me-for-local}

๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•œ change-me-for-local์€ ๊ธธ์ด๊ฐ€ ์งง์•„ HMAC-SHA256 ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ตœ์†Œ ์š”๊ตฌ ํ‚ค ๊ธธ์ด์ธ 256๋น„ํŠธ(32๋ฐ”์ดํŠธ)๋ฅผ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.

HMAC-SHA256์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ secret ํ‚ค๋Š” ์ตœ์†Œ 32๋ฐ”์ดํŠธ ์ด์ƒ์ด์–ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ณด๋‹ค ์งง์€ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด jjwt๊ฐ€ WeakKeyException์„ ๋ฐœ์ƒ์‹œ์ผœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘์„ ๋ง‰๋Š”๋‹ค.

4. ํ•ด๊ฒฐ

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ jwt.secret ๊ฐ’์„ 32์ž ์ด์ƒ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ๋Š” ์ถฉ๋ถ„ํ•œ ๊ธธ์ด์˜ ์ž„์‹œ secret ๊ฐ’์„ ์„ค์ •ํ•ด ์„œ๋ฒ„๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๊ธฐ๋™๋˜๋„๋ก ํ–ˆ๋‹ค.

jwt:
  secret: booktine-secret-key-for-jwt-signing-must-be-32bytes-or-longer

secret ํ‚ค ๊ธธ์ด๋ฅผ ์ถฉ๋ถ„ํžˆ ๋Š˜๋ฆฐ ๋’ค ์„œ๋ฒ„๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๊ธฐ๋™๋˜์—ˆ๊ณ , JwtProvider ์ดˆ๊ธฐํ™”๋„ ์„ฑ๊ณตํ–ˆ๋‹ค.

์šด์˜ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  secret ํ‚ค๋Š” ์ง์ ‘ ์ž‘์„ฑํ•˜๊ธฐ๋ณด๋‹ค, ์•„๋ž˜์™€ ๊ฐ™์€ ๋ช…๋ น์–ด๋กœ ์ถฉ๋ถ„ํžˆ ๊ธด ๋žœ๋ค ๊ฐ’์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•˜๋‹ค.

openssl rand -base64 64

์ƒ์„ฑํ•œ ๊ฐ’์€ ์ฝ”๋“œ๋‚˜ ์„ค์ • ํŒŒ์ผ์— ์ง์ ‘ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ  ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ๋ถ„๋ฆฌํ•œ ๋’ค, application.yml์—์„œ ์ฐธ์กฐํ•˜๋„๋ก ๊ตฌ์„ฑํ•œ๋‹ค.

jwt:
  secret: ${JWT_SECRET}

๋กœ์ปฌ ํ™˜๊ฒฝ์€ application-local.yml์— ๋ณ„๋„๋กœ ๊ด€๋ฆฌํ•˜๊ฑฐ๋‚˜, .env ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌํ•ด๋‘๋Š” ๋ฐฉ์‹์ด ๊น”๋”ํ•˜๋‹ค.


5. ์™œ ๋Ÿฐํƒ€์ž„์ด ์•„๋‹ˆ๋ผ ์‹œ์ž‘ ์‹œ์ ์— ํ„ฐ์ง€๋Š”๊ฐ€

์ฒ˜์Œ์—๋Š” ์š”์ฒญ์„ ์ฒ˜์Œ ์ฒ˜๋ฆฌํ•  ๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์™œ ์„œ๋ฒ„ ์‹œ์ž‘ ์‹œ์ ์— ๋ฐ”๋กœ ์‹คํŒจํ•˜๋Š”์ง€ ์˜๋ฌธ์ด ๋“ค์—ˆ๋‹ค.

์ด์œ ๋Š” jjwt๊ฐ€ ์˜๋„์ ์œผ๋กœ ์ดˆ๊ธฐํ™” ์‹œ์ ์— ํ‚ค ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. @PostConstruct๋กœ ํ‚ค๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ์‹œ์ ์— ์ŠคํŽ™ ๋ฏธ๋‹ฌ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ณ , ๊ธฐ์ค€์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•˜๋ฉด ์ฆ‰์‹œ ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค.

 

์ž˜๋ชป๋œ ํ‚ค๋กœ ์„œ๋ฒ„๊ฐ€ ๋œฌ ๋’ค ์ธ์ฆ ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค, ์•„์˜ˆ ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰๋Š” ์ชฝ์ด ๋” ์•ˆ์ „ํ•˜๋‹ค. ์ด๋Ÿฐ ๋ฐฉ์‹์„ fail-fast๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

fail-fast๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ์„ค์ •์ด๋‚˜ ์ƒํƒœ๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ ๋น ๋ฅธ ์‹œ์ ์— ๋ฐœ๊ฒฌํ•˜๊ณ  ์ฐจ๋‹จํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ๋ณด์•ˆ ์„ค์ •์ฒ˜๋Ÿผ ์ž˜๋ชป๋œ ์ƒํƒœ๋กœ ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋˜๋ฉด ์œ„ํ—˜ํ•ด์งˆ ์ˆ˜ ์žˆ๋Š” ์˜์—ญ์—์„œ๋Š” ํŠนํžˆ ์ค‘์š”ํ•œ ํŒจํ„ด์ด๋‹ค.

์ŠคํŽ™ ๋ฏธ๋‹ฌ ํ‚ค๋กœ ์„œ๋ช…๋œ ํ† ํฐ์ด ์‹ค์ œ ํŠธ๋ž˜ํ”ฝ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ƒํ™ฉ ์ž์ฒด๋ฅผ ๋ง‰๋Š”๋‹ค๋Š” ์ ์—์„œ, jjwt์˜ ์ดˆ๊ธฐํ™” ์‹œ์  ๊ฒ€์ฆ์€ ๋ณด์•ˆ ์ธก๋ฉด์—์„œ๋„ ์˜ฌ๋ฐ”๋ฅธ ์„ค๊ณ„๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.


6. ๋ฐฐ์šด ์ 

  • HMAC-SHA256 ๊ธฐ์ค€ secret ํ‚ค๋Š” ์ตœ์†Œ 32๋ฐ”์ดํŠธ, ์ฆ‰ 256๋น„ํŠธ ์ด์ƒ์ด์–ด์•ผ ํ•œ๋‹ค.
  • jjwt๋Š” ์ŠคํŽ™ ๋ฏธ๋‹ฌ ํ‚ค๋ฅผ ๋Ÿฐํƒ€์ž„์ด ์•„๋‹ˆ๋ผ ์ดˆ๊ธฐํ™” ์‹œ์ ์— ์ฐจ๋‹จํ•œ๋‹ค.
  • ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” secret ๊ฐ’์„ ์„ค์ • ํŒŒ์ผ์— ์ง์ ‘ ์ž‘์„ฑํ•˜์ง€ ๋ง๊ณ  ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ๋ถ„๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.
  • ์šด์˜ secret์€ ์ง์ ‘ ์ž‘์„ฑํ•œ ๋ฌธ์ž์—ด๋ณด๋‹ค ์ถฉ๋ถ„ํ•œ ๊ธธ์ด์˜ ๋žœ๋ค ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•˜๋‹ค.
์ •๋ฆฌํ•˜๋ฉด, JWT secret์€ ๋‹จ์ˆœํ•œ ๋ฌธ์ž์—ด ์„ค์ •๊ฐ’์ด ์•„๋‹ˆ๋ผ ํ† ํฐ์˜ ์‹ ๋ขฐ์„ฑ์„ ๊ฒฐ์ •ํ•˜๋Š” ๋ณด์•ˆ ์š”์†Œ๋‹ค. ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์š”๊ตฌํ•˜๋Š” ์ตœ์†Œ ๊ธธ์ด๋ฅผ ๋งŒ์กฑํ•˜๊ณ , ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋ฐ˜๋“œ์‹œ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.
728x90