불과 저번주까지 log4j만 쓰다가 slf4j를 통해 logback 을 사용해보기로 결정했습니다.

사실 logback이라는게 있다는걸 오늘 알았습니다. ㅡㅡ;

다들 아는 사실이겠지만 log4j를 만든사람이 새롭게 만든 log관련 라이브러리라서 (이유)

log4j를 사용해본 분들이라면 손쉽게 적응할수 있다고 합니다.



http://logback.qos.ch/



간단하게 본인위주로 정리하겠습니다.

자세한 설명은 맨아래 참조란을 따라가시면 됩니다.



1. 새롭게 제공되는 주요 기능 및 개선

 . log4j에 비해 속도나 메모리 사용면에서 개선

 . 설정파일의 Dynamic Reloading 지원

 . 설정파일의 조건부 처리 기능

 . 로그파일에 대한 자동압축, 자동 삭제 기능 제공

 . 런타임에 설정한 값에 따라 로그를 분리하여 처리할 수 있는 SiftingAppender 제공

 . groovy 언어로 설정파일 작성 기능

 . FileAppender 사용 시 다수의 JVM이 동시에 하나의 파일에 로그를 남길 수 있는 prudent mode를 지원

 . 다양한 조건에 따른 로깅처리 여부를 결정할 수 있는 Filter 제공


이것중에 관심이 가는 것은 설정파일의 Dynamic Reloading 지원 , 로그파일에 대한 자동 압축, 자동 삭제기능 제공 입니다.


2. Dynamic Reloading 지원

예전같으면 INFO 모드로 로그를 쌓고 있다가 여러가지이유로 DEBUG모드로 로그를 쌓고 싶을때 

설정화일을 변경하고 서버를 재기동해야 했습니다.

하지만 LOGBACK에서는 설정을 바꾸면 주기적으로 변경사항이 있는지 체크하여 자동으로 설정파일의

내용을 reloading 하여 변경합니다.


방법은

<configuration scan="true" scanPeriod="30 seconds"> ..... </configuration>


이렇게하시면 됩니다.


그럼 30초단위로 설정화일을 스캔합니다.


3. 로그파일에 대한 자동압축, 자동 삭제기능 제공

저역시 하루에 몇기가씩 로그가 쌓이는(INFO인데도...) 서버를 운영중입니다.

그래서 그전에 했던 방법은 주기적으로 하루전의 로그파일을 압축해서 보관하는 스크립트를 작성하여

crontab으로 스케줄링하여 사용하고 있었습니다.

하지만 logback에서는 스스로 이러한 처리를 할수있는 옵션을 제공합니다.


 <configuration scan="true" scanPeriod="30 seconds">
        .....
 </configuration>
 
 <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
            
            <fileNamePattern> someFileName.log.zip (or gz) </fileNamePattern>

              <maxHistory>90</maxHistory>     
        </rollingPolicy> 
        ....
    </appender>


fileNamePattern : 마지막 확장자를 zip 이나 gz 로 지정하면 자동으로 압축합니다.

maxHistory : (조금 혼란스러웠지만 이제는 이해가 되는 내용이였습니다). 남겨놓을 로그파일의 갯수입니다.

즉 size 단위로 한다고 하면 90개가 넘어가게 되면 옛날것부터 삭제합니다.

그리고 백업을 SIZE 단위가 아니고 매일단위로 백업을 한다면 위에같은 경우에는 

90일동안 보관하다가 삭제를 하게됩니다.

(정확히 말하자면 90개가 넘어가게되면 옛날것부터 삭제).

그리고 만일 매월단위로 백업을 한다면 90개월후에 삭제되겠지요.

이해가 되시나요? 그럼 만일 중간의 파일을 임의로 삭제하게된다면?

저도 테스트해보고 블로그에 남기도록 하겠습니다.


참조

http://dev.anyframejava.org/docs/anyframe/plugin/optional/logback/1.0.2/reference/html/index.html

logback 사용해야 하는 이유 (Reasons to prefer logback over log4j)

Posted by 빨강토끼
,

특정월의 메인아이디 별로 매출을 뽑을려고 다음과 같이 코딩을 하였습니다.

sql.xml 소스

