🏛️ 홍익인간CMS 개발자 매뉴얼

Version 202506 | Updated 2025-06-12
🌐 언어 선택: 🇰🇷 한국어 🇲🇳 Монгол 🇺🇸 English

8. ⚡ 성능 최적화

8.1 캐시 시스템

홍익인간CMS는 성능 향상을 위해 EhCache 기반의 캐시 시스템을 제공합니다. 자주 사용되는 데이터를 메모리에 캐싱하여 데이터베이스 접근을 최소화하고 응답 시간을 개선합니다.

8.1.1 캐시 설정

홍익인간CMS는 다음과 같은 캐시를 제공합니다:

🗄️제공 캐시 유형

  • humanCommonCache: 사이트 메뉴 등 공통 데이터 캐싱
  • humanCodeCache: 코드 데이터 캐싱

🌐분산 캐시 네트워크 포트 확인

홍익인간CMS의 EhCache는 다중 서버 환경에서 캐시 동기화를 위해 다음 네트워크 포트들을 사용합니다:

  • 멀티케스트 주소: 230.0.0.1
  • 피어 멀티케스트 포트: 4446
  • 메시지 수신 포트: 40001

중요: 다중 서버 환경에서 캐시 동기화 오류가 발생하는 경우, 해당 포트들이 다른 애플리케이션에 의해 사용 중인지 확인이 필요합니다. 포트 충돌 시 캐시 클러스터링이 정상적으로 작동하지 않을 수 있습니다.

포트 사용 확인 방법
# Linux/Unix 환경에서 포트 사용 확인
netstat -an | grep 4446
netstat -an | grep 40001

# Windows 환경에서 포트 사용 확인
netstat -an | findstr 4446
netstat -an | findstr 40001
ehcache-human.xml 설정
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false">
    <diskStore path="user.dir/second"/>
    <defaultCache maxEntriesLocalHeap="100"
                  eternal="false"
                  overflowToDisk="false"
                  />

    <cache name="humanCommonCache"
           maxEntriesLocalHeap="5000"
           eternal="false"
           overflowToDisk="false"
           timeToLiveSeconds="300"
           memoryStoreEvictionPolicy="LRU">
           <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
    </cache>

    <cache name="humanCodeCache"
           maxEntriesLocalHeap="1000"
           eternal="false"
           overflowToDisk="false"
           timeToLiveSeconds="7200"
           memoryStoreEvictionPolicy="LRU">
    </cache>
</ehcache>

8.1.2 캐시 서비스

홍익인간CMS는 캐시를 관리하기 위한 HumanEhcacheService를 제공합니다.

주요 기능

구현 클래스
@Service("humanEhcacheService")
public class HumanEhcacheServiceImpl extends HumanAbstractServiceImpl implements HumanEhcacheService {

    @Resource(name="comm.ehcache.humanCommonCache")
    Ehcache humanCommonCache;

    @Resource(name="comm.ehcache.humanCodeCache")
    Ehcache humanCodeCache;

    @Override
    public void removeCache(String targetCache, String cacheCode) throws Exception {
        if(EgovStringUtil.equals("code", targetCache)){
            if (humanCodeCache.isKeyInCache(cacheCode)) {
                humanCodeCache.remove(cacheCode);
            }
        } else if(EgovStringUtil.equals("common", targetCache)){
            if (humanCommonCache.isKeyInCache(cacheCode)) {
                humanCommonCache.remove(cacheCode);
            }
        }
    }

    @Override
    public void removeAllCaches(String targetCache) throws Exception {
        List cacheKeyList = null;

        if(EgovStringUtil.equals("code", targetCache)){
            cacheKeyList = humanCodeCache.getKeys();
            for (int i=0; i<cacheKeyList.size(); i++) {
                String cacheKey = (String) cacheKeyList.get(i);
                if (humanCodeCache.isKeyInCache(cacheKey)) {
                    humanCodeCache.remove(cacheKey);
                }
            }
        } else if(EgovStringUtil.equals("common", targetCache)){
            cacheKeyList = humanCommonCache.getKeys();
            for (int i=0; i<cacheKeyList.size(); i++) {
                String cacheKey = (String) cacheKeyList.get(i);
                if (humanCommonCache.isKeyInCache(cacheKey)) {
                    humanCommonCache.remove(cacheKey);
                }
            }
        }
    }
}

