💬
목차
< 뒤로가기
인쇄

IDE 설치가이드

요구사항

시스템 요구사항은 아래와 같다.

  • 서버
항목 설명
운영체제 (OS) Windows, Unix, Linux, MacOS
JVM Java 1.8
WAS Java 1.8을 지원하는 WAS는 기본적으로 지원
Database Oracle 12c/19c, SQL Server 2012, Mysql 5.7+, Mariadb 10.0+, Tibero 6.0
  • 개발환경 (Spring Tool Suite 4.19)
항목 설명
운영체제 (OS) Windows, Linux, MacOS
JRE Java 17 (32bit, 64bit)
CPU 2GHz 이상, dual/quad core processor
메모리 1GB, (Recommend 2GB)
디스크 공간 2.1GB 이상

라이선스

v2.2 버전이후 캐모마일은 라이선스를 필요로 한다.

라이선스를 발급받아 아래와 같이 라이선스를 적용하여 사용한다.

적용 대상

캐모마일 프레임워크를 사용하는 경우 라이선스가 필요하며, 대표적으로 아래와 같다.

  • 사용자 어플리케이션
  • 어드민 어플리케이션 (웹, 배치)
  • 모바일 앱스토어 서버

라이선스 종류

라이선스 종류는 아래와 같다.

분류 설명 캐모마일
정식 라이선스 정식 라이선스 체결 후 배포되는 라이선스.
운영 환경에서 사용
✔ 운영 서버에 적용
개발 라이선스 개발 시 사용하기 위한 라이선스이며, 특정 기간동안 발급 된다.
로컬 개발 및 개발 서버 구성에 사용한다.
✔ 2개월 (로컬 및 개발 서버에 적용)
체험 라이선스 초기 체험 을 위한 라이선스이며, 짧은 기간 동안 사용할 수 있는 라이선스이다. ✔ 2주 (기간이 만료되는 경우 동작하지 않음)

체험 및 개발 라이선스의 경우 기간이 만료된 경우 동작하지 않습니다.

적용 방법

캐모마일 라이선스는 해당 어플리케이션의 클래스패스 내 발급 된 chamomile.license 파일을 로드하여 라이선스의 유효성을 검증한다.

단, 배치 어드민 어플리케이션의 경우 배포 된 압축파일의 conf 폴더를 우선하여 로드한다.

로컬 개발환경

  • 어플리케이션

    • 어플리케이션의 클래스패스(즉, src/main/resources)에 라이선스 파일을 위치시킨다.
  • 어드민

    • 개발도구에서 어드민을 실행하는 경우에도 라이선스 파일이 필요하다.
    • 개발도구의 상단 메뉴 중 Window를 선택하고 Chamomile > Administrator를 선택하여 라이선스 파일의 위치를 정의한다.

    image-20210929115644069

    어드민이 실행될때, 설정에서 지정한 파일이 아래 경로로 복사되어 라이선스가 로드된다.
    C:\Chamomile\eclipse\plugins\chamomile.ide_1.1.0[버전].202109232237[빌드날짜]\server\jettyRoot_admin\webapps\ROOT\WEB-INF\classes

서버 개발환경

  • 어플리케이션
    • maven profile을 이용하여 개발서버 혹은 운영서버에 라이선스 파일을 별도로 적용시킨다.
  • 어드민
    • 배포 된 어드민[모바일 앱스토어] 서버의 WAS의 클래스패스에 라이선스 파일을 위치시킨다.
    • e.g. [tomcat 설치경로]/webapps/어드민[모바일 앱스토어]/WEB-INF/classes

로드 우선 순위

