묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결실습으로 배우는 선착순 이벤트 시스템
안녕하세요 강사님 동시성 테스트에 대한 질문이 있습니다.
현재 apply 메서드에서 if (count > 100) return; 입니다.이러한 코드는 테스트하기 편하고 수강생들이 쉽게 이해할 수 있게 작성해주셨는데,실제 비즈니스 로직에서는 예외가 터질텐데 이거에 대해서는 어떻게 테스트하고 적용할 수 있나요?현재 제 코드는 이러합니다.주석이 되어있는 부분만 테스트했을 때는정상적으로 제가 원하는 값을 받을 수 있었는데, ExecutorService executorService = Executors.newFixedThreadPool(32); CountDownLatch latch = new CountDownLatch(threadCount);이 부분을 적용해서 테스트를 돌리면 무한으로 돌아가고 테스트가 종료가 되지 않습니다. 이러한 에러코드가 뜨는데 해결 방법을 모르겠습니다 ㅠㅠconstraint 뒤에는 syntax error라고 적혀있습니다. 왜 저 두 줄을 작성했을 때 이러한 에러가 발생할까요..?
-
미해결실전! 스프링 데이터 JPA
EntityGraph을 할 때, 페치조인 대상이 여러 개인 경우
안녕하세요. 강의를 듣고 개인 프로젝트 진행 중에 있는데, 궁금한게 있어서 질문드립니다.@Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class SecurityMedia { @Id @GeneratedValue @Column(name = "secu_no") private Long secuNo; // 보안매체 번호(pk) .... @OneToMany(mappedBy = "kftcSecurityMedia", fetch = LAZY) private List<KftcToken> kftcToken = new ArrayList<>(); // 토큰 @OneToMany(mappedBy = "kftcSecurityMedia") // 보안매체 이력 private List<KftcSecurityMediaHistory> kftcSecurityMediaHistoryList = new ArrayList<>();현재 SecurityMedia 라는 엔티티 객체에서 pk인 secuNo를 key로 하여 manyToOne 관계로 있는 TOKEN 클래스, HISTORY클래스를 가지고 오려고 합니다.패치 조인을 하나 이상하면 조인 되는 ROW 수 때문에 총 데이터 갯수가 꼬여버릴 수 있다고 기억하여.. SecurityMedia - Token / SecurityMedia - History 각각 패치조인 하여 가지고 오는 메소드를 따려고 생각했습니다. 그런데 서비스 영역에서 이를 로직으로 표현하고자 할 때 어떤 식으로 표현을 해야할지 감이 잘 안 오는데요. token 리스트를 가지고 있는 SecurityMedia 객체 하나, History 리스트를 가지고 있는 SecurityMedia 객체 하나, 총 두 개의 객체가 만들어질텐데.. List<Token> tokenList = repository.findSecurityMediaWithToken(secuNo).getToken();List<History> historyList = repository.findSecurityMediaWithHistory(secuNo).getHistory();이렇게 각각 패치 조인으로 가지고온 데이터를 get하는 방식이 옳은 방식인지 의문입니다. 2. 각 리스트로 가지고 온 값에서 유효한 토큰, 최신 보안 이력 1개만 뽑아낼 생각인데 이것은 쿼리를 통해 전체 리스트를 받아오고, 서비스 영역에서 entity 함수로 원하는 값을 필터하는 식으로 대상을 추려내면 될까요? 아니면 레포지토리 영역에서 select한 리스트를 필터를 해줘서 서비스 영역에 리턴 해주는게 맞는걸까요?
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
@Autowired 역할
컴포넌트 스캔과 자동 의존관계 설정 강의를 보고 제가 이해한 것이 맞는지 궁금하여 질문 드립니다. 각 컨트롤러, 서비스, 레포지토리에 @Controller, @Service, @Repository 를 붙여주면new로 객체 생성하지 않아도 @Autowired로 스프링 컨테이너에서 가져다 쓸 수 있는 것인가요?그리고 프로그램 동작 중 오직 하나의 컨트롤러, 서비스, 레포지토리만 존재하는 것인지 궁금합니다.
-
해결됨자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
배포 시기 질문입니다
안녕하세요 태현님, 항상 강의 잘 듣고 있습니다.강의를 들으며 프로젝트를 진행하고 있는데 배포 관련하여 여쭙고 싶어서 글 남깁니다.현재 백엔드와 프론트엔드(안드로이드)가 나눠진 상태로 개발 중인데 이때 스웨거라던지 프론트와 소통을 위해서 base url이 필요합니다. 그러면 강의처럼 모든 개발을 끝내고 배포하지않고 먼저 배포를 하고 시작하는 방식을 택하는 것도 괜찮나요?보통 모든 코드를 마무리하고 배포를 하는지 아니면 먼저 무중단 배포를 하고 개발을 하는지 그 방법이 궁금합니다.감사합니다!
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
대칭키 암호화 취약점
대칭키 암호화 내용을 보고 의문이 들었습니다.config server에서 관리하는 yml 파일이 git 에 올라갔을 때 적혀 있는 데이터를 평문으로 저장하지 않고 암호화 하여 보호하려는 것은 이해를 했습니다.그러나 config server 프로젝트를 내려받으면 config 설정 파일명은 알 수 있으니 실행 후 브라우저를 통해 접근하면 원본값 반환으로 바로 알 수 있는 것 아닌가요?
-
미해결스프링과 JPA 기반 웹 애플리케이션 개발
실제 구동은 되지만 테스트는 실패합니다.
강사님 현재 스프링과 JPA 기반 웹 애플리케이션을 듣는 중입니다.여러 번 반복하면서 개발 흐름을 파악하는 중인데요.AccountControllerTest에서 회원 가입 테스트- 잘못된 입력값을 테스트하는 중인데, 실제로는 구동이 잘 되지만 테스트 중에는 매번 테스트 실패로 뜹니다. 코드는 다음과 같습니다.@Test @DisplayName("회원 가입 테스트 - 잘못된 입력값") public void signUpSubmitTest_wrong() throws Exception{ mockMvc.perform(post("/sign-up") .param("nickname", "yena") .param("email", "yenice") .param("password", "12354") .with(csrf())) .andDo(print()) .andExpect(status().isOk()) .andExpect(view().name("account/sign-up")); }깃허브 주소: https://github.com/KrillM/studyclub이 문제를 넘어가기에는 앞으로 수업을 들으면서, 이후 포트폴리오를 만들 때 발목을 잡을 것 같아 질문합니다.
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
Junit5 테스트 시, JDK 17 stackoverflow error 해결 문의드립니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]jdk 17로 사용하고 있는데회원 리포지토리 테스트 케이스 작성 강의를 보면서Hashmap과 Long 때문에 stackoverflow error가 발생하는데 어떻게 해결해야 하나요?
-
미해결토비의 스프링 부트 - 이해와 원리
독립 실행형 스프링 애플리케이션까지 본 수강생입니다. 질문있습니다.
질문은 다음과 같습니다...!====Spring Container 제작시, 자기자신을 Bean으로 등록하는 이유==== 코드를 수정했습니다.Servlet Container, DispatcherServlet을 Bean으로 등록하는 코드를 config 패키지의 클래스로 따로 빼버렸습니다.[ :이유:ComponentScan은 자기자신을 탐색범위에 넣지 않는다->클래스 내부의 Configuration을 찾지 못한다-> Configuration만 외부로 빼면 자기자신을 Bean으로 등록하지 않아도 된다] Spring Container를 만드는 과정에 Servlet Container를 만들지 않습니다. 분리시켰습니다.(순서대로 만들어진다는 느낌을 받기위해...) 다음은 제가 작성한 main 문의 코드입니다.@ComponentScan public class DemoApplication { public static void main(String[] args) { //Spring Container 구성정보 AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(); // Bean 등록 applicationContext.register(DemoApplication.class); //Spring Container 실행(초기화) applicationContext.refresh(); // ========================================= //Servlet Container 구성정보 ServletWebServerFactory serverFactory = applicationContext.getBean(ServletWebServerFactory.class); //servlet 만들기 DispatcherServlet dispatcherServlet = applicationContext.getBean(DispatcherServlet.class); dispatcherServlet.setApplicationContext(applicationContext); //Servlet Container 인스턴스 WebServer webServer = serverFactory.getWebServer(servletContext -> { servletContext.addServlet("dispathcerServlet", dispatcherServlet).addMapping("/*"); }); //서버 실행 webServer.start(); } }1번의 이유로,// Bean 등록 applicationContext.register(DemoApplication.class);이걸 주석처리했습니다.같은 클래스내에 ApplicationContext가 있고, 생성도 완료한 시점이기 때문에, 본인이 Bean에 직접 접근해서 꺼내 써도 된다고 생각했습니다.실제로도 직접 Bean을 꺼내서 주입시켜버립니다. ServletWebServerFactory serverFactory = applicationContext.getBean(ServletWebServerFactory.class); DispatcherServlet dispatcherServlet = applicationContext.getBean(DispatcherServlet.class); 따라서 저는, Spring Container가아래 2줄의 코드에서 Bean을 다 생성하고 DI까지 완료한줄 알았습니다.//Spring Container 구성정보 AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(); // Bean 등록 //applicationContext.register(DemoApplication.class); //Spring Container 실행(초기화) applicationContext.refresh();어차피 서블릿 환경 설정도 저 어딘가에서 ComponentScan 해서 Bean으로 등록하기 때문에자기자신을 Bean으로 등록하는건 필요 없는줄 알았습니다. 그리고 발생한 에러 입니다.No qualifying bean of type 'org.springframework.boot.web.servlet.server.ServletWebServerFactory' available =======주석만 풀면 잘 돌아갑니다. 왜이럴까요...?
-
미해결실습으로 배우는 선착순 이벤트 시스템
컨슈머를 왜 다른 모듈로 구성하는지 궁금해요!
안녕하세요. 강의 잘 듣고 있습니다.왜 쿠폰 모듈 아래 api모듈과 컨슈머 모듈을 나눠서 구성했는지 알고싶어요!!감사합니다.
-
미해결스프링 시큐리티 OAuth2
keyclock page not found 오류
clientFundamentals 클라이언트앱 커리큘럼을 실습하고 있는데요저는 9090 포트를 프로젝트의 서버 포트로 설정하고8080으로 키클락을 띄운상태인데요server: port: 9090 spring: security: oauth2: client: registration: # 클라이언트 설정 keyclock: authorization-grant-type: authorization_code # Oauth 2.0 권한부여타입 client-id: oauth2-client-app # 서비스 공급자에 등록된 클라이언트 아이디 client-name: oauth2-client-app # 클라이언트 이름 client-secret: XkPnnSZ9RLdMX6vJBsgcbTIL7gtYJ8m8 # 서비스 공급자에 등록된 클라이언트 비밀번호 redirect-uri: http:localhost:9090/login/oauth2/code/keyclock # 인가서버에 권한 코드 부여 후 클라이언트로 리다이렉트하는 위치 authorizationGrantType: authorization_code clientAuthenticationMethod: client-secret-basic # 클라이언트 자격증명 전송방식 scope: openid,profile,email # 리소스에 접근 제한 범위 provider: # 공급자 설정 keyclock: authorization-uri: http://localhost:8080/realms/oauth2/protocol/openid-connect/auth # oauth 2.0 권한 코드 부여 엔드포인트 issuer-uri: http://localhost:8080/realms/oauth2 # 서비스 공급자 위치 jwk-set-uri: http://localhost:8080/realms/oauth2/protocol/openid-connect/certs token-uri: http://localhost:8080/realms/oauth2/protocol/openid-connect/token user-info-uri: http://localhost:8080/realms/oauth2/protocol/openid-connect/userinfo user-name-attribute: preferred_username user 아이디로 로그인시 강나님처럼 do you grant these access privilliges? 화면이 뜨지않고http://localhost:8080/realms/oauth2/login-actions/localhost:9090/login/oauth2/code/keyclock?state=kCCPxAYfg3uXfG7M_vmcVzq4FVQIldvt_3viiZlE0U0%3D&session_state=09a4fb12-19eb-4f15-991e-24365d7b5b05&code=6b7b3d33-8f8f-4979-8bfe-e038f7a275a4.09a4fb12-19eb-4f15-991e-24365d7b5b05.2912d929-159d-4403-b7cb-7e7cb0d24f5e 해당 URI 로 이동하면서 we are sorry... page not found가 뜹니다어떤부분이 누락되서 오류가 나는건지 모르겠습니다
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
2.6버전 이상만 있을때 어떻게 진행하나요
zuul은 지원이 안됩니다. 그러면 zuul 대신 다른 gateway를 사용해야하는건지 억지로 2.3대이하로 내려서 zuul을 사용해야하는건지 궁금합니다.혹시 zuul이외에 다른 게이트웨이를 사용해야한다면 어떤것을 사용해야하는지, 혹시 참고할 자료가 없는지 여쭙습니다
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
윈도우 사용자인데 빌드는 어디서 어떻게 하신건가요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]윈도우 사용자는 cmd에서 하는건가요?
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
config name 기준
각 마이크로서비스에서 지정하는 config name이 파일 명으로 들어가는데요, 만약 다른 확장자의 동일이름인 파일인 경우 어떻게 되는건가요?ecommerce.yml, ecommerce.properties name을 ecommerce로만 지정해도 되는 이유가 무엇인지 궁금합니다. 단순 설정 파일의 확장자를 제외하는 이유인지 아님 yml 파일로만 config server에 등록될 수 있는지요
-
해결됨스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
최초 세팅 오류
안녕하세요.최초에 스프링부트 파일을 열고 모델을 빌드했을 때 문제가 발생하여 질문 남깁니다.자바 버전의 문제인가 싶어 java8, java17 둘 다로 해봤는데 여전히 오류가 사라지지 않습니다.오류로그와 plugins는 다음과 같습니다.No matching variant of org.springframework.boot:spring-boot-gradle-plugin:3.1.3 was found. The consumer was configured to find a library for use during runtime, compatible with Java 8, packaged as a jar, and its dependencies declared externally, as well as attribute 'org.gradle.plugin.api-version' with value '8.2.1' but:plugins { id 'java' id 'org.springframework.boot' version '3.1.3' id 'io.spring.dependency-management' version '1.1.3' }감사합니다.
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
gateway route 순서
gateway에 작성하는 routes의 작성 순서가 의미가 있는건가요?Path=/user-service/** 를 먼저 작성하고Path=/user-service/actuater를 뒤에 작성하면 actuater에 대한 처리를 위의 path에서 가져가는 것 같았습니다.순서를 바꾸어서 작성하니 정상 동작하네요알아서 내부 로직으로 처리가 되지 않고 ,(ex) url에 actuater가 포함 시 해당 라우팅으로 수행)작성 순서에 따른 우선순위로 처리되는건지 궁금합니다.
-
해결됨스프링 시큐리티 OAuth2
키클록 서버 종료후 realm 삭제
안녕하세요.키클록 종료 후 재기동 하니 만들었던 realm, client, user 가 삭제됩니다. 원래 그런건가요..?
-
미해결생산성을 향상시키는 스프링부트 기반의 API 템플릿 프로젝트 구현
OAuthAttributes 클래스의 toMemberEntity의 파라미터로 memberType이 들어가야하는 이유가 궁금합니다.
@Getter @Builder public class OAuthAttributes { private String name; private String email; private String profile; private MemberType memberType; public Member toMemberEntity(MemberType memberType, Role role){ return Member.builder() .memberName(name) .email(email) .profile(profile) .memberType(memberType) .role(role) .build(); } }강사님 안녕하세요 강의 잘 듣고 있습니다.다름이 아니라 소셜로그인(4) 소셜 로그인 구조 설계 강의를 듣던 중 toMemberEntity 메소드에 대해 궁금한 점이 있어서 질문 드리게 되었습니다. OauthAttributes 클래스 같은 경우 필드로 memberType을가지고 있는데 메소드 파라미터로 따로 memberType을 받아야 하는 특별한 상황이 있는지 궁금합니다. 감사합니다 :)
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
stock_quantity 동시성 해결하는 방법에 대해
@Test public void 상품_주문() { //given Member member = new Member(); member.setName("회원1"); member.setAddress(new Address("서울", "강가", "123-123")); em.persist(member); Book book = new Book(); book.setName("시골 JPA"); book.setPrice(10000); book.setStockQuantity(10); book.setAuthor("kim"); em.persist(book); //when int orderCount = 2; // 두권 주문 Long orderId = this.orderService.order(member.getId(), book.getId(), orderCount); //then Order getOrder = this.orderRepository.findOne(orderId); Assertions.assertEquals(OrderStatus.ORDER, getOrder.getStatus()); }강의 내용 중 테스트 코드//==생성 메서드==// public static OrderItem createOrderItem(Item item, int orderPrice, int count) { OrderItem orderItem = new OrderItem(); orderItem.setItem(item); orderItem.setOrderPrice(orderPrice); orderItem.setCount(count); item.removeStock(count); // 해당 상품의 재고 수량 차감 return orderItem; }강의 내용 중 OrderItem 엔티티 내 생성 메서드 createOrderItem()강의에서는 위와 같이 OrderItem 엔티티의 생성 메서드라는 것을 통해 주문상품을 만들고 상품의 재고를 감소시키는데요. jpa가 상품 수량(stock_quantity) 감소시킬 때 사용한 UPDATE 쿼리를 보니까 UPDATE item SET stock_quantity = 8; 과 같이 되어있더라고요. 이러면 여러 클라이언트가 동시에 해당 상품 주문할 때 덮어쓰는 문제가 발생하니까 따로 해결 방법을 찾아봤습니다.JPA에 낙관적 락이라는 게 있길래 적용해봤더니 다른 트랜잭션이 중간에 상품 수량을 변경하고 커밋하면 해당 트랜잭션에서 변환된 스프링 예외(ObjectOptimisticLockingFailureException)가 올라오며 덮어쓰는 문제는 막을 수 있었습니다(테이블 데이터 생성 후 ddl-auto: none 모드로 실행, h2 콘솔과 함께 테스트). 예외를 잡고 새 스냅샷으로 다시 호출할 수 있겠지만, db에 stock_quantity 데이터만 정확히 맞추면 되는 게 목적이어서 createOrderItem 로직을 별도의 리포지토리로 대체해보았습니다.@Slf4j @Repository @RequiredArgsConstructor public class OrderItemRepository { private final EntityManager em; /** * 주문 상품 생성 * @param item * @param orderPrice * @param count * @return */ public OrderItem createOrderItem(Item item, int orderPrice, int count) { OrderItem orderItem = new OrderItem(); orderItem.setItem(item); orderItem.setOrderPrice(orderPrice); orderItem.setCount(count); int restStock = item.getStockQuantity() - count; if (restStock < 0) { log.info("need more stock for {}.{}", item.getId(), item.getName()); throw new NotEnoughStockException("need more stock"); } // 해당 상품의 재고 수량 차감 em.createQuery("UPDATE Item i " + "SET stock_quantity = stock_quantity - :count " + "WHERE item_id = :item_id") .setParameter("count", count) .setParameter("item_id", item.getId()) .executeUpdate(); // em.refresh(item); return orderItem; }em.createQuery()로 item.removeStock(count); 부분을 바꿨습니다. SET stock_quantity = stock_quantity - :count /** OrderService 내 order 메서드 */ @Transactional(readOnly = false) public Long order(Long memberId, Long itemId, int count) { //엔티티 조회 Member member = this.memberRepository.findOne(memberId); Item item = this.itemRepository.findOne(itemId); //배송 정보 생성 Delivery delivery = new Delivery(); delivery.setAddress(member.getAddress()); //주문 상품 생성 OrderItem orderItem = this.orderItemRepository.createOrderItem(item, item.getPrice(), count); //주문 생성 Order order = Order.createOrder(member, delivery, orderItem); //주문 저장 this.orderRepository.save(order); return order.getId(); }기존에 호출하던 OrderItem.createOrderItem(item, item.getPrice(), count); 대신에 orderItemRepository.createOrderItem()를 호출하도록 OrderService 코드를 변경강의에서 작성한 상품_주문() 테스트를 단일 실행했을 때도 em.createQuery.executeUpdate()할 때 보니까, flush인가 그것도 호출안했는데 jpa가 그전에 persist한 book이랑 member까지는 실제로 인서트하고 업데이트 쿼리를 실행하는 것을 확인했습니다.[질문]1. 강의에선 OrderItem 엔티티 자체에서 createOrderItem()을 처리해주기 때문에 OrderItem의 기본 생성자도 protected로 지정해서 막았는데, 글에서 적용한 방식으로 해결하려면 public으로 바꿔야 했습니다. 지금처럼 OrderItemRepository를 따로 만들어서 처리하는 게 구조상 문제가 없는 건지 리포지토리의 역할이 맞는지 모르겠고, 문제가 생길 수 있는지 궁금합니다.(예측되는 문제점: 주문/주문 취소/상품 수정 등 stock_quantity와 얽혀있는 로직마다 쿼리를 작성해야 됨) 2. JPA의 기본적인 변경 감지 방식을 유지하면서 낙관적 락 없이도 간단하게 해결할 수 있는 방법이 있는지 알고 싶습니다.
-
해결됨Spring Boot JWT Tutorial
new User 생성자 오류 발생하는 분들...
아래 코드와 같이 에러 발생하는 분들...바보 같았네요.User principal = new User(claims.getSubject(), "", authorities);import me.{..}.jwttutorial.entity.User;이 아니고import org.springframework.security.core.userdetails.User;입니다
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
혹시 강의 중에 PDF 파일 관련해서는 다운 받을 수 없나요?
혹시 pdf 파일은 어디서 다운 받을 수 있나요?