참고사항 : 개발자가 되는 법(http://wiki.kldp.org/wiki.php/HowToBeAProgrammer#s-2.1.4)

2.1.4 로그를 이용해서 디버그 하는 방법 

  로그 기록(logging)이란 정보를 제공하는 일련의 기록인 로그(log)를 생성하도록 시스템을 작성하는 활동을 말한다. 프린트 줄 넣기(printlining)는 간단한, 보통은 일시적인, 로그를 생성하기만 한다. 완전한 초보자들은 프로그래밍에 대해 아는 것에 한계가 있기 때문에 로그를 이해하고 사용해야 한다. 시스템 설계자들은 시스템의 복잡성 때문에 로그를 이해하고 사용해야 한다. 로그가 제공하는 정보의 양은, 이상적으로는 프로그램이 실행되는 중에도, 설정 가능해야 한다. 일반적으로 로그 기록은 다음의 이점이 있다.
  • 로그는 재현하기 힘든 (예를 들어, 개발 완료된 환경에서는 발생하지만 테스트 환경에서는 재현할 수 없는) 버그에 대한 유용한 정보를 제공할 수 있다.
  • 로그는, 예를 들어, 구문(statement)들 사이에 걸리는 시간과 같이, 성능에 관한 통계와 정보를 제공할 수 있다.
  • 설정이 가능할 때, 로그는 예기치 못한 특정 문제들을 디버그하기 위해, 그 문제들을 처리하도록 코드를 수정하여 다시 적용하지(redeploy) 않아도, 일반적인 정보를 갈무리할 수 있게 한다. 

  로그에 남기는 정보의 양항상 정보성과 간결성 사이의 타협으로 결정된다. 정보를 너무 많이 남긴다면 로그가 낭비적이 되고 스크롤에 가려지게(scroll blindness) 되어, 필요한 정보를 찾기 어려워질 것이다. 너무 조금 남긴다면 필요한 정보가 남지 않을 것이다. 이런 점에서, 무엇이 출력될지 설정할 수 있게 하는 것은 매우 유용하다. 일반적으로 로그에 남는 기록을 통해, 그 기록을 남긴 소스 코드의 위치, (적용 가능하다면) 문제가 되는 작업을 실행한 쓰레드, 정확한 실행 시각, 그리고 일반적으로, 어떤 변수의 값, 여유 메모리의 양, 데이터 객체의 개수 등 그 밖의 유용한 정보를 알 수 있다. 이러한 로그 생성 구문들은 소스 코드 전체에 흩어져 있는데, 특히 주요 기능이 있는 지점과 위험 부담이 있는 코드 근처에 있다. 구문마다 수준이 정해질 수 있으면 시스템의 현재 설정에 따라 그 수준에 해당하는 기록만 남기게 될 것이다. 로그 생성 구문을 설계할 때에는 어디에서 문제가 생길지 예상해서 그것을 기록으로 남길 수 있게 해야 한다. 성능을 측정할 필요성도 예상하고 있어야 한다.

영구적인 로그를 남긴다면, 로그 기록이 프린트 줄 넣기(printlining)를 대신 할 수 있을 것이고, 디버그 구문들 중에도 로그 기록 시스템에 영구적으로 추가할 것들이 있을 것이다.

로그(Logging) 과 관련된 글이 올라온 것을 보고,
급하게 내용을 찾아서 정리해본다.


  개발하는 과정에서 데이터의 처리 과정이나 발생한 오류에 대한 기록을 남기는 용도로 많이 활용하는 기능이다. 제대로 읽고 분석할 수 있는 능력을 갖춘다면, 개발실력이 한단계 향상될 것이라 믿어 의심치 않는다. 개발자가 갖춰야할 능력 중 하나는 '로그 분석' 능력!


 

/springbook/etc/testGenericApplicactionContext.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5.  
  6. <bean id="hello" class="springbook.etc.Hello">
  7. <property name="name" value="Spring" />
  8. <property name="printer" ref="printer" />
  9. </bean>
  10. <bean id="printer" class="springbook.etc.StringPrinter" />
  11.  
  12. </beans>

 

GenericApplicationContext의 사용방법에 대한 학습 테스트

 

  1. @Test
  2. public void testGenericApplicationContext(){
  3. GenericApplicationContext ac = new GenericApplicationContext();
  4. XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(ac);
  5. //XmlBeanDefinitionReader는 기본적으로 클래스패스로 정의돈 리소스로부터 파일을 읽는다.
  6. reader.loadBeanDefinitions("springbook/etc/testGenericApplicactionContext.xml");
  7. //모든 메타정보 등록이 완료됐으니 애플리케이션 컨테이너를 초기화하라는 명령이다.
  8. ac.refresh();
  9. Hello hello = ac.getBean("hello", Hello.class);
  10. hello.print();
  11. assertThat(ac.getBean("printer").toString(), is("Hello Spring"));
  12. }

 

 

 

 

 

이 글은 스프링노트에서 작성되었습니다.

Hello.java

 

  1. package springbook.etc;

  2. public class Hello {
  3. private String name;
  4. private Printer printer;
  5. public String sayHello() {
  6. return "Hello " + name;
  7. }
  8. public void print() {
  9. this.printer.print(sayHello());
  10. }
  11. public void setName(String name) {
  12. this.name = name;
  13. }
  14. public void setPrinter(Printer printer) {
  15. this.printer = printer;
  16. }
  17. }

 

Printer.java(인터페이스)

 

  1. package springbook.etc;

     

  2. public interface Printer {
  3. void print(String message);
  4. }

StringPrinter.java(인터페이스 Printer.java 구현체)

 

 

  1. package springbook.etc;

  2. public class StringPrinter implements Printer {
  3. private StringBuffer buffer = new StringBuffer();
  4. public void print(String message) {
  5. this.buffer.append(message);
  6. }
  7. public String toString() {
  8. return this.buffer.toString();
  9. }
  10. }

 

TestHello.java(DI 정보 테스트)

 

  1. package springbook.etc;
  2.  
  3. import org.junit.Test;
  4. import static org.junit.Assert.*;
  5. import static org.hamcrest.CoreMatchers.*;
  6.  
  7. import org.springframework.beans.factory.config.BeanDefinition;
  8. import org.springframework.beans.factory.config.RuntimeBeanReference;
  9. import org.springframework.beans.factory.support.RootBeanDefinition;
  10. import org.springframework.context.support.StaticApplicationContext;

  11. public class TestHello {
  12. @Test
  13. public void testHelloBean() {
  14. //IoC 컨테이너 생성. 생성과 동시에 컨테이너로 동작한다.
  15. StaticApplicationContext ac = new StaticApplicationContext();
  16. //Hello 클래스를 hello1이라는 이름의 싱글톤 빈으로 컨테이너에 등록한다.
  17. ac.registerSingleton("hello1", Hello.class);
  18. //IoC 컨테이너가 등록한 빈을ㄹ 생성했는지 확인하기 위해 빈을 요청하고 Null이 아닌지 확
  19. Hello hello1 = ac.getBean("hello1", Hello.class);
  20. assertThat(hello1, is(notNullValue()));
  21. //빈 메타정보를 담은 오브젝트를 만든다. 빈 클래스는 Hello로 지정한다.
  22. //<bean class="springbook.etc.Hello" />에 해당하는 메타정
  23. BeanDefinition helloDef = new RootBeanDefinition(Hello.class);
  24. //빈의 name프로퍼티에 들어갈 값을 지정한다.
  25. //<property name="name" value="Spring" />에 해당한다.
  26. helloDef.getPropertyValues().addPropertyValue("name", "Spring");
  27. //앞에서 생성한 빈 메타정보를 hello2라는 이름을 가진 빈으로 해서 등록흔다.
  28. //<bean id="hello2" /> 에 해당한다.
  29. ac.registerBeanDefinition("hello2", helloDef);
  30. //BeanDefinition으로 등록된 빈이 컨테이너에 의해 만들어지고 프로퍼티에 설정이 됐는지 확인한다.
  31. Hello hello2 = ac.getBean("hello2", Hello.class);
  32. assertThat(hello2.sayHello(), is("Hello Spring"));
  33. //처음 등록한 빈과 두 번쨰 등록한 빈이 별개의 오브젝트임을 확인
  34. assertThat(hello1, is(not(hello2)));
  35. assertThat(ac.getBeanFactory().getBeanDefinitionCount(), is(2));
  36. }
  37. @Test
  38. public void registerBeanWithDependency() {
  39. StaticApplicationContext ac = new StaticApplicationContext();
  40. //StringPrinter 타입이며, printer라는 이름을 가진 빈을 등록한다.
  41. ac.registerBeanDefinition("printer", new RootBeanDefinition(StringPrinter.class));
  42. BeanDefinition helloDef = new RootBeanDefinition(Hello.class);
  43. helloDef.getPropertyValues().addPropertyValue("name", "Spring"); // 
  44. helloDef.getPropertyValues().addPropertyValue("printer", new RuntimeBeanReference("printer"));
  45. ac.registerBeanDefinition("hello", helloDef);
  46. Hello hello = ac.getBean("hello", Hello.class);
  47. hello.print();
  48. assertThat(ac.getBean("printer").toString(), is("Hello Spring"));
  49. }
  50. }
  51.  
IoC 컨테이너가 POJO 클래스와설정 메타정보를 이용해 어떻게 최종사용할 애플리케이션 런타임 오브젝트를 만들어내는 지 이해할 수 있을 것이다. 이렇게 애플리케이션을 구성하는 빈 오브젝트를 생성하는 것이 IoC 컨테이너의 핵심이다. IoC 컨테이너는 일단 빈 오브젝트가 생성되고 관계가 만들어지면 그 뒤로는 거의 관여하지 않는다. 기본적으로 싱글톤 빈은 애플리케이션 컨텍스트의 초기화 작업 중에 모두 만들어진다.

 

 

이 글은 스프링노트에서 작성되었습니다.

토비의스프링3
카테고리 컴퓨터/IT > 프로그래밍/언어 > 프로그래밍일반
지은이 이일민 (에이콘출판, 2010년)
상세보기

1. 소프트웨어 개발에서 절대로 바뀌지 않는 것은 없기 때문이다.
클래스 대신 인터페이스를 사용하고, new 를 이용해 생성하는 대신 DI를 통해 주입받게 하는 건 아주 단순하고 쉬운 작업이다.
2. 클래스의 구현 방식은 바뀌지 않는다고 하더라도 인터페이스를 두고 DI를 적용하게 해두면 다른 차원의 서비스 기능을 도입할 수 있기 때문이다.

3. 테스트 때문이다.  
단지 효율적인 테스트를 손쉽게 만들기 위해서라도 DI를 적용해야 한다. 그러기 위해서는 가능한 한 작은 단위의 대상에 국한해서 테스트 해야한다.  
process-resources resources:resources
compile compiler:compile
process-test-resources resources:testResources
test-compile compiler:testCompile
test surefire:test
package jar:jar
install install:install
deploy deploy:deploy

+ Recent posts