2016년 7월 2일 토요일

Mybatis Plugin으로 특정 DB컬럼값을 암호화/복호화 처리

Mybatis를 이용하여 DAO 클래스를 생성하여 DB 조회/처리를 담당하게 만들어서 사용하고 있다. DB의 특정 테이블의 특정 컬럼은 값을 암호화하여 저장하고 있다. DB에 넣기 전에 암호화하고, 읽고 나서는 복호화를 해야 어플리케이션에서 처리가 가능하다.

1. 현재 암복호화 방식
현재는 DAO 패턴을 사용하고 있고, DAO에 데이터를 항상 DVO를 이용해서 전달하고 전달받고 있다. 그리고 암호화 대상인 컬럼인 경우에는 DVO에 encrypt() 메서드와 decrypt() 메서드를 DAO에서 호출해서 암호화/복호화를 수행하고 있다.

2. 문제1
암호화 대상 컬럼이 변경되는 경우, 대상 컬럼이 포함된 기존의 DVO 소스를 모두 변경(또는 재생성)해야 한다. 암호화 대상은 자주 바뀌는 성질은 가지고 있진 않지만, 변경되는 경우 그 변경 영향도가 매우 크고, 테스트에 대한 부담감도 커지게 된다.

3. 문제2
DAO에 DVO이외의 자료구조를 이용해서 데이터를 주고 받고자 한다면, 암호화컬럼에 대한 처리 방식을 고민해야 한다.

3. 문제3
DVO마다 encrypt()와 decrypt() 메서드를 항상 구현해야 한다. 비록 그 메서드 내용이 아무것도 없다고 하더라도. 또는 모든 DVO가 특정 클래스를 상속받도록 하고, 상위 클래스에 아무것도 구현안된 encrypt()와 decrypt()를 구현해 놓아야 한다. 이러면 DVO가 일반 POJO가 아니게 된다.

4. 해결책
Mybatis의 plugin 기능으로 해결이 가능하다. 모든 쿼리에 대해서 실행 전에 Parameter 중 특정 컬럼에 해당하는 이름을 가진 필드값을 암호화하고, 실행 후에 ResultSet에서 같은 이름의 필드값에 대해서 복호화를 수행하는 것이다.

5. 여전히 문제점
아직 DAO의 Parameter와 ResultSet이 DVO로 구성된다는 가정이 존재한다. Primitive 타입이나 String, Map과 같은 Java 기본 클래스도 사용하게 된다면, 그런 자료구조에 대한 처리도 추가로 필요할 것이다.

6. 걱정
모든 쿼리의 입출력 DVO에 대해서 Reflection을 사용하고 있어서 성능상 문제가 되지는 않을지 걱정이다.

7. 한계
실제로 DB에서는 암호화 컬럼인데, SQL의 ALIAS를 이용해서 컬럼의 이름을 변경하면 복호화되지 않은 체로 ResultSet이 리턴될 수 있다.