묻고 답해요
169만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 핵심 원리 - 기본편
appconfig
안녕하세요 김영한 개발자님 강의를 복습하다가 궁금한 점이 생겨서 질문남깁니다. appconfig class에서, 아래 코드 public class AppConfig { public MemberService memberService() { return new MemberServiceImpl(new MemoryMemberRepository()); } } ... 처럼 구현 객체를 생성하고 연결하는 책임을 가진다고 하셨는데, 그럼 제 생각에는 MemberServiceImpl 클래스가 생성되기 전에 AppConfig 클래스가 먼저 실행되어야 한다고 여겨집니다. 그런데 코드 어느 부분에서도(MemberApp, OrderApp 제외) Appconfig 클래스를 호출하는 부분이 없어서 매커니즘(?)이 궁금했습니다. appConfig라는 이름의 클래스가 있으면 스프링이 자동으로 실행시켜주는 것인지, 아님 MemberApp, OrderApp과 같은 클래스를 만들어서 사용해야 하는 것인지 헷갈리는데 어떤게 맞을까요?! (여담이지만, 처음들었을 때 헷갈렸던 내용이 반복해서 들으니 이해가 자연스럽게 돼서 너무 감격스럽고 성장한 것 같아 행복합니다. 아직 궁금한점도 많고 부족하지만 꾸준히 공부하겠습니다. 좋은 강의와 항상 답변해주시는 서포터즈 분들도 감사드려요)
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
bindingReault.addError rejectedValue 값에 item.getPrice() 는 어떻게 전달되는건가요?
화면에서 qqq와 같은 문자열이 전달될 경우, bindingReault.addError 프로퍼티에 rejectedValue에 item.getPrice()를 넘기는데, qqq는 숫자가 아니여서 item 객체에 저장이 안되어 있는데 어떻게 넘어갈 수 있는 걸까요? log를 찍어보면, item.getPrice()=null 인데요. @PostMapping("/add")public String addItemV2(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) { //검증 처리 if(!StringUtils.hasText(item.getItemName())) { bindingResult.addError(new FieldError("item", "itemName", item.getItemName(), false, null, null,"상품 이름은 필수 입니다.")); } log.info("item.getPrice()={}", item.getPrice()); if(item.getPrice() ==null || item.getPrice() < 1000 || item.getPrice() > 1000000) { bindingResult.addError(new FieldError("item", "price", item.getPrice(), false, null, null,"가격은 1,000원 ~ 1,000,000원 까지 허용합니다.")); }
-
해결됨스프링 핵심 원리 - 고급편
target 인스턴스도 빈으로 등록은 되는 건가요?
강의를 재밌게 보고 있는데, 의문이 있어서 질문드립니다. "대안1 자기 자신 주입" 강의 0:47 때 그림을 보여주시는데, 해당 그림에서는 target 인스턴스 내에서 proxy 를 의존성 주입 받아서 사용하는 걸로 표현됩니다. 여기서 의문이 들었습니다. 제 지식으로는 "스프링 빈으로 proxy 가 등록되고, target 은 빈으로 등록되지 않고, proxy 가 내부에서 참조만 한다"라고 알고 있습니다.(틀리다면 꼭 지적해주십쇼!) 그리고 또 한가지는 제가 알기로는 "의존성 주입을 위해서는 쓰는 쪽과, 받는 쪽 모두 빈으로 등록되어 있어야 한다."라는 것입니다. 이 두 가지 생각을 합치니 0:47 에 나오는 그림이 이상해 보였습니다. 그림 상에서는 빈으로 등록되지 않은 target 인스턴스가 의존성 주입을 받고 있는 걸로 보이거든요... 그림 처럼 되려면 target 인스턴스도 빈으로 등록이 되어야 하는데... 혹시 target 인스턴스도 빈으로 등록이 된건가요??
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
멀티쓰레드 환경관련 몇 가지 질문드립니다.
ConcurrentHashMap 이야기를 해주실 때 좀 궁금해서 찾아보며 몇 가지 궁금증이 생겨서 질문드립니다. 1.일반적으로 HashMap은 멀티쓰레드환경에서 사용하면 안 된다고 하는데, 이것은 '전역변수일 때만' 적용되는 개념이 맞나요? 예를들어 웹개발시 비지니스 로직 메소드(itemSave 등) 에서 new HashMap 등으로 선언 후 값을 넣어 mybatis insert 등을 한다고 할 때, 그냥 HashMap을 사용하잖아요? 이 때는 멀티쓰레드 환경이더라도, 메소드 호출시 스택에 쌓이고 인스턴스가 따로 생성(new HashMap)되니 동시성접근관련 고민을 할 필요가 없는건거죠? 2.store 전역변수를 멀티쓰레드 환경에서 ConcurrentHashMap으로 선언해야한다는 것은 쓰레드들이 동시 접근시 안의 value값을 덮어쓰거나 바꾸거나 등등 동시적 작업으로 원치않는 결과를 반환할 수 있기 때문인거죠? 감사합니다.
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
th:errors
<div> <label for="itemName" th:text="#{label.item.itemName}">상품명</label> <input type="text" id="itemName" th:field="*{itemName}" th:errorclass="field-error" class="form-control" placeholder="이름을 입력하세요"> <div class="field-error" th:errors="*{itemName}"> 상품명 오류 </div></div> 여기에서 궁금한게 th:field="*{itemName}"이거는 모델에 담긴 item의 itemName이고 th:errors="*{itemName}" 이거는 바인딩리절트에 담긴 에러 item의 itemName이라고 보면 되나요? 그리고 필드네임이 맞춰져있어서 쓸 수 있다는 강사님의 말이 th:field와 th:errors의 변수이름이 같다는 걸 의미하는건가요?
-
해결됨스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
Hibernate 질문
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]JpaMemberRepository 만들고 SpringConfig 업데이트 해서 통합 테스트 돌려보면 강의 영상에 나온 것처럼 콘솔창에 'Hibername: insert into member(id, name) values(null, ?)'라는 SQL문이 뜬다고 하셨는데 저는 'Hibernate: insert into member (id, name) values (default, ?)'라고 뜹니다. 코드는 강의랑 똑같이 작성했고 여러 번 확인해서 코드 문제는 아닌 거 같은데 혹시 다른 이유가 있을까요? 답변 감사합니다.
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
thymeleaf에서 자바스크립트 인라인을 사용할 때 질문있습니다.
html 내에서 <script th:inline="javascript"></script> 태그를 이용하는 것이 아니라, 자바스크립트 파일을 static 에 있는 외부로 분리하는 경우에 어떻게 하면 변수를 사용할 수 있나요? 예를 들어 static에 js라는 경로를 만들고 그 안에 test.js라는 외부 자바스크립트 파일을 html 내에서 사용하는 경우에 <script th:inline="javascript" th:src="@{/js/test.js}"></script>와 같이 할 수 있습니다. 그런데 이 경우에 앞에서 사용한 변수인 var username = [[${user.username}]]; var age = [[${user.age}]]; 등등을 사용할 수가 없습니다. 어떻게 하면 이 문제를 해결할 수 있나요?
-
미해결스프링 핵심 원리 - 고급편
Advisor의 빈 저장소 등록 시점이 빈 처러기의 대상이 될 객체의 빈 저장소 등록 시점 보다 어떻게 더 빠를 수 있나요?
1. 생성: 스프링이 스프링 빈 대상이 되는 객체를 생성한다. ( @Bean , 컴포넌트 스캔 모두 포함)2. 전달: 생성된 객체를 빈 저장소에 등록하기 직전에 빈 후처리기에 전달한다.3. 모든 Advisor 빈 조회: 자동 프록시 생성기 - 빈 후처리기는 스프링 컨테이너에서 모든 Advisor 를 조회한다.4. 프록시 적용 대상 체크: 앞서 조회한 Advisor 에 포함되어 있는 포인트컷을 사용해서 해당 객체가 프록시를 적용할 대상인지 아닌지 판단한다. 이때 객체의 클래스 정보는 물론이고, 해당 객체의 모든 메서드를 포인트컷에 하나하나 모두 매칭해본다. 그래서 조건이 하나라도 만족하면 프록시 적용 대상이 된다. 예를 들어서 10개의 메서드 중에 하나만 포인트컷 조건에 만족해도 프록시 적용 대상이 된다. 제가 이해한 바로는 3.에서 스프링 컨테이너에 Advisor들은 이미 스프링 컨테이너에 등록 되어있는 것을 찾아오고 빈 후처리기에서 Advisor를 적용하여 프록시 객체를 생성할 target객체들은 생성만 되어있고 스프링 컨테이너에는 등록이 안되어 있는 것으로 이해했습니다. 이렇게 되려면 스프링이 Advisor를 구분해서 먼저 스프링 컨테이너에 등록 할 수 있어야 할 것 같은데 제가 제대로 생각하고 있는 것이 맞을까요?
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
영속성 컨텍스트 관련 질문
안녕하세요! 영한님 먼저 양질의 강의를 제공해주셔서 감사의 말씀 드립니다. 갑자기 영속성 컨텍스트에 대한 개념이 헷갈려서 질문드립니다. 😭 만약에 order테이블에서 member의 id가 동일한 경우 ordersV2()를 사용하면 쿼리가 총 4번 나가는데 이때 영속성 컨텍스트에서 관리되어(1차 캐시에서 조회하기 때문으로 이해했습니다.) 기존에 있는 것을 가져온다고 말씀하셨습니다. 그런데 @Transactional 안에서 DB를 조회해야 영속성 컨텍스트에서 관리되는 것 아닌가요? 🤔 감사합니다.
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
Test코드에 @Transaction 동작 문의
안녕하세요 , 영한님 강의 항상 잘보고 있습니다. 프로젝트를 진행하면서 궁금한 점이 생겨 혹시 도움을 받을 수 있는지 해서 문의남겨봅니다.. Service 에 @Transaction 어노테이션이 있는데 JPA repository save 를 호출하고 의도적으로 exception 을 발생시켰는데요, Test 클래스의 @Transaction 여부에 따라 결과가 제대로 확인되지 않는 점을 발견했습니다. Test 에서 findById 로 rollback 된 회원의 아이디를 조회하려고 하면, @Transaction 어노테이션이 테스트에 없다면 기대한대로 회원이 조회되지 않는데, @Transaction 을 붙이면 서비스에서 exeption 이 발생했는데도 rollback 이 되지 않은건지 테스트클래스에서 회원이 조회가 됩니다. 영속성 컨텍스트를 초기화하거나 @Transaction(readonly=true) 로 해도 마찬가지였고 , 서비스 트랜잭션 propagation 은 REQUIRES_NEW 로 트랜잭션을 분리했을 때는 롤백된 것이 확인되었는데요. 트랜잭션과 서비스가 하나의 트랜잭션으로 묶이면 서비스에서 발생한 exception 에 대한 rollback 은 일어나지 않고 마지막에 테스트가 끝날 때 rollback 이 발생하는 것인가요? 열심히 검색을 해봤는데, 힌트를 찾기 어려워 도움을 구합니다.. 물론 Test에서 findById 를 하는데 @Transactional 이 필요하지는 않지만, 그래도 붙였을 때 영향을 미치는 것이 궁금하여 문의 남깁니다.
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
build 오류(JAVA_HOME)
Window 사용중이구요 다음과 같은 초기 빌드에러 가 발생했습니다. ERROR: JAVA_HOME is set to an invalid directory: C:\Program Files\Java\jdk-11\bin Please set the JAVA_HOME variable in your environment to match the location of your Java installation. [Project SDKs 캡쳐] [환경변수 설정 결과] [디렉토리 구조] [빌드 실패 명령어 및 결과] [시스템 변수 설정1] [시스템 변수 설정2] 시스템 변수 설정 시 bin 의 위치를 다르게 하여 설정1, 설정2 모두 해보았구요 명령어도 ./gradlew ./gradlew build ./gradlew.bat ./gradlew.bat build gradlew 모두 해보았구요 그럼에도 불구하고 에러가 발생하는데 원인을 더 찾아볼 곳이 있을까요?
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
인텔리제이가 jsp를 인식 못하는 거 같습니다..
url로 들어가보면 jsp가 잘 뜨긴하는데, ide에서는 인식이 안되는지.. 자동 import도 안되고.. 아래 사진과 같은 상황입니다 ..
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
질문드립니다
항상 친절한 강의와 답변 모두 감사드립니다! 강의듣다가 두 가지 질문이있는데요. MemberService.update Method 에서 return 값으로 Member를 넘기게 되면 영속성이 끊긴다고 하셨는데 그러면 Controller 쪽에서 Member updateMember = memberService.update(id, name); 라고 하면 이 updateMember 는 준영속 상태인가요 ? 그리고 일단 기본적으로 독립된 트랜잭션마다 각각 다른 영속성 컨텍스트가 생성되는 게 맞죠? (OSIV 는 추후 듣도록 하겠습니다!)
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
FK, 인덱스 비교 질문
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]엔티티 클래스 개발2에서 FK 관련 질문입니다! FK를 안걸고 인덱스를 거는 방식도 있고 시스템마다 다르다고 하셨는데, Id값은 똑같이 가지고 있고 거기에 인덱스를 거는 것인가요? 그리고 이렇게 하면 속도가 왜 더 빨라지는 것인가요?
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
AOP 적용 후 프록시
안녕하세요 AOP를 적용하면 스프링 컨테이너가 진짜 빈 앞에 가짜 빈을 세워놓는다고 하셨고 실제로도 콘솔에 찍어서 확인을 했는데요, AOP 관련 코드를 싹 다 지우고 AOP를 아예 안 써도 아래와 같이 hello.hellospring.service.MemberService 가 아닌 MemberService$$EnhancerBySpringCGLIB$$d7471118 이라고 뜹니다. 왜 그런 것인가요? AOP 적용 여부와 상관없이 빈이면 무조건 그 앞에 가짜 빈을 만드는 것인가요?
-
미해결스프링 핵심 원리 - 기본편
필드 주입 문제점 해결 방안
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 안녕하세요. 강의 너무 잘 듣고 있습니다. 강의에서 필드주입시 순수 자바코드로 실행이 불가능해서 테스트 하기 힘들다고 하셨습니다. public class MemberServiceImpl implements MemberService{ @Autowired private MemberRepository memberRepository;// @Autowired public MemberServiceImpl(MemberRepository memberRepository) { this.memberRepository = memberRepository; } 위 코드처럼 생성자를 따로 작성해주면 해결될 문제인거 같아 문의드립니다. 1. 필드주입시 생성자를 따로 작성하는 방법을 사용하면 필드주입의 모든 문제점이 해결되는 것이 맞을까요? 2.만약 생성자를 따로 작성하여 문제점이 해결된다해도 필드주입을 추천하지 않으신다면 그 이유를 알 수 있을까요? 감사합니다!
-
해결됨스프링 핵심 원리 - 고급편
Junit Test 에서 setDaemon(true) 를 안했어도 테스트 코드가 종료되는 이유가 뭘까요?
안녕하세요. "동시성 문제-예제코드" 강의 07:35 쯤에 나오는 설명과 실행결과가 이해가 안되서 질문드립니다. 제가 알기로는 메인 쓰레드가 종료가 되더라도, Thread thread = new Thread(); thread.setDaemon(true); 처럼 하지 않으면 프로그램이 끝나지 않는 걸로 알고 있습니다. 그런데 Junit Test 내에서는 thread.setDaemon(true)를 안 했음에도 그냥 테스트 코드가 종료되버립니다. 대체 이렇게 동작하는 원인이 뭘까요?
-
해결됨스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
JdbcTemplate 오류
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]JdbcTemplate 강의대로 코드 작성했는데 MemberServiceIntegrationTest를 돌려보니 중복_회원_예외() 메소드랑 회원가입() 두 메소드 다 에러가 뜹니다. 두 에러 내용은 <Data Conversion error converting "spring"; SQL statement>로 동일합니다. 구글링 해봤는데도 해결방법을 찾을 수 없어 질문 드립니다 ㅠㅠ
-
해결됨스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
회원 웹 기능 - 등록 강의 내용 질문
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용] 안녕하세요. 본 강의를 통해 스프링 공부를 시작한 학생입니다. 강의를 듣다가 궁금한 점이 생겨 질문 드립니다. domain의 Member 클래스에도 Getter, Setter가 있고, controller의 MemberForm 클래스에도 Getter, Setter가 있는데 MemberController의 create 함수에서 member.setName은 있고 form.setName은 없는 이유가 궁금합니다. createMemberForm.html의 <form action="/members/new/ method="post">를 통해 사용자가 입력한 "spring"이라는 이름이 value값으로 넘어가는 것, 그리고 @PostMapping이 있는 create 함수로 넘어가는 것까진 이해했는데 왜 이 함수에서 MemberForm의 set 함수 코드는 없는 것인지 궁금합니다. 사용자가 이름을 입력했을 때, 스프링이 자동으로 MemberForm의 name 값을 입력한 이름으로 설정해준 건가요? 답변 미리 감사합니다.
-
해결됨스프링 DB 2편 - 데이터 접근 활용 기술
KeyHolder가 데이터베이스에 따라 다르게 동작할까요?
안녕하세요 :) @Override public Item save(Item item) { String sql = "insert into item(item_name, price, quantity)" + " values (:itemName,:price,:quantity)"; BeanPropertySqlParameterSource param = new BeanPropertySqlParameterSource(item); KeyHolder keyHolder = new GeneratedKeyHolder(); template.update(sql, param, keyHolder); long id = keyHolder.getKey().longValue(); item.setId(id); return item; } save 메서드를 강의대로 했을때 저는 InvalidDataAccessApiUsageException 이 발생 하더라고요. org.springframework.dao.InvalidDataAccessApiUsageException: The getKey method should only be used when a single key is returned. The current key entry contains multiple keys: [{id=7, item_name=productE, price=50000, quantity=20}] 그래서 id 를 받아 오는 부분을 ```java Long id = (Long) keyHolder.getKeys().get("id"); ``` key를 받아오고 id 를 빼는 식으로 변경 했더니 잘 동작 합니다. 혹시나 해서 테이블을 확인 했는데 primary key 설정도 되어 있는 상태 입니다. 강의를 회사에 일찍 출근해서도 듣고 집에 퇴근하고 와서도 듣다보니 연속성을 위해 PostgresDB를 따로 구축해두고 사용하고 있는데 .. 혹시나 해서 H2 로 변경 해서 테스트 해 보니 getKey() 만 해도 정상적으로 동작 되었습니다. KeyHolder의 getKey가 DB에 따라 상이하게 동작하는걸까요..? update 파라미터를 우연히 보았더니 keyColumn 을 파라미터로 받길래 혹시나 해서 "id" 를 넣었더니, 이 때에도 getKey()가 정상적으로 동작 하였습니다. 우연히 해결을 하기는 했는데 KeyHolder의 작동 원리에 대한 이해가 없다보니 궁금하네요.. 1. DB 에 테이블을 등록할 때 제가 뭔가 누락한게 있어서 그럴까요? 아니면 단순히 Postgres 를 사용해서 그런 걸까요? 2. DB에 따라 getKey()가 안될 수 있다면, getKeys() 후에 원하는 key를 받아오는 것과 update 할 때에 key column을 명시해 주는 것 중 어느쪽이 더 명확할까요? 혹은 더 나은 방법이 있을까요? 감사합니다