IT_Programming/Java

[정리] Java Application에서 점검해야 하는 대상들...

JJun ™ 2009. 10. 8. 20:03

--------------------------------------------------------------------------------------------------

참고 : 자바 성능을 결정짓는 코딩 습관과 튜닝 이야기

--------------------------------------------------------------------------------------------------

 

 

1. 패턴과 아키텍처는 잘 구성되어 있는가?


  1) 너무 많은 패턴을 사용하지 않았는가?
     : 어떤 시스템을 만들더라도 패턴은 애플리케이션을 구성할 때 반드시 적용해야 한다.
       하지만 너무 많은 패턴을 적용하면 유지 보수성이 떨어지고, 문제가 발생했을 때 추적이 어려워진다.
       좋은 패턴이라고 무작정 적용하기보다는 꼬 필요한 패턴만을 사용해야 한다.

 

  2) 데이터를 리턴할 때 TO(혹은 VO)패턴을 사용하였는가?

     혹은 Collection 관련 클래스를 사용하였는가?
     : 데이터를 주고 받는 시간을 절약하기 위해서 TO 패턴을 일반적으로 사용한다.
       그리고 때에 따라서는 Collection 관련 클래스를 사용하기도 한다. 이러한 패턴을 적용하지 않거나
       관련 표준을 정하지 않고 개발을 할 경우 시스템의 응답 시간도 영향이 있겠지만,

       유지 보수성이 떨어진다. 게다가 HashMap으로 데이터를 주고 받으면, 소스를 완전히 뜯어 보지 않는

       이상 개발자만 어떤 키와 값이 들어있는지 알게 된다.

 

  3) Service Locator 패턴은 적용이 되어 있는가?
     : 서비스 로케이터 패턴을 사용하면 애플리케이션에서 필요한 대상을 찾는 룩업(lookup) 작업을 할 때
       소요되는 대기 시간을 줄일 수 있다. 만약 서버의 CPU 사용량이 높지 않을 때 응답 속도가 느리다면,
       서비스 로케이터를 적용해야 하는 부분이 있지 않은가 한번쯤 확인을 해봐야 한다.

 

 

 