클래스패스 內 라이선스 로드 우선순위는 WAS의 리소스 로드 정책을 따른다.
tomcat의 경우 라이선스를 로드하는 순서는 아래와 같다.

  • Bootstrap classes of your JVM
  • /WEB-INF/classes of your web application
  • /WEB-INF/lib/*.jar of your web application
  • System class loader classes (described above)
  • Common class loader classes (described above)

웹 애플리케이션 클래스 로더가 <Loader delegate="true"/>로 구성된 경우 순서는 다음과 같다.

  • Bootstrap classes of your JVM
  • System class loader classes (described above)
  • Common class loader classes (described above)
  • /WEB-INF/classes of your web application
  • /WEB-INF/lib/*.jar of your web application

에러 및 경고

아래와 같이 캐모마일의 라이선스 파일이 존재하지 않는 경우 어플리케이션이 동작하지 않습니다.
LicenseNotFoundError

Caused by: net.lotte.chamomile.core.license.LicenseNotFoundError: chamomile license file('chamomile.license') cannot be found in the classpath.
  at net.lotte.chamomile.core.license.Licenser.loadInputStream(Licenser.java:112) ~[chamomile-core-3.0.0-RELEASE.jar:3.0.0-RELEASE_6e9289d]
  at net.lotte.chamomile.core.license.Licenser.loadLicense(Licenser.java:31) ~[chamomile-core-3.0.0-RELEASE.jar:3.0.0-RELEASE_6e9289d]

개발 도구(Eclipse)

개발환경은 응용 S/W를 개발하기 위한 개발도구 이다.

개발도구는 개발에 필요한 도구들을 포함하고 있으며, 구성요소는 아래와 같다.

  • 개발도구

  • 테스트도구

  • 빌드도구

  • 형상관리도구

  • Etc.

개발도구에서 제공하는 주요 기능은 아래와 같다.

  • Create Chamomile Project(Maven Project – Archetype)
  • Generate Code [web, batch] – template based
  • Debugging
  • Testing
  • Start/Stop Admin
  • Build
  • Etc.

설치 (Windows)

인터넷에서 별도로 다운로드하여 구성하지 않아도 바로 개발에 착수 할 수 있도록 개발환경을 제공한다.

구성요소들은 아래와 같다.

  • 전체 용량 : 약 2.12GB
  • Spring Tool Suite 4.19
  • Lombok v1.18.28
  • jdk : amazon jdk 1.8
  • maven : 이클립스 내장 maven을 사용하며 settings.xml파일만 제공
  • maven repository : 라이브러리들을 바로 사용할 수 있도록 maven repository를 제공
  • server : tomcat 8.5
  • workspace : 이클립스의 설정을 최적화한 기본 workspace제공(workspace변경시 설정 초기화)
  • DB : mariadb-10.5.8-winx64 버전 및 설치가이드 제공

설치 방법

배포되는 zip파일의 압축을 해제 한다.

압축 해제 경로는 C:아래로 올 수 있도록한다.(기본설정이 C:로 설정되어있다.)

image-20231127131255.png

[그림] 개발환경 위치

로컬 개발 환경에서 사용할 DB를 설치한다.(선택사항)
첨부되는 "MariaDB설치.pdf"문서를 참고한다.

폴더 설명

image-20231127093313.png

[그림] 개발환경 폴더구조

chamomile-batch-3.0.0 배치프레임워크
Database MariaDB설치 파일 및 가이드
sts-4.19.0.RELEASE 자체 제공하는 플러그인이 설치된 이클립스폴더
Java JDK 폴더
maven settings.xml 제공
repository maven repository목록
server tomcat 폴더
workspace 이클립스 기본 worksapce

경로 변경

C드라이브 외에 별도의 위치에 개발환경을 구성하고 싶다면 아래의 항목들을 수정한다.

아래 예시는 D드라이브로 개발환경을 변경하는 방법을 가이드한다.

  1. maven폴더의 settings.xml

    아래 경로를 D드라이브로 변경한다.

<localRepository>D:/Chamomile/repository</localRepository>
  1. eclipse폴더의 eclipse.ini

    아래 경로를 D드라이브로 변경한다.

-vm
D:/Chamomile/java/amazon-jdk/jdk1.8.0_265/bin/javaw.exe
  1. eclipse바로가기를 실행하여 settings 파일 위치를 변경한다.
    • Window -> Preferences -> Maven -> User Settings 에서 User Settins항목의 XML파일경로를 D:\Chamomile\maven\settings.xml 으로 변경한다.
      0f25ab23199909ec4a611251d2577f0f.png
      [그림] Maven Settings.xml파일 위치 변경

macOS

캐모마일 개발 도구는 현재 Windows만을 정상적으로 지원합니다.

환경 설정

메인화면

image-20200915162414289

[그림] 메인화면

datasource설정

image-20200915162544112

[그림] 환경설정(데이터베이스 설정)

END

IDE 사용가이드

개요

개발표준프레임워크란?

개발표준프레임워크는 개발표준을 확립하고 효율적이고 안정적인 개발과 운영환경을 제공한다.

  • 자바기반 웹/배치 어플리케이션 개발을 위한 플랫폼

  • 전사비즈니스 요구사항 신속 대응을 위한 L.Cloud 기반 플랫폼

표준프레임워크

특장점

개발표준 프레임워크는 아래와 같은 특장점을 제공한다.

  • 표준 개발 환경 (개발 생산성 제고)

    • 단순 업무를 위한 자동화된 개발도구

    • Eclipse, 프로젝트/소스코드/배치JOB 생성도구

  • 클라우드 환경 및 MSA 대응

    • 캐모마일 기반의 어플리케이션을 쉽게 만들기 위한 독립형(standalone) 캐모마일 Boot

    • 멀티 인스턴스(어플리케이션) 관리

  • 상용 솔루션 연계 (손쉬운 시스템 통합)

    • 다양한 형태의 연계모듈 제공

    • UI 어댑터, 카톡, 텔레그램, 이노룰스 BRMS, SAP JCO

  • 그룹 보안성 심의 준수

    • 프레임워크 차원의 그룹 보안성 심의 사전 대응
    • 인증/인가, 암호화(SHA, AES, ARIA), 로그 마스킹
  • 시스템 공통 컴포넌트/어드민

    • 검증된 시스템 컴포넌트

    • 자원관리, 권한관리, 시스템관리, 통계, 모니터링 등

  • 모바일 앱 실행/운영 환경

    • iOS, Android Hybrid 모바일 앱 개발, 실행 환경 제공

    • 모바일 앱 관리, 배포를 위한 운영 환경 제공

  • 배치 어플리케이션 개발 및 관리

    • 독립형, 내장 배치 컴포넌트, 워크플로우, 실행(재시작) 및 중지
  • 오픈소스 APM을 활용한 모니터링

    • Xlog, Active Service, CPU, Memory, Network, TPS 등.
  • 설치/교육/운영 지원

    • 전담 지원조직을 통한 지원

아키텍처

Java 기반의 Spring Framework로 구성되어져 있으며, 그룹사의 다양한 환경을 고려해 Spring 버전 5.3으로 구성되었다.

v1.2 이후부터는 모바일 및 스프링 부트를 지원한다. (Spring Boot 버전 2.7)

자사의 클라우드 플랫폼인 L.Cloud와 Clepass에서의 동작을 지원하고, 아래와 같은 다양한 기능들을 제공한다.

image-20231201101005.png
[그림] 개발 표준 프레임워크 아키텍처


구성요소

개발표준 프레임워크의 구성요소는 아래와 같다.

image-20231130155517.png

[그림] 개발 표준 프레임워크 구성요소

프레임워크 차별성

  • 상용솔루션 서비스 연계

  • 글로벌 다국어 지원 (화폐표현 및 로케일정보 포함)

  • 오픈소스 그리드 컴포넌트 선정 및 연동

  • 캐모마일 Boot(클라우드 및 MSA 대응), 모바일 실행/운영 환경 제공

  • 테스트(시나리오)관리, 배치관리, 모니터링 지원기능

  • 보안서비스 강화(그룹 보안성 심의 항목 대응)

요구사항

시스템 요구사항은 아래와 같다.

  • 서버
항목 설명
운영체제 (OS) Windows, Unix, Linux, MacOS
JVM Java 1.8
WAS Java 1.8을 지원하는 WAS는 기본적으로 지원
Database Oracle 12c/19c, SQL Server 2012, Mysql 5.7+, Mariadb 10.0+, Tibero 6.0
  • 개발환경 (eclipse oxygen 4.7)
항목 설명
운영체제 (OS) Windows, Linux, MacOS
JVM Java 1.8+ (32bit, 64bit)
CPU 2GHz 이상, dual/quad core processor
메모리 1GB, (Recommend 2GB)
디스크 공간 2.1GB 이상

개발 도구

서버 생성

image-20200915163347336

[그림] 서버생성

프로젝트 생성

image-20231129141845.png
[그림] 프로젝트 생성

코드 생성

image-20200928110207811

[그림] 코드 자동생성1

image-20200928110324157

[그림]코드 자동생성2

image-20231129142040.png

[그림] 코드 자동생성3 – API template

image-20231129142716.png

[그림] 코드 자동생성4 – API template

Template

image-20200915163054565

[그림] 템플릿 등록

image-20200915163146953

[그림] 템플릿구성요소 등록1

image-20200915163241823

[그림] 템플릿구성요소 등록2

  • 템플릿파일 등록시 각 항목 설명

    • Output name : 템플릿 파일이 생성될 최종 이름

    • package name : 템플릿 파일이 생성될 경로. java파일의 경우 root path아래로 생성되며 그 외에는 폴더 형식으로 경로를 입력하여 생성 될 수 있도록 한다.

    • root path : 파일이 생성될 최상위 폴더를 지정해 준다. 해당 폴더 아래의 package name을 참조하여 폴더를 만들어준다.

  • 기타 추가 버튼 설명

    • Edit : 선택된 템플릿 구성요소를 수정한다. 폴더, 파일, 템플릿 파일에 맞게 수정창을 띄워준다.
  • Delete : 선택된 템플릿 구성요소를 삭제한다.
  • Export : 선택된 템플릿 구성요소를 별도로 저장한다.

Template 파일 변수목록

  • pagakeName
  • entityCamel
  • entityPascal
  • entityOrigin
  • projectName
  • voList
  • pkColumns

packageName

설명

  • 사용자가 입력한 package명

사용법

${packageName}

예시

package ${packageName}.${entityCamel}.controller;

import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

entityCamel

설명

  • 선택한 테이블명을 camel case로 변환한 문자열

사용법

${entityCamel}

예시

  • package명
package ${packageName}.${entityCamel}.controller;

import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

entityPascal

설명

  • 선택한 테이블명을 Pascal case로 변환한 문자열

사용법

${entityPascal}

예시

  • 클래스명
@Controller
public class ${entityPascal}Controller {

  /** Log Factory */
  private final Logger logger = LoggerFactory.getLogger(this.getClass());
  //...
}

