백엔드와 프론트엔드 간의 통신에서 흥미로운 점을 발견했습니다.
서버에서 클라이언트로 오는 응답은 JWT를 사용해 안전하게 암호화되어 있는데, 정작 클라이언트에서 서버로 보내는 로그인 요청은 왜 평문 비밀번호를 그대로 전송할까요?
// 현재 로그인 요청
POST /login
{
"email": "test1234@gmail.com",
"password": "test1234@" // 평문으로 전송되는 비밀번호
}
이러한 의문점을 시작으로, 안전한 로그인 시스템 구현에 대해 자세히 알아보았습니다.
// POST 메서드 사용
const login = async (email: string, password: string) => {
try {
const response = await axios.post('/login', {
email,
password: hashedPassword
});
return response.data;
} catch (error) {
console.error('Login failed:', error);
throw error;
}
};
import bcrypt from 'bcrypt';
const hashPassword = async (password: string) => {
const salt = await bcrypt.genSalt(10);
return bcrypt.hash(password, salt);
};
// 로그인 시
const hashedPassword = await hashPassword(password);
// axios 인스턴스 설정
const axiosInstance = axios.create({
baseURL: 'https://api.example.com',
// SSL/TLS 인증서 확인
httpsAgent: new https.Agent({
rejectUnauthorized: true
})
});
클라이언트 → 서버 (로그인 요청)
POST /login
{
"email": "test1234@gmail.com",
"password": "$2b$10$..." // 해시된 비밀번호
}
서버 → 클라이언트 (JWT 응답)
{
"accessToken": "eyJhbG...",
"refreshToken": "eyJhbG..."
}
통신 보안
데이터 보안
인증 보안
비밀번호 처리
토큰 관리
에러 처리
처음에는 단순한 의문에서 시작했지만, 이를 통해 클라이언트-서버 간 보안 통신의 중요성을 깊이 이해하게 되었습니다. 특히 JWT의 안전한 응답만큼이나 로그인 요청의 보안도 중요하다는 것을 알게 되었죠.
프론트엔드 개발자로서 보안에 대한 이해는 선택이 아닌 필수입니다.
단순히 기능 구현에만 집중하는 것이 아니라, 어떻게 하면 더 안전하게 구현할 수 있을지 항상 고민해야 합니다.
이번 경험을 통해 보안적인 측면에서의 시야를 넓힐 수 있었고, 더 나은 개발자가 되기 위한 소중한 교훈을 얻을 수 있었습니다.