묻고 답해요
169만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
@Transactional(readOnly=true) 설정에 대한 질문입니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예[질문 내용]안녕하세요, 최근 부하테스트를 진행하며 성능개선을 해보려하고 있습니다. 그 중 단순 DB 조회 API에 대해 테스트를 진행하고 있는데, 스레드 덤프를 확인한 결과 SessionImpl.doFlush()가 호출되는 것을 보고 트랜잭션이 끝나는 시점에 자동으로 flush가 호출되는 것을 발견했고, 때문에 readOnly 설정이란 것을 찾아서 설정하고 다시 테스트를 진행했습니다. 반복해서 테스트를 진행해 봤는데, readOnly를 설정하지 않았을때가 TPS가 높게 측정이 됩니다. 왜 그런지 알 수 있을까요.. 그림은 순서대로 readOnly를 설정하지 않았을 때와 설정했을 때 입니다. 테스트 대상 API의 코드는 아래 링크의 getMovieList() 입니다. https://github.com/hapHollys/booook/blob/main/src/main/kotlin/com/haphollys/booook/presentation/controller/MovieController.kt
-
미해결실전! 스프링 데이터 JPA
jpa 여러개 repository findById
안녕하세요... 토이프로젝트를 하다가 궁금한것이 있어서 문의드립니다... 제가 원하는건 결론적으로 이렇습니다. if(){ Test1Repository.findById(Long Id); }else if(){ Test2Repository.findById(Long Id); } else { Test3Repository.findById(Long Id); } 이런식으로 계속 분기처리하기보단 레포지토리를 하나의 값으로 findById를 할수 있는지가 궁금합니다..
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
무한 대기 설정 질문드립니다.
안녕하세요. 강의를 보고 따로 책으로 학습중인데 책 내용에 서비스에서 서비스 끼리 호출할때 timeout 설정을 하지 않으면 무한정 대기가 걸릴 수 있다고 하더라고요.그런데 강의 실습하면서 따로 timeout 설정한 부분이 없었던 거 같았는데, 혹시 제가 놓쳤던 것인지 아니면 의도적으로 설정하지 않으신건지 궁금해서 여쭤봅니다!감사합니다.
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
URI 구조 질문
안녕하세요 영한님 야생형코스를 듣고 토이프로젝트를 하던 도중 URI를 어떤 식으로 정해야 할지 감이 안잡혀서 활용1편에 있는 컨트롤러들의 URI를 참고하는 도중 궁금한점이 생겨서 여쭈어보게 되었습니다. MemberController와 ItemController의 등록과 관련된 URI에서는 /members/new , /items/new와 같이 복수단어를 사용하였지만 OrderController에서는 /order와 같이 URI가 단수로 되어있었습니다. HTTP 강의 중 비슷한 내용이 있던게 기억나서 찾아보았더니 HTTP 메서드 부분에서는 "계층 구조상 상위를 컬렉션으로 보고 복수단어 사용 권장(member -> members)" 이라고 설명해 주셨지만 혹시나 order의 경우 다른 뜻이 있으셔서 URI를 단수로 작성한건지 궁금해서 여쭈어 보게 되었습니다!
-
해결됨Spring Boot JWT Tutorial
genericFilterBean
genericFilterBean에 doFilter라는 메소드가 없네요.. ㅠㅠ 이제 바뀐걸까요?
-
해결됨Spring Boot JWT Tutorial
permitAll()질문드립니다.
기존질문 - security config에서 antMatchers.permitAll()이 작동하지 않는 것 같습니다. 찾아보니 csrf때문이란 말도 있어 csrf.disable사용해봐도 똑같이 계속 401에러가 뜹니다. ㅠ 왜 이러는 걸까요.. ++해결 config파일을 메인클래스와 같은 패키지안에 넣지않아서 bean을 인식하지 못하는 경우였습니다. 같은 패키지안에 넣으니 해결되었습니다!! 추가질문!!! 근데 추가적으로 왜 메인클래스안에 넣지않으면 인식이 되지않는 것인지 궁금합니다. 이게 스프링부트 작동순서와 연관된 것 인가요?
-
해결됨Spring Boot JWT Tutorial
dependency설정
spring start에서 dependency넣지않고 나중에 따로 넣는다했을때 공식적으로 어떤 dependency를 써야한다고 적힌 문서는 어떻게 찾아야하나요? 구글에 spring security gradle dependency 등등 여러가지로 쳐봐도 공식문서를 못찾겠네요 ㅠ
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
Mockito 를 사용하여 테스트할 때, 테스트 요구사항의 반영 질문
이번 강의의 1분 30초 쯤, 현재 작성하는 테스트 방법이 그다지 좋은 방법은 아니다라는 말을 들었습니다. 그래서 좋은 테스트 방법은 무엇인지 찾아보게 되었고 돌아돌아 Mockito 같은 테스트 프레임워크를 알게되었습니다. 좋은건 일단 맛은 봐야하는 성격이라, 강의를 듣다말고 Mockito 를 사용하여 단위 테스트 하는 방법 알아보는 길로 한참 새버렸습니다 ㅎㅎㅎ Mockito 를 사용해서 OrderService 의 주문 성공에 대한 테스트 코드를 작성해보았습니다. 근데 영한 선생님이 강의에서 작성할 때의 assertEquals 이나 그런 요구사항들에 대해선 테스트를 못해서 제가 테스트 코드 작성을 잘못한건가 하는 생각이 들었습니다. 코드는 다음과 같이 간단하게 작성했습니다. @ExtendWith(MockitoExtension.class) class OrderServiceTest { @Mock MemberRepository memberRepository; @Mock ItemRepository itemRepository; @Mock OrderRepository orderRepository; @InjectMocks OrderService orderService; @Test @DisplayName("주문 성공") void order() { Member member = new Member( 1L, "irostub", new Address("seoul", "street", "10000"), new ArrayList<>()); Item item = new Book( 1L, "itemName", 15000, 2021, new ArrayList<>(), "5pg", "isbn5100"); //given given(memberRepository.findOne(anyLong())) .willReturn(member); given(itemRepository.findOne(anyLong())) .willReturn(item); //when orderService.order(1L, 1L, 100); //then ArgumentCaptor<Order> captor = ArgumentCaptor.forClass(Order.class); then(orderRepository).should(times(1)).save(captor.capture()); } } 코드는 위와 같습니다. 뭔가 많이 허전합니다. 강의에서 처럼 assertEqual()에 인자로 넣을 객체를 받아올 방법이 없어서 , orderRepository.save(...) 는 void를 반환하고 orderService.order(...) 은 Long 을 반환하지만 영속성 컨텍스트도 없으므로 null 을 반환합니다. 그래서 결국 테스트 한 것이라곤, Mock 을 통해 적당한 맴버, 상품을 정해놓고 orderService.order(...) 메서드를 실행중에 orderRepository.save(...) 을 잘 호출했는가? 뿐입니다. 이렇게 하는게 맞는걸까요..? (테스트에 대한 강의가 아님에도 이런 질문을 하는게 죄송스러울 따름입니다..ㅠㅠ 근데 어디다 물어볼 곳도 없어서 심란한 마음에 글을 씁니다)
-
해결됨스프링 배치
EXIT_CODE 반영 문의
안녕하세요 강사님 한가지 궁금한게 있어 문의 남깁니다 flow1에서 failed 시점에 flow3으로 흐르도록 했을 때 flow3의 모든 스탭이 성공하여서 제 생각으로는 JobExecution 기록에 EXIT_CODE가 COMPLETED로 기록될 줄 알았는데 JobExecution 기록에 EXIT_CODE 가 FAILED로 기록되어 있습니다. JobExecution의 EXIT_CODE가 마지막 스탭이나 플로우의 상태값을 반영되는 것으로 인지하고 있었는데 위와 같은 경우와 같이 Job의 과정중 하나의 스탭이라도 실패하게 된다면 EXIT_CODE에는 FAILED로 기록이 되는건가요?
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
강사님 안녕하세요. 강의 항상 잘 듣고 있습니다.
질문은.. 강의랑 똑같이 했는데 이상하게 whitelabel error page만 보이네요.. 혹시 datasource 설정해줘야하나 해서 추가해봤는데도 안 되고.. 1편 강의처럼 Spring Security 때문도 아니고.. 원인을 못 찾겠어서 문의드립니다..
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
강의 테스트 도중 한가지 db에 대해서 한가지 궁금한게 생겨 질문남깁니다!
정말 부끄러운 질문일수도 있겠지만 궁금한건 알고싶어서 이렇게 질문 남깁니다(야생형 코스 밟으면서 진행하고있습니다) 저번 강의때 db가 꺼져있어도 local db? 로 테스트를 진행할 수 있다고 들었던거 같은데 저는 테스트를 돌릴때 db가 꺼져있으면 쿼리가 제대로 올라오지 않고 테스트에서 IllegalStateException이 뜨게 되는데 혹시 저의 미천한 궁금증을 해결해주실수 있을까요? 아니면 원래 개발할때는 db서버를 상시 열어두는게 기본중에 기본인가요...?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
카테고리 다대다 매핑 => 다대일, 일대다로 매핑
@ManyToMany를 다대일 일대다 관계로 바꿔보았는데 이렇게 바꾸는 게 맞을까요?? <CategoryItem.java> package jpabook.jpashop.domain;import jpabook.jpashop.domain.item.Item;import lombok.Getter;import lombok.Setter;import javax.persistence.*;@Entity@Getter @Setterpublic class CategoryItem { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "category_item_id") private Long id; @ManyToOne @JoinColumn(name = "category_id") private Category category; @ManyToOne @JoinColumn(name = "item_id") private Item item;} <Category.java> package jpabook.jpashop.domain;import jpabook.jpashop.domain.item.Item;import lombok.Getter;import lombok.Setter;import javax.persistence.*;import java.util.ArrayList;import java.util.List;import static javax.persistence.FetchType.*;@Entity@Getter @Setterpublic class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "category_id") private Long id; private String name; @ManyToOne(fetch = LAZY) @JoinColumn(name = "parent_id") private Category parent; @OneToMany(mappedBy = "parent") private List<Category> child = new ArrayList<>();} <Item.java> package jpabook.jpashop.domain.item;import jpabook.jpashop.domain.Category;import jpabook.jpashop.domain.CategoryItem;import lombok.Getter;import lombok.Setter;import javax.persistence.*;import java.util.ArrayList;import java.util.List;@Entity@Getter @Setter@Inheritance(strategy = InheritanceType.SINGLE_TABLE)@DiscriminatorColumn(name = "DTYPE")public abstract class Item { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "item_id") private Long id; private String name; private int price; // 가격 private int stockQuantity; // 재고수량 @OneToMany(mappedBy = "item") private List<CategoryItem> categoryItems = new ArrayList<>();}
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
객체지향에 대해 궁금한 점
안녕하십니까 강사님 객체지향에 대해 궁금한 점이 생겨 질문드립니다. 17:05에서 order라는 메서드 안에 createOrderItem, createOrder 메서드들이 있습니다. 이 두 메서드는 OrderService 입장에서 OrderItem과 Order한테 "니네가 무슨 일은 하는지는 모르겠지만, 나는 이 두 개를 받아서 주문을 생성한다"라는 말이잖아요? OrderService가 하는 일은 OrderItem과 Order에서 받은 것들을 이용하여 주문 생성 OrderItem이 하는 일은 주문 상품 생성 Order가 하는 일은 주문 생성 그렇다면 이게 객체지향성을 나타내는 것일까요? 감사합니다
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
assertThat 오류
이번 강의에서 회원 서비스 테스트 클래스에서 assertThat 오류가 발생합니다. 다른 클래스에서 assertThat를 이용할 때는 잘 사용이 되었지만 이번 클래스에서는 오류가 뜨네요 오류 내용 The method assertThat(String, T, Matcher<? super T>) in the type Assert is not applicable for the arguments (String) 임포트 내용 구글링을 해서 많은 방법을 써봤지만 해결이 되지 않았습니다.
-
해결됨스프링 시큐리티
런타임 중, 메소드 인가 맵 등록시, 서비스 Proxy 가 만들어지지 않는 이유의 질문입니다.
좋은강의 감사드립니다. 약간 다른 시도를 해보고 잘 안풀리게되어 질문을 남기게 되었어요.메소드 권한 부여는 반드시 MapBasedMethodSecurityMetadataSource 생성자를 통해서만 등록이 가능할까요? 초기화가 끝난 이후 런타임에서 addSecureMethod(string, configAttrList) 를 통해 등록하면 프록시 생성이 안되는것 같더라구요.. 그래서 아래와 같은 시도가 있었습니다. 저는 MapBasedMethodSecurityMetadataSource 를 extends 하여 CustomMapBasedMethodSecurityMetadataSource 를 만들어, 생성이 된 이후, 메소드 리소스맵 등록을 super.addSecureMethod() 메서드로 하려는 시도를 했습니다. 이후 @EventListener(ContextRefreshedEvent.class) 이벤트 핸들러를 MethodSecurityConfig 에 작성하고, 이벤트 발생 시점에 App컨택스트로 부터 CustomMapBasedMethodSecurityMetadataSource 를 가져와 reload() 를 호출하여 Map 을 통해 메서드 정보 등록이 되도록 구성했습니다 문제는서버 기동 및 컨트롤러 호출 후, Method Resource 가 등록 과정에 서비스 프록시 가 생성되지 않아 서비스 메서드 가 그대로 호출이 되었는데요, Debug 확인 결과 클래스 명 메소드명 Map 파싱은 문제가 없었습니다. 아래는 서버 기동 후, 커스텀 메소드 메타데이터 소스 를 메모리에서 조회 결과입니다. 위의 과정으로반드시 생성자를 통해 Map 을 전달 해야만 Proxy 생성이 되는것으로 판단되었습니다이벤트 리스너를 통해 methodMap 등록을 지연하게 되면 필터링 처리가 안되는 이유가 궁금한데요..이런 부분에 대해 조언을 구합니다. 아래는 작성한 Method..Config 와 Method...Source 입니다 MethodSecurityConfig public class MethodSecurityConfig { ... /** * DB 초기화 직후, METHOD 인가정보 등록 */ @EventListener(ContextRefreshedEvent.class) @Transactional public void onContextRefreshed(ContextRefreshedEvent event) { ApplicationContext ctx = event.getApplicationContext(); var customMapBasedMethodSecurityMetadataSource = ctx.getBean(CustomMapBasedMethodSecurityMetadataSource.class); customMapBasedMethodSecurityMetadataSource.reload(); } ...} CustomMapBasedMethodSecurityMetadataSource public class CustomMapBasedMethodSecurityMetadataSource extends MapBasedMethodSecurityMetadataSource { private final MethodResourceMapFactoryBean methodResourceMapFactoryBean; public CustomMapBasedMethodSecurityMetadataSource(MethodResourceMapFactoryBean methodResourceMapFactoryBean) { /* 생성자를 통해 methodMap 전달시 작동 */// super(Map.of(// "io.security.corespringsecurity.aopsecurity_test.AopMethodAuthTestService.methodSecured",// List.of(new SecurityConfig("ROLE_USER"))// )); this.methodResourceMapFactoryBean = methodResourceMapFactoryBean; } /** * DB 데이터 초기와 직전 로딩 이슈로, DB 초기화 이후 값을 가져오기위한 리로딩 메서드 */ public void reload() { LinkedHashMap<String, List<ConfigAttribute>> resourceMap = methodResourceMapFactoryBean.getObject(); for (Map.Entry<String, List<ConfigAttribute>> resourceEntry : resourceMap.entrySet()) { String fullPackageClassMethodName = resourceEntry.getKey(); List<ConfigAttribute> configAttributes = resourceEntry.getValue(); addSecureMethod(fullPackageClassMethodName, configAttributes); } } /** * 보안 메서드에 대한 설정을 추가합니다. 메서드 이름은 여러 메서드를 등록하기 위해 `*` 로 끝나거나 시작할 수 있습니다.<br /> * 풀패키지 클래스명 + 메서드명 파싱 및 S.Security 에 메서드 정보 추가 <br /> * Key: 풀패키지 클래스명 + 메서드명(ex: "a.b.Class.*method or method*") <br /> * Value: ConfigAttribute List <br /> * 참고: super 클래스 private addSecureMethod(name, attr) 메소드 복제 */ private void addSecureMethod(String name, List<ConfigAttribute> attr) { int lastDotIndex = name.lastIndexOf("."); Assert.isTrue(lastDotIndex != -1, () -> "'" + name + "' is not a valid method name: format is FQN.methodName"); String methodName = name.substring(lastDotIndex + 1); Assert.hasText(methodName, () -> "Method not found for '" + name + "'"); String typeName = name.substring(0, lastDotIndex); Class<?> type = ClassUtils.resolveClassName(typeName, ClassUtils.getDefaultClassLoader()); super.addSecureMethod(type, methodName, attr); } } 읽어주셔서 감사합니다.
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
4분 20초에 동시성에 문제가 있을수 있다고 말씀해주셨는데요.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 아니오[질문 내용]4분 20초에 실무에서는 동시성을 고려해야 할수 있다고 말씀해주셨는데요. 저코드에서 동시성에 관련된 문제가 어떻게 발생이 되는지 알려주시면 감사하게습니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
member_Id, item_id,order_id 가 공유되는거 같은데 따로 할려면 어떻게 해야하나요?
4:33에 order 하나 만들었는데 #3이 되어있어서 확인해보니까 멤버 하나 만들면member_id=1 아이템 하나 만들면 item_id=2 주문 하나 만들면 order_id=3 이런식으로 id가 공유되는거 같은데 @GeneratedValue 때문인가요? 각각 따로 id를 만들어줄려면 어떻게 해야하나요?
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
run을 클릭할 때 실행이 되지 않아요
강의 내용 중 run을 실행시키는 부분에서 왼쪽에 화살표 모양이 나타나지 않습니다 상단에 있는 목록 중 run을 눌러 실행을 하면 밑의 이미지와 같은 문구만 나타납니다
-
미해결실전! 스프링 데이터 JPA
Auditing transaction
안녕하세요, auditing 강의를 듣고 적용해보았습니다. 게시글을 처음에 만들때 원하는 값들이 잘 들어가지만 게시글을 수정하여 다시 저장할 경우audit 부분에서 createdBy, modifiedBy 를 못가져오면서 transaction 에러를 냅니다..! 혹시 실무에 적용하기 위해 추가로 적용해야 할 부분이 있을까요? 아마 AuditorAwareImpl에서 @Autowired MemberRepository memberRepository; 부분이 이상한 것 같은데...이유는 모르겠습니다 ㅠ_ㅠ public class AuditorAwareImpl implements AuditorAware<Long> { @Autowired MemberRepository memberRepository; @Override public Optional<Long> getCurrentAuditor() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (null == authentication || !authentication.isAuthenticated()) { return null; } DefaultOAuth2User principal = (DefaultOAuth2User) authentication.getPrincipal(); String email = (String) principal.getAttributes().get("email"); if(email == null ){ return null; } Member member = memberRepository.findByEmail(email).orElse(null); if(member == null){ return null; } return Optional.of(member.getId()); } }
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
Junit4와 Junit5에서 테이스 차이 질문입니다
Junit5와 Junit4 에서의 회원가입테스트에서 Junit5는 Long savedId = memberService.join(member); 에서 NullPoniterException이 터지게 되는데 Junit4에서는 정상적으로 테스트가 완료됩니다. 야생형코스로 하고있는데 이러한 테스트 결과에서 도저히 이해가 안되서 이렇게 질문 남깁니다...