2. 기본적인 애플리케이션 코딩은 잘 되어 있는가?


  1) 명명 규칙은 잘 지켰는가?
     : 문제에 더 빨리 접근할 수 있도록 Java의 기본 명명 규칙을 따라주는 것이 좋다.

 

  2) 필요한 부분은 예외처리가 잘 되어 있는가?
     : 예외 처리를 제대로 하지 않으면 사용자는 아무런 응답을 받지 못하고, 여러분이 운영하는 시스템을
       더 이상 사용하지 않을 수도 있다. 문제가 발생했을 때 원인을 밝히기 위해서 예외 처리는 필수다.

 

  3) 예외 화면은 지정되어 있는가?
     : 예외 화면에 대한 표준이 있는지 확인해 보아야 한다. 만약 예외 화면을 구성하지 않고 지정하지도
       않는다면, 사용자는 여러분이 사용하는 서버의 종류가 어떤 것인지 알게 될 것이다.
       때에 따라서는 시스템에 어떤 클래스가 있는지도 확인할 수 있을 것이다.

 

  4) 예외 정보를 혹시 e.printStackTrace()로만 처리하고 있지 않은가?
     : e.printStackTrace() 메서드를 호출하면, 서버의 스택 정보를취합하여야 하기 때문에 서버에 많은

       부하가 발생하게 된다. 다른 로그와 섞여있는 스택 정보 로그를 통해서 얼마나 문제를 해결할 수 있을까?

 

  5) System.gc() 메서드가 소스에 포함되어 있지 않은가?
     : 이 메서드를 코드 이곳 저곳에 심어 놓을 경우, 운영해야 하는 서버를 2배 이상으로 늘려야 할 것이다.
       만약 아무리 많은 요청이 들어오더라도 힙 메모리의 사용량이 전혀 늘어나지 않고 일직선을 유지하고

       있다면, System.gc() 메서드가 소스 안에 있는지 확인 해보기 바란다.

       그리고 이 메서드를 웹 애플리케이션에서 사용하면 WAS의 CPU 사용량은 상상도 못할 만큼 급격히

       증가한다.
      
  6) System.exit() 메서드가 소스에 포함되어 있지 않은가?
     : 웹 애플리케이션의 경우 이 메서드가 수행되면 WAS의 프로세스가 죽는다. 스레드가 죽는 것이 아니라

       프로세스가 죽는 것이니 이 메서드가 소스에 포함되어 있다면 반드시 제거해 주기 바란다.
      
  7) 문자열을 계속 더하도록 코딩하지는 않았는가?
     : String 클래스는 더할 경우 새로운 객체를 생성한다. 이것이 길어지거나 많아 진다면,

       서버는 GC를 처리하느라 바빠질 것이다.


     : jdk5.0 이상을 사용하면 자동으로 StringBuilder 클래스로 변환해 주기는 한다.
       하지만 루프를 수행하면서 문자열을 더할 경우는 컴파일러도 어쩔 수 없으니 반드시 필요에 따라서
       StringBuilder나 StringBuffer 클래슬르 선택하여 사용하기 바란다.

 

  8) StringBuilder나 StringBuffer 클래스도 제대로 사용했는가?
     : StringBuilder나 StringBuffer 클래스 안에서 문자열을 더하면, 이 두 개의 클래스를 쓸 필요가 전혀 없다.
       한마디로 제대로 이해하지도 못하고 이 클래스들을 사용하는 경우라고 말할 수 있다.

 

  9) 무한 루프가 작동할 만한 코드는 없는가?
     : '해당 구문 안에서 조건을 만족시키지 못하고 무한 루프를 돌게 된다면'이라는 가정을 할 필요 없도록

        코딩을 하자. 즉, 되도록이면 for문을 사용하자는 말이다.

 

 10) static을 남발하지 않았는가?
     : 메모리를 아낀다고 static을 남발하다가는 시스템이 심각한 오류를 발생시킬 수 있다.
       static의 특징은 다른 JVM에서는 static이라고 선언해도 다른 주소나 다른 값을 참조하지만,
       같은 JVM이나 같은 WAS 인스턴스에서는 같은 주소와 같은 값을 참조한다는 것이다.
       그리고 GC의 대상도 되지 않는다. 잘만 사용하면 성능을 향상시킬 수 있지만 잘못 사용하면 예기치

       못한 결과를 초래하게 된다.

     : static을 잘 활용하기 위한 방법
       - 자주 사용하고 절대 변하지 않는 변수는 final static으로 선언하자
       - 설정 파일 정보도 static으로 관리하자
       - 코드성 데이터(건수가 많지 않되 조회 빈도가 높은 데이터)는 static을 사용해서 DB에서 한 번만 읽자.
    

 11) 필요한 부분에 synchronized 블록을 사용하였는가?
     : 그냥 동시에 해당 메서드가 호출될 것 같아서 synchronized 블록을 사용한 것은 아닌지 확인해야 한다.
       필요 없는 부분에 synchronized 블록을 사용하게 될 경우 성능 저하를 발생시킬 수 있다.

 

 12) IO가 계속 발생하도록 개발되어 있지 않은가?
     : IO를 매번 발생시키면서 시스템의 아까운 자원을 낭비하지 말자.
       예) 설정 파일을 매번 파일에서 읽도록 개발하는 것

 

 13) 필요 없는 로그는 다 제거했는가?
     : "로그 레벨이 DEBUG가 아니니 괜찮겠지" 하는 생각은 버려라. 여러분이 개발하는 시스템은 필요한

        데이터만 처리하기 위해서 메모리가 소비된다. 프린트 하지도 않을 로그 데이터를 문자열로

        만들기 위해서 아까운 메모리를 사용하고, 그 메모리를 청소하기 위해서 GC를 해야 하는 불쌍한 JVM을

        생각해보라.

 

 14) 디버그용 System.out.println은 다 제거했는가?
     : 로그 레벨을 바꾼다고 해도 지워지지 않는 것이 System.out.println() 로그이다.
       본인이 만든 애플리케이션이 조금이라도 빨라지기를 우너한다면, 이 디버그용 로그도 제발 지워주기

       바란다.

 

 

 

