안전한 로그인 구현하기: 클라이언트-서버 간 보안 통신의 이해

oversleep·2025년 2월 17일
0

Web

목록 보기
9/11
post-thumbnail

들어가며

백엔드와 프론트엔드 간의 통신에서 흥미로운 점을 발견했습니다.
서버에서 클라이언트로 오는 응답은 JWT를 사용해 안전하게 암호화되어 있는데, 정작 클라이언트에서 서버로 보내는 로그인 요청은 왜 평문 비밀번호를 그대로 전송할까요?

// 현재 로그인 요청
POST /login
{
  "email": "test1234@gmail.com",
  "password": "test1234@"  // 평문으로 전송되는 비밀번호
}

이러한 의문점을 시작으로, 안전한 로그인 시스템 구현에 대해 자세히 알아보았습니다.

현재 구현의 문제점

1. 잘못된 HTTP 메서드 사용

  • GET 메서드 사용의 문제점:
    • URL에 데이터가 노출될 수 있음
    • 브라우저 히스토리에 요청이 남을 수 있음
    • 보안에 취약한 평문 전송
    • RESTful 원칙에 맞지 않음

2. 비밀번호 평문 전송

  • 중간자 공격(Man-in-the-Middle Attack)에 취약
  • 네트워크 스니핑으로 비밀번호 탈취 가능
  • 서버 로그에 평문 비밀번호가 남을 수 있음

개선 방안

1. HTTP 메서드 변경

// 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;
  }
};

2. 비밀번호 해싱

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);

3. HTTPS 사용

// axios 인스턴스 설정
const axiosInstance = axios.create({
  baseURL: 'https://api.example.com',
  // SSL/TLS 인증서 확인
  httpsAgent: new https.Agent({  
    rejectUnauthorized: true
  })
});

전체 보안 흐름

  1. 클라이언트 → 서버 (로그인 요청)

    POST /login
    {
      "email": "test1234@gmail.com",
      "password": "$2b$10$..." // 해시된 비밀번호
    }
  2. 서버 → 클라이언트 (JWT 응답)

    {
      "accessToken": "eyJhbG...",
      "refreshToken": "eyJhbG..."
    }

보안 체크리스트

  1. 통신 보안

    • HTTPS 필수 사용
    • 적절한 HTTP 메서드 선택
    • 요청/응답 데이터 암호화
  2. 데이터 보안

    • 비밀번호 해싱
    • 민감한 정보 암호화
    • 토큰 안전한 저장
  3. 인증 보안

    • JWT 토큰 관리
    • 세션 관리
    • 로그아웃 처리

구현 시 주의사항

  1. 비밀번호 처리

    • 클라이언트에서도 최소한의 해싱 필요
    • 서버에서 추가 해싱 권장
    • 평문 저장 절대 금지
  2. 토큰 관리

    • 안전한 저장소 사용
    • 적절한 만료 시간 설정
    • 주기적인 갱신
  3. 에러 처리

    • 상세한 에러 메시지 제한
    • 실패 시도 제한
    • 보안 로그 관리

마치며

처음에는 단순한 의문에서 시작했지만, 이를 통해 클라이언트-서버 간 보안 통신의 중요성을 깊이 이해하게 되었습니다. 특히 JWT의 안전한 응답만큼이나 로그인 요청의 보안도 중요하다는 것을 알게 되었죠.

프론트엔드 개발자로서 보안에 대한 이해는 선택이 아닌 필수입니다.
단순히 기능 구현에만 집중하는 것이 아니라, 어떻게 하면 더 안전하게 구현할 수 있을지 항상 고민해야 합니다.

이번 경험을 통해 보안적인 측면에서의 시야를 넓힐 수 있었고, 더 나은 개발자가 되기 위한 소중한 교훈을 얻을 수 있었습니다.

profile
궁금한 것, 했던 것, 시행착오 그리고 기억하고 싶은 것들을 기록합니다.

0개의 댓글