plugins { id 'org.springframework.boot' version '3.0.2' id 'io.spring.dependency-management' version '1.1.0' id 'java' } group = 'hello' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' //테스트에서 lombok 사용 testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' } tasks.named('test') { useJUnitPlatform() } 위와 같이 build.gradle을 구성하고 강의대로 따라가고 있는데 여기에 있는 외부라이브러리 (롬복,테스트라이브러리)가 인식이 되지 않고 있습니다. 롬복까지는 수동으로 다운로드해서 진행하고 있는데 계속 이러면 부트를 사용하는 의미가 없는것 같아서 문제를 해결하고 싶습니다!
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 8장 빈 생명주기 콜백 의 빈 등록 초기화, 소멸 메서드 관련 질문입니다. 마지막 종료 메서드 추론 부분에서 "추론 기능을 사용하기 싫으면 destroyMethod="" 처럼 빈 공백을 지정하면 된다"라고 말씀 하셨습니다. 그런데 추론 기능을 사용하기 싫으면 destroyMethod에 close나 shutdown이 아닌 내가 지정한 메소드 이름을 입력해야 하는 거 아닌가요? 빈 공백을 지정하면 소멸 메서드를 아예 지정하지 않아서 실행도 되지 않는 것 같은데 저게 무슨 말인지 이해가 안갑니다. 답변 미리 감사합니다. (destroyMethod의 디폴트 값이 close와 shutdown이어서 @Bean에 destroyMethod를 적지 않으면 자동으로 close와 shutdown 메소드를 실행하는 것까진 이해했습니다.)
[질문 내용] 스프링 부트와 JPA 활용 1편에서 제가 작성한 코드에서는 POST: http://localhost:8080/api/v1/members 해당 API가 잘 작동하는데 스프링 부트와 JPA 활용 2편에서 제공하신 강의 소스에서는 작동이 안되어서 문의드립니다. 해당 사진처럼 오류가 발생(상태코드 500) 아래 링크에 있는 내용대로 패키지 이름 변경은 다 했습니다. (javax -> jakarta) https://docs.google.com/document/d/1j0jcJ9EoXMGzwAA2H0b9TOvRtpwlxI5Dtn3sRtuXQas/edit?tab=t.0#heading=h.vfy9wirpglmx
[질문 내용] 탐색할 패키지의 시작 위치를 지정할 때 basePackages의 위치를 "hello.core.order 로 하였을 때 OrderServiceImpl에 @Component 와 @Autowired 어노테이션이 있으니 로그에 분명 orderServiceImpl이 나올 것으로 예상하는데 테스트 실패가 나오는 이유가 뭔지 궁금합니다.
[질문 내용] 컴포넌트 스캔과 의존관계 자동 주입 시작하기 영상에서 김영한 강사님께서 @Componenet 어노테이션을 등록한 클래스 MemberServiceImpl 가 자동으로 스프링 빈에 등록이 되는데 의존성 주입이 안되어 있으니 같이 해주기 위해 생성자 코드 상단에 @Autowired를 붙인다는 것 까지는 이해하였습니다. 그런데 10분 2초 쯤에 @Autowired를 붙인 MemberServiceImpl 생성자 파라미터에 MemberRepository 타입에 맞는 MemoryMemberRepository가 올거라고 어떻게 예상 하는거죠? 혹시 MemoryMemberRepository 클래스에도 @Component를 붙였으니 MemoryMemberRepository 가 올거라고 확신하는거죠?
현재 지금 프론트와 백엔드로 나누어져 웹 개발을 하고 있습니다 여기서 궁금한점은 선생님 코드를 다 따라 적었는데 프론트에서 로그인 요청을 해서 로그인한 이후 프론트에서 메인 페이지로 보내는데 거기서 다음 기능을 쓰려고 하면 서버 500에러가 뜨고 어나니머스필터가 요청을 받는거 같습니다 저도 정확하게 알 수 없어서 그런데 혹시 CSRF기능을 안써서 어나니머스필터로 가는 것인지 아니면 뭐가 잘못 된건지 알 수 없습니다 좀 알려주시면 감사하겠습니다
[질문 내용] @Configuration과 바이트코드 조작의 마법 강의영상에서 8분 19분쯤에 김영한 강사님께서 부모타입으로 조회하면 모든 자식이 끌려 나온다 했는데, 부모타입으로 된 변수명에 자식 인스턴스를 초기화할 때 기능을 호출하면 부모 타입에 없을 때 자식타입에서 못가져오는 것으로 알고있습니다. 상속 관계는 부모 방향으로 찾아 올라갈 수는 있지만 자식 방향으로 찾아 내려갈 수는 없기 때문이죠. 그래서 강사님께서 말한 "부모 타입으로 조회하면 자식들이 다 끌려 나온다"라는 말은 틀린 말 아닌가요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요 강사님 훌륭한 강의 항상 잘 보고 있습니다. 다름이 아니라, 이번에 빈 후처리기와 프록시 패턴에 대해 질문이 있습니다. 아래와 같이 빈 후처리기에서 A 객체를 A 프록시로 바꿔치기 해서 스프링 빈에 저장하고, A 프록시를 싱글톤으로 관리한다라고 이해했습니다. 이때, 궁금한 부분이 A 프록시가 A 객체를 상속받아서, 부가기능인 advisor 기능을 추가한 A 프록시라는 객체를 새롭게 생성해서 스프링 빈으로 등록을 한다라고 이해하면 되는건가요? 예를 들어, A 클래스가 A 메소드만 구현한 클래스라면 A 프록시 객체는 A메소드와 A advisor라는 부가기능이 추가된 클래스같은 형태로 구현되고, 스프링 빈으로 등록된다고 이해를 하면 되는건가요?? 왜냐하면, 제가 이해한게 맞다면, 아래와 같이 proxy가 advisors를 호출한 뒤에, target을 호출한다는 개념이 잘 이해가 되질 않습니다. proxy가 target의 비지니스 로직도 가지고 있고, advisor도 가지고 있는 객체라서 proxy에서 내부적으로 로직을 다 처리하면 되는 것 아닌가요?? 설명 부탁드립니다 감사합니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 아니오 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예 [질문 내용] 여기에 질문 내용을 남겨주세요. 개인 프로젝트 진행중 해당 부분과 같이 프론트측에 Dto를 전송하려 합니다. 아래에서는 log를 확인하여 json 객체가 잘 만들어졌는지 값이 제대로 들어갔는지 확인하였습니다. 이후 objectMapper.writeValue(response.getWriter(), loginResponse); 로 프론트에 값을 보냈는데 해당 페이지처럼 값들이 제대로 전달되지 않습니다. 저희가 원래 생각한 로직은 next step의 값에 따라 프론트가 알맞게 처리하는것인데 이건 프론트측의 로직 문제인가요 아니면 백엔드측이 잘못보내준건지 모르겠습니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 강의에서 order 테이블을 조회하면 id값이 4, 11로 나오는데 저는 1, 2로 나옵니다. 아무리 생각해봐도 4, 11로 나올 이유가 없어보이는데 왜 4,11로 나오는지 궁금합니다
안녕하세요. 강사님 05:00 분에 WAR를 설명하십니다. WAR : 정적리소스(HTML) + 클래스파일 이라고 설명하십니다. JAR 도 WAR와 마찬가지로 위와같이 HTML, 클래스파일을 갖을 텐데요. 강사님께서는 HTML을 WAR설명때만 언급을 하십니다. WAR 와 JAR가 갖는 파일들에 대해 차이점을 구별하지 못하고 있습니다. 단순 내부구조가 복잡하거나 단순한 걸로 구별을 해야할까요?
안녕하세요 존경하는 토비님. 강의 너무 재밌게 보고 있습니다. 이번 강의(오브젝트와 의존관계)를 보다가 제가 지금까지 생각해왔던것과 다른부분이 있어서, 다르게 알고 있었다면 이번 기회에 다시 바르게 잡고 싶어서 질문을 올립니다. 오브젝트 = 클래스의 인스턴스 저는 지금까지 오브젝트를 조금 다르게 해석하고 있었습니다. 객체: 컴파일 시점의 타입 인스턴스: 런타임 시점의 타입 컴파일 시점에서는 객체는 참조하는 클래스 또는 인터페이스로 타입이 정해지지만, 다형성에 의해 런타임 시점에서는 참조하는 인스턴스로 정해진다고 생각했었습니다. 의존관계를 설정할때도, 코드를 작성할땐 (컴파일시점) 의존할 객체를 인터페이스/클래스로 참조하지만, 구현체(인스턴스)는 런타임 시점에 정의되므로, 인스턴스는 곧 런타임의 타입이라고.. 생각해왔습니다. 제가 객체와 인스턴스에 대해 잘못 생각하고 있었던걸까요? 바쁘시겠지만 시간되실때 조언 한마디 주시면 감사하겠습니다~~!
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 안녕하세요 김영한님 ! REQUIRES_NEW는 완전히 물리적으로 트랜잭션이 분리되어 REQUIRED(A 메서드)에서 REQUIRES_NEW(B 메서드)를 호출 했을 때 B 메서드에 발생한 예외가 A 메서드에 전파되지 않는다고 이해했습니다. 실제 확인을 위해 아래 코드를 구성해 @Service @RequiredArgsConstructor public class MeetingService { private final MeetingRepository meetingRepository; private final MemberService memberService; @Transactional public void save() { meetingRepository.save(new Meeting("스터디 모임", LocalDate.now(), LocalTime.now(), "AB3AS2EG")); memberService.save(); } @Transactional(readOnly = true) public List<Meeting> findAll() { return meetingRepository.findAll(); } } @Service @RequiredArgsConstructor public class MemberService { private final MemberRepository memberRepository; @Transactional(propagation = Propagation.REQUIRES_NEW) public void save() { memberRepository.save(new Member("김철수")); throw new IllegalArgumentException(); } @Transactional(readOnly = true) public List<Member> findAll() { return memberRepository.findAll(); } } 아래 테스트 코드로 테스트를 진행했습니다. @Test void test() { assertThatThrownBy(() -> meetingService.save()) .isInstanceOf(IllegalArgumentException.class); // 롤백 여부 확인 List<Meeting> meetings = meetingService.findAll(); List<Member> members = memberService2.findAll(); assertThat(meetings).isEmpty(); assertThat(members).isEmpty(); } 결과를 로그로 분석해보니 MemberService의 트랜잭션은 독립적으로 롤백 발생한 예외가 MeetingService로 전파 전파된 예외로 인해 MeetingService의 트랜잭션도 롤백 이런식으로 흐름이 진행됐습니다. 제가 추측하기로는 물리적으로 분리는 되어 있지만 하나의 스레드에서 생긴 커넥션이고 자바의 예외 전파 메커니즘에 따라 A 메서드에서 호출한 B 메서드의 예외가 A 메서드에 전파된 것이 아닌가 생각을 했는데요 REQUIRES_NEW 사용 시 예외가 전파 되지 않는다. 라고 이해를 했어서 제가 실험한 결과가 맞는지 간과한 부분이 있었던 것인지 궁금합니다 !
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요 항상 강의 잘 보고 있습니다. 강의에서 1.생성 : 스프링이 스프링 빈 대상이 되는 객체를 생성함 2.전달 : 생성된 객체를 빈 저장소에 등록하기 직전에 빈 후처리기에 전달함 ~ 그 후에 프록시 적용대상인 클래스가 있으면 3.프록시 생성 : 프록시 적용 대상이고, 프록시를 생성하고 반환해서 프록시를 스프링 빈으로 등록한다. 라고 말씀하셨습니다. 그 후에, 생성된 프록시와 어드바이저의 동작 과정을 설명하실 때 , client -> ( proxy <-> advisors ) -> target 이런 동작 과정이라고말씀하셨는데 이 부분에서 이해가 안되는 부분이 있습니다. 1.프록시 객체를 생성했는데 target을 호출하는 이유가 무엇인가요? 예를 들어, 프록시 객체는 target을 기반으로 만들어진 클래스라고 이해를 했습니다. 그러면 프록시 객체는 target의 구현체로서 target의 메소드도 가지고 있고, advisor 메소드도 가지고 있는 것 아닌가요? 그래서 그냥 타겟을 호출할 필요없이, 프록시 객체에서 모든 요청을 처리하면 되는것 아닌가요?? 왜 프록시 객체는 advisor을 호출하고, 다시 타겟을 통해서 메서드를 또 실행하는건가요? 즉, 전 프록시 객체를 만든다는 것을 아래와 같은 예시로 이해를 했습니다. 그래서 굳이 target을 다시 호출하지 않고, 프록시 객체가 모든 요청을 처리하는게 맞는거 같은데 왜 target을 다시 호출하는건가요?? // AClass public class AClass { public void say() { System.out.println("Hello from AClass!"); } } // LoggingAspect ㅇ@Aspect @Component public class LoggingAspect { @Before("execution(* com.example.AClass.say(..))") public void logBefore() { System.out.println("Before calling say method"); } } //Proxy public class AClassProxy extends AClass { @Override public void say() { logBefore(); // 로그 출력 super.say(); // 실제 AClass의 say 메서드 호출 } public void logBefore() { System.out.println("Before calling say method"); } } 감사합니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요, 강사님. 항상 강의 잘 보고 있습니다. 해당 강의를 듣고 개인 학습을 하던 중에 @Transactional 에 대해 궁금한 점이 생겼습니다. 특히, **"@Transactional은 접근 제어자가 public 이 아닌 메서드에는 적용되지 않는다"**는 부분에 대해 잘 이해가 되지 않았습니다. 저는 이전에 강사님 강의를 듣고, @Transactional 을 메서드에 적용할 때 빈 후처리기와 프록시 방식에 대해 아래와 같이 이해했습니다. A 클래스의 A 메서드에 @Transactional 을 적용 스프링은 해당 메서드에 트랜잭션을 적용할 수 있도록 AOP 기반으로 동적 프록시를 생성함. 스프링 컨테이너가 @Transactional 이 붙은 메서드를 가진 클래스는 AOP가 적용된 클래스임 스프링은 @Transactional 이 적용된 메서드를 감지하여, 트랜잭션을 적용하기 위해 AOP 기능을 사용함. 스프링 컨테이너에 A 클래스를 bean으로 등록할 때, 빈 후처리기에서 A 클래스의 프록시 객체를 스프링 빈으로 등록 스프링에서는 빈 후처리기에서 트랜잭션을 적용하는 프록시 객체를 생성함. 실제 A 객체가 아닌 프록시 객체가 빈으로 등록되며, 이 프록시 객체는 실제 A 클래스의 메서드들을 호출할 때 트랜잭션을 관리하는 추가 로직을 삽입함. 그런데 이렇게 생성되고 사용될 때, **"@Transactional은 접근 제어자가 public 이 아닌 메서드에는 적용되지 않는 이유"**가 잘 이해되지 않습니다. 예를 들어, 아래와 같은 코드에서: public class MyService { @Transactional public void performAction() { // 트랜잭션이 필요한 메서드 } } 프록시 객체는 다음과 같이 생성될 것이라고 생각했습니다 : public class MyServiceProxy extends MyService { @Override @Transactional public void performAction() { // 트랜잭션 관련 로직 추가 (시작, 커밋, 롤백 등) // 원래의 MyService.performAction() 호출 super.performAction(); } } 그런데, "왜 @Transactional 이 붙은 메서드는 public 이 아닌 접근 제어자에는 적용되지 않나요?" 이 부분에 대한 설명이 부족하여 궁금합니다. 왜냐하면, 어차피 기존 클래스를 바탕으로 만들어지는게 프록시 객체라면 @Transactional을 적용할때, 접근 제어자가 왜 중요한지 잘 이해가 안됩니다 설명 부탁드립니다