낙서장이자 오답 노트이자 컨닝 페이퍼
패스트캠퍼스 환급챌린지 25일차 : 코드팩토리의 백엔드 아카데미 : 한 번에 끝내는 NestJS 패키지 - 기초부터 MSA까지 강의 후기 본문
패스트캠퍼스 환급챌린지 25일차 : 코드팩토리의 백엔드 아카데미 : 한 번에 끝내는 NestJS 패키지 - 기초부터 MSA까지 강의 후기
NangIn 2025. 4. 25. 12:47본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.
강의 내용 정리
Hashing 이론
인증 전체 흐름 요약
- 회원가입 요청
- 이메일 + 비밀번호를 서버로 전송
- 서버에서 비밀번호 암호화(해싱) 후, DB에 저장
- 로그인 요청
- 입력한 비밀번호를 다시 암호화
- DB에 저장된 해시값과 비교 → 일치하면 로그인 성공
- 토큰 발급
- 로그인 성공 시, 액세스 토큰 + 리프레시 토큰 발급
- 클라이언트는 이후 요청 시, 이 토큰을 함께 전송
- 인증 처리
- 서버는 토큰 검증을 통해 사용자를 식별하고, 프라이빗 리소스를 응답
비밀번호 암호화의 핵심 원칙
- 원본 비밀번호는 절대 저장 X
- 서버에서도 원문을 복구할 수 없음 (복호화 불가)
- 항상 같은 결과가 나오는 해시 알고리즘 사용
- 동일한 입력값 → 동일한 출력값
- 비밀번호 비교 방식
- 로그인 시, 입력된 비밀번호를 해싱하여 기존 해시와 비교
- 가장 널리 쓰이는 암호화 도구: bcrypt
해킹 위협과 해싱의 필요성
- 데이터 유출 시 위험
- A 사이트가 해킹되면, 같은 이메일+비밀번호로 B 사이트에 로그인 시도 가능
- 해싱 도입
- 123123 → a8fz...처럼 해시된 형태로만 저장
- 같은 입력값 → 항상 같은 해시값
- 복호화 불가 → 보안성↑
딕셔너리 어택(DICTIONARY ATTACK) 문제
- 해커의 전략
- 자주 쓰는 비밀번호를 미리 해싱하여 DB 생성
- 해킹한 해시값과 사전(DB)과 비교해 실제 비밀번호 추정 가능
솔트(Salt)로 딕셔너리 어택 방지
- Salt란?
- 비밀번호에 추가 문자열을 덧붙여 해싱
- 예: 123123 + "CodeFactory" → 해싱
- 효과
- 사전 해싱 DB로는 비교 불가
- Salt가 다르면 같은 비밀번호도 완전히 다른 해시값 생성됨
- 해커가 솔트를 모르면 해독 불가
bcrypt를 사용하는 이유
| 항목 | SHA-256 | bcrypt |
| 속도 | 빠름 | 느림 |
| Salt | 필요 없음 | 자동 사용 |
| 딕셔너리 공격 대응 | 약함 | 강함 |
| 커스터마이징 | X | 해싱 속도 조절 가능 |
- 느리게 작동하는 점이 보안에 이점
- 딕셔너리 생성 속도를 현저히 낮춤
- 해커가 브루트포싱을 하려 해도 시간이 너무 오래 걸려 비효율적
Token 이론
토큰의 종류와 사용 목적
- 총 세 가지 토큰을 구분해서 이해해야 함:
- Basic Token: 로그인 시 아이디/비밀번호 전달 시 사용.
- "아이디:비밀번호"를 Base64로 인코딩해 Authorization 헤더에 Basic 토큰 형태로 전송
- Access Token: 인증된 사용자가 프라이빗 리소스에 접근할 수 있도록 인증
- 요청 시 Authorization 헤더에 Bearer 액세스토큰
- Refresh Token: Access Token이 만료됐을 때 새로운 Access Token을 발급받는 용도
- Authorization 헤더에 Bearer 리프레시토큰 형태로 전송
- Basic Token: 로그인 시 아이디/비밀번호 전달 시 사용.
로그인 및 인증 흐름
- 클라이언트 → 서버에 로그인 요청
- Basic Token을 Authorization 헤더에 포함 (Base64 인코딩된 "이메일:비밀번호")
- 서버
- Base64 디코딩하여 이메일/비밀번호 추출
- 검증 후 Access Token, Refresh Token 발급
- 클라이언트
- 발급받은 두 토큰을 저장 (보통 Access는 메모리, Refresh는 쿠키 등)
Access Token 사용 방식
- 로그인 이후 프라이빗 리소스에 접근할 때, Access Token을 Authorization 헤더에 Bearer 액세스토큰 형태로 포함해 요청
- 서버는 해당 토큰의 시그니처를 검증하여 위조/변조 여부 판단
Access Token 만료 시
- 클라이언트가 만료된 토큰으로 요청
- 서버에서 검증 시 만료 확인 → 401 Unauthorized 에러 응답
- 클라이언트는 Refresh Token으로 Access Token 재요청
- 서버는 Refresh Token 검증 후 새 Access Token 발급
- 클라이언트는 새 Access Token으로 다시 요청 → 성공
JWT란?
- 무상태 인증에 사용
- 인터넷으로 전송할 만큼 작으며 인증에 필요한 모든 정보가 자체적으로 담겨 있음
- Header, Payload, Signature 세개의 구간으로 이루어져 있음
- 표준화된 클레임이 존재 (iss, exp, sub, aud 등)
- 인증 (Authentication), 인가 (Authorization)에 효율적
JWT 구조 설명
- JWT는 3개의 부분으로 구성됨:
부분 설명 Header 타입 (JWT)과 해싱 알고리즘 (HS256) 등 메타 정보 Payload 유저 정보 및 클레임 (sub, iat, exp 등) Signature 위 Header + Payload를 서버 비밀키로 서명한 값 - ., 즉 점으로 구분된 문자열 세 덩어리
- Base64로 인코딩되어 전송
- 시그니처는 변조 여부를 검증하기 위한 장치
- → Payload가 조작되면 시그니처 불일치로 바로 걸러짐
학습 후기
이번 강의를 통해 단순히 인증 기능을 구현하는 기술적인 방법을 넘어, 왜 그렇게 구현해야 하는가에 대한 보안적 배경과 설계 의도를 깊이 있게 이해할 수 있었습니다. 특히 해싱과 토큰의 역할을 전체 인증 흐름 안에서 위치시켜 사고하는 것이 실무적인 감각을 기르는 데 큰 도움이 되었습니다.
먼저 비밀번호 해싱과 관련하여, 단순히 bcrypt.hash()만 호출해서 저장하면 된다는 식의 피상적인 이해에서 벗어나, 왜 복호화가 불가능한 해시 알고리즘을 사용하는지, 왜 느린 알고리즘이 오히려 보안에 유리한지, Salt가 어떤 보안 위협을 막는지를 체계적으로 이해할 수 있었습니다. 특히 dictionary attack이라는 현실적인 공격 시나리오와 bcrypt가 그것을 어떻게 원천 차단하는지를 알게 되면서, 단순한 도구 사용법이 아니라 해킹 대응 전략의 일환으로 해싱을 이해하게 된 점이 인상 깊었습니다.
토큰 이론 파트에서는 기존에 알고 있던 JWT의 개념이 훨씬 더 명확하게 정리되었습니다. Access Token과 Refresh Token의 유효기간 전략, 그리고 두 토큰의 역할 분리를 통해 인증과 세션 유지의 책임이 어떻게 나뉘는지 실전 관점에서 정리할 수 있었습니다. 특히 Refresh Token을 사용함으로써 Access Token을 짧게 가져가면서도 사용자 경험을 유지하는 전략은 실제 서비스를 설계할 때 반드시 고려해야 할 포인트임을 깨달았습니다.
JWT의 구조적 특성과 함께, Header, Payload, Signature 세 요소의 역할을 명확히 이해한 것도 중요한 수확입니다. 특히 Payload가 단순히 Base64로 인코딩되어 있다는 점에서, 민감한 정보를 절대 넣지 말아야 한다는 원칙은 보안 설계 시 항상 염두에 두어야 함을 다시금 확인했습니다.
무엇보다도 이번 학습을 통해, 단순히 코드를 따라 치는 것을 넘어서서 왜 이렇게 동작하고 왜 이렇게 설계되어야 하는지에 대한 근본적인 질문을 스스로 던지게 되었습니다. 인증이라는 도메인은 단순한 기술 구현을 넘어서 보안, 성능, 사용자 경험 모두와 맞닿아 있기 때문에, 그만큼 깊이 있는 사고가 필요한 영역이라는 것을 실감했습니다. 이번 기회를 통해 그 사고의 출발점을 만들 수 있어 큰 의미가 있었습니다.
학습 인증샷



