묻고 답해요
169만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 핵심 원리 - 고급편
Thread local 과 Prototype bean 문의
안녕하세요 강의 감사히 잘 듣고있습니다. 이게 Request Scope 하고도 비슷한 답변일거같긴한데.. 혹시, Prototype bean 으로도 해당문제를 해결할수 있지않나요?? 무슨기준으로 어떤때는 Prototype bean 을사용하고 어떤때는 Thread local 을가지고 사용하는지가궁금합니다.
-
미해결스프링 핵심 원리 - 기본편
SOLID에 관해서
안녕하세요. SOLID에 관한 형식에 맞게 Appconfig를 작성해서 의존관계 주입을 해서 해결하는건 정말 멋진 생각입니다. 그러다 문득 드는 생각이 구현체에 new RateDiscountPolicy 를 수정하던지 AppConfig에 new RateDiscountPolicy로 수정하던지 프로그래밍적으로는 실행시점(런타임 상태)에 어떤 정책을 선택할지가 결정되지만 결국 프로그래머가 물리적으로 수정하는 영역은 동일하지 않나라는 생각이 들어서요. 제가 아직 프로젝트를 만들어보지 않아서 이런 생각을 하는건지.. 어떤 이점이 있는지 많이 궁금합니다.
-
미해결스프링 핵심 원리 - 기본편
ac.getBean()의 반환값에 대해서
안녕하세요. 스프링 입문강의부터 열심히 보고 있는 수강생 입니다. 강의를 듣다가. 스프링 빈조회 기본 편에서는 assertThat().isInstanceOf(구현객체.class)이렇게 하셔서 getBean()의 반환값이 config의 return값이 들어오는줄 알았습니다. 근데 해당강의에서는 구현객체 클래스가 아닌 MemberRepository.class인 인터페이스로 비교를 하길래, 궁금하여 질문합니다. 코드상에서는 인터페이스든, 구현 클래스든 둘다 상관없이 비교가 가능한 것 같은데, 그 이유가 궁금합니다 !
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
테이블 생성은 되지만, 데이터 삽입이 되지 않습니다!!ㅜㅜ!!
package jpabook.jpashop;import org.assertj.core.api.Assertions;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.annotation.Rollback;import org.springframework.test.context.junit4.SpringRunner;import org.springframework.transaction.annotation.Transactional;import static org.junit.Assert.*;@RunWith(SpringRunner.class) //스프링과 관련된 것을 테스트할 것임을 JUnit에게 알려줌@SpringBootTestpublic class MemberRepositoryTest { @Autowired MemberRepository memberRepository; //의존성 주입 @Test @Transactional @Rollback(value = false) public void MemberRepositoryTest() throws Exception { //given Member member = new Member(); member.setUsername("memberA"); //when Long saveId = memberRepository.save(member); Member findMember = memberRepository.find(saveId); //then Assertions.assertThat(findMember.getId()).isEqualTo(member.getId()); Assertions.assertThat(findMember.getUsername()).isEqualTo(member.getUsername()); }} spring: datasource: url: jdbc:h2:tcp://localhost/~/jpashop username: sa password: driver-class-name: org.h2.Driver jpa: open-in-view: false hibernate: ddl-auto: create properties: hibernate:# show_sql: true format_sql: truelogging.level: org.hibernate.SQL: debug# org.hibernate.type: trace
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
세션을 이용한 로그인에 관해 질문이 있습니다
로그인 세션을 생성할때 해당하는 유저의 객체를 그대로 담아서 생성해도 괜찮은지 궁금합니다. 제가 토이프로젝트를 하면서 로그인의 경우는 사용자가 로그인 요청을 했을때 정보가 일치하다면 해당 객체를 session.addAttribute("user",유저객체); 이런 식으로 세션을 생성했고 로그인이 필요한 로직(글,댓글,예약 등)의 경우는 컨트롤러에서 @sessionAttribute를 사용하여 해당 세션이 유효한지를 체크하고 해당 객체의 PK를 가져와 해당 로직을 수행할 수 있는 유저인지 확인하는 방식을 수행했습니다. 제가 생각하는게 맞는지 모르겠지만 이 경우엔 유저의 개인정보가 고스란히 담겨있어서 안전하지 못하다는 생각이 드는데 사용자는 단순히 세션ID만 알고 있으니 상관이 없는지 아니면 보안상의 문제가 있는지 궁금합니다. 이런 방식보다는 사용자의 PK만 세션으로 생성해서 보내는게 좋을까요? 아니면 더 좋은 방식이 있을까요?
-
해결됨스프링 시큐리티
로그인 후 로그인 페이지 접속
스프링 시큐리티에서 별도로 로그인 후에 로그인 페이지 접속을 제한하는것은 없는건가요? 로그인 컨트롤러에서 principal을 통해 리다이렉트하는 방법 밖에 없는걸까요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
테이블 생성은 되는데 insert 쿼리가 실행이 되지 않습니다.
package jpabook.jpashop;import org.junit.jupiter.api.Assertions;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;import org.springframework.boot.test.context.SpringBootTest;import org.junit.jupiter.api.Test;import org.springframework.test.annotation.Rollback;import org.springframework.transaction.annotation.Transactional;import static org.junit.jupiter.api.Assertions.*;import static org.hamcrest.MatcherAssert.assertThat;import static org.hamcrest.Matchers.equalTo;// 내장 서버를 실행하지 않고 테스트 수행@SpringBootTest@AutoConfigureMockMvcpublic class MemberRepositoryTest { @Autowired MemberRepository memberRepository; //의존성 주입 @Test //테스트 실행 함수 @Transactional // 트랜잭션 추가 @Rollback(value = false) public void MemberRepositoryTest() throws Exception { //given Member member = new Member(); member.setUsername("memberA"); //when Long saveId = memberRepository.save(member); Member findMember = memberRepository.find(saveId); //then assertThat(findMember.getId(), equalTo(member.getId())); assertThat(findMember.getUsername(), equalTo(member.getUsername())); }}
-
해결됨스프링 핵심 원리 - 기본편
BeanDefinition 관련 질문
1. 우선 강의 내용을 듣고 이해한 바로는 ApplicationContext 구현체들의 각 BeanDefinitionReader들이 자신들이 읽어들일 수 있는 설정 파일에 따라 읽어들인 후 Bean 하나당 하나의 BeanDefinition들을 만들어내는 걸로 이해했습니다. 제가 이해한 것이 맞을까요? 2. 그리고 설정 정보를 읽어 오는 것이 BeanDefinitionReader라면 그 BeanDefinition을 읽어서 Bean을 생성하는 것은 어떤 것인가요? 3. 마지막으로 수업에서 BeanDefinition의 내용을 출력하며 확인해보는 부분이 있었는데 그 BeanDefinition 속성들의 설정 및 수정은 각 Reader들이 읽어들이는 그 파일에서 설정 및 수정이 가능한건가요??
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
v3.1 쿼리 최적화
안녕하세요 선생님! v3.1에서 쿼리 실행 결과 order 조회-> orderItem 조회 -> item 이 조회됩니다. 저는 OrderItem 안에 item이 Lazy 로딩이니 페치 조인으로 가지고 오고 싶어서 다음과 같은 로직을 작성해보았습니다. @GetMapping("/api/v3.2/orders")public List<OrderDto> ordersV3_page2( @RequestParam(value = "offset", defaultValue = "0") int offset, @RequestParam(value = "limit", defaultValue = "100") int limit) { List<Order> orders = orderRepository.findWithMemberDelivery(offset, limit); List<Long> ids = orders.stream().map(order -> order.getId()).collect(toList()); List<OrderItem> orderItems = orderQueryRepository.findOrderDto(ids); return orders.stream() .map(order -> new OrderDto(order, orderItems)) .collect(toList());} public List<OrderItem> findOrderDto(List<Long> ids) { return em.createQuery( "select oi from OrderItem oi join fetch oi.item where oi.order.id in :ids", OrderItem.class) .setParameter("ids", ids) .getResultList();} public OrderDto(Order order, List<OrderItem> orderItems) { orderId = order.getId(); name = order.getMember().getName(); orderDate = order.getOrderDate(); orderStatus = order.getStatus(); address = order.getDelivery().getAddress(); this.orderItems = orderItems.stream().map(OrderItemDto::new).collect(toList());} 이와 같이 로직을 작성 하고 결과를 확인하니 위와 같이 모든 Item이 조회되었습니다. 혹시 fetch join 이 문제 일까 싶어서 fetch join 을 제외하고 실행하더라도 동일한 결과가 나왔습니다. fetch join을 빼고 실행하면 강의에서 나온 것과 동일하게 쿼리가 실행되지만 결과값은 다른 것을 확인했습니다. -> batch_fetch_size를 사용했을때만 동일한 쿼리가 실행됨.(결과값은 다름) batch_fetch_size 사용 시 단순히 in 쿼리로 결과를 가져오는 것이 아니라 지연로딩을 생각해서 결과값을 가져온다고 생각하면 되는걸까요? 동일한 쿼리가 실행되는데도 결과 값이 다르게 나오는게 이해가 잘안됩니다 ㅠㅠ
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
생성자 주입 선택 시 테스트 코드 작성의 장점?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 안녕하세요 선생님. 좋은 강의 늘 감사드립니다. 스프링 기본 편부터 해서, 생성자 주입을 선택하는 것에 여러 장점들이 있고 그 중 테스트케이스를 작성하는 데 용이 하다는 설명을 들었는데요. 다른 부분은 납득이 되었으나 테스트케이스 작성의 용이함은 무엇일까? 하고 여러 번 생각해봤는데 답을 내릴 수가 없어서 질문 드립니다. 본 예제코드에서도 테스트 코드에서 결국 @AutowiredMemberService memberService; @Autowired MemberRepository memberRepository; 로 테스트 클래스에 직접 빈을 주입 받아서 해당 메소드를 사용했는데요. 이 경우 실제 클래스에서 DI 주입 방식을 어떤식으로 선택하든 테스트 케이스에서 차이가 없지 않나요? 생성자 주입이 테스트 코드 작성에 용이하다는 부분이 어떤 부분인지 잘 모르겠어요 ㅠ
-
미해결스프링 핵심 원리 - 기본편
빈 Destroy관련 질문
안녕하세요. 강의를 듣다가 의문점이 들어서 질문 남깁니다. 지금까지는 빈의 스코프가 싱글톤으로 되어 있어 빈이 스프링 시작과 종료에 소멸 된다는 것까지 이해가 되었습니다. 그런데 싱글톤 스코프에서 Destroy 메소드를 어떤 상황에서 무엇을 위해 사용하지는 이해가 되지 않습니다.
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
NumberFormat 추상클래스 인스턴스화에대해서
추상클래스는 인스턴스화 될수없다고 알고있는데요. NumberFormat.getInstace();로 인스턴스를 생성하는것을 수업시간에봤습니다. 추상클래스가 어떻게 인스턴스화할수있는건가요?
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
REPEATABLE READ 등은 Serializable보다 완전히 안전하지는 않지만 성능이 좋기 때문에 사용하는 것인가요?
생각하다 보니까 고립도라는 것은 근본적으로 이런 경우에는 이런 고립도만 쓰지 않으면 100% 안전하기 때문에, 쓸 수 있는 고립도 중 가장 성능이 좋은 고립도를 쓰는게 아니라, 어떤 고립도를 쓰더라도 확률적으로 위험한 경우가 발생할 수 있지만 잘 일어나지 않기 때문에 Serializable 아닌 성능적으로 빠른 REPEATABLE READ 등을 사용하는 것인지 궁금합니다. ====================== 제가 생각한 일반적인 예는 아래와 같습니다. 아버지와 아들이 있습니다.아들은 다음날 수학 여행에 필요한 버스비가 1000원이라고 아버지께 말해놓았습니다. 그래서 아버지는 저녁때 아들의 계좌를 확인해서 1000원으로 맞춰놓기로 약속하셨습니다.그날 저녁 아버지의 행동을 함수로 구현하면 아래와 같습니다. 아들 계좌를 확인하고 1000원이 되도록 채워주기_f() {select해서 아들 계좌의 돈을 확인합니다. 1000 - 아들 계좌의 돈 만큼 다시 아들 계좌로 송금합니다.} 그날 저녁 아들 계좌에는 700원이 있었는데 자기 돈을 사용해서 200원짜리 포켓몬 빵을 사먹었습니다. (아들의 update문)그런데 그때 하필 아버지가 아들 계좌를 확인하고 1000원이 되도록 채워주기_f() 를 실행한 겁니다. 아버지가 select 할 때는 아들 계좌는 700원이었습니다. 그래서 아버지는 300원만 더 넣어주면 1000원이 되겠군, 이라고 결론을 내리고 300원을 아들 계좌로 송금합니다. 300원을 송금하는 부분을 쪼개어보면 select 해서 아들의 계좌 잔액을 가져오고 거기에 300원을 더한 값을 set 하는 방식이었습니다. (SQL에 add라는 기능이 없기 때문에)그래서 결국 락이 풀림과 동시에 set 1000이 될 겁니다. 아들은 분명 200원짜리 포켓몬을 샀는데도 계좌에는 800원이 아닌 1000원이 남게 됩니다. 무에서 유가 창출되는 사건이 발생하는 것입니다!============================================위의 예처럼 update문에만 락이 걸려도 무결성에 위배되는 경우가 생길 것 같습니다. Serializable이라는 고립 레벨이 있긴 해도 성능상의 이유로 Serializable은 잘 안 쓴다고도 알고 있습니다. 그럼 Serializable 아닌 경우라면 위와 같이 절묘하게 타이밍만 맞아 떨어지면 데이터 무결성이 깨지는 경우가 발생할 수 있다는 것인데... 그럼 일반적으로 REPEATABLE READ를 사용할 수 있는 논리와 아닌 논리로 나누어져 있다기 보다는 위와 같이 절묘한 순간이 잘 일어니지 않기 때문에 성능적으로 더 좋은 REPEATABLE READ 등을 사용한다고 보면 되나요?
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
view가 제대로 나오지 않습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 뭘 잘못했는지 어느 순간부터 화면이 안나오네요... 강의 보고 했는데 뭘 안했는지 잘 모르곘어요 ㅠㅠ 아래 프로젝트 파일입니다.. https://drive.google.com/file/d/1EE_x_MA0bFVMgCQ5zXXVruwdzGyjZT2p/view?usp=sharing
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
import domain.Member 오류
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 안녕하세요 김영한 강사님. 강의 잘 보고 있습니다. 다름이 아니라, repository 패키지에 생성한 두 파일에 Member Class를 import 하는 과정에서 문제가 생겨 질문 드립니다. Member Class의 경우 문제없이 작동되는데, 어떤 부분이 문제인지 모르겠습니다.
-
해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
API서버에서 일반 컨트롤러의 역할을 잘 모르곘습니다!
백엔드에서 api를 개발하고 프론트엔드에게 제공하면 @RestController가 아닌 일반 @Controller는 단순히 클라이언트에게 html파일만 건네주는 용도쓰면 되는건가요??
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
h2 처음 사용시 몇 가지 의문점
1. h2 사용시 왜 처음 외에는 jdbc:h2:tcp://localhost/~/test 로 접속해야하나요? 그냥 넘어가도 되는 부분이기도 하지만 계속 궁금해서요. 만약 그렇게 하지 않으면 무슨 문제가 생기나요? 2. 그리고 jdbc:h2:~/test 이게 파일로 접근하는 방식이라고 하셨는데요. 이 부분이 잘 이해가 안 갑니다. 예를 들어서 MySQL같은걸 사용하면 데몬서버에 JDBC를 사용하는 클라이언트가 요청을 보내면, MySQL의 엔진과 스토리지 엔진이 돌아가면서 DB에 데이터도 저장하고 읽기도 한다고 알고 있거든요. h2가 아무리 경량이라고 하더라도 DB라면 데몬 프로그램으로 어딘가 떠서 돌아가고 있고, 거기에 H2 콘솔이 JDBC를 사용해서 TCP로 요청을 보내고 응답을 받으며 작업을 해야할 것 같은데... 파일로 접근한다는 개념은 무엇인지 잘 모르겠습니다.
-
미해결스프링 핵심 원리 - 기본편
@Scope 관련 질문이 있습니다.
안녕하세요! 항상 좋은 답변 달아주셔서 감사합니다. 한 가지 궁금한 점이 있어 글을 적게 되었습니다. 1. A라는 클래스에 Request Scope를 사용하게 될 경우, 각 HTTP 요청마다 다른 A 클래스가 생성되서 오는 것을 확인했습니다. 이 때, 각 쓰레드별로 다른 Request Scope 빈을 사용하는 것으로 확인이 되었고, @PreDestory 메서드까지 처리되는 것을 확인했습니다. 정리해보면 요청이 올 때마다 새로운 Request 스코프빈이 만들어져서 스프링 컨텍스트에서 관리된다는 것으로 이해를 할 수 있을 것 같습니다! 그럼 요청 10개가 오면, 동시에 10개의 쓰레드가 활동하면서 동일한 빈을 만들고, 스프링 컨테이너에 저장되어있는 것으로 보입니다! 이 때, 각 쓰레드는 어떻게 자기가 처음에 배정받았던 Request Scope 빈을 스프링 컨테이너에서 받아오는지 궁금합니다. 그리고 각 Request Scope 빈은 동일한 타입의 다른 이름으로 저장이 되는 걸까요? 2. Set Proxy 모드로 Request 객체를 만들었습니다 .이 때, Controller 클래스에 @RequiredArgusConstruct를 이용해서 @Controller 클래스가 스프링 빈으로 등록될 때, RequestScope 빈을 DI 받도록 설정했습니다. 이 때, Http 요청을 동시에 10개를 하게 되면 각 쓰레드마다 다른 프록시 객체를 가지는 것을 확인했습니다. 그런데 이 RequestScope는 이미 Controller 빈이 등록될 때, 정해진 빈인데 어떻게 각 쓰레드가 요청할 때 마다 쓰레드별로 다른 빈을 반환해주게 되는 것인가요? 너무 궁금합니다 항상 좋은 답변 주셔서 감사합니다. 좋은 하루 되세요.
-
미해결스프링부트 시큐리티 & JWT 강의
20초가량에 csrf 를 disable 한 이유가 뭔가요?
이전 수업을 들었으면 알 거라고 하는데 어디에 나와있을까요? 1강에서도 그냥 말없이 disable만 하셔서 질문 남겼는데 여기서도 그냥 넘어가서 제가 빼먹은 부분이 있나 싶어서요
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
stream이 아닌 querydsl transform을 이용하는 방법에대한 문의
안녕하세요 8:30초대 강의를 보면 1:N관계의 list형태를 mapping하기 위해 flats .stream ~ .collect ~ 형태를 이용하고 있는데요 실무에서도 비슷한 사례가있어, 처음에 강사님처럼 어플리케이션단에 코드를 짰다가, 코드가 너무 복잡해져서 QueryDsl에서 transform + GroupBy.list를 이용하는식으로 변경해봤는데요. (아래 예시참조) from(Entity) // 1:N 관계의 List<Object> 를 추출, key : Entity.Id .transform( groupBy(Entity.Id) .list( Projections.fields(Example.class, Entity.Id, list( Projections.fields(Detail.class, Detail.id Detail.name ) ).as("DetailList") ) ) ) 문제는 구글링을 해보니, 해당 방식이 쿼리결과를 memory에서 리스트형태로 만들어내는것이라고 하더라구요. 예전에 강사님의 강의에서 '컬렉션 fetch join은 페이징을 이용할 수 없다'는 내용을 설명해주실 때, 해당 동작이 메모리에서 일어나기때문에 OOM이 발생할 수 있다 라고 말씀해주셨는데 이와 마찬가지로 transform , Groupby.list를 이용하는 것 역시 문제가 발생할까봐 우려스럽네요 아래 두가지 질문에 답변 부탁드립니다. Q1) 강사님의 application단에서 짜는 방식이 나을지 아니면 querydsl단에서 transform & Groupby.list를 이용하는게 나을지 고민되는데 두가지 방법중 무엇을 선택하는게 좋을까요? 후자의 경우 OOM이 발생하지는 않을지도 궁금합니다.. Q2) memory에서 작업하는게 위험한 이유가 뭔가요? 강사님처럼 application단에서 로직을 수행하는것도 memory에서 동작하는것 아닌가요? 친절하고 유익한 강의 늘 감사드립니다. 답변 부탁드립니다!