월 24,200원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결스프링 핵심 원리 - 고급편
OrderControllerV1 인터페이스에 @RequestMapping 선언 시 404 not found 뜨시는 분들
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]저와 같은 문제를 겪을까 포스팅 합니다.스프링 부트 3.2 버전 사용 중이며, @RequestMapping 어노테이션 사용 시에 404 not found가 반환될텐데, 해당 부분 @RestController로 변경 시 정상적으로 ok 반환됩니다.
- 해결됨스프링 핵심 원리 - 고급편
spring-boot-starter-jdbc dependency 추가 시 에러
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]커리큘럼 완강 후 샘플 프로젝트 만들면서 공부 중에 질문이 생겼습니다. 빈 후처리기 적용하는 과정 중에 추가로 jdbc dependency를 넣었습니다. build.gradle 파일에implementation 'org.springframework.boot:spring-boot-starter-jdbc'위와 같이 추가하고 실행하면create proxy: target class=class hello.proxy.app.v3.OrderRepositoryV3$$SpringCGLIB$$0 proxy class=class jdk.proxy2.$Proxy63 The bean 'orderRepositoryV3' could not be injected because it is a JDK dynamic proxy OrderRepositoryV3의 target 클래스가 SpringCGLIB로 생성되서 오류가 나고JDBC dependency를 주석 처리하고 gradle 빌드 후 다시 실행해보면 잘 실행됩니다. jdbc dependency를 추가해서 오류가 발생하는 이유와 해결 방법이 궁금합니다.
- 미해결스프링 핵심 원리 - 고급편
다중 상속
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]인스턴트에 인터페이스가 있다면 JDK 동적 프록시를 사용하고 그렇기 때문에 "proxyFactory.getProxy()"의 반환값을 인터페이스로 타입 캐스팅할 수 있다고 알려주셨습니다. 그런데 만약이 객체가 인터페이스를 다중 상속하고 있다면 어떻게 동작하나요? 예를 들어서이런 예제가 있다고하면 InterfaceImpl는 A와 B 인터페이스를 모두 구현한 건데 JDK 동적 프록시는 InterfaceImpl이 A를 구현한건지 B를 구현한건지 어떻게 구분할까요?참고로 test 코드를 작성해보니 A와 B 둘다 타입 캐스팅이 되네요
- 해결됨스프링 핵심 원리 - 고급편
로그관련 리소스에 대해서 질문이 있습니다.
안녕하세요 수강 중인 실무 주니어 개발자입니다!강의를 듣던 도중 실무에 관해서 궁금한 것이 있어서 질문드립니다.[b7a653ac] OrderControllerV1.request()[b7a653ac] |-->OrderServiceV1.orderItem()[b7a653ac] | |-->OrderRepositoryV1.save()[b7a653ac] | |<--OrderRepositoryV1.save() time=1001ms[b7a653ac] |<--OrderServiceV1.orderItem() time=1003ms[b7a653ac] OrderControllerV1.request() time=1005ms 강의 때 진행했던 방식으로 로그 추적기를 도입을 하고자 합니다.질문은 다음과 같습니다.실무에서 저렇게 메서드 호출을 다 나열하시는 지 궁금합니다.저렇게 sl4j를 적용하면 메모리나 리소스 낭비가 심하지는 않는지 궁금합니다.발생한 로그 info를 db에 적재시키는지 궁금합니다.감사합니다.
- 미해결스프링 핵심 원리 - 고급편
http://localhost:8080/v0/request?itemId=hello 실행 시 에러
1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]예제 프로젝트 만들기에서 http://localhost:8080/v0/request?itemId=hello실행 시에 java.lang.IllegalArgumentException: Name for argument of type [java.lang.String] not specified, and parameter name information not found in class file either.이런 에러가 뜹니다.소스는 하도 안되서 다 복붙 해봤는데도 안됩니다.자바 17에 스프링부트 3.2.0 버전입니다.
- 미해결스프링 핵심 원리 - 고급편
프로젝트 생성시 자바 버전 관련
2023-11-25 기준으로 spring initializer 에 자바 11버전이 지원이 안되는건지 그림과 같이 21,17 버전만 있습니다 ㅜㅜ 혹시 왜그런건지...그리고 11버전으로느 ㄴ다운받을 수 없는건지 궁금합니다.
- 미해결스프링 핵심 원리 - 고급편
어떻게 ProxyFactory() 생성시 인터페이스가 있는 target과 없는 target을 구분하는지 궁금합니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]new ProxyFactory()생성시 내부 로직의 생성자에는 setTarget(target);과setInterface(ClassUtils.getAllInterfaces(target)); 으로 이루어져있고 setInterface(...)의 로직에는 Assert.notNull으로 인터페이스가 없을 경우 exception을 발생하게 되어있던데 어떻게 인터페이스가 없는 target으로 ProxyFactory가 생성되는지 궁금합니다.
- 미해결스프링 핵심 원리 - 고급편
Parent는 굳이 빈을 등록할 필요가 없는 이유가 궁금합니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]본 강의 6:20초 쯤, "Parent는 굳이 @Bean으로 등록할 필요가 없겠네요." 라고 말씀해주셨는데, 이 부분이 잘 이해가 안 되어 문의드립니다!저희가 지금까지 배웠던 AOP는 스프링의 어플리케이션 컨텍스트에 객체를 @Bean으로 등록할 때, 실제 객체 대신에 프록시 객체를 등록하는 방식으로 동작했었는데,만약 Parent 객체를 @Bean으로 등록하지 않는다면 @target 을 통한 parentMethod 호출 시에도 Advice의 부가기능이 실행되지 않는 것 아닌가요~? 제가 잘못 이해하고 있는 부분이 있다면 짚어주시기를 부탁드립니다!
- 미해결스프링 핵심 원리 - 고급편
LogTrace의 Bean을 메인 클래스에서 생성한 이유
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? [질문 내용]LogTrace의 @Bean 어노테이션으로 빈 생성할 때 메인 클래스에서 생성한 이유가 따로 있으신가요??Config 클래스에서 하지 않고 따로 메인 클래스에서 하신 이유가 있으신가 해서요@Bean 어노테이션은 다른 클래스에서도 사용이 가능한지도 궁금합니다
- 미해결스프링 핵심 원리 - 고급편
@target 관련
안녕하세요 강의 잘 듣고 있습니다.강의 말미에 args, @args, @target은 단독으로 사용하면 안 된다고 하셨고 다음과 같은 이유를 말씀하셨습니다. '실제 객체 인스턴스가 생성되고 런타임에 적용 여부를 알 수 있다'아규먼트의 실제 타입을 요구하는 args, @args는 비교적 직관적으로 이해했는데, @target은 어째서 런타임에 적용 여부를 알아야만 하는 걸까요? 마치 @within이 그런 것처럼 클래스 내부에 특정 어노테이션이 있으면 해당 클래스부터 부모 클래스까지 AOP를 적용하면 될 것 같은데 말이죠.
- 해결됨스프링 핵심 원리 - 고급편
포인트컷 표현식 질문
안녕하세요 강의 잘 듣고있습니다.강의에서 등장하는 AtTargetAtWithinAspect의 execution 표현식을 보면 * hello.aop..*(..)로 기재되어 있습니다.이전 강의에서 학습했던 표현식(* hello.aop..*.*(..))과 어떤 차이점이 있는건가요?
- 해결됨스프링 핵심 원리 - 고급편
@AfterReturning에서 질문있습니다.
안녕하세요 강사님!강사님께서 말씀해주신 AOP로 구현하면 좋은 기능을 실제 코드로 작성해봤습니다.로그 트레이스기능에 매서드 종료가 1초 5초 10초가 될때 로그 레벨을 높여서 로그를 찍는 기능입니다. @Aspect @Slf4j static class LogTraceSelf { ThreadLocal<TraceStatus> trace = new ThreadLocal<>(); private TraceStatus SynchronizedTrace(){ TraceStatus traceStatus = trace.get(); if (traceStatus == null) { trace.set(new TraceStatus()); traceStatus = trace.get(); } return traceStatus; } @Pointcut("@annotation(hello.aop.exam.annotation.Trace)") public void logTrace() {} @Before("logTrace()") public void doTrace(JoinPoint joinPoint) { TraceStatus traceStatus = SynchronizedTrace(); traceStatus.begin(joinPoint.getSignature().getName()); } @AfterReturning("logTrace()") public void doTraceSuccess(JoinPoint joinPoint) { TraceStatus traceStatus = SynchronizedTrace(); long gap = traceStatus.end(joinPoint.getSignature().getName()); } @AfterThrowing(value = "logTrace()", throwing = "ex") public void doTraceException(JoinPoint joinPoint, Exception ex) { TraceStatus traceStatus = SynchronizedTrace(); traceStatus.end(joinPoint.getSignature().getName(),ex); } }조인포인트 실행 권한이 필요없는 부가 기능이다보니@Around 사용을 하지 않고 나누어서 처리를 하다보니 불필요한 코드가 더 증가하게되었습니다.그리고 @Around와 다르게 어드바이스내 지역변수에 TraceStatus를 저장하고 사용할수 없기때문에ThreadLoacal에 공유할 데이터와 본인이 가지고 있어야하는 timestamp도 저장했습니다.@Slf4j public class TraceStatus { private final String id; private int depth = 0; private Deque<Long> timeStampHolder = new ArrayDeque<>(); private final int offsetInfoMs; private final int offsetWarningMs; private final int offsetErrorMs; }기능은 stack 자료구조를 활용해서 begin을 할때마다 timeStampHolder에 시작시간을 저장합니다.end를 호출하면 pop으로 자신이 넣은 시작 시간을 꺼내서 시간을 계산하고 로그를 출력합니다.기타 기능 메서드들은 강사님이 작성하신거와 유사해서 제외했습니다. 이제 소요된 시간이 1초, 5초, 10초가 걸릴 경우 info,warning,error로 출력하는 로그를 남기려고할때어드바이스가 조건을 가지고 추가 기능을 만든다.위 코드처럼 로그 트레이스 내에 저장하고 로그 트레이스 내부에서 출력하도록 한다.경고 알림용 트레이스를 따로 만들고 상태를 전달한다.제 생각은 트레이스에게 넘길경우 트레이스를 인터페이스로 만들어서 필요에 따라 다른 트레이스를 사용한다고 한다면 이 기능을 계속 구현해야 된다는 단점이 생길거 같습니다.저라면 어드바이스에서 소요시간을 트레이스에게 받아서 추가 로직을 수행하려고 할거같습니다. 강사님께서 코드를 작성하신다면어떤 포인트컷을 사용하셔서 구현하실건지,그리고 애노테이션에서 넘어온 값을 가지고 어드바이스에서 처리하게 하시는지아니면 로그 트레이스 내에서 처리하게 하실건지 그 이유가 궁금합니다.
- 해결됨스프링 핵심 원리 - 고급편
Enhancer.setSuperclass
/** * Set the class which the generated class will extend. As a convenience, * if the supplied superclass is actually an interface, <code>setInterfaces</code> * will be called with the appropriate argument instead. * A non-interface argument must not be declared as final, and must have an * accessible constructor. * @param superclass class to extend or interface to implement * @see #setInterfaces(Class[]) */ public void setSuperclass(Class superclass) { if (superclass != null && superclass.isInterface()) { setInterfaces(new Class[]{superclass}); // SPRING PATCH BEGIN setContextClass(superclass); // SPRING PATCH END } else if (superclass != null && superclass.equals(Object.class)) { // affects choice of ClassLoader this.superclass = null; } else { this.superclass = superclass; // SPRING PATCH BEGIN setContextClass(superclass); // SPRING PATCH END } } 강사님 PDF 5.동적 프록시 기술 마지막 장인터페이스가 있는 경우에는 JDK 동적 프록시를 적용하고, 그렇지 않은 경우에는 CGLIB를 적용하려면어떻게 해야할까?두 기술을 함께 사용할 때 부가 기능을 제공하기 위해서 JDK 동적 프록시가 제공하는InvocationHandler 와 CGLIB가 제공하는 MethodInterceptor 를 각각 중복으로 만들어서 관리해야할까?라고 작성되어 있더라구요진짜 구현 클래스만 프록시를 만들어 주는지 궁금해서 찾아보니Enhancer 클래스 내부 메서드를 보면 setSuperclass 가 있는데내부에 인터페이스가 들어오던, 구체 클래스가 들어오던 알아서 구현체를 만들어준다고 되어있더라구요Enhancer 클래스 주석에도하지만 프록시가 인터페이스를 구현하는 것 외에 구체적인 기본 클래스를 확장할 수 있게 해준 것입니다.라고 작성되어 있습니다. 실제 코드로 작성해도 잘 동작합니다.package hello.proxy.my; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; @Slf4j public class EnhancerTest { @Test void enhancerInterface() { MyInterfaceImpl myInterface = new MyInterfaceImpl(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(MyInterface.class); enhancer.setCallback(new MyInterceptor(myInterface)); MyInterface myInterfaceProxy = (MyInterface) enhancer.create(); myInterfaceProxy.call(); } static class MyInterceptor implements MethodInterceptor { private final MyInterface myInterface; public MyInterceptor(MyInterface myInterface) { this.myInterface = myInterface; } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { log.info("로그 시작"); myInterface.call(); log.info("로그 종료"); return null; } } } interface MyInterface { void call(); } @Slf4j class MyInterfaceImpl implements MyInterface { @Override public void call() { log.info("나는 인터페이스를 구현한 클래스입니다."); } } //log 19:11:27.315 [Test worker] INFO hello.proxy.my.EnhancerTest - 로그 시작 19:11:27.317 [Test worker] INFO hello.proxy.my.MyInterfaceImpl - 나는 인터페이스를 구현한 클래스입니다. 19:11:27.317 [Test worker] INFO hello.proxy.my.EnhancerTest - 로그 종료Enhancer 클래스도 인터페이스나 구체 클래스를 모두 프록시로 생성할 수 있고더 향상된 호출 핸들러을 제공하는 MethodInterceptor 를 사용할 수도 있습니다.제 생각에는 MethodInterceptor 사용할 수 있는 Enhancer 프록시 객체를 디폴트로 사용할거같거든요 그런데 ProxyFactory는 false로 인터페이스랑 구체 클래스를 분리해서 생성하게 했더라구요 그 이유도 궁금합니다.제가 이해한게 맞다면 Enhancer도 인터페이스를 구현할 수 있는데 별도로 개발해야한다고 말씀하신 이유도 궁금합니다 !!
- 미해결스프링 핵심 원리 - 고급편
어드바이저 빈에 대해서는 프록시를 적용하지 않나요?
자동 프록시 생성기는 빈이 후처리기로 들어오면 어드바이저 빈과 후처리기로 들어온 빈을 매칭해서 프록시의 생성여부를 결정하는 걸로 이해했습니다.그러면 처음에 어드바이저 빈을 생성할 때에는 자동 프록시 생성기가 '얘는 어드바이저 빈이구나. 프록시를 생성할 필요가 없겠어' 라고 판단하고 걸러주는 건가요?
- 미해결스프링 핵심 원리 - 고급편
실행순서
안녕하세요실행 순서: @Around , @Before , @After , @AfterReturning , @AfterThrowing 라고 적어주셨는데 @After 이게 왜3 번째로 실행된다고 표현 해주신게 이해가 조금 안갑니다. 실제로는 @AfterReturnin 다음에 실행되는거 아닌가요 ?
- 미해결스프링 핵심 원리 - 고급편
setProxyTargetClass()
문서에는 true가 기본적으로 설정해서 사용한다고 적혀있는데 default는 false 아닌가요?? 그냥 true를 기본적으로 많이 쓴다는 소리일까요 ?
- 미해결스프링 핵심 원리 - 고급편
joinPoint.proceed() 실행결과인 result 에 관한 질문
안녕하세요강의 정말 감사히 잘 듣고 있습니다.다름이 아니라 예전부터 궁금했던 건데 Object result = joinPoint.proceed();여기서 각 비즈니스 로직(target) 을 실행시키고 난 뒤에 항상 result 를 받습니다.그러나 정작 result 를 활용하여 어떤 동작을 하는 것은 보지를 못해서요....이 result 를 항상 return 시켜주는 데 1) 어떠한 상황에서 result 값을 유용하게 사용할 수 있는지?2) result 를 return 하는데 어디로 return 하는지?가 궁금합니다.혹시 제가 놓친 부분이 있는지 지적해주시면 감사하겠습니다.(항상 감사합니다. 소중한 강의 정말 잘 보고 있습니다)
- 미해결스프링 핵심 원리 - 고급편
프록시 기능
프록시 주요 기능중접근제어 캐싱 지연로딩이건프록시 없이는 불가능한 기술인가요??프록시 기술이 꼭 필요한 기술인지 궁금해서요 !
- 미해결스프링 핵심 원리 - 고급편
스프링에서 CGLiB를 기본적으로 설정했는데, JDK 프록시 방식이 더 유용한 경우가 있을까요?
스프링에서 CGLiB를 기본적으로 설정했는데, CGLiB와 비교하여 JDK 프록시 방식이 더 유용한 경우가 있을까요?
- 미해결스프링 핵심 원리 - 고급편
4:56쯤에 나오는 포인트 컷 지시자 관련해서 궁금한 점이 있습니다.
강의 4:56쯤 보면, 다음처럼 포인트 컷 지시자를 표현해주는데,execution(* hello.app..*(..)) && @target(hello.aop.member.annotation.ClassAop)앞에 hello.app..*(..))안붙여줘도 뒤 조건에 만족하는 것만 AOP만 적용되지 않나요?앞에 위와 같은 조건을 붙여주신 이유가 궁금합니다.