entityOrigin

설명

  • 조회된 테이블의 원본이름

사용법

${entityOrigin}

예시

  • SQL쿼리
SELECT * from ${entityOrigin} A

projectName

설명

  • 프로젝트 명

사용법

${projectName}

예시

${projectName}

voList

설명

  • 테이블에서 제공하는 컬럼 목록을 변수 화 한 목록

  • 하위요소

변수명 타입 설명
dataType String java형 데이터 타입으로 변환한 값(Deprecated)
– TINYINT, SMALLINT, BOOLEAN, INTEGER, BIGINT => Integer
– REAL, FLOAT, DOUBLE, DECIMAL => Double
– VARCHAR, LONGVARCHAR, CLOB, NVARCHAR, CHAR, DATE, TIME, TIMESTAMP, 기타 => String
colNameOrg String 테이블에서 조회된 컬럼명
colNameCamel String 테이블에서 조회된 컬럼명을 camel case로 변환시킨 값
colNamePascal String 테이블에서 조회된 컬럼명을 pascal case로 변환시킨 값
colBindValue String colNameCamel 값을 mybatis 에서 사용할 수 있도록 "#{변수명}" 형태로 처리한 값(deprecated)
colBindValueItemPrefix String colNameCamel 값을 mybatis 에서 사용할 수 있도록 "#{item.변수명}" 형태로 처리한 값(deprecated)
length integer 컬럼의 길이
pk boolean Primary key여부 (pk일 경우 true)
nullable boolean null 허용 여부(null허용일 경우 true)
comment String 컬럼 comment값(SQL Server는 지원하지 않음)
dataTypeClassName String java형 데이터 타입으로 변환한 값
NUMERIC, DECIMAL => java.math.BigDecimal
BIT => java.lang.Boolean
TINYINT => java.lang.Byte
SMALLINT => java.lang.Short
INTEGER => java.lang.Integer
BIGINT => java.lang.Long
REAL => java.lang.Float
FLOAT, DOUBLE => java.lang.Double
BINARY, VARBINARY, LONGVARBINARY => byte[]
DATE => java.sql.Date
TIME => java.sql.Time
TIMESTAMP => java.sql.Timestamp
BLOB => java.sql.Blob
CLOB => java.sql.Clob
나머지 -> java.lang.String

