<aside>

</aside>

μ•ˆλ…•ν•˜μ„Έμš”! λ“œλ””μ–΄ 6λΆ€ '인증 및 λ³΄μ•ˆ'의 첫 번째 κ΅¬ν˜„ μ‹œκ°„, 28κ°•μž…λ‹ˆλ‹€! πŸ”βœ¨

μ§€λ‚œ 27κ°•μ—μ„œλŠ” 인증(AuthN)κ³Ό 인가(AuthZ)의 κ°œλ…μ„ 배우고, OAuth2와 JWTλ₯Ό μ‚¬μš©ν•˜μ—¬ 우리 ToDo API에 둜그인 κΈ°λŠ₯을 κ΅¬ν˜„ν•  κ³„νšμ„ μ„Έμ› μŠ΅λ‹ˆλ‹€.

둜그인 κΈ°λŠ₯을 λ§Œλ“€λ €λ©΄, λ‹Ήμ—°νžˆ λ¨Όμ € μ‚¬μš©μžκ°€ κ°€μž…ν•  수 μžˆμ–΄μ•Όκ² μ£ ? 이번 μ‹œκ°„μ—λŠ” λ°”λ‘œ 이 μ‚¬μš©μž 등둝(νšŒμ›κ°€μž…) APIλ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€. μ‚¬μš©μžκ°€ 이메일과 λΉ„λ°€λ²ˆν˜Έλ₯Ό μ œκ³΅ν•˜λ©΄, 이λ₯Ό λ°μ΄ν„°λ² μ΄μŠ€μ— μ•ˆμ „ν•˜κ²Œ μ €μž₯ν•˜λŠ” λ‘œμ§μ„ λ§Œλ“€ κ±°μ˜ˆμš”.

μ—¬κΈ°μ„œ κ°€μž₯ μ€‘μš”ν•œ 핡심! μ‚¬μš©μžμ˜ λΉ„λ°€λ²ˆν˜Έλ₯Ό μ ˆλŒ€λ‘œ κ·Έλƒ₯ μ €μž₯ν•˜λ©΄ μ•ˆ λœλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€! πŸ™…β€β™€οΈ 이번 μ‹œκ°„μ—λŠ” λΉ„λ°€λ²ˆν˜Έλ₯Ό μ•ˆμ „ν•˜κ²Œ μ²˜λ¦¬ν•˜λŠ” ν‘œμ€€μ μΈ 방법인 **ν•΄μ‹±(Hashing)**에 λŒ€ν•΄ 배우고, Python의 passlib 라이브러리λ₯Ό μ‚¬μš©ν•˜μ—¬ λΉ„λ°€λ²ˆν˜Έλ₯Ό ν•΄μ‹±ν•˜κ³  κ²€μ¦ν•˜λŠ” ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€. 그리고 이 ν•¨μˆ˜λ“€μ„ ν™œμš©ν•˜μ—¬ μ‚¬μš©μž 등둝 API(POST /users/)λ₯Ό μ™„μ„±ν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

μ•ˆμ „ν•œ APIλ₯Ό ν–₯ν•œ 첫걸음, ν•¨κ»˜ μ‹œμž‘ν•΄λ΄…μ‹œλ‹€!


πŸ“š 챕터 μ†Œκ°œ

이번 28κ°•μ—μ„œλŠ” μ‚¬μš©μžκ°€ 우리 μ„œλΉ„μŠ€μ— κ°€μž…ν•  수 μžˆλ„λ‘ μ‚¬μš©μž 등둝 API μ—”λ“œν¬μΈνŠΈ(POST /users/)λ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€. 이 κ³Όμ •μ—μ„œ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ³΄μ•ˆμ˜ κ°€μž₯ κΈ°λ³Έμ μ΄λ©΄μ„œλ„ μ€‘μš”ν•œ 원칙인 μ•ˆμ „ν•œ λΉ„λ°€λ²ˆν˜Έ 처리 방법을 μ€‘μ μ μœΌλ‘œ λ‹€λ£Ήλ‹ˆλ‹€.

