Skip to main content

박수완

1. 📌 핵심 개념 정리

✅ 요약하기

  1. 경계 살피고 익히기

    외부 코드를 사용하면 적은 시간에 더 많은 기능을 출시하기 쉬워진다. 만약 외부에서 가져온 패키지를 사용하고 싶다면 어디사 어떻게 시작해야 좋을까? 외부 패키지 테스트가 우리 책임은 아니다. 하지만 우리 자신을 위해 우리가 사용할 코드를 테스트하는 편이 바람직하다.


  1. log4j 익히기

    • 개선 전

       // 1.
       // 우선 log4j 라이브러리를 다운받자.
       // 고민 많이 하지 말고 본능에 따라 "hello"가 출력되길 바라면서 아래의 테스트 코드를 작성해보자.
       @Test
       public void testLogCreate() {
           Logger logger = Logger.getLogger("MyLogger");
           logger.info("hello");
       }
      
       // 2.
       // 위 테스트는 "Appender라는게 필요하다"는 에러를 뱉는다.
       // 조금 더 읽어보니 ConsoleAppender라는게 있는걸 알아냈다.
       // 그래서 ConsoleAppender라는 객체를 만들어 넣어줘봤다.
       @Test
       public void testLogAddAppender() {
           Logger logger = Logger.getLogger("MyLogger");
           ConsoleAppender appender = new ConsoleAppender();
           logger.addAppender(appender);
           logger.info("hello");
       }
      
       // 3.
       // 위와 같이 하면 "Appender에 출력 스트림이 없다"고 한다.
       // 이상하다. 가지고 있는게 이성적일것 같은데...
       // 구글의 도움을 빌려, 다음과 같이 해보았다.
       @Test
       public void testLogAddAppender() {
           Logger logger = Logger.getLogger("MyLogger");
           logger.removeAllAppenders();
           logger.addAppender(new ConsoleAppender(
               new PatternLayout("%p %t %m%n"),
               ConsoleAppender.SYSTEM_OUT));
           logger.info("hello");
       }
      
       // 성공했다. 하지만 ConsoleAppender를 만들어놓고 ConsoleAppender.SYSTEM_OUT을 받는건 이상하다.
       // 그래서 빼봤더니 잘 돌아간다.
       // 하지만 PatternLayout을 제거하니 돌아가지 않는다.
       // 그래서 문서를 살펴봤더니 "ConsoleAppender의 기본 생성자는 unconfigured상태"란다.
       // 명백하지도 않고 실용적이지도 않다... 버그이거나, 적어도 "일관적이지 않다"고 느껴진다.
      
    • 게선 후

       // 조금 더 구글링, 문서 읽기, 테스트를 거쳐 log4j의 동작법을 알아냈고 그것을 간단한 유닛테스트로 기록했다.
       // 이제 이 지식을 기반으로 log4j를 래핑하는 클래스를 만들수 있다.
       // 나머지 코드에서는 log4j의 동작원리에 대해 알 필요가 없게 됐다.
      
       public class LogTest {
           private Logger logger;
      
           @Before
           public void initialize() {
               logger = Logger.getLogger("logger");
               logger.removeAllAppenders();
               Logger.getRootLogger().removeAllAppenders();
           }
      
           @Test
           public void basicLogger() {
               BasicConfigurator.configure();
               logger.info("basicLogger");
           }
      
           @Test
           public void addAppenderWithStream() {
               logger.addAppender(new ConsoleAppender(
                   new PatternLayout("%p %t %m%n"),
                   ConsoleAppender.SYSTEM_OUT));
               logger.info("addAppenderWithStream");
           }
      
           @Test
           public void addAppenderWithoutStream() {
               logger.addAppender(new ConsoleAppender(
                   new PatternLayout("%p %t %m%n")));
               logger.info("addAppenderWithoutStream");
           }
       }
      

  1. 학습 테스트는 공짜 이상이다

    학습 테스트는 공짜 이상이다. 투자하는 노력보다 얻는 성과가 더. ㅡ다. 패키지 새 버전이 나온다면 학습 테스트를 돌려 차이가 있는지 확인한다. 학습 테스트를 이용한 학습이 필요하든 그렇지 않든, 실제 코드와 동일한 방식으로 인터페이스를 사용하는 테스트 케이스가 필요하다. 이런 경계 테스트가 있다면 패키지의 새 버전으로 이전하기 쉬워진다. 그렇지 않다면 낡은 버전을 필요 이상으로 오랫동안 사용하려는 유혹에 빠지기 쉽다.


  1. 깨끗한 경계

    경계에 위치하는 코드는 깔끔히 분리한다. 또한 기대치를 정의하는 테스트 케이스도 작성한다. 이쪽 코드에서 외부 패키지를 세세하게 알아야 할 필요가 없다. 통제가 불가능한 외부 패키지에 의존하는 대신 통제가 가능한 우리 코드에 의존하는 편이 훨씬 좋다. Map 객체를 래핑하든 Adapter를 사용해 우리 입맛에 맞게 인터페이스를 변경하든, 코드는 보기 편해지고 경계 인터페이스를 일관적으로 사용할 수 있게 해주며 그들의 변경에도 유연하게 대응할 수 있게 해준다.



2. 🤔 이해가 어려운 부분

🔍 질문하기

책을 읽으며 이해하기 어려웠던 개념이나 명확하지 않았던 내용을 정리합니다.

  1. 개념 또는 원칙의 이름
    • 어려웠던 부분
      해당 개념이 헷갈리거나 명확하지 않았던 점을 구체적으로 설명합니다.
    • 궁금한 점
      해당 개념이 어떤 원리로 동작하는지, 실무에서 어떻게 활용되는지 등을 질문 형태로 정리합니다.

  1. 개념 또는 원칙의 이름
    • 어려웠던 부분
      .
    • 궁금한 점
      .

  1. 개념 또는 원칙의 이름
    • 어려웠던 부분
      .
    • 궁금한 점
      .

3. 📚 참고 사항

📢 논의하기

관련된 자료가 있다면 공유하고, 더 깊이 논의하고 싶은 아이디어나 의견을 정리합니다.

  1. 관련 자료 공유
    • 추가 자료
      관련 블로그 글이나 공식 문서 링크를 제공합니다.

  1. 논의하고 싶은 주제
    • 주제
      논의하고 싶은 내용을 간략히 정리합니다.
    • 설명
      논의하고 싶은 이유를 작성합니다.