사용법

<#if voList??>    
  <#list voList as op>
    ${op.colNameOrg}
    ${op.colNameCamel}
    ${op.colNamePascal}
    ${op.colBindValue}
    ${op.colBindValueItemPrefix}
    ${op.length}
    ${op.pk}
    ${op.nullable}
    ${op.comment}
    ${op.dataTypeClassName}
 </#list>
</#if>

예시

  • dataType
<#if voList??>    
    <#list voList as op>  
        private ${op.dataType} ${op.colNameCamel};  
    </#list>  
</#if>
  • colNameOrg
<#if voList??>    
        <#list voList as op>  
            ${op.colNameOrg} ${op.colNameCamel} <#if op_has_next>,</#if>
        </#list>   
</#if>
  • colNameCamel
<#if voList??>    
    <#list voList as op>  
    private ${op.dataType} ${op.colNameCamel};  
    </#list>  
</#if>
  • colNamePascal
<#if voList??>    
    <#list voList as op>      
    public ${op.dataType} get${op.colNamePascal}(){
        return this.${op.colNameCamel};
    }   
    public void set${op.colNamePascal}(${op.dataType} ${op.colNameCamel}){
        this.${op.colNameCamel} = ${op.colNameCamel};
    }

    </#list>  
</#if>
  • colBindValue
SELECT 
*    
            FROM 
            table A

            WHERE
            <#if voList??>    
                    <#list voList as op>  
                        ${op.colNameOrg} = ${op.colBindValue} <#if op_has_next> and </#if>
                    </#list>   
            </#if>

# 문자가 freemarker에서 예약된 문자이기 때문에 바로 사용할 수 없다. 이 때문에 사용의 편의를 위해 제공하는 변수로 좀더 확장성있게 사용하고자 할 경우 #문자를 ${}으로 감싸서 표현한다. 아래와 같이 작성할 경우 colBindValue 에서 제공하는 값과 동일하게 사용할 수 있다.

${"#"}{${op.colNameCamel}}
  • length
<#if voList??>    
    <#list voList as op>  
    @Size(max=${op.length})
        private ${op.dataType} ${op.colNameCamel};  
    </#list>  
</#if>
  • pk (boolean값으로 조건문에서만 사용해야 한다.)
<#if voList??>    
    <#list voList as op>  
        <#if op.pk>
            This is pk!
        </#if>
    </#list>
</#if>
  • nullable (boolean값으로 조건문에서만 사용해야 한다.)
<#if voList??>    
    <#list voList as op>  
        <#if !op.nullable>
            @NotNull
        </#if>
  </#list>
</#if>
  • comment
<#if voList??>    
    <#list voList as op>  
    //${op.comment}
        private ${op.dataType} ${op.colNameCamel};  
    </#list>  
</#if>
  • dataTypeClassName
<#if voList??>    
    <#list voList as op>      
        private ${op.dataTypeClassName} ${op.colNameCamel};     
    </#list>  
</#if>

pkColumns

  • 테이블의 PK컬럼들만 모아놓은 변수로 사용법은 voList와 같다.
<#if pkColumns??> 
    <#list pkColumns as op>   

    ${op.colNameOrg}
    ${op.colNameCamel}
    ${op.colNamePascal}
    ${op.colBindValue}
    ${op.colBindValueItemPrefix}
    ${op.length}
    ${op.pk}
    ${op.nullable}
    ${op.comment}
    ${op.dataTypeClassName}

    </#list>
</#if>

freemarker의 자세한 문법은 아래 사이트를 참고 한다.

https://freemarker.apache.org/docs/index.html

로컬서버에 배포

서비스 모듈 설정

image-20200928110426053

[그림] 로컬 서버 배포1

image-20200928110523336

[그림] 로컬 서버 배포 2

원격 저장소 사용