μ‚¬μš©μž λΉ„λ°€λ²ˆν˜Έλ₯Ό λ°μ΄ν„°λ² μ΄μŠ€μ— 평문(plain text)으둜 μ €μž₯ν•˜λŠ” κ²ƒμ˜ μœ„ν—˜μ„±μ„ 배우고, 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•œ **λΉ„λ°€λ²ˆν˜Έ ν•΄μ‹±(Password Hashing)**의 κ°œλ…(단방ν–₯ ν•¨μˆ˜, μ†”νŠΈ(Salt))을 μ΄ν•΄ν•©λ‹ˆλ‹€. 특히, λΉ„λ°€λ²ˆν˜Έ 해싱에 널리 μ‚¬μš©λ˜λŠ” κ°•λ ₯ν•œ μ•Œκ³ λ¦¬μ¦˜μΈ Bcrypt에 λŒ€ν•΄ μ•Œμ•„λ΄…λ‹ˆλ‹€.

Pythonμ—μ„œ λΉ„λ°€λ²ˆν˜Έ 해싱을 μ‰½κ²Œ μ²˜λ¦¬ν•  수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” ν‘œμ€€ 라이브러리인 **passlib**λ₯Ό μ„€μΉ˜ν•˜κ³  μ‚¬μš©ν•˜λŠ” 방법을 λ°°μ›λ‹ˆλ‹€. passlib의 CryptContextλ₯Ό μ„€μ •ν•˜κ³ , 이λ₯Ό μ΄μš©ν•˜μ—¬ λΉ„λ°€λ²ˆν˜Έλ₯Ό ν•΄μ‹±ν•˜λŠ” ν•¨μˆ˜(get_password_hash)와 ν•΄μ‹œλœ λΉ„λ°€λ²ˆν˜Έλ₯Ό κ²€μ¦ν•˜λŠ” ν•¨μˆ˜(verify_password)λ₯Ό app/security.py νŒŒμΌμ— κ΅¬ν˜„ν•©λ‹ˆλ‹€.

λ§ˆμ§€λ§‰μœΌλ‘œ, 이 ν•΄μ‹± ν•¨μˆ˜λ“€κ³Ό Pydantic μž…λ ₯ λͺ¨λΈ(UserCreate), SQLAlchemy μ„Έμ…˜(AsyncSession)을 ν•¨κ»˜ μ‚¬μš©ν•˜μ—¬ μ‚¬μš©μž 등둝 μ—”λ“œν¬μΈνŠΈ λ‘œμ§μ„ μ™„μ„±ν•©λ‹ˆλ‹€. 이 κ³Όμ •μ—μ„œ 이미 λ“±λ‘λœ 이메일인지 ν™•μΈν•˜λŠ” 쀑볡 체크 λ‘œμ§λ„ ν•¨κ»˜ κ΅¬ν˜„ν•©λ‹ˆλ‹€.


🎯 챕터 λͺ©ν‘œ

이 κ°•μ˜λ₯Ό 마치면 μ—¬λŸ¬λΆ„μ€ λ‹€μŒμ„ ν•  수 있게 λ©λ‹ˆλ‹€:

  1. λ°μ΄ν„°λ² μ΄μŠ€μ— 평문 λΉ„λ°€λ²ˆν˜Έλ₯Ό μ €μž₯ν•˜λŠ” κ²ƒμ˜ μœ„ν—˜μ„±μ„ μ„€λͺ…ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  2. λΉ„λ°€λ²ˆν˜Έ ν•΄μ‹±μ˜ κΈ°λ³Έ κ°œλ…(단방ν–₯, μ†”νŠΈ)κ³Ό Bcrypt μ•Œκ³ λ¦¬μ¦˜μ„ μ΄ν•΄ν•©λ‹ˆλ‹€.
  3. passlib 라이브러리(bcrypt 지원 포함)λ₯Ό μ„€μΉ˜ν•˜κ³  CryptContextλ₯Ό μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  4. passlibλ₯Ό μ‚¬μš©ν•˜μ—¬ λΉ„λ°€λ²ˆν˜Έλ₯Ό ν•΄μ‹±ν•˜λŠ” ν•¨μˆ˜μ™€ ν•΄μ‹œλ₯Ό κ²€μ¦ν•˜λŠ” ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. (app/security.py)
  5. μ‚¬μš©μž 등둝 μš”μ²­μ„ μœ„ν•œ Pydantic λͺ¨λΈ(UserCreate)을 μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. (app/models/user.py)