묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨스프링 핵심 원리 - 기본편
TestBean 클래스 관련 질문입니다.
ApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);해당 코드를 통해서 TestBean 클래스가 컨테이너에 빈으로 등록이 되었으나,TestBean 클래스 내부의 @Autowired 어노테이션의 warning을 살펴보니 **Autowired members must be defined in valid Spring bean** 라는 경고 문구를 볼 수 있었습니다.해당 내용은, 자동의존주입을 받기 위해서는 현재 클래스 또한 스프링 빈으로 등록되어 있어야 한다는 의미로 해석했습니다. 결론은, 이러한 경고가 뜨는 이유를 잘 모르겠습니다.ide가 이 시점에 경고를 잡아주지 못하는 것인가요? 한가지 더 질문을 드리자면,TestBean 클래스에 @Configuration 애노테이션을 붙이게 되면, @Autowiredpublic void setNoBean2(@Nullable Member noBean2) { System.out.println("noBean2 = " + noBean2);}해당 코드에서 noBean2 부분에 빨간 밑줄이 생깁니다. (Could not autowire. No beans of 'Member' type found.)Member 타입의 빈을 찾을 수 없기 때문에 자동주입을 할 수 없다는 의미인데, 당연히 Member는 빈이 아니지만 왜 @Configuration 애노테이션을 붙였을 때 빨간 밑줄이 뜨는지 이유가 궁금합니다. @Autowiredpublic void setNoBean1(Member noBean1) { System.out.println("noBean1 = " + noBean1);}해당 코드 역시 @Configuration 애노테이션이 붙었을 때 noBean1에 빨간 밑줄이 뜹니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
주문 수량이 재고를 넘어섰을 때
주문 수량이 재고를 넘어섰을 때,현재는 Error가 발생해서 whitelabel ErrorPage가 뜨는데요, 이 대신 MemberForm처럼 BindingResult를 걸어 hasError() -> 폼에 message를 표시해주는 것과 같은 기능을 넣고 싶은데, 혹시 어떻게 할 수 있을 지 힌트를 주실 수 있으실까요..?
-
해결됨스프링 핵심 원리 - 기본편
AnnotationConfigApplicationContext 관련
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); 위 부분에서 AnnotationConfigApplicationContext 구현체 타입을 사용한 이유가 있을까요? 보니까 AnnotationConfigApplicationContext 타입에서만 getBeanDefinition 메서드를 사용할 수 있더라구요 그러면 AnnotationConfigApplicationContext이 ApplicationContext이 구현체인데 왜 getBeanDefinition을 못하는지가 궁금합니다. (하지만, ApplicationContext에서는 여러 구현체 중에 AnnotationConfigApplicationContext 있는것은 확인했으나 AnnotationConfigApplicationContext클래스에서는 ApplicationContext가 아닌 AnnotationConfigRegistry 구현체로 서로 다르게 명시 되어 있는 것도 궁금합니다. - 구현체는 하나의 인터페이스(하나의 부모)로만 구현한다고 알고 있습니다.)
-
해결됨스프링 부트 개념과 활용
버전 업데이트에도 살아있는 이유가 있을까요?
안녕하세요 기선님 좋은 강의 감사합니다 :) 스피링 코어 모듈을 개발할 때, Commons Logging 을 사용하고 있었기 때문에, 현재까지도 Commons Logging 이 남아있다고 하셨는데 스프링 5 버전을 만들 때 JCL이란 모듈을 만들어 가며 Commons Logging 코드를 컴파일 타임에 Slf4j 로 바꾸는 이유가 궁금합니다. 짧은 생각으로는 그냥 commons logging 을 빼버리고 slf4j 를 넣었으면 되지 않았나 싶은데 .. 내부적으로 스프링코어의 코드가 commons logging 과 깊게 얽혀있어서 그것보다 JCL을 만드는게 더 비용이 적어서 였을까요??
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
domain과 repository 질문
안녕하세요, 강의 듣다 궁금증이 생겨 질문 남깁니다. 질문 1. domain == vo, repository == dao 이렇게 똑같이 봐도 괜찮은 건가요? 같은 것이라면 왜 vo, dao가 아닌 다른 이름을 사용한 것인지, 다른 것이라면 (vo, dao)와 (domain, repository)의 차이점에 대해서도 알려주시면 감사하겠습니다. 질문2. 강의자료에 나오는 Memberservice, MemberRepository, MemoryMemberRepository들의 클래스 의존관계 그림은.. 이번 예제의 상황을 고려하여 만들어진 그림인가요? 아니면 실제 업무에서도 저런식으로 구성된다고 보면 되나요? + 어떤 디비를 사용할지 모르기 때문에 인터페이스로 만들었다는 말이 잘 이해가 안 되는데.. 디비접근방식을 탑재하지 않은 인터페이스를 만들어놓고 사용할 디비에 따라서 implements해서 사용하겠다..는 말이 맞나요?
-
미해결스프링 핵심 원리 - 기본편
static class TestBean 질문입니다
static inner class로 TestBean을 사용했는데요. static 키워드를 빼면 예외가 발생합니다. 내용을 보니 TestBean.class를 인자로 받아 스프링 컨테이너를 생성하고 인자로 받은 클래스를 빈으로 등록(생성)하는 과정에서 문제가 생기는 걸로 보입니다. 이 상황을 TestBean을 생성하려면 외부클래스(AutowiredTest)의 인스턴스가 필요한데 컨테이너에서 관리하는 정보에 없어서(AutowiredTest가 빈으로 등록되지 않아서) 외부클래스의 인스턴스를 생성할 수가 없고 그로 인해 static이 아닌 내부클래스를 생성(빈으로 등록)하지 못해 발생한 예외라 이해하면 될까요..? static이 붙었을 때는 TestBean을 컨테이너에 등록( 내부적으로 생성자 호출)할 때 외부클래스의 인스턴스 유무는 상관이 없기 때문에 문제없이 동작한다고 이해했고요. 몇 강 전부터 궁금했는데 이제야 질문드립니다. 제가 이해한 내용이 맞을까요? 혹시 잘못 이해한 부분이 있는지 궁금합니다^^ 강의는 정말 재미있게 잘 보고있습니다! 감사합니다^^*
-
해결됨스프링 핵심 원리 - 기본편
안녕하세요
스프링 입문 스프링 데이터 JPA 강의에서 Spring Data JPA에서 제공하는 Repository를 구현하고 있으면 Spring Data JPA가 자동으로 구현체를 등록 해준다. 이 말씀을 하셨었는데 AppConfig가 생성자 주입으로 전달하듯이 Spring Data JPA가 Repository를 구현하고 있는 인터페이스들을 찾아서 주입 역할을 해주고 있는건가요?? @Autowiredpublic SpringConfig(MemberRepository memberRepository){ this.memberRepository = memberRepository;}@Beanpublic MemberService memberService(){ return new MemberService(memberRepository);} 여기에서 SpringDataJpaMemberRepository를 어떻게 찾아가는지 궁금해서 질문 드립니다. (강의 보면서 SI 다니며 묵힌 갈증이 확 풀리는 것 같네요. 강의 감사히 듣고 있습니다. HTTP강의 까지 꼭 완강 하겠습니다!)
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
인텔리J tdd 라이브템플릿 생성하는 방법 입니다.
안녕하세요 강사님 강의를 보다가 tdd라는 명령어로 테스트 메서드를 생성하는 방법이 궁금해서 관련 가이드를 만들어 보았습니다. https://blog.naver.com/nateen7248/222184184776 혹시 궁금하신 분은 참고해 보시면 될 것 같아요 감사합니다.
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
동일한 레코드의 참조 값을 가지고 있는 영속성 컨텍스트의 동일 객체를, 동시에 서로 다른 값으로 업데이트하여 커밋할 때의 작동 방식
안녕하세요. 추천해주신 야생형 스타일에 따라 활용 1편부터 듣고 있는 수강 중인 학생입니다. 매번 강의 너무 잘 듣고 있습니다. 제가 스프링에 대한 이해도가 아직 낮기도 하고, 다른 강의를 이어서 듣다보면 해결될 문제일진 모르겠지만, 이해가 잘 안되는 부분이 자꾸 생각나서 질문 남깁니다. @GetMapping("/test1") @ResponseBody public String test1() { log.info("test1 controller"); try { Thread.sleep(5000); } catch(Exception e) { } log.info("test1 controller finished"); return "test1 finished"; } @GetMapping("/test2") @ResponseBody public String test2() { log.info("test2 controller"); try { Thread.sleep(5000); } catch(Exception e) { } log.info("test2 controller finished"); return "test2 finished"; } 위와 같은 컨트롤러 메서드 코드가 있다고 가정할 때, 각 컨트롤러 메서드가 다른 메서드라면, 각각의 메서드 별로 스레드를 가진 채 실행한다고 이해가 되었습니다. 즉, test1이 실행하는 도중에 test2가 실행될 수는 있지만, test1이 실행하는 도중에 test1은 중복해서 실행될 수 없는 것처럼 보였습니다. 일단 스프링의 작동 방식은 이처럼 이해되었습니다. 그런데 만약 아래와 같이 test1과 test2에서, 동일한 Item객체를 JPA에서 동시에 꺼내온 상황에 업데이트가 일어나면 어떻게 되는지 궁금합니다. 아래의 실행 과정은 제가 개인적으로 생각해본 과정인데, 어떠한 부분이 잘못되었는지 지적해주시면 감사하겠습니다. 1. test1에서 서비스 로직을 실행하는 도중 JPA를 이용하여 Item 객체를 findOne해서 꺼내온다(동시에 영속성 컨텍스트에 등록이 된다는 것처럼 이해되었습니다.) 2. test1가 아직 실행되고 있는 와중에, test2에서 서비스 로직을 실행하는 도중 JPA를 이용하여 Item객체를 findOne해서 꺼내온다(이 객체 또한 영속성 컨텍스트에 등록이 된다는 것처럼 이해되었습니다.) 3. 현재 test1과 test2에서 각각 동일한 Item 객체를 가져와서 영속성 컨텍스트에 등록이 된 상황이라고 보겠습니다. 앞으로 실행 될 test1의 서비스에서는 count를 10올릴 것이고, test2에서는 count를 10내린다고 가정해보겠습니다. 현재 Item 객체에는 100이라는 값이 저장되어있습니다. 4. test1에서 item.addCount(10)을 하면, count는 110이 될 것입니다. 바로 이어서 test2에서 item.removeCount(10)을 하면, count는 90이 될 것입니다. 5. test1의 서비스 로직이 끝나면, @Transactional 어노테이션을 통해 commit이 일어나고, dirty checking을 하며 item 객체의 count를 110으로 업데이트하는 쿼리문을 날릴 것입니다. 6. test2의 서비스 로직이 끝나면, @Transactional 어노테이션을 통해 commit이 일어나고, dirty checking을 하며 item 객체의 count를 90으로 업데이트하는 쿼리문을 날릴 것입니다. 7. 따라서 최종적으로 item 객체의 count값은 90으로 업데이트 될 것입니다. 하지만 실제로는 test1에서 10을 더하고, test2에서 10을 차감하였으니, 동일한 item 객체에 대한 count값은 DBMS 상에서 100으로 유지되어야 맞을 것입니다. 제가 생각한 실행 과정은 90으로 값이 업데이트되며 DBMS의 값의 일관성을 깨뜨리는 상황입니다(물론 제가 짧은 생각대로 실행한 과정의 결과가 90이란 것이지, 코드의 실행 결과가 90이라고 단언한 것은 아닙니다. 결과도 궁금하지만, 100이라는 결과가 나오는 과정에서 어떻게 실행되는지가 궁금한 것입니다!). 어떠한 부분이 잘못되었고, 그 부분은 어떻게 해결되어지는 것인지 궁금합니다. 개인적으로 생각해본 가정은 다음과 같습니다. 가정1 : 동일한 레코드를 조회한 객체에 대해서는 영속성 컨텍스트에 동일한 객체로 기억되기때문에 test1과 test2에서는 동일한 참조 값을 가진 item 객체를 가지고 있다. 따라서 addCount를 할 때 110으로 바뀌고, removeCount를 할 때 100으로 다시 바뀌기 때문에, test1과 test2의 커밋 각각에서는 count 값을 100으로 바꾸는 동일한 update문이 두 번 일어난다. 가정 2 : 동일한 레코드에 대해서 이미 commit 또는 업데이트 된 내역이 있으면, 지금 일어나는 commit은 그냥 ROLLBACK을 시켜버린다. 하지만 이렇게 할 경우, 자바 코드 상에서 DBMS에 저장된 아이템에 대해 동일한 것을 접근했는지 어떻게 기억할 것이며, rollback으로 인한 오버헤드는 감수하는 것인지 의문점이 남습니다. 가정 3 : 동일한 레코드로 조회된 객체에 대해서는 업데이트가 일어나는 전 과정에, 해당 객체에 lock을 걸어둔다. 그러면, 업데이트가 끝나서 commit이 되고, lock을 해제할 때까지 해당 객체에는 접근하지 못한다. 처음에는 이러한 과정이 @Transactional 어노테이션이 붙어있으면, 이 어노테이션이 달려있는 메서드 중에 1개씩만 실행되면서 수행되는 줄 알았는데 제가 아직 개념이 부족한 탓인지 딱히 그렇게 실행되는 것 같지는 않았습니다. 가정 4 : 애초에 이러한 설계가 잘못된 것이다. test1과 test2에서 동시에 item 객체를 수정하는 과정의 코드는 없어야한다. test1 또는 test2, 둘 중에 하나의 메서드에서만 item 객체를 수정할 수 있어야한다. 가정 5 : 그냥 DBMS에서의 트랜잭션처럼 관리된다. 자바 상에서 동시에 실행되는것처럼 보여도 JPA를 통해 serializable한 실행 결과를 보장해준다. 일단 DBMS에서 트랜잭션 간에 동시성을 관리하는 체계를 생각하면, 위와 같은 가정들이 나온다고 생각했습니다. 하지만 그건 DBMS에서의 동시성 관리 체계이지, JPA 상에서도 @Transactional 어노테이션 하나로 그것처럼 동일하게 관리되는지는 잘 모르겠어서 의문이 남습니다. 질문이 미흡해서 제가 의문점을 제대로 남긴 것인지 모르겠네요. 바쁘신 와중에 시간 내 주셔서 감사합니다. +++ @Test@Transactional@Rollback(false)public void 동시업데이트() { // given Book book = new Book(); book.setName("희재의 책"); book.setIsbn("1234"); book.setStockQuantity(100); book.setPrice(30000); em.persist(book); Book book1 = em.find(Book.class, 1L); Book book2 = em.find(Book.class, 1L); // when book1.addStock(10); book2.removeStock(20); Book book3 = em.find(Book.class, 1L); // then assertThat(book1).isSameAs(book2); assertThat(book2).isSameAs(book3); assertThat(book3.getStockQuantity()).isEqualTo(90);} 일단 위와 같은 테스트 코드로 DBMS 상에서 같은 레코드를 조회한 아이템에 대해서는 동일한 객체를 반환하는 것을 확인했습니다. (같은 트랜잭션 상에서만?) 그런데 처음 적은 예시처럼 영속성 컨텍스트에 등록된 동일한 객체에 대해 동시에 커밋이 여러 개 일어나면 어떻게 되는지, 또 이것을 확인해보고 검증하는 테스트 코드는 어떤 식으로 작성해야하는지 잘 모르겠네요.. ㅠㅠ
-
미해결스프링 핵심 원리 - 기본편
안녕하세요! 스프링 관련해서 질문 드립니다.
안녕하세요 영한님, 항상 좋은 강의 감사드립니다. 수업을 듣던 중 의문점이 생겨서 질문 드립니다. 결국 스프링을 사용하는 목적은 애플리케이션 개발에 필요한 기본 뼈대가 되는 기능들은 제공해 줄테니 개발자들은 비즈니스 로직에 집중하여 생산성을 높이는데 집중하자는 것이 목적이라는 생각이 드는데요. 혹시, 예를들어, 파이썬의 장고나 nodejs는 사용목적이 생산성을 높이기 위해 사용하는 프레임워크가 아닌건가요? 만약, 다른 프레임워크들도 결국 생산성을 높여준다는 것이 목적이라면, 다른 프레임워크들과 비교해서 자바의 스프링이 차별성을 갖는 점은 무엇이길래 메이저 it 기업에서 그토록 많이 사용되는 것인지 궁금합니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
static create 메소드
setter를 쓰기보다, static create로 메소드를 만들어 주는게 좋다고 하셨는데, 생성자 메소드로 만들지 않고, 왜 일반 정적 메소드로 만드시는지 궁금합니다..
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
안녕하세요 강사님 질문있습니다.
첫번째로 제가 api란 용어를 application program interface라고 알고 있는데 맞나요? 두번째는 1번째 강의에서 만든건 API라는게 적용이 안된 프로젝트인가요? API개념이 햇갈려서요;;; 세번째로는 postman을 깔긴 깔았는데요 왜 이걸로 테스트를 하는거에요? 그냥 첫강의때처럼 쌩으로 크롬같은데서 켜서 하는거랑 무슨차이인가요? 네번째는 @RequestBody에 대해서인데요. 이 어노테이션이 파라미터에 붙으면 ajax에서 json 형태로 전송하면 그 전송한걸 받는 곳에 이걸 붙으는걸로 알고 있는데 맞나요? 그래서 postman에서 json형태로 컨트롤러쪽에 post형태로 쏴줬으니 저 어노테이션을 붙인 곳에 바인딩된다고 생각을 하면 되는게 맞지요?
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
save() 메소드에서 member를 리턴하는 이유가 뭔가요??
안녕하세요. 좋은 강의 감사하게 잘 보고있습니다. MemoryMemberRepository에서 Member를 리턴하는 이유가 있는지 궁금합니다. store에 저장만하면 save()의 기능은 끝나는거 아닌가요? 굳이 member를 리턴하는건 왜 그런건가요??
-
해결됨스프링 시큐리티
get 요청으로 민감한 정보를 가져오는경우
안녕하세요 기선님 항상 좋은 강의 감사합니다 !! :) Http get 요청으로 민감한 정보를 가져오는 경우에 보안을 위해 get 요청에도 csrf 토큰값을 확인하는 과정을 거치고 싶다면.. CsrfFIlter 의 코드를 추적해보니 private static final class DefaultRequiresCsrfMatcher implements RequestMatcher { private final HashSet<String> allowedMethods = new HashSet<>(Arrays.asList("GET", "HEAD", "TRACE", "OPTIONS")); @Override public boolean matches(HttpServletRequest request) { return !this.allowedMethods.contains(request.getMethod()); } @Override public String toString() { return "CsrfNotRequired " + this.allowedMethods; }} 이렇게 DefaultRequiresCsrfMatcher 를 사용해 GET, HEAD, TRACE, OPTIONS 요청인 경우에는 다른 도메인에서 온 요청에도 응답을 해주는 설정을 하는거 같고, 이 부분을 수정하면 될거같은데 시큐리티 설정 클래스에서 http.csrf().requireCsrfProtectionMatcher() 다음과 같은 방법으로 수정하면 되는게 맞을까요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
Ctrl + Alt + M 단축키가 안되는 분들 보세요!
Geforce Experience가 설치된 분들에 한해서 Ctrl + Alt + M(Extract Method) 단축키가 작동하지 않는 오류를 발견했습니다. Geforce Experience를 켜고 설정에서 빨간색 네모 친 게임 내 오버레이 기능을 OFF하시면 단축키가 잘 작동할 것입니다!
-
해결됨스프링 시큐리티
csrf 토큰
안녕하세요 기선님 좋은 강의 감사드립니다!! :) 흐름을 살펴보니 csrf필터를 거치는 요청의 경우 csrf 토큰이 없는 경우 csrf 토큰을 생성해서 요청을 반환하고, 폼요청을 보낼 때, 반환받은 csrf토큰을 같이 보내는 것 같은데, 그럼 서버쪽에서는 생성해준 csrf 토큰의 값을 어디서 보관하고 있는건가요? csrf 토큰을 포함한 요청이 왔을때 비교를 하기 위해선 반환한 토큰값을 서버측에서도 어디선가 유지하고 있어야 할텐데 그 부분이 어디일지 또 언제까지 유지하는지 궁금해서 질문남깁니다!! ======================= 질문을 남기고 구글링을 통해 찾아본 결과는 CsrfTokenRepository를 사용해서 토큰정보를 가지고 있는 것같은데 기본구현체는 HttpSessionCsrfTokenRepository를 사용하는 것으로 보아 Session을 기반으로해서 토큰 정보를 유지하고, session이 사라지면 자연스럽게 토큰 정보도 날라가는것 처럼 보이는데 맞을까요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
src/test/resources/application.yml 인식 문제입니다.
안녕하세요 강사님! 테스트 수행 중 application.yml 파일을 test 밑에 두고 따라하는중에 application.yml 파일을 찾지 못하고 자꾸 main 밑에있는 파일을 불러왔습니다. 찾아보니 test/resources/config/application.yml 로 두어야 인식한다고 되어있고 저도 config 디렉토리를 생성해 그 밑에 두었더니 별도의 application.yml 파일로 읽어오더라구요. https://stackoverflow.com/a/53134737 인텔리제이로 학습중인데 이부분 한번 확인 부탁드리겠습니다!
-
해결됨스프링 핵심 원리 - 기본편
AppConfig에서 MemberRepository 객체 생성에 관하여 질문있습니다.
현재 AppConfig에선는 MemberService, OrderService 둘 다 memberRepository()를 통해 MemoryMemberRepository 객체를 주입 받고 있습니다. 하지만 memberRepository()를 호출할 때마다 MemoryMemberRepository 객체가 새로 생성됩니다. 따라서 MemberService와 OrderService는 서로 다른 Repository를 참조하고 있습니다. 이렇게 서로 다른 MemoryMemberRepository를 참조해도 되는지 여쭤보고 싶습니다. 아니면 저장소인 store를 static으로 선언했기 때문에 서비스간 참조하는 객체는 다르지만 store는 공유하고 있기 때문에 상관없을까요? 아니면 추후에 서비스들이 하나의 MemberRepository만 참조하도록 하는게 나을까요?
-
미해결스프링 핵심 원리 - 기본편
싱글톤 DIP 위반에 관한 질문입니다.
이전 강의와, 이번 강의 내에서, 싱글톤 패턴을 사용하는 경우 DIP 위반이라고 말씀하셔서 질문 드립니다. 과거 강의에서 작성한 AppConfig 클래스 내부에 public MemberRepository memberRepository() { return MemoryMemberRepository.getInstance(); } 이런식으로 작성한다면, 예전에 말하셨던 Configuration(구성?) 하는 부분만 변경될 뿐, 사용하는 부분에서는 new AppConfig().memberRepository 를 하면 되는데 왜 DIP 위반이라고 하시는지 궁금해서 질문드립니다. ^_^
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
상품 등록시에 데이터 받는 로직
안녕하세요따로 공부하다가 궁금한 점이 생겨서 질문 남깁니다. item에서 InheritanceType.JOINED 를 사용하게 되면 화면에서 컨트롤러로 Form data를 받아와서 처리하는 로직은 어떤식으로 구현을 하는게 효과적인가요? 예를들면 formData에 타입을 넣어줘서 if else문으로 각각에 맞는 Controller(formData){if(formData.getType equals "B") persist( new B(formData.a formData.b , formData.c)) else if ("A") persist( new A(formData.dd formData.gg ) else if ~~~~} 이런식으로 전부 빼야 하나요?? 만약 위와 같은 상황이라면 타입이 엄청나게 많아지는 경우 무한if else을 쓰기는 좀 비효율적인 코드가 될 거 같아서 질문드립니다.