1) 왼쪽 영역에서 Git Repositories를 선택한다. 없을 경우 Window -> show view -> other -> Git Repositories 검색 후 Open 한다.

[그림] Git Repositories View화면

2) Clone a Git repository항목을 클릭하여 저장소 정보와 계정을 입력한다.

(Location URI항목에 주소만 입력하면 Authentication외 나머지 항목들은 자동으로 채워진다.)

[그림] 저장소 정보 입력

3) Next를 클릭하면 clone시킬 Branch를 선택하게 되고 알맞은 Branch를 선택한후에 Next버튼을 클릭한다.

[그림] Branch선택

4) Directory항목에서 프로젝트가 위치할 경로를 지정하고Finish를 진행한다.

[그림] 프로젝트 경로 지정

5) 프로젝트 import

clone된 프로젝트의 working tree에서 마우스 오른쪽 버튼을 클릭하여 Import Project를 선택하여 import를 진행한다.

[그림] 프로젝트 import 1

[그림] 프로젝트 import 2

commit/push

수정사항이 생길경우 아래 그림처럼 수정된 파일에 > 표시가 추가된다.

[그림] 파일 변경

이 상태에서 Git staging View를 확인해보면 Unstaged Changes 영역에 수정된 파일이 있는것을 확인할 수 있다.

저장소에 적용하고자 하는 파일들을 Staged Changes영역으로 드래그 하여 옮긴 후 Commit Message를 상세하게 작성한다.

image-20200928110749980

[그림] 변경내역 commit/push

이후 Commit을 하거나 Commit and Push버튼으로 저장소에 저장한다. Commit만 수행했을 경우 추후에 [생성된 Project] 마우스오른쪽 버튼 -> Team -> push to upstream으로 commit 내역들을 저장소에 적용해야 한다.

pull

push전에 항상 자신의 로컬저장소와 원격저장소간의 정보를 동일하게 해야 한다. 로컬저장소의 버전이 원격저장소 버전과 다를경우 push는 reject된다.(non fast-forward)

pull을 실행하여 원격 저장소에서 최신정보들과 head정보를 받아온다. 그 다음 push를 수행한다.

[생성된 Project] 마우스오른쪽 버튼 -> Team -> pull

pull을 수행할 때 내가 수정한 파일과 원격지에서 내려받게되는 파일이 동일할 경우
충돌이 발생한다.(conflict)

[그림] conflict발생

이경우 아래와 같이 조치한다.

[생성된 Project] 마우스오른쪽 버튼 -> Team -> Rebase..

[그림] Rebase 1

위의 화면에서Rebase를 클릭

[그림] 충돌이 발생한 파일 확인

위 대화상자에서 충돌이 발생한 파일을 확인하고 Stash.. 버튼을 클릭하여 나의 변경
내용을 저장해둔다.

[그림] Stash저장

그다음 다시 pull을 한번더 수행하여 최신 상태로 적용 될 수 있도록 한다.

그리고 본인이 변경한 내용을 다시 적용시킨다.

[생성된 Project] 마우스오른쪽 버튼 -> Team -> Stashs를 클릭하여 방금 적용한 내용을 살펴본다.

[그림] Stash 확인

파일이 열리면 오른쪽 상단의 (Apply Stashed Changes) 버튼으로 바로 적용하거나 변경된 내용을 하나씩 살펴보며 변경해주고 다시 Commit/push를 진행한다.

Ignore설정

공동작업을 하다보면 이클립스 설정파일까지 push되어 다른 사용자가 해당 파일을 내려받았을 때 프로젝트가 정상적으로 동작하지 않는 경우가 있다. 원격저장소에는 항상 소스만 위치할 수 있도록 하며 설정파일들은 ignore처리하여 다른사용자에게 영향을 주지 않도록 한다.

Ignore처리할 파일/폴더에서 마우스오른쪽 버튼 -> Team -> Ignore

[그림] Ignore설정

위와 같이 할경우 .gitignore파일이 생성/변경되며 해당 파일을 서버에 push시켜준다.

[그림] .gitignore파일

.gitignore파일에 선택된 경로가 저장되어 다음에 해당 파일/폴더가 변경 되더라도 unstage영역에 노출되지 않는다.

.gitignore파일을 열어보면 아래와 같이 형상에 포함하지 않아야할 파일이나 폴더 목록이 나열되어있은 것을 확인 할 수 있다.

/target/
*.class
.settings/
.classpath
.project
/bin/
/logs/

*.jar
*.war
*.ear
/readme.md

PMD

정적 분석

정적 분석은 소프트웨어를 분석하는 방법의 하나로, 프로그램을 실행하지 않은 상태에서 코드 레벨에서 분석하는 방법이다. 올바른 형식의 소스 파일만 처리할 수 있기 때문에 컴파일 오류를 보고하지는 않으며, 개발자들이 표준 코드에 부합할 수 있는 코드를 작성하여 소스 코드 품질을 높이기 위해 사용한다.

PMD

PMD는 대표적인 오픈소스 기반 정적 소스 코드 분석기다. 사용되지 않는 변수, 비어 있는 try-catch 블록, 불필요한 객체 생성 등 전반적으로 프로젝트 내의 소스를 검토하여 다소 비효율적이거나 치명적일 수 있는 프로그래밍 결함을 찾는다.