3. 웹 관련 코딩은 잘 되었는가?

 

  1) JSP의 include는 동적으로 했는가? 아니면 정적으로 했는가?
     : JSP를 동적으로 include하면 서버에도 부하를 줄 뿐만 아니라 응답 시간에도 영향을 준다.
       꼭 필요한 부분에만 동적 include를 하기 바라며, 그렇지 않은 경우는 정적 include의 사용을 권장한다.
       그렇다고 무작정 정적으로 include를 하면변수를 공유하게 되어 예기치 못한 문제가 발생할 수도 있으니

       유의하자.

 

  2) 자바 빈즈는 너무 많이 사용하지 않았나?
     : 하나의 화면에서 자바 빈즈를 수십 개씩 사용하지 않는가? 하나의 TO(Transfer Object)를 사용해서

       처리할 수도 있는 데이터라면, 여러 개의 자바 빈즈를 사용해서 응답 시간에 영향을 주는 일이 없도록

       하자.

 

  3) 태그 라이브러리는 적절하게 사용했나?
     : 많은 양의 데이터를 태그 라이브러리로 처리할 경우에는 성능에 많은 영향을 끼친다.
       데이터 양이 적을 경우에는 상관이 없겠지만 무조건 태그 라이브러리를 사용한다면,
       10000 건이 넘는 데이터 처리는 대부분 JSP에서 소요될 것이다.

 

  4) EJB는 적절하게 사용하였나?
     : EJB를 많이 사용하다고 해서 시스템이 안정화되는 것은 아니다. 서버를 가동하는데 시간의 여유가

       있거나 서버의 메모리가 충분히 여유가 있다면 상관 없다. 하지만 EJB 하나 하나는 일반 클래스보다

       많은 메모리를 점유해야 하며, 서버를 기동할 때에도 많은 시간이 소요된다. 반드시 필요한 경우에만

       EJB를 사용하자.

 

  5) 이미지 서버를 사용할 수 있는 환경인가?
     : 이미지, 자바 스크립트, CSS, 플래시 등 정적인 컨텐츠가 많고 사용자의 요청이 많은 경우에는

       웹 서버 이외의 이미지 서버를 사용할 수 있다.
       정적인 컨텐츠만을 제공하는 서버로서, 웹 서버에서 파일을 읽어서 처리하는 것이 효율적이다.

 

  6) 사용 중인 프레임웍은 검증되었는가?
     : 검증되지 않은 프레임웍에서 많은 문제가 발생할 수 있다. 가장 좋은 방법으로는 검증된 프레임웍을

       사용하는 것이지만, 만약 새로 개발된 프레임웍을 사용할 경우에는 성능 테스트 및 메모리 프로파일링을

       통해서 해당 프레임웍의 안정성을 확인해 놓아야 한다.

 

 

 

4. DB 관련 코딩은 잘 되어 있는가?

 

  1) 적절한  JDBC 드라이버를 사용하는가?
     : 현재 DB에 맞는 버전의 JDBC를 사용하고 있는가? 간혹 버그가 있는 JDBC를 사용하여 성능이

       나오지 않는 경우가 발생한다.
       되도록이면 가장 최신 WAS 및 DB 벤더에서 추천하는 문제 없는 JDBC를 사용하기를 권장한다.

 

  2) DB Connection, Statement, ResultSet은 잘 닫았는가?
     : 반드시 finally 구문을 사용해서 Connection, Statement, ResultSet을 명시적으로 닫아 주기 바란다.
       그렇지 않으면 사용 가능한 연결이 부족해져 여러분들이 개발한 시스템이 사용 불가능한 상태가

       되는 것은 시간 문제다.

 

  3) DB Connection Pool은 잘 사용하고 있는가?
     : 프로젝트 규모가 크면 클수록 표준을 따르지 않을 확률도 커진다. DB 연결 부분을 개발자의 역량에

       맡기면 여러 가지 형태로 DB에 연결하게 될 것이다.
       관련되는 표준을 반드시 정하고, DB Connection Pool은 반드시 사용해야 DB의 리소스를 보다

       효율적으로 사용할 수 있다.

 

  4) 자동 커밋 모드에 대한 고려는 하였는가?
     : 기본 커밋 모드는 자동 모드로 되어 있다. 하지만 조회성 프로그램도 자동 커밋 여부를 지정하게 되면,

       약간의 응답 시간 저하가 발생하게 된다.
       반드시 필요하지 않은 경우에는 자동 커밋을 하도록 하자.

 

  5) ResultSet.last() 메서드를 사용하였는가?
     : 전체 건수를 처리하기 위해서 last() 메서드를 사용했는지 확인해봐야 한다. 데이터 건수가 많을수록

       응답 시간이 느려진다. 쿼리를 두 번 수행하더라도 전체 건수를 가져오기 위해서 last() 메서드의 사용을

       자제해주기 바란다.
 
  6) PreparedStatements를 사용하였는가?
     : Statement를 사용하면 매번 쿼리를 수행할 때마다 SQL 쿼리를 컴파일하게 된다. 이 작업은 DB에

       많은 부하를 주게 된다. 그러므로 쿼리 문장이 계속 동적으로 변경되어야 하는 경우를 제외한 대부분의

       경우에는 PreparedStatements를 사용하기 바란다.

 

 

 

