목차

    개요

    현재 근무하고 있는 회사에서 MyBatis를 통해 DB와 통신 할 때, 파라미터를 HashMap으로 넘기고 있습니다. 이 경우 VO를 써야한다와 HashMap을 써야 한다에 대해서는 꽤 오래된 논의인 것으로 보입니다. 여기서는 VO를 써야한다 HashMap을 써야한다에 대한 논의는 하지 않으려고 합니다.

    다만 현재 팀에서 HashMap을 파라미터로 사용하고 있을 때 겪는 문제가 있는데 이 부분을 HashMap을 쓰지 말자가 아닌 쓰더라도 오류가 있을 시 최대한 컴파일러 오류로 나타나게 하여 IDE에서 확인이 되어 배포 전에 확인 가능한 방법을 고민한 결과를 공유하고 혹시 더 좋은 아이디어가 있을지에 대해 정리하고자 합니다.

     

    현재 회사에서 진행되는 코드 방식

    현재 회사에서는 DBconnection을 만들어주는 클래스를 Mapper 클래스로 지정하고 있습니다. 

    Mapper 클래스에서는 회사에서 제공해주는 코드를 상속하여 DB와의 연결을 진행하는데 해당 클래스는 SqlSessionSupport를 상속받은 클래스 입니다.

    xml 파일을 통해 SqlSessionFactory 빈을 설정하여 DB Connection에 대한 설정을 해주고 그를 Mapper 클래스에 주입해서 사용하게 합니다.

    @Resource(name = "sqlSessionFactory")
    public void setSqlSessionFactory(SqlSessionFactory sqlSession) {
        super.setSqlSessionFactory(sqlSession);
    }

     

    이후에는 원하는 쿼리문을 작성한 xml 파일의 쿼리 아이디와 연결해주면 끝입니다.

    예를 들어 ID로 특정 상태값을 가진 회원의 정보를 조회하는 쿼리 아이디가 selectMemberByStatus 라면 아래와 같은 메서드를 만들면 되는 것인거죠.

    public HashMap<String, Object> selectMemeberByStatus(HashMap<String, Object> param) {
        return selectOne("mapper.service.memberMapper.selectMemeberByStatus", param);
    }

    정말 단순히 연결하는 것외에는 아무것도 안하는 메서드입니다.

     

    현재 코드 방식의 문제점

    위에서 안내드린 회사 코드 진행 방식으로 작업해오며 제가 겪은 문제는 크게 2가지 입니다.

    1. 조회 조건에 값이 추가되는 경우 해당 메서드를 사용하는 모든 곳을 하나하나 찾아가며 수정해주어야 한다.

    2. HashMap으로 만들어서 넘기는 과정에서 실수가 생기는 경우가 종종 있다.

     

    1. 조회 조건에 값이 추가되는 경우 해당 메서드를 사용하는 모든 곳을 하나하나 찾아가며 수정해주어야 한다.

    예를 들어 서비스 단에서 mapper 메서드를 사용하는 곳이 30곳이 된다고 해보죠. 이 상황에서 조회 조건이 하나, 두 가지 추가된다고 생각해봅니다. memeber를 조회 하는 상태값에 대한 정의가 추가되어 a, b가 추가되었다고 생각해보는거죠.

    그러면 selectMemberByStatus를 참조하는 모든 메서드를 하나하나 찾아서 아래와 같이 코드를 변경해주어야 합니다.

    new HashMap<String, Object> {{
    	put("기존Key", "기존Value");
        put("aKey","a");
        put("bKey","b");
    }};

    IDE에서 해당 메서드를 사용한 곳을 모두 알려주겠지만 간혹 작업하다가 실수로 누락되는 케이스가 발생할 수 있습니다.

     

    2. HashMap으로 만들어서 넘기는 과정에서 실수가 생기는 경우가 종종 있다.

    위 내용에서처럼 HashMap으로 만드는 과정 중에 실수가 생기는 경우가 종종 있습니다. 예를 들어 위와 같은 HashMap을 설정해서 mapper로 넘기는데 아래와 같이 설정을 했다고 해보죠.

    new HashMap<String, Object> {{
    	put("기존key", "기존Value");
        put("aKey","a");
        put("bKey","b");
    }};

    이 경우 실제 동작 시 오류가 발생할 수 있는데 왜 발생하는지는 에러 메시지를 받기 전까지는 알기가 쉽지 않습니다. k를 대문자로 써야하는데 소문자로 써야했다는걸 IDE에서 오류로 보여주지 않는데 눈으로 발견하기는 쉽지 않습니다.

    키 값을 enum으로 처리하여 받는 방법도 있겠지만 그 경우 만약 동일한 키값을 가진 서로 다른 Entity에 대해서는 어떻게 처리할지 걱정되기도 하고 그럴거면 그냥 VO를 쓰는게 낫지 않을까라는 생각을 하였습니다.

     

    위 상황에 대해 최대한 컴파일러 오류를 내기 위한 아이디어

    제가 생각한 방법은 Mapper 클래스에 값을 넘길 때, 완성된 HashMap으로 넘기는 방법이 아닌 각각의 파라미터로 넘긴 후 Mapper 클래스 메서드 내부에서 합쳐 전달하는 것 입니다. 아래의 예시처럼 말이죠!

    public HashMap<String, Object> selectMemeberByStatus(long a, String b) {
    	HashMap<String, Object> param = new HashMap<String, Object>() {{
        	put("aKey", a);
            put("bKey", b);
     	}};
        return selectOne("mapper.service.memberMapper.selectMemeberByStatus", param);
    }

    위와 같은 방식으로 진행하면 만약 파라미터를 추가해야되는 경우 아래와 같이 변경하게 될 것 입니다.

    public HashMap<String, Object> selectMemeberByStatus(long a, String b, Sting c, String d) {
    	HashMap<String, Object> param = new HashMap<String, Object>() {{
        	put("aKey", a);
            put("bKey", b);
            put("cKey", c);
            put("dKey", d);
     	}};
        return selectOne("mapper.service.memberMapper.selectMemeberByStatus", param);
    }

    이렇게 바뀌게 되면 기존에 selectMemberByStatus(a, b)로 사용하던 메서드들에 대해 IDE가 오류를 표시해줄 것이며 컴파일 시에도 에러가 발생할 것입니다. 그렇기에 에러가 발생하는 곳을 가서 고치면 되는 것이죠.