PMD에는 내장 규칙 세트(룰셋)가 포함되어 있으며, 사용자 정의 규칙을 작성하는 기능을 제공한다.

주로 Java 및 Apex을 포함하여 6개의 다른 언어를 지원한다. 지원하는 언어는 Java, JavaScript, Salesforce.com Apex and Visualforce, Modelica, PLSQL, Apache Velocity, XML, XSL, Scala 등이다.

PMD 주요 점검 내용

PMD는 소스 코드를 점검하여 표준 코드 기준, 코드 안티패턴, CPD(Cut and Paste Detector)를 기준으로 위반 여부를 확인한다.

PMD 룰셋 (Ruleset)

룰셋은 PMD에서 실행될 규칙들을 설명하는 XML 파일이다. 개발자가 작성한 소스 코드를 검사하며, 위험 요인 및 오류를 발견하여 알려 주기 위한 기준이 된다.

PMD에서 기본적으로 제공하는 룰셋이 있다. 사용자가 개별 프로젝트를 위해 룰셋을 커스터마이징하여 사용할 수 있다. 룰셋을 커스터마이징하는 방법은 [사용자 지정 룰셋 파일 생성 방법](#사용자 지정 룰셋 파일 생성 방법)을 참고한다.

자바 룰셋 카테고리

1) Best Practices

사용자가 일반적으로 통용되는 모범 사례를 따를 수 있도록 하는 규칙이다. 파라미터 재사용 방지, 인터페이스 내의 상수 지정 방지, default가 없는 switch 문 방지, 사용하지 않는 private 메서드 제거 등이 있다.

2) Code Style

사용자가 특정한 코드 스타일을 따를 수 있도록 하는 규칙이다. 필드, 파라미터, 지역 변수, 메서드, 클래스의 네이밍 컨벤션 규칙과 사용하지 않는 괄호 삭제 등이 있다. 3) Design

사용자가 디자인 이슈를 발견할 수 있도록 하는 규칙이다. 메서드가 존재하지 않는 추상 클래스 방지, 널 포인터 예외 처리 방지 등이 있다.

4) Documentation

사용자가 코드 문서를 적절하게 작성할 수 있도록 하는 규칙이다. 보디가 비어 있는 메서드에 대해 주석을 권장하는 규칙, 너무 긴 주석 길이를 권장하지 않는 규칙 등이 있다.

5) Error Prone

발생하기 쉬운 오류를 방지할 수 있도록 하는 규칙이다. 생성자 안에 오버라이드 할 수 있는 메서드를 호출하는 것을 권장하지 않는 규칙, 비어있는 try-catch 문 제거 등이 있다.

6) Multithreading

다중 스레드 실행 시 발생하기 쉬운 이슈를 방지할 수 있도록 하는 규칙이다. 스레드 그룹 사용을 권장하지 않는 규칙, Thread.run() 메서드를 권장하지 않는 규칙 등이 있다.

7) Performance

사용자에게 차선책을 요구하는 규칙이다. 새로운 Integer 객체 인스턴스를 권장하지 않는 규칙, short 타입 사용을 권장하지 않는 규칙 등이 있다.

8) Security

잠재적인 보안 결함을 방지할 수 있도록 하는 규칙이다. 암호화 작업에 하드 코딩된 값을 권장하지 않는 규칙 등이 있다.

우선순위 (Priority)

PMD는 규칙의 우선순위를 1단계에서 5단계로 분류하며 값이 낮을수록 높은 위험성을 가지고 있다. PMD 실행 후 소스 코드 옆의 마커로 우선순위를 파악할 수 있다.

속성 (Property)

PMD는 규칙을 XML 파일에서 직접 커스터마이징 할 수 있도록 속성값을 지정할 수 있다. 규칙을 바로 참조하여 사용하면 기본값으로 설정이 유지된다.

다음은 Error Prone에 해당하는 EmptyCatchBlock 규칙의 설명이다. 해당 규칙은 allowCommentedBlocks, allowExceptionNameRegex라는 두 가지 속성값을 가지고 있으며 아래 코드와 같이 \<property>태그 안에서 속성값을 지정할 수도 있다.

캐모마일 룰셋 (67건)

캐모마일에서 선정한 룰셋은 다음과 같다.

Blocker, Critical 단계(심각도 Medium High 이상)에 해당하는 Java Global Ruleset 선정 후, 통용되는 Medium, Medium Low, Low 단계의 규칙을 추가로 선정하였다. 룰셋 목록은 다음과 같다.

