믿는 도끼에 발등 찍힌다: 입력값 검증과 암호화
사용자가 입력한 데이터를 절대 믿지 않고 검증하는 방법과, 데이터베이스가 털려도 안전한 비밀번호 해싱 원리를 배웁니다.
백엔드 개발의 제1 원칙은 "절대로 유저의 입력을 믿지 마라"입니다. 비개발자들이 바이브코딩으로 서비스를 만들 때 가장 먼저 뚫리는 구멍이 바로 프론트엔드(화면) 화면에서 검사했다고 백엔드에서 검사를 생략하는 것입니다. 해커들은 화면을 거치지 않고 서버로 직접 조작된 폭탄 데이터를 날려 보냅니다. 이번 시간에는 외부에서 들어온 오물(잘못된 데이터)을 깨끗하게 걸러내는 '입력값 검증'과, 만약 창고가 털리더라도 도둑이 쓸모없게 만드는 마법의 '비밀번호 해싱'에 대해 배웁니다.
화면의 경고창은 해커를 막지 못한다: 입력값 검증 (Validation)
우리가 웹사이트에서 회원가입을 할 때 이메일에 골뱅이(`@`)를 빼먹거나 비밀번호를 짧게 치면 화면에 붉은색 경고 메시지가 뜹니다. 초보자들은 "아, 프론트엔드(화면)에서 방어했으니 안전하겠지?"라고 생각하고 백엔드 서버(Handler/Service)에서는 아무런 검사 없이 들어온 값을 DB에 냅다 저장해 버립니다.
하지만 해커들은 웹 브라우저를 쓰지 않습니다. 터미널(까만 창)을 열어 특수한 명령어(`curl` 등)로 프론트엔드 화면을 무시한 채, 여러분의 백엔드 서버로 직접 나이가 -5살이고 이메일이 없는 괴상한 가짜 회원가입 데이터를 쏴버립니다.
백엔드 검증의 철칙
- 1프론트엔드의 유효성 검사(경고창)는 '착한 유저의 편의성'을 위한 것이지 해커를 막는 방어막이 아닙니다.
- 2백엔드의 핸들러(Handler)는 문을 열어주기 전에 들어온 데이터가 규칙에 맞는지 무조건 100% 다시 검사(Validation)해야 합니다.
- 3이메일 형식, 비밀번호 길이, 나이의 범위, 필수 입력값 누락 여부 등을 빈틈없이 체크해야 쓰레기 데이터가 DB에 쌓이지 않습니다.
Go 언어에서는 `validator`라는 아주 유명하고 훌륭한 외부 패키지를 사용하여, 구조체 옆에 꼬리표(태그)를 달아주는 것만으로 강력한 검사를 0.1초 만에 수행할 수 있습니다. AI에게 코드를 맡길 때 반드시 "Go validator 패키지를 사용해서 핸들러 단에서 입력값 검증 로직을 빡세게 추가해 줘"라고 지시하세요.
데이터베이스가 통째로 털린다면?: 비밀번호 해싱 (Hashing)
입력값 검증을 거친 정상적인 회원가입 요청이 서비스(Service) 계층에 도착했습니다. 유저가 입력한 비밀번호 "123456"을 데이터베이스에 저장할 차례입니다. 만약 이 "123456"이라는 글자를 그대로 DB에 저장한다면(평문 저장, Plain text), 해커가 DB를 뚫는 순간 모든 회원의 비밀번호가 고스란히 유출되는 대참사가 벌어집니다. 대표가 뉴스에 나와서 고개 숙여 사과해야 합니다.
이를 막기 위해 현대 백엔드의 필수 교양인 해싱(Hashing)을 수행해야 합니다.
정의
해싱 (Hashing)
해시 함수라는 마법의 믹서기에 원본 데이터를 넣고 갈아버리는 과정입니다. "123456"을 믹서기에 넣고 돌리면 "$2a$10$xyz..." 같은 알아볼 수 없는 긴 쓰레기 문자열로 변합니다. 가장 큰 특징은, 갈려 나온 쥬스(해시값)를 아무리 분석해도 원래의 사과(원본 비밀번호)로 절대 되돌릴 수 없다는 점입니다. (일방향 암호화)
해시의 똑똑한 검증 원리
원본 비밀번호를 버려버렸는데, 유저가 나중에 로그인할 때 진짜 주인이 맞는지 어떻게 알까요?
- 가입 시: "1234" -> [믹서기] -> "A8f9" (DB에 "A8f9"만 저장)
- 로그인 시: 유저가 폼에 "1234" 입력 -> [믹서기] -> "A8f9" 생성
- 백엔드는 DB에 저장된 "A8f9"와 방금 갈려 나온 "A8f9"가 똑같은지 텍스트만 비교합니다.
해커가 DB를 훔쳐 가서 "A8f9"를 가져가도 원래 비밀번호가 무엇인지 풀 수 없으므로 무용지물이 됩니다.
바이브코딩 시대에 AI는 간혹 귀찮다는 이유로 비밀번호를 쌩으로(Plain text) 저장하는 코드를 짜줍니다. 혹은 지금은 뚫려버린 낡고 허술한 믹서기(`MD5` 등)를 가져다 씁니다.
이때 여러분은 AI에게 호통을 쳐야 합니다. "비밀번호 평문 저장하지 마! 반드시 가장 안전한 `bcrypt` 패키지를 이용해서 암호화(해싱) 한 뒤에 DB에 저장하고, 로그인할 때 비교하는 서비스 로직으로 다시 짜!"
개념 퀴즈
퀴즈 답을 맞춰야 학습 완료가 됩니다.회원가입 기능을 바이브코딩으로 구현했습니다. 프론트엔드(화면) 코드에서 자바스크립트로 비밀번호가 8자리 이상인지 꼼꼼하게 검사하는 코드를 추가해 두었습니다. 그렇다면 백엔드 서버(Go 언어 코드)에서는 이 비밀번호 길이 검사를 생략해도 안전할까요?
3줄 요약
- 1프론트엔드(화면)의 입력값 검사는 해커의 직접적인 API 공격을 막을 수 없으므로, 백엔드의 핸들러 단에서 validator 패키지 등을 이용해 철저하게 재검증해야 합니다.
- 2유저의 비밀번호는 절대 원본(평문) 그대로 데이터베이스에 저장해서는 안 되며, 해킹 시 피해를 막기 위해 해싱(Hashing)이라는 믹서기 작업을 거쳐야 합니다.
- 3바이브코딩 시 AI에게 비밀번호 처리를 지시할 때는 낡은 암호화 방식 대신 현대 표준인 bcrypt를 사용하여 안전하게 단방향 암호화 처리하라고 콕 집어 요구하세요.