개발 slecs

시스템별 비밀번호 정책 추가

목차

비밀번호 정책을 "그냥 8자 이상이면 되는 거 아니야?" 정도로 볼 수도 있는데, 이번 작업하면서 생각보다 챙길 게 많다는 걸 다시 확인했다.

시스템이 단일 서비스로만 돌아가면 상관없다. 정책 하나 박아두면 끝이니까. 근데 플랫폼 성격으로 여러 시스템이 물려 있으면 얘기가 달라진다. 시스템 A는 일반 사용자가 쓰고, 시스템 B는 내부 관리자가 쓰는 구조라면 같은 정책을 강제하는 게 오히려 이상한 일이다. 이번에 그 부분을 제대로 끊어냈다.

DB에 정책값을 저장하는 구조로 간 이유

하드코딩이나 properties 파일로 박아두면 정책 바꿀 때마다 배포가 필요하다. 운영 중에 "특수문자 필수 조건 풀어줘" 같은 요청이 오면 그때마다 코드 건드리고 배포하는 건 피하고 싶었다. 그래서 DB에 시스템별 설정값으로 저장하는 방식을 택했다.

구조 자체는 단순하다. 시스템 식별자를 키로 해서 정책 항목들을 조회하고, 서비스 레이어에서 받아서 쓴다. MyBatis XML에 쿼리 관리하는 방식이라 변경도 깔끔하게 분리된다.

정책 항목 구성은 아래처럼 정리했다.

항목 기본값 비고
최소 길이 8 시스템별 재정의 가능
최대 길이 20 초과 입력 차단
대문자 필수 선택 비트플래그 또는 boolean
소문자 필수 선택
숫자 필수 선택
특수문자 필수 선택

최대 길이를 굳이 설정하는 이유가 뭐냐고 물을 수 있는데, 실제로 무제한으로 뚫어두면 bcrypt 같은 해싱 알고리즘 특성상 과도하게 긴 입력이 들어왔을 때 CPU를 갈아 먹는 케이스가 생긴다. 보안 측면에서도 입력 길이 제한은 기본 중에 기본이다.

서버-클라이언트 이중 검증

검증 로직은 서버 측과 클라이언트 측 둘 다 태웠다. 서버에서만 하면 UX가 떨어지고, 클라이언트에서만 하면 보안이 뚫린다. 이건 선택의 문제가 아니다.

서버 측 핵심 검증은 이렇게 짰다.

boolean valid = password.length() >= minLen
    && password.length() <= maxLen
    && matchesRequiredTypes(password, requiredTypes);

matchesRequiredTypes는 정책으로 설정된 필수 문자 타입들을 정규식으로 순회하면서 다 통과하는지 확인한다. 타입마다 패턴을 따로 두는 방식이라 조합이 자유롭다.

클라이언트 쪽은 JSP에서 정책값을 동적으로 받아서 실시간 피드백에 쓴다. 비밀번호 입력 중에 "대문자가 없습니다" 같은 안내를 바로 보여주는 거다. 정책이 DB에 있으니까 JSP가 렌더링될 때 서버에서 값을 내려주면 클라이언트 검증 로직도 그걸 기준으로 동작한다. 정책 바꾸면 클라이언트 코드 건드릴 필요 없이 DB값만 갱신하면 반영된다.

이걸 적용한 지점은 세 군데다.

  • 회원가입 폼
  • 비밀번호 변경 (본인 변경)
  • 관리자 강제 비밀번호 변경

세 지점 모두 같은 서비스 메서드를 타도록 했다. 각각 별도 검증 로직이 흩어져 있으면 나중에 정책 바뀔 때 하나 빠뜨리는 사고가 난다. 단일 진입점으로 모으는 게 맞다.

작업하면서 챙긴 것들

Spring MVC + MyBatis 구조에서 이런 설정성 기능을 넣을 때 조심할 게 있다. 정책값을 매 요청마다 DB에서 읽어오면 조회가 쌓인다. 자주 바뀌는 값이 아니니까 적당한 캐싱을 고려할 수 있는데, 이번엔 일단 직접 조회로 두고 이후 필요하면 손보는 방향으로 했다. 오버엔지니어링보다 단순하게 돌아가는 걸 먼저 만드는 게 낫다.

배포 흐름은 로컬 기동 확인 → 개발 DB 반영 → 배포 순서로 진행했다. 정책값이 DB에 있는 구조라 초기 데이터를 같이 넣어줘야 한다. 스크립트 누락되면 서비스 기동 후 NPE 맞는 수가 있으니 이 부분은 배포 체크리스트에 명시해뒀다.

작업 규모 자체는 크지 않았다. 그런데 이런 류의 작업이 실제로는 꽤 중요하다. 비밀번호 정책이 없거나 허술하면 나중에 보안 감사나 인증 항목 점검할 때 가장 먼저 걸리는 항목 중 하나다. 기능 단위로 보면 작아 보여도, 시스템 신뢰성을 구성하는 조각 중 하나라고 생각하고 꼼꼼하게 처리했다.

댓글 0

첫 댓글 달아줘.