# Rule Priority Type
1 AbstractClassWithoutAnyMethod High Design
2 AssignmentInOperand Medium Error Prone
3 AssignmentToNonFinalStatic Medium Error Prone
4 AvoidArrayLoops Medium Performance
5 AvoidAssertAsIdentifier Medium High Error Prone
6 AvoidBranchingStatementAsLastInLoop Medium High Error Prone
7 AvoidEnumAsIdentifier Medium High Error Prone
8 AvoidFileStream High Performance
9 AvoidLosingExceptionInformation Medium High Error Prone
10 AvoidMultipleUnaryOperators Medium High Error Prone
11 AvoidReassigningParameters Medium High Best Practices
12 AvoidSynchronizedAtMethodLevel Medium Multithreading
13 AvoidThrowingNullPointerException High Design
14 AvoidThrowingRawExceptionTypes High Design
15 AvoidUsingNativeCode Medium High Code Style
16 AvoidUsingShortType High Performance
17 AvoidUsingVolatile Medium High Multithreading
18 BooleanInstantiation Medium High Performance
19 BrokenNullCheck Medium High Error Prone
20 ByteInstantiation Medium High Performance
21 ClassNamingConventions High Code Style
22 ClassWithOnlyPrivateConstructorsShouldBeFinal High Design
23 ConstantsInInterface Medium Best Practices
24 ConstructorCallsOverridableMethod High Error Prone
25 DoNotCallGarbageCollectionExplicitly Medium High Error Prone
26 DoubleCheckedLocking High Multithreading
27 DuplicateImports Medium Low Code Style
28 EmptyCatchBlock Medium Error Prone
29 EmptyFinallyBlock Medium Error Prone
30 EmptyIfStmt Medium Error Prone
31 EmptyMethodInAbstractClassShouldBeAbstract High Code Style
32 EmptyStatementNotInLoop Medium Error Prone
33 EmptyTryBlock Medium Error Prone
34 EmptyWhileStmt Medium Error Prone
35 EqualsNull High Error Prone
36 FieldNamingConventions High Code Style
37 FinalFieldCouldBeStatic Medium Design
38 FormalParameterNamingConventions High Code Style
39 ImmutableField Medium Design
40 ImportFromSamePackage Medium Error Prone
41 InefficientEmptyStringCheck Medium Performance
42 InefficientStringBuffering Medium Performance
43 IntegerInstantiation Medium High Performance
44 LocalVariableNamingConventions High Code Style
45 LongInstantiation Medium High Performance
46 MethodNamingConventions High Code Style
47 MoreThanOneLogger Medium High Error Prone
48 ProperCloneImplementation Medium High Error Prone
49 ReturnEmptyArrayRatherThanNull High Error Prone
50 ShortInstantiation Medium High Performance
51 SimpleDateFormatNeedsLocale Medium Error Prone
52 SimplifyBooleanExpressions Medium Design
53 SingleMethodSingleton Medium High Error Prone
54 SingletonClassReturningNewInstance Medium High Error Prone
55 StringInstantiation Medium High Performance
56 StringToString Medium Performance
57 SuspiciousEqualsMethodName Medium High Error Prone
58 SwitchStmtsShouldHaveDefault Medium Best Practices
59 SystemPrintln Medium High Best Practices
60 UncommentedEmptyMethodBody Medium Documentation
61 UnnecessaryConversionTemporary Medium Error Prone
62 UnnecessaryWrapperObjectCreation Medium Performance
63 UnusedFormalParameter Medium Best Practices
64 UnusedPrivateField Medium Best Practices
65 UnusedPrivateMethod Medium Best Practices
66 UselessParentheses Medium Low Code Style
67 UselessStringValueOf Medium Performance

PMD 설치

본 가이드는 이클립스 PMD 플러그인 설치 방법을 안내한다. 커맨드라인 사용 시 다음 링크를 참조한다. https://sourceforge.net/projects/pmd/files/

1) Help → Eclipse Marketplace에서 pmd-eclipse-plugin을 검색 후 설치한다.

2) Help → About Eclipse 클릭 후 Installation Details를 클릭한다.

3) Eclipse Installation Details에서 PMD Plug-in의 버전을 확인할 수 있다.

사용자 지정 룰셋 파일 생성 방법

기존 룰셋 참조

템플릿을 사용하여 비어있는 룰셋 파일을 작성한다.

<?xml version="1.0"?>
<ruleset name="Custom Rules"
    xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
    <description>
        My custom rules
    </description>
    <!-- Your rules will come here -->
</ruleset>

PMD가 제공하는 룰셋을 사용하려면 이에 대한 참조를 추가해야 한다. 기본적으로 제공하는 룰셋과 각 규칙에 대한 설명은 다음을 참고한다.
https://pmd.github.io/latest/pmd_rules_java.html

아래와 같이 검색한 규칙의 설명, 우선순위, 규칙이 정의된 클래스, 간단한 예시와 참조를 확인할 수 있다.

속성이 명시된 규칙의 경우 각 속성의 설명과 기본값, 그리고 커스터마이징할 수 있는 예시를 확인할 수 있다.

해당 라인을 ruleset에 추가하면 규칙 EmptyCatchBlock이 룰셋에 추가된다.

<rule ref="category/java/errorprone.xml/EmptyCatchBlock" />

대량으로 추가하고 싶다면 다음과 같이 특정 규칙을 제외한 나머지 전체 룰셋을 참조할 수도 있다.

참조할 때는 액세스 가능한 파일 시스템 경로 혹은 상대 경로를 사용할 수 있다.

<rule ref="category/java/codestyle.xml">
    <exclude name="WhileLoopsMustUseBraces"/>
    <exclude name="IfElseStmtsMustUseBraces"/>
</rule>

우선순위를 지정하거나 속성을 변경하는 등 더 자세한 룰셋 설정은 아래 링크를 참고한다.