5. 서버의 설정은 잘 되어 있는가?

 

  1) Java VM 관련 옵션들은 제대로 설정되어 있는가?
     : 64bit 기반의 시스템을 사용하면서 -d64 옵션을 사용하지 않으면, 32비트로 시스템이 
운영된다.        

     : 클래스 패스는 순차적으로 인식된다. 여러 Jar 파일 중 만약 같은 패키지 명에 같은 클래스가

       존재할 경우에는 앞에 명시한 클래스 패스에 우선권이 있다.

 

  2) 메모리는 몇 MB로 설정해 놓았는가?
     : 가끔 서버의 메모리를 설정하지 않고, 성능이 나오지 않는다고 이야기 하는 사이트가 있다.
       설정하지 않으면 서버는 기본 64MB로 시작한다는 사실을 반드시 기억하기 바란다. 

 

  3) GC 설정은 어떻게 되어 있는가?
     : 혹시 -client로 설정되어 있는지 확인한다.
     : GC 방식에 따라서 서버의 성능이 엄청난 차이가 발생할 수 있다.
       가능하면 성능 테스트를 통해서 시스템과 서버에 맞는 GC 옵션을 설정하자.

 

  4) 서버가 운영 모드인지 개발 모드인지 확인하였는가?
     : 서버가 개발 모드라면, WAS는 주기적으로 변경된 클래스가 있는지 확인할 것이다.
       이 작업은 서버에 많은 부하를 주게 된다. 서버가 주기적으로 느려진다면, 이 부분을 확인하자.

 

  5) WAS의 인스턴스가 몇 개 기동되고 있는가?
     : WAS에서 하나의 인스턴스당 적어도 한 개는 있어야 제대로 된 운영이 가능하다. CPU는 4장인데,

       인스턴스가 30개 정도 있는 것은 아닌지 확인하기 바란다. 자바는 코볼이나 포트란이 아니다.


     : WAS의 CPU 개수가 적을 경우, 때에 따라서 인스턴스의 개수를 증가시키면, 서버의 처리량은

       증가될 수 있다. 이 인스턴스의 개수에 대해서는 정답이 없다.
       그러므로 서버 및 애플리케이션의 상황에 맞게 성능 테스트를 통해서 시스템의 적절한 인스턴스 개수를

       도출해야 한다.

 

  6) JSP Precompile 옵션은 지정해 놓았는가?
     : 서버를 기동할 때 JSP를 미리 컴파일하도록 해놓으면 사용자는 JSP가 수정이 되었는지 여부와 상관없이

       일정한 응답 속도를 느낄 것이다. 하지만 이 옵션을 지정해 놓으면 서버가 기동될 때 JSP를 컴파일하기

       위한 시간도 많이 소모되기 때문에 상황에 맞게 옵션을 설정하자.

 

  7) DB Connection Pool 개수와 Thread 개수는 적절한가?
     : 스레드의 개수가 DB Connection Pool의 수보다 절대로 적으면 안된다.

       스레드의 개수는 DB Connection Pool의 개수보다 보통 10개 정도 더 많이 설정한다.
       만약 DB Connection Pool의 설정을 서버 기본 설정으로 해놓고 운영을 한다면,

       서버의 리소스도 별로 사용하지 않고 10명 이상의 동시 사용자를 처리하지 못할 것이다.
       대부분 WAS의 Connection Pool의 초기값은 10 ~ 20개이다.

 

  8) 세션 아웃 타임은 적절한가?
     : 세션을 더 이상 사용하지 않을 때 세션 정보는 삭제 되어야 한다. 만약 세션 타임 아웃 시간을

       하루 이상의 큰 값으로 지정하고, 해당 서버를 재시작하지 않으면 해당 서버는 메모리 릭이 발생하여

       더 이상 사용할 수 없는 상황이 될 것이다.

 

  9) 검색 서버가 있다면, 검색 서버에 대한 설정 및 성능 테스트를 하였는가?
     : 일반적으로 검색 서버에서 주기적으로 데이터를 모으기 위해서 서버의 리소스를 많이 사용하게 된다.
       만약 검색 서버의 세팅을 점검하지 않고, 성능 테스트를 하지 않는다면, 예기치 못한 부분에서 시스템의

       리소스를 점유하고 있을지도 모른다.

 

 

 

