diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ee987b544..c900dc918 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* π Add Korean translation for `docs/ko/docs/tutorial/security/oauth2-jwt.md`. PR [#13333](https://github.com/fastapi/fastapi/pull/13333) by [@yes0ng](https://github.com/yes0ng). * π Add Vietnamese translation for `docs/vi/docs/deployment/cloud.md`. PR [#13407](https://github.com/fastapi/fastapi/pull/13407) by [@ptt3199](https://github.com/ptt3199). ### Internal diff --git a/docs/ko/docs/tutorial/security/oauth2-jwt.md b/docs/ko/docs/tutorial/security/oauth2-jwt.md new file mode 100644 index 000000000..d8bac8346 --- /dev/null +++ b/docs/ko/docs/tutorial/security/oauth2-jwt.md @@ -0,0 +1,273 @@ +# ν¨μ€μλ ν΄μ±μ μ΄μ©ν OAuth2, JWT ν ν°μ μ¬μ©νλ Bearer μΈμ¦ + +λͺ¨λ 보μ νλ¦μ ꡬμ±νμΌλ―λ‘, μ΄μ <abbr title="JSON Web Tokens">JWT</abbr> ν ν°κ³Ό ν¨μ€μλ ν΄μ±μ μ¬μ©ν΄ μ ν리μΌμ΄μ μ μμ νκ² λ§λ€ κ²μ λλ€. + +μ΄ μ½λλ μ€μ λ‘ μ ν리μΌμ΄μ μμ ν¨μ€μλλ₯Ό ν΄μ±νμ¬ DBμ μ μ₯νλ λ±μ μμ μ νμ©ν μ μμ΅λλ€. + +μ΄μ μ₯μ μ΄μ΄μ μμν΄ λ΄ μλ€. + +## JWT + +JWT λ "JSON Web Tokens" μ μλ―Έν©λλ€. + +JSON κ°μ²΄λ₯Ό κ³΅λ°±μ΄ μλ κΈ΄ λ¬Έμμ΄λ‘ μΈμ½λ©νλ νμ€μ΄λ©°, λ€μκ³Ό κ°μ ννμ λλ€: + +``` +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + +JWTλ μνΈνλμ§ μμ λꡬλ μ§ ν ν°μμ μ 보λ₯Ό 볡μν μ μμ΅λλ€. + +νμ§λ§ JWTλ μλͺ λμ΄ μμ΅λλ€. κ·Έλμ μμ μ΄ λ°κΈν ν ν°μ λ°μμ λ, μ€μ λ‘ μμ μ΄ λ°κΈνκ² λ§λμ§ κ²μ¦ν μ μμ΅λλ€. + +λ§λ£ κΈ°κ°μ΄ μΌμ£ΌμΌμΈ ν ν°μ λ°ννλ€κ³ κ°μ ν΄ λ΄ μλ€. λ€μ λ μ¬μ©μκ° ν ν°μ κ°μ Έμμ λ, κ·Έ μ¬μ©μκ° μμ€ν μ μ¬μ ν λ‘κ·ΈμΈλμ΄ μλ€λ κ²μ μ μ μμ΅λλ€. + +μΌμ£ΌμΌ λ€μλ ν ν°μ΄ λ§λ£λ κ²μ΄κ³ , μ¬μ©μλ μΈκ°λμ§ μμ μ ν ν°μ λ°κΈ° μν΄ λ€μ λ‘κ·ΈμΈν΄μΌ ν κ²μ λλ€. λ§μ½ μ¬μ©μ(λλ μ 3μ)κ° ν ν°μ μμ νκ±°λ λ§λ£μΌμ λ³κ²½νλ©΄, μλͺ μ΄ μΌμΉνμ§ μκΈ° λλ¬Έμ μμμ± μ μμ κ²μ λλ€. + +λ§μ½ JWT ν ν°μ λ€λ€λ³΄κ³ , μλ λ°©μλ μμλ³΄κ³ μΆλ€λ©΄ <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a> μ νμΈνμμμ€. + +## `PyJWT` μ€μΉ + +νμ΄μ¬μΌλ‘ JWT ν ν°μ μμ±νκ³ κ²μ¦νλ €λ©΄ `PyJWT` λ₯Ό μ€μΉν΄μΌ ν©λλ€. + +[κ°μνκ²½](../../virtual-environments.md){.internal-link target=_blank} μ λ§λ€κ³ νμ±νν λ€μ `pyjwt` λ₯Ό μ€μΉνμμμ€: + +<div class="termy"> + +```console +$ pip install pyjwt + +---> 100% +``` + +</div> + +/// info | μ°Έκ³ + +RSAλ ECDSA κ°μ μ μ μλͺ μκ³ λ¦¬μ¦μ μ¬μ©νλ €λ©΄, `pyjwt[crypto]`λΌλ μνΈν λΌμ΄λΈλ¬λ¦¬ μμ‘΄μ±μ μ€μΉν΄μΌ ν©λλ€. + +λ μμΈν λ΄μ©μ <a href="https://pyjwt.readthedocs.io/en/latest/installation.html" class="external-link" target="_blank">PyJWT μ€μΉ</a> μμ νμΈν μ μμ΅λλ€. + +/// + +## ν¨μ€μλ ν΄μ± + +"ν΄μ±(Hashing)"μ μ΄λ€ λ΄μ©(μ¬κΈ°μλ ν¨μ€μλ)μ ν΄μν μ μλ μΌλ ¨μ λ°μ΄νΈ μ§ν©(λ¨μ λ¬Έμμ΄)μΌλ‘ λ³ννλ κ²μ μλ―Έν©λλ€. + +λμΌν λ΄μ©(λκ°μ ν¨μ€μλ)μ ν΄μ±νλ©΄ λμΌν λ¬Έμμ΄μ μ»μ΅λλ€. + +νμ§λ§ κ·Έ λ¬Έμμ΄μ λ€μ ν¨μ€μλλ‘ λλ릴 μλ μμ΅λλ€. + +### ν¨μ€μλλ₯Ό ν΄μ±νλ μ΄μ + +λ°μ΄ν°λ² μ΄μ€λ₯Ό νμ·¨λΉνλλΌλ, μΉ¨μ μλ μ¬μ©μμ νλ¬Έ ν¨μ€μλ λμ ν΄μ κ°λ§ μ»μ μ μμ΅λλ€. + +λ°λΌμ μΉ¨μ μλ νμΉ μ¬μ©μ ν¨μ€μλλ₯Ό λ€λ₯Έ μμ€ν μμ νμ©ν μ μμ΅λλ€. (λλ€μ μ¬μ©μκ° μ¬λ¬ μμ€ν μμ λμΌν ν¨μ€μλλ₯Ό μ¬μ©νκΈ° λλ¬Έμ νλ¬Έ ν¨μ€μλκ° μ μΆλλ©΄ μνν©λλ€.) + +## `passlib` μ€μΉ + +PassLibλ ν¨μ€μλ ν΄μλ₯Ό λ€λ£¨λ νλ₯ν νμ΄μ¬ ν¨ν€μ§μ λλ€. + +λ§μ μμ ν ν΄μ μκ³ λ¦¬μ¦κ³Ό λꡬλ€μ μ§μν©λλ€. + +μΆμ²νλ μκ³ λ¦¬μ¦μ "Bcrypt"μ λλ€. + +[κ°μνκ²½](../../virtual-environments.md){.internal-link target=_blank} μ λ§λ€κ³ νμ±νν λ€μ PassLibμ Bcryptλ₯Ό μ€μΉνμμμ€: + +<div class="termy"> + +```console +$ pip install "passlib[bcrypt]" + +---> 100% +``` + +</div> + +/// tip | ν + +`passlib`λ₯Ό μ¬μ©νμ¬, **Django**, **Flask** μ 보μ νλ¬κ·ΈμΈμ΄λ λ€λ₯Έ λκ΅¬λ‘ μμ±ν ν¨μ€μλλ₯Ό μ½μ μ μλλ‘ μ€μ ν μλ μμ΅λλ€. + +μλ₯Ό λ€μλ©΄, FastAPI μ ν리μΌμ΄μ κ³Ό Django μ ν리μΌμ΄μ μ΄ κ°μ λ°μ΄ν°λ² μ΄μ€μμ λ°μ΄ν°λ₯Ό 곡μ ν μ μμ΅λλ€. λλ κ°μ λ°μ΄ν°λ² μ΄μ€λ₯Ό μ¬μ©νμ¬ Django μ ν리μΌμ΄μ μ μ μ§μ μΌλ‘ λ§μ΄κ·Έλ μ΄μ ν μλ μμ΅λλ€. + +κ·Έλ¦¬κ³ μ¬μ©μλ FastAPI μ ν리μΌμ΄μ κ³Ό Django μ ν리μΌμ΄μ μ λμμ λ‘κ·ΈμΈν μ μμ΅λλ€. + +/// + +## ν¨μ€μλμ ν΄μμ κ²μ¦ + +νμν λꡬλ₯Ό `passlib`μμ μν¬νΈν©λλ€. + +PassLib "컨ν μ€νΈ(context)"λ₯Ό μμ±ν©λλ€. μ΄κ²μ ν¨μ€μλλ₯Ό ν΄μ±νκ³ κ²μ¦νλλ° μ¬μ©ν©λλ€. + +/// tip | ν + +PassLib 컨ν μ€νΈλ λ€μν ν΄μ± μκ³ λ¦¬μ¦μ μ¬μ©ν μ μλ κΈ°λ₯μ μ 곡νλ©°, λ μ΄μ μ¬μ©μ΄ κΆμ₯λμ§ μλ μ€λλ ν΄μ± μκ³ λ¦¬μ¦μ κ²μ¦νλ κΈ°λ₯λ ν¬ν¨λμ΄ μμ΅λλ€. + +μλ₯Ό λ€μ΄, λ€λ₯Έ μμ€ν (Django κ°μ)μμ μμ±ν ν¨μ€μλλ₯Ό μ½κ³ κ²μ¦ν μ μμΌλ©°, μλ‘μ΄ ν¨μ€μλλ₯Ό Bcrypt κ°μ λ€λ₯Έ μκ³ λ¦¬μ¦μΌλ‘ ν΄μ±ν μλ μμ΅λλ€. + +κ·Έλ¦¬κ³ λμμ κ·Έλ° λͺ¨λ μκ³ λ¦¬μ¦κ³Ό νΈνμ±μ μ μ§ν©λλ€. + +/// + +μ¬μ©μλ‘λΆν° λ°μ ν¨μ€μλλ₯Ό ν΄μ±νλ μ νΈλ¦¬ν° ν¨μλ₯Ό μμ±ν©λλ€. + +κ·Έλ¦¬κ³ λ°μ ν¨μ€μλκ° μ μ₯λ ν΄μμ μΌμΉνλμ§ κ²μ¦νλ λ λ€λ₯Έ μ νΈλ¦¬ν° ν¨μλ μμ±ν©λλ€. + +κ·Έλ¦¬κ³ μ¬μ©μλ₯Ό μΈμ¦νκ³ λ°ννλ λ λ€λ₯Έ ν¨μλ μμ±ν©λλ€. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} + +/// note + +μλ‘μ΄ (κ°μ§) λ°μ΄ν°λ² μ΄μ€ `fake_users_db`λ₯Ό νμΈνλ©΄, ν΄μ μ²λ¦¬λ ν¨μ€μλκ° μ΄λ»κ² μκ²Όλμ§ λ³Ό μ μμ΅λλ€: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`. + +/// + +## JWT ν ν° μ²λ¦¬ + +μ€μΉλ λͺ¨λμ μν¬νΈ ν©λλ€. + +JWT ν ν° μλͺ μ μ¬μ©λ μμμ λΉλ°ν€λ₯Ό μμ±ν©λλ€. + +μμ ν μμμ λΉλ°ν€λ₯Ό μμ±νλ €λ©΄ λ€μ λͺ λ Ήμ΄λ₯Ό μ¬μ©νμμμ€: + +<div class="termy"> + +```console +$ openssl rand -hex 32 + +09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7 +``` + +</div> + +κ·Έλ¦¬κ³ μμ±ν λΉλ°ν€λ₯Ό 볡μ¬ν΄ λ³μ `SECRET_KEY`μ λμ ν©λλ€. (μ΄ μμ μ λ³μ κ°μ κ·Έλλ‘ μ¬μ©νμ§ λ§μμμ€.) + +JWT ν ν°μ μλͺ νλ λ° μ¬μ©λ μκ³ λ¦¬μ¦μ μν λ³μ `ALGORITHM` μ μμ±νκ³ `"HS256"` μΌλ‘ μ€μ ν©λλ€. + +ν ν° λ§λ£ κΈ°κ°μ μν λ³μλ₯Ό μμ±ν©λλ€. + +μλ΅μ μν ν ν° μλν¬μΈνΈμ μ¬μ©λ Pydantic λͺ¨λΈμ μ μν©λλ€. + +μ μ‘μΈμ€ ν ν°μ μμ±νκΈ° μν μ νΈλ¦¬ν° ν¨μλ₯Ό μμ±ν©λλ€. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} + +## μμ‘΄μ± μμ + +`get_current_user` ν¨μλ₯Ό μ΄μ κ³Ό λμΌν ν ν°μ λ°λλ‘ μμ νλ, μ΄λ²μλ JWT ν ν°μ μ¬μ©νλλ‘ ν©λλ€. + +λ°μ ν ν°μ λμ½λ©νμ¬ κ²μ¦ν ν νμ¬ μ¬μ©μλ₯Ό λ°νν©λλ€. + +ν ν°μ΄ μ ν¨νμ§ μλ€λ©΄ HTTP μ€λ₯λ₯Ό λ°νν©λλ€. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} + +## `/token` κ²½λ‘ μμ μμ + +ν ν°μ λ§λ£ μκ°μ μ€μ νκΈ° μν΄ `timedelta` λ₯Ό μμ±ν©λλ€. + +μ€μ JWT μ‘μΈμ€ ν ν°μ μμ±νμ¬ λ°νν©λλ€. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} + +### JWT "주체(subject)" `sub`μ λν κΈ°μ μΈλΆ μ¬ν + +JWT λͺ μΈμ λ°λ₯΄λ©΄ ν ν°μ 주체λ₯Ό ν¬ν¨νλ `sub`λΌλ ν€κ° μμ΅λλ€. + +μ¬μ© μ¬λΆλ μ νμ¬νμ΄μ§λ§, μ¬μ©μμ μλ³ μ 보λ₯Ό μ μ₯ν μ μμΌλ―λ‘ μ¬κΈ°μλ μ΄λ₯Ό μ¬μ©ν©λλ€. + +JWTλ μ¬μ©μλ₯Ό μλ³νκ³ μ¬μ©μκ° APIλ₯Ό μ§μ μ¬μ©ν μ μλλ‘ νμ©νλ κ² μΈμλ λ€λ₯Έ μ©λλ‘ μ¬μ©λ μλ μμ΅λλ€. + +μλ₯Ό λ€μ΄ "μλμ°¨"λ "λΈλ‘κ·Έ κ²μλ¬Ό"μ μλ³νλ λ° μ¬μ©ν μ μμ΅λλ€. + +κ·Έλ¦¬κ³ "μλμ°¨λ₯Ό μ΄μ νλ€"λ "λΈλ‘κ·Έ κ²μλ¬Όμ μμ νλ€"μ²λΌ ν΄λΉ μν°ν°μ λν κΆνμ μΆκ°ν μ μμ΅λλ€. + +κ·Έ ν μ΄ JWT ν ν°μ μ¬μ©μ(λλ λ΄)μκ² μ 곡νλ©΄, κ·Έλ€μ κ³μ μ λ°λ‘ λ§λ€ νμ μμ΄ APIκ° μμ±ν JWT ν ν°λ§μΌλ‘ μμ (μλμ°¨ μ΄μ λλ λΈλ‘κ·Έ κ²μλ¬Ό νΈμ§)μ μνν μ μμ΅λλ€. + +μ΄λ¬ν κ°λ μ νμ©νλ©΄ JWTλ ν¨μ¬ λ 볡μ‘ν μλ리μ€μλ μ¬μ©ν μ μμ΅λλ€. + +μ΄ κ²½μ° μ¬λ¬ μν°ν°κ° λμΌν IDλ₯Ό κ°μ§ μ μμ΅λλ€. μλ₯Ό λ€μ΄ fooλΌλ IDλ₯Ό κ°μ§ μ¬μ©μ, μλμ°¨, λΈλ‘κ·Έ κ²μλ¬Όμ΄ μμ μ μμ΅λλ€. + +κ·Έλμ ID μΆ©λμ λ°©μ§νκΈ° μν΄, μ¬μ©μμ JWT ν ν°μ μμ±ν λ μ λμ¬λ‘ `sub` ν€λ₯Ό μΆκ°ν μ μμ΅λλ€. μλ₯Ό λ€μ΄ `username:` μ λΆμ΄λ λ°©μμ λλ€. μ΄ μμ μμλ `sub` κ°μ΄ `username:johndoe`μ΄ λ μ μμ΅λλ€. + +κ°μ₯ μ€μν μ μ `sub` ν€λ μ 체 μ ν리μΌμ΄μ μμ κ³ μ ν μλ³μκ° λμ΄μΌ νλ©° λ¬Έμμ΄μ΄μ΄μΌ νλ€λ μ μ λλ€. + +## νμΈν΄λ΄ μλ€ + +μλ²λ₯Ό μ€ννκ³ λ¬Έμλ‘ μ΄λνμμμ€: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>. + +λ€μκ³Ό κ°μ μ¬μ©μ μΈν°νμ΄μ€λ₯Ό λ³Ό μ μμ΅λλ€: + +<img src="/img/tutorial/security/image07.png"> + +μ΄μ κ³Ό κ°μ λ°©λ²μΌλ‘ μ ν리μΌμ΄μ μ μΈμ¦νμμμ€. + +λ€μ μΈμ¦ μ 보λ₯Ό μ¬μ©νμμμ€: + +Username: `johndoe` +Password: `secret` + +/// check + +μ½λ μ΄λμλ νλ¬Έ ν¨μ€μλ "`secret`" μ΄ μλ€λ μ μ μ μνμμμ€. ν΄μλ λ²μ λ§ μμ΅λλ€. + +/// + +<img src="/img/tutorial/security/image08.png"> + +`/users/me/` λ₯Ό νΈμΆνλ©΄ λ€μκ³Ό κ°μ μλ΅μ μ»μ μ μμ΅λλ€: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false +} +``` + +<img src="/img/tutorial/security/image09.png"> + +κ°λ°μ λꡬλ₯Ό μ΄μ΄λ³΄λ©΄ μ μ‘λ λ°μ΄ν°μ ν ν°λ§ ν¬ν¨λ κ²μ νμΈν μ μμ΅λλ€. ν¨μ€μλλ μ¬μ©μλ₯Ό μΈμ¦νκ³ μ‘μΈμ€ ν ν°μ λ°κΈ° μν 첫 λ²μ§Έ μμ²μλ§ μ μ‘λλ©°, μ΄νμλ μ μ‘λμ§ μμ΅λλ€: + +<img src="/img/tutorial/security/image10.png"> + +/// note + +`Bearer `λ‘ μμνλ `Authorization` ν€λμ μ£Όλͺ©νμμμ€. + +/// + +## `scopes` μ κ³ κΈ μ¬μ©λ² + +OAuth2λ "μ€μ½ν(scopes)" λΌλ κ°λ μ κ°κ³ μμ΅λλ€. + +μ΄λ₯Ό μ¬μ©νμ¬ JWT ν ν°μ νΉμ κΆν μ§ν©μ μΆκ°ν μ μμ΅λλ€. + +κ·Έ ν μ΄ ν ν°μ μ¬μ©μμκ² μ§μ μ 곡νκ±°λ μ 3μμκ² μ 곡νμ¬, νΉμ μ νμ¬ν νμμλ APIμ ν΅μ νλλ‘ ν μ μμ΅λλ€. + +**FastAPI** μμμ μ¬μ© λ°©λ²κ³Ό ν΅ν© λ°©μμ **μ¬ν μ¬μ©μ μλ΄μ** μμ μμΈν λ°°μΈ μ μμ΅λλ€. + +## μμ½ + +μ§κΈκΉμ§ μ΄ν΄λ³Έ λ΄μ©μ λ°νμΌλ‘, OAuth2μ JWT κ°μ νμ€μ μ¬μ©νμ¬ μμ ν **FastAPI** μ ν리μΌμ΄μ μ λ§λ€ μ μμ΅λλ€. + +κ±°μ λͺ¨λ νλ μμν¬μμ 보μ μ²λ¦¬λ μλΉν 볡μ‘ν μ£Όμ μ λλ€. + +μ΄λ₯Ό λ¨μννλ λ§μ ν¨ν€μ§λ λ°μ΄ν° λͺ¨λΈ, λ°μ΄ν°λ² μ΄μ€, μ¬μ© κ°λ₯ν κΈ°λ₯λ€μ λν΄ μ¬λ¬ μ μ½μ΄ μμ΅λλ€. κ·Έλ¦¬κ³ μ§λμΉκ² λ¨μννλ μΌλΆ ν¨ν€μ§λ€μ μ¬κ°ν 보μ κ²°ν¨μ κ°μ§ μλ μμ΅λλ€. + +--- + +**FastAPI** λ μ΄λ€ λ°μ΄ν°λ² μ΄μ€, λ°μ΄ν° λͺ¨λΈ, λꡬλ κ°μνμ§ μμ΅λλ€. + +νλ‘μ νΈμ κ°μ₯ μ ν©ν κ²μ μ νν μ μλ μ μ°μ±μ μ 곡ν©λλ€. + +κ·Έλ¦¬κ³ `passlib` μ `PyJWT` μ²λΌ μ κ΄λ¦¬λκ³ λ리 μ¬μ©λλ ν¨ν€μ§λ€μ λ°λ‘ μ¬μ©ν μ μμ΅λλ€. **FastAPI** λ μΈλΆ ν¨ν€μ§ ν΅ν©μ μν΄ λ³΅μ‘ν λ©μ»€λμ¦μ΄ νμνμ§ μκΈ° λλ¬Έμ λλ€. + +κ·Έλ¬λ μ μ°μ±, κ²¬κ³ μ±, 보μμ±μ ν΄μΉμ§ μμΌλ©΄μ κ³Όμ μ λ¨μνν μ μλ λꡬλ€μ μ 곡ν©λλ€. + +κ·Έλ¦¬κ³ OAuth2μ κ°μ νμ€ νλ‘ν μ½μ λΉκ΅μ κ°λ¨ν λ°©λ²μΌλ‘ ꡬννκ³ μ¬μ©ν μ μμ΅λλ€. + +λ μΈλΆνλ κΆν 체κ³λ₯Ό μν΄ OAuth2μ "μ€μ½ν"λ₯Ό μ¬μ©νλ λ°©λ²μ **μ¬ν μ¬μ©μ μλ΄μ**μμ λ μμΈν λ°°μΈ μ μμ΅λλ€. OAuth2μ μ€μ½νλ μ 3μ μ ν리μΌμ΄μ μ΄ μ¬μ©μλ₯Ό λμ ν΄ κ·Έλ€μ APIμ μνΈμμ©νλλ‘ κΆνμ λΆμ¬νκΈ° μν΄, Facebook, Google, GitHub, Microsoft, Twitter λ±μ λ§μ λν μΈμ¦ μ 곡μ 체λ€μ΄ μ¬μ©νλ λ©μ»€λμ¦μ λλ€.