https://pmd.github.io/pmd-6.9.0/pmd_userdocs_configuring_rules.html

특정 룰만 추출

1) Eclipse 메뉴에서 Windows → Preferences 선택 후 PMD → Rule Configuration을 클릭한다.

2) 상단의 Use global rule management를 체크하여 활성화된 룰셋을 확인한다. 규칙 선택 후 export 버튼을 클릭한다. 주의할 점은 추출할 규칙을 선택할 때 체크 표시가 아닌 규칙 항목 자체를 클릭해야 한다. 다중 선택할 경우 Ctrl 버튼으로 한 항목씩 여러 번 선택, 혹은 Shift 버튼으로 다중 항목 선택 후 export 버튼을 클릭한다.

새로운 룰 생성

PMD는 기존에 제공하던 룰셋 이외에도 Java, XPath를 이용한 두 가지 방법으로 룰을 새로 정의할 수 있다. 새로 생성할 룰은 참조되기 전에 룰셋에 정의되어 있어야 한다.

자세한 사항은 아래 링크를 참조한다.
https://pmd.github.io/pmd-6.9.0/pmd_userdocs_extending_writing_pmd_rules.html


PMD 사용

이클립스 플러그인으로 분석

1) Eclipse 메뉴에서 Windows → Preferences 선택 후 PMD → Rule Configuration을 클릭한다.

2) 상단의 Use global rule management를 클릭하여 활성화한 후 X 버튼을 눌러 모든 룰셋을 삭제한다.

3) Import 버튼을 클릭한다. Browse 버튼을 클릭하여 룰셋 파일을 선택한다.

4) 모든 룰셋을 체크하고 하단의 Apply and Close 버튼을 클릭하면 자동으로 프로젝트를 재빌드한다.

5) 적용할 프로젝트를 우클릭 후 PMD → Check Code를 클릭한다.

6) 코드 분석이 완료되면 PMD 뷰로 전환되며 규칙에 위반된 코드를 표시한 결과가 나타난다. 뷰가 전환되지 않는다면 Window → Show View → Other를 클릭하여 Violations Outline, Violations Overview를 선택하면 분석 결과를 확인할 수 있다.

7) Violations Outline과 Violations Overview에서 파일 이름과 에러 메시지 등을 확인할 수 있으며 코드에도 표시된다. Violations Outline에서는 간략한 위반 규칙 내용을 확인할 수 있다. Violations Overview에서는 위반된 소스 코드의 패키지명, 각 파일의 위반 사항 수, 라인당 위반 수, 그리고 메소드당 위반 수를 볼 수 있다. 오른쪽 상단의 마커를 클릭하여 우선순위에 따른 Violation을 확인할 수 있다.

8) PMD 비활성화 시 프로젝트 우클릭 후 PMD → Clear Violations, Clear Violation Reviews를 클릭한다.

Maven으로 분석

1) Maven 사용 시 프로젝트 pom.xml 파일에 maven-pmd-plugin을 추가한다. 기본적인 포맷은 다음과 같다. Maven 환경 설정에 대한 세부 사항은 다음 링크를 참고한다.
https://maven.apache.org/plugins/maven-pmd-plugin/usage.html

<project>
  ...
  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-pmd-plugin</artifactId>
        <version>3.13.0</version>
        <configuration>
          <linkXref>true</linkXref>
          <sourceEncoding>utf-8</sourceEncoding>
          <minimumTokens>100</minimumTokens>
          <targetJdk>1.5</targetJdk>
          <excludes>
            <exclude>**/*Bean.java</exclude>
            <exclude>**/generated/*.java</exclude>
          </excludes>
          <excludeRoots>
            <excludeRoot>target/generated-sources/stubs</excludeRoot>
          </excludeRoots>
        </configuration>
      </plugin>
    </plugins>
  </reporting>
  ...
</project>

2) 특정 룰셋 지정 시 마찬가지로 \<configuration>\</configuration> 안에 명시한다. 프로젝트 구조에 따라 경로가 변하기 때문에 파일 위치 작성에 주의한다. 하단의 예시를 참고한다.

<rulesets>
  <!-- A rule set, that comes bundled with PMD -->                            
  <ruleset>/category/java/bestpractices.xml</ruleset>
  <!-- Custom local file system rule set -->
  <ruleset>d:\rulesets\strings.xml</ruleset>
  <!-- Custom remote rule set accessed via a URL -->
  <ruleset>http://localhost/design.xml</ruleset>
</rulesets>

3) 메이븐으로 pmd 실행 시 mvn pmd:pmd 명령어로 Run한다. 해당 프로젝트의 target
폴더에 pmd.xml 실행 결과 파일이 추가된다.


오탐 (False Positive)

PMD 의 경우 해당 라인에 //NOPMD 를 추가하면 해당 라인은 검사를 하지 않고 진행한다 소스 코드의 해당 라인을 예외 처리하는 것이기 때문에 해당 라인에서 발견되는 모든 보안 약점이 예외 처리된다.

구분 판정기준
정탐(True Positive) 취약점을 정확하게 탐지함
오탐(False Positive) 취약점이 해결된 내용을 탐지함
미탐(False Negative) 취약점을 탐지 못함

다음 다운로드