콘텐츠로 이동

2021 08 26 Spring

2021-08-26 Spring

로깅

  • 로깅이 왜 필요하죠? Sout에 비해 갖는 장점은? - 실시간으로 디버깅할 수 없는 상황에는 로그를 남겨 에러상황 발생시 추적할 수 있도록 해야함 - 내가 느낀바로는 - logging은 좀더 쉽게 양식을 커스텀 할 수 있다 - logging 라이브러리를 활용하여 특정한 레벨 이상의 로그 발생시 어펜더(?)를 사용하여 슬랙 알림 보낼 수 있다 - 실시간 디버깅 갬성 가능 - 파일로 차곡차곡 관리하는 것도 쉽게 제공한다 - 느껴본적은 없지만,, - 성능이 더 좋다고 들었습니당
  • log4j, slf4j, logback 뭔지 알아? - slf4j - 로깅 인터페이스! JPA의 갬성 - 실제 로거 구현체로 연결을 해줌! - facade 패턴이라는데... - "어떤 소프트웨어의 다른 커다란 코드 부분에 대한 간략화된 인터페이스를 제공하는 객체이다" - logback/log4j - slf4j의 구현체! hibernate의 갬성
  • 로깅 전략 공유해주세요 - 우선 로깅 레벨 - FATAL-ERROR-WARN-INFO-DEBUG-TRACE 레벨 - ERROR 이상이 의도하지 않은 익셉션 - 의도하지 않은 익셉션이다 보니 커스텀 익셉션 발생하면 INFO로 로깅 지정 - XML으로 로깅 설정 작성 후 yml에서 spring profile로 추가하여 사용 - 로깅 설정을 모듈화 할 수 있다는 것이 장점이었음
    logback-spring.xml
    <springProfile name="console-logging">
        //log 형태 설정, 로그 메시지 출력 대상 결정 요소
        <appender name="LOCAL_CONSOLE_POLICY" class="ch.qos.logback.core.ConsoleAppender">
            <layout class="ch.qos.logback.classic.PatternLayout">
                <Pattern>%d{HH:mm:ss.SSS} %highlight([%-5level]) [%thread] %cyan([%logger{36}]) - %m%n</Pattern>
            </layout>
        </appender>
    </springProfile>
    
    application.yml
    spring:
      profiles:
        active: local
        group:
          local: console-logging
    
  • 로깅 설정 읽는 순서 아시나요? - 참고: https://newwisdom.tistory.com/80?category=956402 - logback-spring.xml 있으면 설정파일 읽기 - 없다면 yml 파일의 설정 읽기 - 둘 다 있다면 yml 설정파일 적용후 xml 파일 적용

빈 생명주기

  • 이게 뭔지 설명 좀 해주세요 - 스프링의 컨테이너 (Application Context)는 빈의 생성/소멸/주입/제공 등을 담당합니다. - 그 과정속에서 빈이 생성 -> 주입 -> 소멸되는 과정이 있어 공부하였습니다. - 과정은 다음과 같습니다. 1. 빈 인스턴스화 및 DI - 어노테이션으로 빈 정의 스캔 - 빈 인스턴스 생성 - 빈 프로퍼티에 의존성 주입 2. 빈이 특정 인터페이스를 구현했다면 호출하게 됨 - BeanNameAware - BeanClassLoaderAware - ApplicationContextAware 3. 빈 생성 생명주기 콜백 - @PostConstruct 4. 빈 소멸 생성주기 콜백 - @PreDestroy
  • 콜백? - 어떤 이벤트가 발생했거나 특정 시점에 도달 시, 시스템에서 호출하는 함수
  • 어쩌다 공부함?? - 전략패턴을 도입할 일이 있었다. - 전략을 Enum으로 관리해서 특정조건에 맞게 Bean을 반환해주고 싶은 코드가 있었다. - 근데 Enum이 Static 이다 보니까 Bean을 주입해주는게 힘들더라. - Enum의 필드로 Bean을 들고 있게 하고 싶은데 Static은 클래스 로더의 로딩 작업에서 먼저 메모리에 올라가게 된다 - 빈들보다 말이지 - 그래서 Enum의 필드로 Bean을 들고 있게 하려면 나중에 Bean을 주입하는 방식의 코드 작성이 필요했다. - 따라서 Enum에 내부 클래스를 하나 만들고 이를 Bean으로 등록해줬고, - 해당 내부 클래스에서 @PostConstruct 어노테이션을 활용하여 Enum 객체에 알맞은 Bean을 집어 넣어주었다.
    @Component
    @AllArgsConstructor
    private static class StrategyInjector {
        private NoneStrategy noneStrategy;
        private QueryOnlyStrategy queryOnlyStrategy;
        private TechsOnlyStrategy techsOnlyStrategy;
        private QueryAndTechsStrategy queryAndTechsStrategy;
    
        @PostConstruct
        private void inject() {
            NONE.setSearchStrategy(noneStrategy);
            QUERY_ONLY.setSearchStrategy(queryOnlyStrategy);
            TECHS_ONLY.setSearchStrategy(techsOnlyStrategy);
            QUERY_AND_TECHS.setSearchStrategy(queryAndTechsStrategy);
        }
    }
    

Spring EventListener & TransactionEventListener

  • 왜 썼죠? - 해당 기능은 알림 기능을 구현할 때 사용했음 - 다른 사용자가 내 글에 좋아요/댓글을 달았을 때 알림을 저장해주고자 사용했다.
  • 그냥 의존성 주입에 비해 갖는 장점? - 의존성 주입에 비해 약한 의존관계를 갖게된다는 점이 있다고 공부하여 사용했었음 - 알림 기능이 딱 그랬다고 생각. - 솔직히 어떤 사용자가 특정 글에 좋아요/댓글을 남기는 기능과 해당 글의 주인에게 알림을 남겨주는 기능은 완전히 별개의 기능 - 좋아요/댓글 남기는 로직 도중에 noficationService 같은걸 주입받아 메서드 호출해 줄 수도 있지만 너무 강한 결합이라고 판단. - 또한 이벤트 리스너는 비동기로 처리하는 것과 굉장히 잘 어울린다고 생각 - @EnableAsync를 통해서 해당 알림을 남기는 기능은 메인 쓰레드에서 따로 벗어나 다른 쓰레드에서 처리할 수 있도록 코드 작성했었음 - 팀원들과 얘기하면서 이게 테스트하기 힘든 코드라는 판별에 우선 없애긴했는데, 꼭 다시 데려올 예정 - 이벤트 리스너의 강점을 가장 부각할 수 있는 갬성인 것 같음
  • Block vs Non-Block vs Async vs Sync? - 참고: https://brunch.co.kr/@springboot/267 - 메서드를 제공하는 곳 입장 - Sync: 메서드의 결과가 완성될 때 까지 반환하지 않는다. 기다려! - Async: 결과값이 결정되기 전에 우선 반환 - 결과 받아보는 클라이언트 입장 - Blocking: 결과 나왔나,,, 조회 (polling) - Non-Blocking: 콜백으로다가 클라이언트에게 알려줌 (webhook)
  • 콜백이 뭐야? - 어떠한 함수가 비동기적으로 실행되었음 - 즉각적으로 결과값을 받아볼수가 없는 상태 - 다른 쓰레드에서 잘 끝난다음에야 콜백으로 호출된거 처리할 거 있으면 처리해줌