<mapper namespace="billMapper">

 <select id="selectListByMonth" parameterType="String" resultType="List<net.red.vo.ResVo>">

 SELECT B.MID, SUM(A.AMT_VAT)/1.1 AS AMT , SUM(A.AMT_VAT) AS TOT_AMT

 FROM UTH A

  WHERE DT LIKE #{value} || '%'

    GROUP BY B.MID 

 </select>

</mapper>


a.java 소스

List<ResVo> listResVo = (List<ResVo>)session.selectList("mapper.selectListByMonth", yyyymm);


MyBatis 에 대하여 경험이 적는 저로서는 문제가 없어보이는 코드였다...

그런데 에러가 났습니다. 컴파일부터 안됐습니다....


구글을 뒤져봐도 한글로 된 제대로된 설명이 없었습니다. ㅜㅜ

심지에 MyBatis 공식 메뉴얼에도 설명을 잘 못찾겠었습니다.


안되는 영어를 보면서 알고 봤더니. 이유가 있었습니다.


너무 쉬운 계념이라서 그랬습니다. ㅡㅡ;


아래는 정상적으로 동작하는 소스입니다.


sql.xml 소스

<mapper namespace="billMapper">

 <select id="selectListByMonth" parameterType="String" resultType="net.red.vo.ResVo">

 SELECT B.MID, SUM(A.AMT_VAT)/1.1 AS AMT , SUM(A.AMT_VAT) AS TOT_AMT

 FROM UTH A

  WHERE DT LIKE #{value} || '%'

    GROUP BY B.MID 

 </select>

</mapper>


a.java 소스

List<ResVo> listResVo = session.selectList("mapper.selectListByMonth", yyyymm);


즉...구지  resultType="List<net.red.vo.ResVo>" 라고 해서 정의하지 않아도

selectList 를 사용하면 <select> 에서는 net.red.vo.ResVo 라는 List 

(즉 여러개의 ResVo 들...)로 회신을 해주는 개념이였습니다.



Posted by 빨강토끼
,

Act with Prudence - Seb Rose


"whatever you undertake, act with prudence and consider the consequences" Anon


NO MATTER HOW COMFORTABLE A SCHEDULE LOOKS at the beginning of an iteration, you can't being under pressure some of the time. If you find yourself having to choose between "doing it right" and "doing it quick." it is often appealing to "do it quick" with the understanding that you'll come back and fix it later. When you make this promise to yourself, your team, and your customer, you mean it. But all too often, the next iteration brings new problems and you become focused on them. This sort of deferred work is known as technical debt in his taxonomy of technical debt, and it should not be confused with inadvertent technical debt.


Technical debt is like a loan: you benefit from it in the short-term, but you have to pay interest on it until it is fully paid off. Shortcuts in the code make it harder ot add features or refactor your code. They are breeding grounds for defects and brittle test cases. The longer you leave it, the worse it gets. By the time you get around to undertaking the original fix, there may be a whole stack of not-quite-right design choices layered on top of the original problem, making the code much harder to refactor and correct. In fact, it is often only when things have got so bad that you must fix the original problem, that you actually do go back to fix it. And by then, it is often so hard to fix that you really can't afford the time or the risk.


There are times when you must uncur technical debt to meet a deadline or implement a thin slice of a  feature. Try not to be in this position, but if the situation absolutely demands it, then go ahead. But (and this is a big but) you must track technical debt and pay it back quickly, or things go rapidly downhill. As soon as you make the decision to compromise, write a tack card or log it in your issue-tracking system to ensure that it dose not get forgotten.


If you schedule repayment of the debt in the next iteration, the cost will be minimal. Leaving the debt unpaid will accrue interest, and that interest should be tracked to make the cost visible. This will emphasize the effect on business value of the project's technical debt and enables appropriate prioritization of the repayment. The choice of how to calculate and track the interest will depend on the particular project, but track it you must.


Pay off technical debt as soon as possible. It would be imprudent to do otherwise.


맞습니다.

급한 프로젝트일정때문에 가끔은 "제대로하기"(doing it right) 보다는 "빨리하기"(doing it quick)를 선택해야될 경우가 많다.

그러지 않기 위해서 노력해야겠지만 어쩔수 없는 경우에는

빠른 주기로 재대로 고치를 작업을 해야한다.

그렇지 않고 놔두다보면 나중엔 정말 일이커져서 엄청난 위기에 봉착할수 있다.

 

Posted by 빨강토끼
,