호환성 점검 도구는 현재 이클립스 플러그인 형태로 제공되며, 전자정부 표준프레임워크 포탈에서 플러그인(egovframe_fit.jar)을 다운로드 받아서 이클립스 설치 폴더의 dropins 폴더에 압축 파일을 집어 넣거나 혹은 plugin 폴더에 압축을 해제하여 설치할 수 있다.
플러그인을 설치한 뒤, 이클립스를 기동 (이미 실행된 경우에는 재기동) 하면 점검도구의 설치가 완료된다.
만약 표준프레임워크 개발환경이 아닌 독자적인 이클립스에 설치하는 경우, eclipse.ini 파일을 열어서 파일 인코딩이 UTF-8로 지정되었는지 확인하고 없다면 다음 옵션을 추가해준다.
-Dfile.encoding=UTF-8
호환성 점검도구는 호환성 점검 규칙을 정의한 룰셋 파일을 필요로 하며, 환경설정을 통해 룰셋 파일의 위치를 지정해주어야 한다. 또한 환경 설정에서는 결과를 저장할 폴더 및 자동저장 여부를 설정할 수 있다.
호환성 점검은 점검을 원하는 프로젝트를 Project Explorer 상에서 우클릭을 눌러서 Context Menu를 호출하여 Framework Inspection을 선택하면, 자동으로 이루어지게 된다. 점검에는 일정한 시간이 소요되며, 점검이 완료되면 하단에 Framework Inspection Tool 뷰가 추가되고 결과가 나타나게 된다. 점검 결과는 에러, 메시지, 위반사항 항목으로 구성된다.
저장 버튼을 누르거나 결과 화면에서 우클릭 하여 Context Menu에서 save result를 선택한 경우 검사 결과가 환경설정에서 지정된 디렉토리에 저장된다. 환경 설정에서 자동 저장 (Auto Save)이 체크된 경우 검사를 실시할 때 마다 지정된 디렉토리에 파일이 저장된다.
전자정부 표준프레임워크 호환성 점검을 위한 표준 룰셋은 표준프레임워크 포탈사이트에서 다운로드 할 수 있으며, 해당 룰셋에 대한 가이드 라인은 다음 파일을 참고하도록 한다.
호환성 점검 규칙을 직접 작성하고자 하는 경우 룰셋 파일을 변경하여 임의의 규칙을 지정하거나 추가, 삭제할 수 있다. 룰셋 파일의 정의는 다음과 같이 한다.
주석문은 #, , ### 으로 표시한다. 주석으로 표시된 영역은 룰셋 파일의 해석에 영향을 주지 않는다. * # 또는 : 해당 문자의 뒷 부분을 모두 주석처리 한다.
체크리스트 클래스와 콜렉터 클래스를 정의한다. 해당 정의는 룰셋 파일의 최상단에 존재해야 한다. 여기에 정의된 클래스들은 점검도구 실행시 동적으로 로딩되어 점검을 수행하게 된다. 만약 정의된 클래스를 찾을 수 없는 경우 에러메시지를 출력하고 해당 체크리스트의 점검은 수행하지 않는다. 이 경우 점검 결과의 정확성을 보장할 수 없으므로 정의시 반드시 존재하는 체크리스트 클래스를 지정하는 것이 중요하다.
Checklist [예약어] : [클래스명] # 주석 Collector [예약어] : [클래스명] # 주석
예제 :
Checklist has class annotation : egovframework.mgt.fit.inspector.checker.impl.ClassAnnotationChecker Collector query id collector : egovframework.mgt.fit.inspector.checker.impl.QueryIDCollector
예약어는 점검 규칙을 정의할 때 검사항목을 표시하는 용도로 쓰인다. 클래스명은 모든 패키지 경로를 포함하여 작성되어야 한다. 주석은 생략 가능하다.
클래스 별칭은 반복적으로 나타나는 클래스의 인용을 위하여 별도의 별칭을 지정하여 룰셋 정의를 간편하게 하기 위한 정의이다.
Class [예약어]([설명]) is [클래스명] # 주석
예약어는 룰셋 정의에서 사용될 별칭(Alias)를 의미한다. 설명은 해당 Alias의 한글명이 들어갈 수 있으며, 생략 가능하다. 클래스명은 모든 패키지 경로를 포함하여 작성되어야 하며, 주석은 생략 가능하다.
그룹 및 리스트 정의는 검사를 위하여 임의의 조건을 가지는 클래스들의 집합을 묶어두기 위한 규칙이다. 그룹 혹은 리스트 정의 내에서 다른 그룹 혹은 리스트에 대한 참조가 발생할 수 있는데, 이 경우 참조할 그룹 혹은 리스트의 정의가 더 상단에 표시되어서 먼저 해석되도록 해야 한다. 만약 순서가 바뀌어서 정의될 경우 그룹에 대한 참조를 찾을 수 없기 때문에 오류가 발생하고 해당 그룹의 정의는 이루어지지 않게 된다.
Group [그룹명]([설명]) is > [검사대상 정의] + [필수체크리스트1] + [필수체크리스트2] - [통과체크리스트1] - [통과체크리스트2] ....
List [리스트명]([설명]) is > [검사대상 정의] + [콜렉터명]
그룹명은 규칙 정의에서 사용될 그룹의 ID를, 설명은 점검 결과에 표시될 그룹명으로, 설명이 정의되지 않은 경우 그룹명이 설명을 대체하게 된다. 검사대상은 해당 그룹이 정검할 대상으로 검사대상 정의 항목을 참고하려 지정하도록 한다. + 혹은 -로 표시된 부분은 체크리스트 상에 정의된 규칙을 실제로 지정하는 부분으로, 필수룰은 +로, 통과룰은 -로 지정하게 된다. 필수룰은 위반시 그룹 정의 대상에서 제외되는 룰을, 통과룰은 단 하나라도 통과할 경우 그룹 정의 대상에 포함되는 룰을 지정하게 된다. 단, 통과룰을 모두 통과하지 못할 경우 필수룰을 모두 통과하였다고 하더라도 규칙을 만족하지 못하게 된다. 리스트의 정의 역시 그룹과 동일하게 지정되지만, 리스트는 단 하나의 콜렉터만을 규칙으로 가진다.
검사대상 정의는 해당 규칙의 점검 대상이 될 규칙을 정하는 것으로 예약어 혹은 그룹명이 들어갈 수 있다. 검사대상은 > 표시 뒤에 작성되게 된다. 검사대상은 다음 검사대상이 지정되기 전 까지 하위에 속한 모든 검사 규칙에 대해서 유효하다. 그룹 또는 규칙 정의의 첫 줄에는 검사대상 정의가 포함되는 것이 좋으며, 포함되지 않을 경우 java class가 기본 검사 대상으로 지정되나 추천하지 않는다.
> [검사대상 정의] java class, xml file, java binary, all group [그룹명], any group [그룹명], just
규칙 정의는 전체를 포괄하는 규칙과 해당 규칙에서 지켜야할 세부 체크리스트의 집합으로 이루어진다.
Rule [규칙명]([설명]) is # 주석 > [검사대상 정의] is + [필수체크리스트1] # 주석 + [필수체크리스트2] # 주석 - [통과체크리스트1] # 주석 - [통과체크리스트2] # 주석 .... > [검사대상 정의] is # 주석 + [필수체크리트스3] # 주석 + [필수체크리스트4] # 주석 - [통과체크리스트3] # 주석 - [통과체크리스트4] # 주석 ....
일반적으로 주석이 룰셋 파일의 해석에 도움을 주는 용도로만 사용되는 것에 비해서 규칙정의의 주석은 검사 결과에 해당 규칙의 위반 여부를 표시할 때 같이 표시되는 의미를 가지고 있다. 따라서 규칙 정의시 주석으로 해당 규칙의 상세한 설명을 적어주는 것이 좋다. 규칙 정의의 주석문은 위반시 표시될 것을 염두해두어 '~해야 한다.' '~는 할 수 없다.' 식으로 적어주는 것이 자연스럽다.
필수룰과 통과룰의 주석 역시 같은 의미를 가지고 있으며, 검사대상 및 각 룰의 사용법은 그룹 및 리스트 정의시와 동일하다. 만약 해당 항목의 결과가 false로 나와야 통과시키고 싶다면 항목 앞에 not 또는 do not을 붙이면 된다.
XML 파일을 검사하기 위해서는 기본제공하는 HasQueryResultChecker를 사용하거나 독자적인 XML 검사 체커 클래스를 정의하여 사용할 수 있다. 이 분석도구에서 XML 파일은 Structure의 형태가 아닌 Map의 형태로 저장 되며, 해당 맵은 각각의 XML 노드에 대하여 노드의 계층적 위치를 Key값으로, 노드의 내용을 Value로 저장하여 활용하고 있다. 해당 노드에 대한 검사를 위해서 다음과 같이 사용할 수 있다.
sqlMap..@id
위 쿼리는 루트 엘레멘트가 sqlMap인 iBatis SQL Map 파일을 기준으로 모든 id 값을 결과값으로 출력한다. 노드의 중간구조를 .. 구분자를 통하여 생략시켰기 때문에 id라는 attribute를 가지는 모든 노드가 결과에 포함된다.
sqlMap..@id=goodsDAO.insertGoods
위 쿼리는 해당 XML 파일에서 id Attribute를 가지는 모든 노드들 중 그 id값이 goodsDAO.insertGoods인 노드를 찾아낸다. XML 파일에 따라서 결과가 다수 나올 수도, 하나도 나오지 않을 수 있다. 이와 같은 경우 HasQueryResultChecker는 해당 결과값이 하나 이상 나왔을때 true를 반환하는 체커 클래스이다.
sqlMap.select..@id|sqlMap.insert..@id|sqlMap.delete..@id|sqlMap.update..@id|sqlMap.procedure..@id
위 쿼리는 | 구분자를 이용하여 해당 XML 파일 내의 모든 CRUD 기능을 담당하는 노드의 id값을 수집하고 있다. sqlMap.select 와 같은 형태로 명시적으로 연결되었기 때문에 루트 엘레멘트의 바로 하위에 select, insert, delete, update, procedure 노드가 있는 경우에만 해당하며 그 이후에는 암시적으로 하위 노드를 검색하고 있으므로 해당 노드의 어떤 하위 노드이더라도 id 값을 포함하고 있으면 결과에 포함시킨다.
[+/-] [체크리스트명] [검사 값] 또는 [+/-] [체크리스트명] $[클래스 별칭] 또는 [+/-] [체크리스트명] group [그룹명]
체크리스트명은 사전에 정의된 체크리스트 명을 그대로 사용한다. 찾을 수 없을 경우 에러메시지를 추가하고, 해당 체크리스트는 검사하지 않는다. 검사값에는 실제 체크리스트 클래스에 전달할 값을 써줄 수 있다. 검사값이 필요없는 클래스의 경우 생략할 수 있다. 만약 특정 클래스명을 전달할 경우 사전 정의된 해당 클래스의 별칭을 지정해 줄 수 있으며, 이는 룰셋 파싱시 해당 클래스의 전체명으로 대체되서 해석된다. 단, $ 기호 뒤의 단어 (공백이 있기 까지의 단어)는 모두 클래스 별칭으로 인식하므로 클래스 별칭을 주고 .[메소드명] 형태로 연결해서 사용하는 것은 불가능하다. 만약 체크리스트가 그룹을 인자로 받을 경우 그룹명을 직접 부여할 수 있다. 이 경우 모든 검사 대상과 모든 그룹 구성요소가 m*n 형태의 체크리스트를 생성하여 검사를 수행하게 된다. 이 경우 검사속도가 매우 떨어질 가능성이 있으므로 group 형태의 인자를 받는 체크리스트 클래스는 Object[] 형태의 인자를 받는 check 메소드를 overriding 하고 GroupChecker 인터페이스를 implements 해주는 것이 좋다. 이 경우 그룹 구성요소가 한 번에 배열의 인자로 전달되기 때문에 검사 시간을 매우 크게 단축시킬 수 있다.
다음은 분석도구에서 기본적으로 제공하는 Checker 클래스의 사용법이다.
1. Annotation 체커
[+/-] has class annotation [어노테이션 명] [+/-] has annotation [어노테이션 명] [+/-] has field annotation [어노테이션 명] [+/-] has local annotation [어노테이션 명] [+/-] has method annotation [어노테이션 명]
다음 코드는 @Repository 어노테이션이 클래스 정의 위에 선언된 클래스들에 대해서 true를 리턴하는 사용예제이다. 어노테이션 명을 지정할때 @표시는 생략할 수 있다.
+ has class annotation @Repository
2. 상속관계 체커
[+/-] extends [클래스 명] [+/-] implements [인터페이스 명 / any ]
3. 메소드 호출 체커
[+/-] invoke method [메소드 명] [+/-] invoked by method [메소드 명] [+/-] invoked by class [클래스 명] [+/-] invoke class [클래스 명] [+/-] has parameter [파라메터 명/ignore case] [리스트 명]
다음 코드는 쿼리ID를 수집하여 리스트로 작성하고 해당 클래스가 수집된 쿼리ID를 실인자로 하는 메소드 호출을 시도하는지 여부를 검사한다.
List QUERY_ID is > xml file + query id collector Rule CALL_QUERY(DAO 클래스) is > java class + has parameter $QUERY_ID
4. 클래스/파일 위치 체커
[+/-] in package [패키지 명] [+/-] under directory [project:[디렉토리 경로] / 디렉토리 경로] [+/-] in directory [project:[디렉토리 경로] / 디렉토리 경로] [+/-] has common super directory [리스트명]
5. 클래스/파일 검증 체커
[+/-] binary equal to [파일명:해시코드] [+/-] if exist and binary equal to 파일명:해시코드] [+/-] size equal to [파일명:크기] [+/-] if exist and size qeual to [파일명:크기] [+/-] file exist [파일명] [+/-] at least one [group 그룹명] [+/-] filename starts with [파일명] [+/-] class name starts with [클래스명]
6. XML 체커
[+/-] has attribute [속성명] [+/-] has bean class [클래스 명] [+/-] has query result [쿼리] [+/-] has element [원소명]
룰셋을 임의 정의한 경우 호환성 점검 도구 상의 RulestParser 클래스를 이용하여 해당 룰셋을 파싱해보고 오류가 발생하지 않는지 테스트 해 볼 수 있다. 만약 임의의 체크리스트 클래스 혹은 콜렉터 클래스를 정의한 경우 실제 샘플 프로젝트의 검사를 수행하여 해당 클래스의 정상 동작여부를 확인하는 것이 좋다. RulesetParser는 룰셋 자체를 인스턴스화 시키면서 문법 검사를 수행할 뿐, 동적으로 체크리스트 클래스를 생성하거나 검사 메소드의 유무를 파악하지는 않는다. 때문에 RulsetParser의 역할은 정적인 룰셋 분석에 한정한다고 생각하는 것이 좋다.