8.1.3 캐시 사용 예시

홍익인간CMS의 다양한 서비스에서 캐시를 활용하여 성능을 최적화합니다.

코드 서비스
@Service("codeService")
public class CodeServiceImpl extends EgovAbstractServiceImpl implements CodeService {

    @Resource(name = "comm.ehcache.humanCodeCache")
    Ehcache humanCodeCache;

    @Resource(name = "humanEhcacheService")
    HumanEhcacheService ehcacheService;

    public List<CodeVO> retrieveCodeList(Map paramMap) throws Exception {
        String cacheNm = "codeCache_" + /* 캐시 키 생성 로직 */;
        
        Element el = humanCodeCache.get(cacheNm);

        if (el == null) {
            List<CodeVO> codeList = codeDAO.retrieveCodeList(paramMap);
            humanCodeCache.put(new Element(cacheNm, codeList));
            el = humanCodeCache.get(cacheNm);
        }

        return (List<CodeVO>) el.getValue();
    }

    public void updateCode(CodeVO codeVO) throws Exception {
        codeDAO.updateCode(codeVO);
        // 코드 변경 시 캐시 제거
        ehcacheService.removeAllCaches("code");
    }
}
사이트 서비스
@Service("siteService")
public class SiteServiceImpl extends EgovAbstractServiceImpl implements SiteService {

    @Resource(name="comm.ehcache.humanCommonCache")
    Ehcache humanCommonCache;

    @Resource(name = "humanEhcacheService")
    HumanEhcacheService ehcacheService;

    public List selectSiteMenuListAll() throws Exception {
        Element el = humanCommonCache.get("siteListCache");

        if (el == null) {
            List<SiteVO> siteMenuList = siteDAO.selectSiteMenuListAll();
            humanCommonCache.put(new Element("siteListCache", siteMenuList));
            el = humanCommonCache.get("siteListCache");
        }
        return (List<SiteVO>) el.getValue();
    }

    public void updateSite(SiteVO siteVO, String pblcateYN) throws Exception {
        // 사이트 정보 변경 시 캐시 제거
        ehcacheService.removeAllCaches("common");
        
        // 사이트 정보 업데이트
        siteDAO.updateSite(siteVO);
    }
}

8.2 데이터베이스 쿼리 최적화

홍익인간CMS는 MyBatis를 사용하여 데이터베이스 쿼리를 관리합니다. 효율적인 쿼리 작성을 통해 데이터베이스 성능을 최적화할 수 있습니다.

8.2.1 인덱스 활용

적절한 인덱스를 생성하여 쿼리 성능을 향상시킬 수 있습니다.

💡

인덱스 활용 팁

  • 자주 검색되는 컬럼에 인덱스 생성
  • WHERE 절에서 사용되는 컬럼 우선 고려
  • 복합 인덱스 활용으로 성능 향상
  • 불필요한 인덱스는 성능 저하 요인이 될 수 있음

8.2.2 페이징 처리

대용량 데이터를 효율적으로 처리하기 위해 페이징 처리를 구현합니다.

📄

페이징 처리 장점

  • 메모리 사용량 최적화
  • 응답 시간 단축
  • 사용자 경험 개선
  • 서버 부하 분산

8.3 결론

홍익인간CMS는 EhCache 기반의 캐시 시스템을 통해 성능을 최적화합니다. 자주 사용되는 데이터를 메모리에 캐싱하여 데이터베이스 접근을 최소화하고 응답 시간을 개선합니다. 또한 효율적인 데이터베이스 쿼리 작성을 통해 시스템의 전반적인 성능을 향상시킬 수 있습니다.

🎯

성능 최적화 핵심 포인트

  • 캐시 활용: EhCache를 통한 메모리 캐싱으로 데이터베이스 부하 감소
  • 쿼리 최적화: 효율적인 SQL 작성과 인덱스 활용
  • 페이징 처리: 대용량 데이터의 효율적 처리
  • 지속적 모니터링: 성능 지표 모니터링을 통한 지속적 개선