익명 커뮤니티를 만드는 서비스 특성상 비밀번호는 물론이고 아이디까지 암호화해서 저장해야 한다. 이 암호화를 어디서 어떻게 해줘야할지에 대해 팀에서 토론이 있었다. 토론이 재밌었고 생각하지 못했던 부분들이 있어서 기록으로 남긴다.
현재는 이런 방식으로 회원가입 요청이 오면 Dto에서 꺼낼 때 바로 암호화해서 저장을 한다. 하지만 이렇게 되면 Username
과 Password
의 도메인 로직을 적용하지 못한다. 예를 들어 글자수 제한 혹은 비밀번호에 꼭 들어가야하는 정규식 규칙 같은 것들말이다.
처음 생각해 본 방식은 DTO에 로직을 넣는 것이었다. 그렇게 하면 애초에 컨트롤러단에서 valid를 해서 처리를 해줄 수 있다. 하지만 그렇게 되면 도메인 로직이 여기저기 흩어지게 되는 것 같았다. 도메인 로직을 쓰고 응집성 높은 방식으로 처리하고 싶었다.
암호화를 서버단이 아닌 DB에 저장할 때 암호화하는 방식도 떠올랐다. SHA2('비밀번호', 256)
와 같이 쿼리를 날리면 쉽게 저장할 때 암호화해서 저장할 수 있다. 하지만 이 방식 역시 서버 코드 단에서 명시적으로 암호화를 해주어 알기 쉽게 해주는게 나을 것 같다는 의견이 나왔다.
현재 코드는 Encryptor 라는 객체를 빈으로 등록해서 암호화를 해주고 있었다.
하지만 엔티티는 빈이 아니기 때문에 Encryptor 라는 빈을 주입받을 수 없다. 이렇게 되면 외부에서 encryptor를 Member를 생성할 때 넣어줘야 한다. 이때 왜 빈을 써야할까에 대한 생각이 들었다. 결국 처음에 Encryptor를 빈으로 등록하는데에는 크게 두 가지 이유가 있었다.
하지만 이미 운영이 시작되었고 유저들이 가입을 한 상황에서 정말로 우리가 Encryptor를 바꿀 이유가 있나? 라는 의문이 제기되었다. 이미 기존 회원들은 단방향 해싱해서 정보를 저장했기 때문에 중간에 Encryptor의 알고리즘을 바꿔버리면 기존 가입한 사람들은 호환이 되지 않는다.
또 예전에 임의의 인증코드를 만들어주는 AuthcodeGenerator
의 경우 랜덤한 값을 반환하기 때문에 모킹을 해야할 필요가 있었다. 하지만 Encryptor의 경우 항상 같은 입력에 대해서는 같은 출력을 반환한다. 그래서 굳이 모킹을 해줄 필요가 없다.
게다가 빈으로 등록하지 않아도 되는 것이라면 등록하지 않는게 조금이라도 테스트를 빠르게 진행할 수 있고 통합테스트가 아닌 단위테스트로 진행이 가능하다.
~~결국 최종적으로 결정된 코드는 아래와 같다. ~~Username
도메인 클래스에서 로직에 따라 한번 검증을 하고 스태틱 클래스 Encryptor로 암호화를 하고 있다. 객체지향적인 관점에서 보면 Username
과 Encryptor
가 강하게 결합되어 있어서 변경에 유연하지 못하다라고 생각할 수 있지만, 변경할 이유가 없다면 괜찮다라는 생각을 한다.
하지만 암호화하는데 키를 가진다던가 하면 당연히 빈으로 등록하는게 낫다.
다시 이 문제가 토론에 제기되었다. 처음에는 성능의 문제등 다양한 이유들로 기존 코드에 대한 반론이 나왔지만 자료를 통해서 그렇지는 않다는 사실이 나왔다.
하지만 아예 변경 가능성을 고려하지 않는 것은 객체지향적이지 않다라는 의견이 나왔다. 양쪽 둘다 크게 유의미한 장점이나 단점이 없는 상황이라면 팀의 공동 자산인 코드에 불안감이 있는 팀원이 없는게 더 낫다라는 개인적인 생각을 했다.
충분한 고민과 이유가 있는 코드!
멋집니다!