Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

스프링 트러블슈팅

7,843 views

Published on

2010년 10월 13일 KSUG 스프링 세미나에서 발표했던 '스프링 트러블슈팅' 발표자료입니다.

스프링 사용시 자주 발생할 수 있는 문제 상황 네가지를 소개하고 문제 원인 및 해결 방법 그리고 적절한 대안들을 소개합니다.

Published in: Technology
  • Be the first to comment

스프링 트러블슈팅

  1. 1. SPRING TROUBLE SHOOTING 백기선 http://whiteship.me whiteship2000@gmail.com
  2. 2. Agenda • 쉬운 문제 • 약간 어려운 문제 • 조금 더 어려운 문제 • 마무리 “순순히 다음 문제들을 해결하면 유혈사태는 일어나지 않을 것입니다.” - 백간디
  3. 3. 쉬운 문제
  4. 4. @Autowired @Repository public class 옥수수{ } @Service public class 간디{ @Autowired 옥수수 옥수수; } 잘 되겠죠?
  5. 5. public interface 옥수수{ } @Repository public class 찰옥수수 implements 옥수수 { } @Repository public class 팝콘옥수수 implements 옥수수 { } @Service public class 간디{ @Autowired 옥수수 찰옥수수; } 간디는 대체 어떤 옥수수를 팔겠다는거지…
  6. 6. @Autowired 동작원리 • 해당 타입의 빈이 없을 때 BAD! • 해당 타입의 빈이 1개일 때 GOOD! • 해당 타입의 빈이 여러개 일 때 • 해당 멤버 변수랑 같은 이름의 빈이 있을 때 GOOD! • 해당 멤버 변수랑 같은 이름의 빈이 없을 때 BAD! • Whiteship’s 권장사항 • 같은 타입의 빈이 여러개 일땐 명시적으로 이름을 설정해 주세요. • @Repository(“찰옥수수”), @Service(“찰옥수수 간디”) • 같은 타입의 빈이 여러개 일땐 빈을 주입 받을 곳에서 @Autowired 대신 @Resource를 사용하세요. • @Resource(“찰옥수수”)
  7. 7. @Repository public class 찰옥수수 implements 옥수수 { } @Repository public class 팝콘옥수수 implements 옥수수 { } @Service public class 간디{ @Autowired 옥수수 찰옥수수; } 근데 간디가 팝콘을 팔던데?
  8. 8. 컴포넌트 스캔과 <bean /> 혼용하기 <context:component-scan default-package=“easy”/> <bean id=“gandhi” class=“easy.Gandhi”> <property name=“maize” ref=“popconMaize”/> </bean> @Service public class 간디{ @Autowired 옥수수 찰옥수수; }
  9. 9. XML과 애노테이션 동작원리 • 컴포넌트 스캔으로 DI 한 다음 XML에서 DI 한 정보로 덮어씁니다. • Whiteship’s 권장사항 • XML로 등록할 빈은 @Component를 사용하지 맙시다. • DI 정보를 굳이 XML로 덮어써야 한다면 반드시 주석을 달아둡시다.
  10. 10. 약간 어려운 문제
  11. 11. @Transactional @Service @Transactional public class 간디 { public 옥수수 거래(다이아 몬드) throws 유열사태 { … } } 간디 클래스의 모든 public 메서드에 트랜잭션 처리 됨. @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class 간디 테스트 { @Autowired 간디 간디; … }
  12. 12. 인터페이스를 만들어 볼까… @Service @Transactional public class 간디 implements 간디서비스 { public 옥수수 거래(다이아 몬드) throws 유열사태 { … } } public interface 간디서비스 { public 옥수수 거래(다이아 몬드) throws 유열사태; } 엥.. 갑자기 간디테스트에서 에러가 나네요?
  13. 13. 간디 빈 구조 간디 간디 프록시 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class 간디 테스트 { @Autowired 간디 간디; … }
  14. 14. 간디 인터페이스 도입시 빈 구조 간디 서비스 간디 간디 프록시 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class 간디 테스트 { @Autowired 간디 간디; … }
  15. 15. 스프링 AOP 동작 원리 • <tx:annotation-driven /> 기본 설정 동작 원리 • 인터페이스가 있으면 JDK 프록시를 사용한다. • 인터페이스가 없으면 CGLib 프록시를 사용한다. • Whiteship’s 권장사항 • 인터페이스를 만들었다면 인터페이스를 사용할 것. • 클래스기반으로 코딩하고 있다면 클래스 기반 프록시를 명시적으로 선언할 것. • <tx:annotation-driven proxy-target-class=“true” />
  16. 16. 애플리케이션 컨텍스트 상속 구조 ApplicationContext ApplicationContext public AC createAC(AC parent) { CAC cac = new ACAC(); cac.setParent(parent); return cac; } ConfigurableApplicationContext
  17. 17. ApplicationContext 상속구조 동작원리 • 부모 App 컨텍스트는 자식 App 컨텍스트에 있는 빈에 접근할 수 없다. • 자식 App 컨텍스트는 부모 App 컨텍스트에 있는 빈에 접근할 수 있다. • 빈을 달라고 요청하면… • 자기 자신이 가지고 있는 빈을 찾아 준다. • 자기 자신한테 없으면 부모 애플리케이션 컨텍스트에서 찾아 준다.
  18. 18. 스프링 웹 애플리케이션 ContextLoaderListener DispatcherServlet WebApplicationContext WebApplicationContext 만든다 만든다 상속 받는다 DispatcherServlet WebApplicationContext DispatcherServlet WebApplicationContext DispatcherServlet WebApplicationContext
  19. 19. 발생 가능한 문제 ContextLoaderListener DispatcherServlet WebApplicationContext WebApplicationContext 만든다 만든다 상속 받는다 DispatcherServlet WebApplicationContext DispatcherServlet WebApplicationContext DispatcherServlet WebApplicationContext @Transactional이 안돼요! AOP 설정 분명히 했는데 안돼요! 빈을 못 찾는다고 에러나요! 빈을 두번씩 만들고 있네;; 흠..
  20. 20. 스프링 웹 애플리케이션 설정 • 부모 WAC • 웹과 관련이 없는 빈 등록 • 예) Service, Dao • 하위 WAC • 웹과 관련이 있는 빈 등록 • 예) Controller • Whiteship’s 권장사항 • 웹과 관련이 있는 것과 그렇치 않은 것을 패키지 레벨에서 잘 구분 할 것 • 패키지 레벨로 구분하기 힘들다면 @Component 애노테이션을 확장해서 사용할 것 • <context:component-scan>의 하위 엘리먼트인 <exclude>와 <include> 활용 할 것.
  21. 21. 조금 더 어려운 문제
  22. 22. DispatcherServlet 매핑 Web.xml <servlet> <servlet-name>mygroups</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>mygroups</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping> 도대체 /app/* 은 머야;;
  23. 23. /app/* -> / http://toby.epril.com/?p=1107 - 스프링 3.0.4에 추가된 <mvc:default-servlet-handler/> 소개 해봤더니 기본 @MVC가 동작하질 않아;;
  24. 24. DispatcherServlet 기본전략 • HandlerMapping • BeanNameUrlHandlerMapping • DefaultAnnotationHandlerMapping • HandlerAdapter • HttpRequestHandlerAdapter • SimpleControllerHandlerAdapter • AnnotationMethodHandlerAdapter • HandlerExceptionResolver • AnnotationMethodHandlerExceptionResolver • ResponseStatusExceptionResolver • DefaultHandlerExceptionResolver • ViewResolver • InternalResourceViewResolver • LocaleResovler • AcceptHeaderLocalerResolver • ThemeResolver • FixedThemeResolver • RequestToViewNameTranslator • DefaultRequestToViewNameTranslator HandlerAdapter ViewResolver View DispatcherSevlet HandlerMaping Handler getHandler handle ModelAndView Controller Service Repository ModelAndView View resolveViewName render
  25. 25. DispatcherServlet 동작원리 • 해당 전략 타입의 빈이 하나라도 등록되면 해당 전략의 기본 전략 빈들은 하나도 등록되지 않는다. • 예) mygroups-servlet.xml에 BeanNameUrlHandleMapping을 등록하면.. DS의 기본 전략 중 하나인 DefaultAnnotationHandlerMapping은 자동으로 등록되지 않는다. • Whiteship’s 권장사항 • 빈으로 등록할 전략에 대해서는 기본 전략에 의지하지 말 것. • HandlerMapping, HandlerAdapter, ViewResolver, HandlerExceptionResovler • DispatcherServlet의 동작원리를 팀 내에 공유할 것.
  26. 26. <mvc:default-servlet-handler/> • HttpRequestHandlerAdapter • DefaultServletHttpRequestHandler • SimplUrlHandlerMapping
  27. 27. 결론 문제가 발생했을 때 발생한 에러 스택은 매우 중요한 정보입니다. 스프링 설정 파일과 web.xml에서 실마리를 찾을 수 있습니다. 간혹 스프링 내부 동작 원리를 이해해야만 해결할 수 있는 문제도 있습니다. 마침 여러분은 매우 좋은 책을 가지고 계십니다.

×