6. 모니터링은 어떻게 하고 있는가?

 

  1) 웹 로그(Access log)는 남기고 있는가?
     : 웹 로그는 애플리케이션의 사용 흔적을 남기는 가장 간단하고도 많은 자료를 제공한다.
       애플레케이션의 사용량과 자주 사용하는 애플리케이션을 분석하기 위해서,
       추후 용량 산정의 기초 자료가 되는 웹 로그는 반드시 남겨서 관리하자.

 

  2) verbosegc 옵션은 남기고 있는가?
     : GC가 어떤 형태로 발생하는지를 확인하고자 한다면, 반드시 verbosegc 옵션을 사용하여 로그를

       남기자. 메모리의 크기를 지정하기 위해서나, GC 옵션을 변경하기 위해서라도 verbosegc 옵션은

       매우 유용하게 활용될 것이다.

 

  3) 각종 로그 파일에 대한 규칙은 있는가?
     : 로그 파일이 그냥 몇 기가씩 쌓이고 있지 않은가? 일별로 로그를 쌓도록 업션을 지정하면,
       특정 이슈가 발생한 날짜의 데이터를 분석하기에도 좋고, 백업하기에도 편리하다.

 

  4) 서버의 시스템 사용률은 로그로 남기고 있는가?
     : WAS나 DB가 얼마나 사용을 하고 있는지 로그를 남겨야 한다. 대부분의 사이트에는 SMS나 APM을

       설치하여 서버를 모니터링 하고 있겠지만, 그렇지 않은 사이트에서는 서버의 사용량을 유닉스의

       vmstat이나 sar 명령어를 사용하여 남겨야 시간대별 서버 사용량을 구할 수 있다.
       그리고 나중에 서버를 증설할 때에도 이 데이터는 매우 유용하게 사용된다.

 

  5) 모니터링 툴은 사용 중인가?
     : WAS를 모니터링 하기 위한 툴은 설치되어 있는가? 모니터링 툴이 없다면,

       장님이 코끼리를 만지는 것과 비슷하다.

       이제 시스템 로그만으로 시스템 상태를 점검하는 시대는 사라지고 있다.


     : 그렇다고 반드시 툴을 구매하라는 것은 아니다. 만약 모니터링 툴을 구매할 여력이 안되고 서버가

       많은 부하를 받고 있지 않는다면, JMX 기술을 사용하여 서버를 모니터링하는 것도 좋은 방법이다.

       JDK5.0 이상에서 제공하는 JConsole을 사용하는 것도 좋다.

 

  6) 모니터링 툴에 대한 설정은 적절하게 되어 있는가?
     : 아무리 좋고 비싼 모니터링 툴이 있다고 하더라도, 제대호 활용하지 않으면 아무런 소용이 없다.
       모든 메서드에 대해서 프로파일링을 하도록 지정을 하면 대부분의 툴이 성능에 많은 영향을 주게 된다.
       그러므로 꼬 필요한 내용만 모니터링이 되도록 설정을 잘 맞추어야 제대로 사용할 수 있다.

 

  7) 서버가 갑자기 코어 덤프를 발생하지 않는가?
     : 서버에서 코어 덤프를 발생시키는 경우의 수는 굉장히 많다. 만약 서버가 지속적으로 코어 덤프를

       발생시킨다면 적어도 다음의 내용을 점검해보기 바란다.
      

       - 10000건 이상 조회하는 것이 있나 확인해야 한다.

          한꺼번에 많은 양의 데이터를 처리하려면 많은 메모리가 필요한데, 이 때 코어 덤프가 발생할 수 있다.
          데이터를 처리하는데 필요한 메모리가 지정된 메모리 크기보다 클 수도 있기 때문이다.


       - 메모리 릭이 있는지 확인해야 한다. 메모리를 점유하고 해제하지 않는 로직이 있으면 서버를 매일

         재기동해도 메모리는 점차적으로 부족해진다. 서버가 기동된 후 힙 덤프를 받아 놓은 뒤, 운영 중과

         운영 후에 각각 덤프를 받아서 메모리 사용량의 추이를 확인해야 한다.    
 
  8) 응답 시간이 너무 느리지 않는가?
     : 응답시간이 느려지는 이유는 상상을 초월할 정도로 많다. 그러므로 이 문제를 해결하기 위해서는 상황을

       정확히 판단해야 한다. WAS 단 이후에서 느린 것인지, 그 이전 단계인 네트워크나 웹 서버에서 느린 것

       인지 확인해야 한다. 만약 WAS에서 느리다면, 정확히 어느 부분에서 느린지 프로파일링을 해서

       확인해 봐야 한다.
 

--------------------------------------------------------------------------------------------------


Java Application에서 점검해야 하는 대상들.txt
0.01MB