묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
도커로 사용해도 카프카 커넥트 설정 다 따라해야하나요?
도커로 사용해도 카프카 바이너리, 카프카 커넥트, 카프카 jdb 커넥트 세개 다 다운하고 설정해줘야하나요?
-
해결됨RabbitMQ를 이용한 비동기 아키텍처 한방에 해결하기
채팅 방식 질문입니다!
학습중 궁금한 것은 언제든 문의 하세요.질문을 최대한 자세히 남겨주시면 반드시 답변 드리도록 하겠습니다.추가로 알고 싶은 내용도 요청해주시면 강의 자료를 업데이트 해서 제공할 예정입니다. 해당 강의에서 http요청은 mq를 사용하게 되는데 채팅의 경우 스프링의 기본 내장브로커를 사용하게 되는 것이 아닌가요?
-
미해결1시간만에 끝내는 spring boot rest api 서비스 개발
swagger spring boot 3 적용 run 실행 에러
spring boot 3.4.3 버전 pom.xml 에러가 납니다 <!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.8.5</version> </dependency>main 함수 run 실행시 아래왜 같은 에러가 나옵니다 Could not transfer artifact org.springdoc:springdoc-openapi-starter-webmvc-ui:pom:2.8.5 from/to central (https://repo.maven.apache.org/maven2): 알려진 호스트가 없습니다 (repo.maven.apache.org)
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
좋아요 락 질문입니다.
안녕하세요 비관적 락, 낙관적 락부분 수업 듣다가 테스트 결과값이 이상해서 질문드립니다.이렇게 나오는데 비관적 락1에서 count가 0이 나오는데 코드가 잘못된 걸까요? 다시 살펴봤는데 이상한 부분은 딱히 없어서 왜 이렇게 나오는지 몰라서 질문드립니다!
-
미해결코드로 배우는 React 19 with 스프링부트 API서버
로그인 성공과 실패처리 강의 중에 궁금한점이 있어 질문드립니다.(추가질문)
db 포스트맨: 에러상황: 포스트맨으로 db에 있는 email과 패스워드 입력해도 로그인이 안됩니다. 참고로 db에 있는 이메일 : user9@aaa.com 직접 db에서 수정하고 저장했습니다. 그리고 user8@aaa.com로 해도 안됩니다.
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
게시판 CRUD 관련 오류
학습 관련 질문을 최대한 상세히 남겨주세요!고민 과정도 같이 나열해주셔도 좋습니다.먼저 유사한 질문이 있었는지 검색해보세요.인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 안녕하세요,저와 비슷한 오류가 많은 것 같은데 해결이 안된것 같아서 질문드립니다.13분쯤에 코드를 같이 따라 쳐보도 위와 같은 오류가 발생합니다. 이문제가 해결이 안되서 코드만 3번째 다시 치고 있습니다 ㅠㅠ... 500 Internal Server Error: "{"timestamp":"2025-03-03T03:54:49.747+00:00","status":500,"error":"Internal Server Error","path":"/v1/articles"}" org.springframework.web.client.HttpServerErrorException$InternalServerError: 500 Internal Server Error: "{"timestamp":"2025-03-03T03:54:49.747+00:00","status":500,"error":"Internal Server Error","path":"/v1/articles"}" at org.springframework.web.client.HttpServerErrorException.create(HttpServerErrorException.java:102) at org.springframework.web.client.StatusHandler.lambda$defaultHandler$3(StatusHandler.java:89) at org.springframework.web.client.StatusHandler.handle(StatusHandler.java:146) at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.applyStatusHandlers(DefaultRestClient.java:698) at org.springframework.web.client.DefaultRestClient.readWithMessageConverters(DefaultRestClient.java:200) at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.readBody(DefaultRestClient.java:685) at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.body(DefaultRestClient.java:631) at kuke.board.article.api.ArticleApiTest.create(ArticleApiTest.java:29) at kuke.board.article.api.ArticleApiTest.createTest(ArticleApiTest.java:16) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) https://velog.io/@ghwns9991/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-3.2-%EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98-%EC%9D%B4%EB%A6%84-%EC%9D%B8%EC%8B%9D-%EB%AC%B8%EC%A0%9C 스프링 3.2 부터 uri 관련 매개변수 어노테이션을 잘 인식하지 못한다고 하나 봅니다. 저는 윗 글의 두 번째(-parameters) 방법으로 해결했습니다. 위와 같이 해결했다고 하는 문구가 많은데,저는 -parameters를 추가해도 같은 오류가 발생합니다. 혹시 추가 설정이 필요한 부분이나 추가적으로 말씀해주시면 업로드 하겠습니다 ! 코드 추가 ArticleControllerpackage kuke.board.article.controller; import kuke.board.article.service.ArticleService; import kuke.board.article.service.request.ArticleCreateRequest; import kuke.board.article.service.request.ArticleUpdateRequest; import kuke.board.article.service.response.ArticleResponse; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor public class ArticleController { private final ArticleService articleService; @GetMapping("/v1/articles/{articleId}") public ArticleResponse read(@PathVariable Long articleId) { return articleService.read(articleId); } @PostMapping("/v1/articles") public ArticleResponse create(@RequestBody ArticleCreateRequest request) { return articleService.create(request); } @PutMapping("/v1/articles/{articleId}") public ArticleResponse update(@PathVariable Long articleId, @RequestBody ArticleUpdateRequest request) { return articleService.update(articleId, request); } @DeleteMapping("/v1/articles/{articleId}") public void delete(@PathVariable Long articleId) { articleService.delete(articleId); } } entity-Article package kuke.board.article.entity; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.ToString; import java.time.LocalDateTime; @Table(name = "article") @Getter @Entity @ToString @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Article { @Id private Long articleId; private String title; private String content; private Long boardId; private Long writerId; private LocalDateTime createAt; private LocalDateTime modifiedAt; public static Article create(Long articleId, String title, String content, Long boardId, Long writerId) { Article article = new Article(); article.articleId = articleId; article.title = title; article.content = content; article.boardId = boardId; article.writerId = writerId; article.createAt = LocalDateTime.now(); article.modifiedAt = article.createAt; return article; } public void update(String title, String content) { this.title = title; this.content = content; modifiedAt = LocalDateTime.now(); } } repository - ArticleRepositorypackage kuke.board.article.repository; import kuke.board.article.entity.Article; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface ArticleRepository extends JpaRepository<Article, Long> { } Service - request - ArticleCreateRequestpackage kuke.board.article.service.request; import lombok.Getter; import lombok.ToString; @Getter @ToString public class ArticleCreateRequest { private String title; private String content; private Long writerId; private Long boardId; }Service - request - ArticleUpdateRequestpackage kuke.board.article.service.request; import lombok.Getter; import lombok.ToString; @Getter @ToString public class ArticleUpdateRequest { private String title; private String content; } Service - response - ArticleResponsepackage kuke.board.article.service.response; import kuke.board.article.entity.Article; import lombok.Getter; import lombok.ToString; import java.time.LocalDateTime; @Getter @ToString public class ArticleResponse { private Long articleId; private String title; private String content; private Long boardId; private Long writerId; private LocalDateTime createAt; private LocalDateTime modifiedAt; public static ArticleResponse from(Article article) { ArticleResponse response = new ArticleResponse(); response.articleId = article.getArticleId(); response.title = article.getTitle(); response.content = article.getContent(); response.boardId = article.getBoardId(); response.writerId = article.getWriterId(); response.createAt = article.getCreateAt(); response.modifiedAt = article.getModifiedAt(); return response; } }ArticleApplicationpackage kuke.board.article; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ArticleApplication { public static void main(String[] args) { SpringApplication.run(ArticleApplication.class, args); } }resources - application.ymlserver: port: 9000 spring: application: name: kuke-board-article-service datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/article username: root password: root jpa: database-platform: org.hibernate.dialect.MySQLDialect open-in-view: false show-sql: false hibernate: ddl-auto: none test - java - kuke.board.article.apipackage kuke.board.article.api; import kuke.board.article.service.request.ArticleCreateRequest; import kuke.board.article.service.response.ArticleResponse; import lombok.AllArgsConstructor; import lombok.Getter; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.client.RestClientTest; import org.springframework.web.client.RestClient; public class ArticleApiTest { RestClient restClient = RestClient.create("http://localhost:9000"); @Test void createTest() { ArticleResponse response = create(new ArticleCreateRequest( "hi", "my contents", 1L, 1L )); System.out.println("response = " + response); } ArticleResponse create(ArticleCreateRequest request) { return restClient.post() .uri("/v1/articles") .body(request) .retrieve() .body(ArticleResponse.class); } @Test void readTest() { ArticleResponse response = read(1234L); System.out.println("response = " + response); } ArticleResponse read(Long articleId) { return restClient.get() .uri("/v1/articles/{articleId}") .retrieve() .body(ArticleResponse.class); } @Test void updateTest() { update(1234L); ArticleResponse response = read(1234L); System.out.println("response = " + response); } void update(Long articleId) { restClient.put() .uri("/v1/articles/{articleId}", articleId) .body(new ArticleUpdateRequest("hi 2", "my content 22")) .retrieve() ; } @Test void deleteTest() { restClient.delete() .uri("/v1/articles/{articleId}", 1234L) .retrieve(); } @Getter @AllArgsConstructor static class ArticleCreateRequest { private String title; private String content; private Long writerId; private Long boardId; } @Getter @AllArgsConstructor static class ArticleUpdateRequest { private String title; private String content; } }article - build.gradle dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.mysql:mysql-connector-j' implementation project(':common:snowflake') }
-
미해결코드로 배우는 React 19 with 스프링부트 API서버
DTO와 인증 서비스 강의 질문있습니다.
1.DTO와 인증 서비스 13분 38초 화면이 [username user9@aaa.com ,password 1111] postman에서 회원가입하는 화면인건가요?2.DTO와 인증 서비스 17분 10초 postman 화면도 있는데 이거는 로그인 화면인건가요?3. 제가 포스트맨에서 username user10@aaa.com ,password 1111으로 넣고 send를 누르면 맨 위 사진과 같이 에러가 나옵니다.참고로 db 테이블에 username user9@aaa.com ,password 1111 내용이 있습니다.포스트맨{"timestamp": "2025-03-02T20:26:21.086+00:00","status": 404,"error": "Not Found","trace": "org.springframework.web.servlet.resource.NoResourceFoundException: No static resource api/member/login.\r\n\tat org.springframework.web.servlet.resource.ResourceHttpRequestHandler.handleRequest(ResourceHttpRequestHandler.java:586)\r\n\tat org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:52)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService spring boot 실행시 아래와 같이 나옵니다. Principal이 username이 user9@aaa.com로 안나옴.[Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]]코드 첨부합니다.https://drive.google.com/file/d/1VtPVj_uRjPC7fYG3gRCeuFKcs2s4wPZm/view?usp=drive_link
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
PathVariable과 RequestParam, Test Code에 관하여
안녕하세요 쿠케님 강의 잘 듣고 있습니다. 너무 좋아서 팀원들한테도 전파했을 정도입니다. 다들 구매예정이시라고 하네용 강의 듣는 도중 궁금점이 생겼는데 PathVariable과 RequestParam의 가장 큰 차이점은 단 하나의 유일한 자원의 식별자를 url 경로에서 표현하는가의 여부로 배웠습니다. 그래서 저는 articleId의 경우는 PatVariable로 남겨두었습니다. 이 두가지를 구분하는 쿠케님의 기준이 있으실까용?이 강의에서 테스트는 전부 JUnit이 아닌 다른 것들로 수행 중이신데요. 실제로 테스트 코드 작성하실때도 JUnit을 사용하지 않으시나요? 아니면 그냥 강의 진행 편의상 JUnit을 사용하지 않으신건가요? 감사합니다.
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
HelloController 부분 오류
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]강의 내용이랑 똑같이 다 따라쳤고 확인도 해봤는데 머 때문에 오류 뜨는지 모르겠어요 ㅠㅠ
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
좋아요 동시성 로직 관련 질문
안녕하세요 강사님, 좋은 강의 잘 듣고 있습니다. 바쁘실텐데도 불구하고 답변해주셔서 감사합니다. 질문은 크게 2가지 입니다.유니크 제약 조건 위반시 예외처리방법like() 로직에선 article_id와 user_id로 유니크 제약 조건을 걸어서 한 명의 사용자가 중복 생성하는 것을 막고 있습니다. 이 유니크 제약 조건을 위반하여 발생하는 에러는 @ControllerAdvice에서 @ExceptionHandler(DataIntegrityViolationException.class) 로 시작하는 핸들러를 통해서 처리하는 것이 일반적인가요? 2.unlike()에서 한 명의 사용자가 삭제 중복요청시 발생하는 동시성 문제 @Transactional public void unlikePessimisticLock2(Long articleId, Long userId) { articleLikeRepository.findByArticleIdAndUserId(articleId, userId) .ifPresent(articleLike -> { articleLikeRepository.delete(articleLike); ArticleLikeCount articleLikeCount = articleLikeCountRepository.findLockedByArticleId(articleId).orElseThrow(); articleLikeCount.decrease(); }); }한 명의 사용자가 "좋아요" 중복 생성 요청하는 것을 방어하는 로직이 있으니 "좋아요 해제" 중복 요청에 대한 고려에 대해서 생각해봤습니다. 이 로직에선 findLockedByArticleId 에서 베타락을 걸게 되어서 하나의 article에 대한 여러 사용자의 "좋아요 해제" 요청시의 동시성 문제를 방어하고 있습니다. 그런데 한 명의 사용자가 "좋아요 해제" 중복 요청 시에 ifPresent 구문을 통과하게 되어 articleLikeRepository.delete(articleLike);를 여러번 수행하게 됩니다. 여기서 delete는 멱등성이 보장되니 큰 문제 없이 넘어가겠지만 그 아래 count감소 로직은 해당 트랜잭션들이 베타락을 획득할 때마다 계속 수행되는 것이 아닌지 궁금합니다. 일단 ifPresent 구문 안으로만 들어오면 count감소는 무조건 일어나게 되니 문제가 생기는게 아닐까요? 그래서 ifPresent구문 전에 락을 걸기 위해 findByArticleIdAndUserId() 여기서 락획득이 이루어져야 하는건 아닌지 궁금합니다. 작성하다 보니 질문이 길어져서 죄송합니다.
-
미해결실전! 스프링 데이터 JPA
Projection 개념과 데이터 전달과정에 대해 질문 있습니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]궁금한게 있어서 질문합니다.Projection관련인데요.제가 이해하기로는 new 오퍼레이션을 이용해서 dto에 생성자로 데이터를 담는 방식에서 진화한 방식이라고 생각되는데, 그렇게 이해는게 맞는지 궁금합니다. interface로 proejction을 사용하면 get()함수를 통해 데이터를 꺼내오는 방식이고class를 사용하면 new 오페레이션을 사용하는 방법과 똑같이 생성자를 이용하는거 같은데, 대신 필드의 이름과 엔터티의 이름이 같던가, 같지 않다면 @Query를 이용해 alias로 맞춰주던가 하면 되는걸까요?? 또한, 이렇게 Projection을 사용해서 데이터를 가져왔을대, interface던 class던 컨트롤러에서 데이터를 프론트로 넘길때 해당 객체를 사용해도 되는건가요? 아니면 따로 또 dto를 만들어서 담은 후에 내보내야 되는건가요??
-
미해결코드로 배우는 React 19 with 스프링부트 API서버
단축키 질문입니다.
DTO와 인증 서비스 2분 33초에서 35초 사이에 코드가 갑자기 생기는데요. 혹시 어떤 단축키 눌른건지 알 수 있을까요?Alt + Insert눌러도 super까지 포함된 메소드는 나오지 않아서요.public MemberDTO(String email, String pw, String nickname, boolean social, List<String> roleNames) { super( email, pw, roleNames.stream().map(str -> new SimpleGrantedAuthority("ROLE_"+str)).collect(Collectors.toList())); this.email = email; this.pw = pw; this.nickname = nickname; this.social = social; this.roleNames = roleNames; }
-
미해결코드로 배우는 React 19 with 스프링부트 API서버
서비스계층과 컨트롤러(3) 질문있습니다.
서비스계층과 컨트롤러(3)-상품수정 5분 42초에서 uuid값은 화면쪽에서 처리되면서 붙는다는게 무슨 의미인지 알 수 있을까요?@Override public void modify(ProductDTO productDTO) { //step1 read Optional<Product> result = productRepository.findById(productDTO.getPno()); Product product = result.orElseThrow(); //change pname, pdesc, price product.changeName(productDTO.getPname()); product.changeDesc(productDTO.getPdesc()); product.changePrice(productDTO.getPrice()); product.changeKeyword(product.getKeyword()); //upload File -- clear first 내용이 있을 수도 있기 때문에. product.clearList(); List<String> uploadFileNames = productDTO.getUploadFileNames(); if(uploadFileNames != null && uploadFileNames.size() > 0 ){ uploadFileNames.stream().forEach(uploadName -> { product.addImageString(uploadName); }); } productRepository.save(product); }CustomFileUtil에서 saveFiles메소드에서 List<String> uploadNames = new ArrayList<>(); 배열을 선언하고 ProductServiceImp에서는 product.clearList();로 있던 배열에서 내용을 지우면서 사용하는데요. CustomFileUtil클래스 에서 데이터 베이스 1행에 저장할 리스트 생성해주고 그 리스트를 수정하는 역할이 product.clearList(); 인가요?
-
미해결코드로 배우는 React 19 with 스프링부트 API서버
로그인 실패 로직 질문
현재 APILoginFailHandler에서 로그인 실패 처리를 하고 있는데 CustomUserDetailService에서 굳이 예외를 던질 필요가 있는지 궁금합니다.제가 이해한 바로는 loadUserByUsername에서 제대로 로그인 처리가 안되면 failHandler가 실행되는 것으로 이해했는데 왜 여기서 예외를 던지는지 궁금합니다.
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
libs가 없습니다... ㅠㅠ
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]hello-spring파일까지 이동한 후 gradlew.bat을 입력해서 실행했는데요 BUILD SUCCESSFUL이라고 떴습니다. 그 후 cd build해서 들어간 후 dir을 입력하니까 libs라는 폴더는 없네요... 이유가 뭘까요 ㅠㅠ께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용]hello-spring파일까지 이동한 후 gradlew.bat을 입력해서 실행했는데요 BUILD SUCCESSFUL이라고 떴습니다. 그 후 cd build해서 들어간 후 dir을 입력하니까 libs라는 폴더는 없네요... 이유가 뭘까요 ㅠㅠ
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
CommentServiceTest에서 테스트 오류가 나요.
학습 관련 질문을 최대한 상세히 남겨주세요!고민 과정도 같이 나열해주셔도 좋습니다.먼저 유사한 질문이 있었는지 검색해보세요.인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. [문의사항]강사님의 코드 그대로 따라서 하나하나 작성하고, 모든 부분의 설정을 똑같이 했습니다. Comment 테스트 중에 <삭제할 댓글이 자식 있으면, 삭제 표시만 한다.> 는 성공이 되었습니다.그러나 <하위 댓글이 삭제되고, 삭제되지 않은 부모면, 하위 댓글만 삭제한다.> 부분의 테스트를 그대로 따라했는데, mockito.exceptions.misusing.UnnecssaryStubbingException 오류가 납니다.강의 자료로 올려주신 소스코드를 그대로 복사하여 붙여넣기 해도 같은 오류가 납니다. 소스코드와 에러메세지 작성드리며, 같은 환경에서 똑같은 소스코드를 작성했는데 어떻게 오류가 나는지 궁금합니다. 해결 부탁드립니다 ㅠㅠㅠpackage kuke.board.comment.service; import kuke.board.comment.entity.Comment; import kuke.board.comment.repository.CommentRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class CommentServiceTest { @InjectMocks CommentService commentService; @Mock CommentRepository commentRepository; @Test @DisplayName("삭제할 댓글이 자식 있으면, 삭제 표시만 한다.") void deleteShouldMarkDeletedIfHasChildren() { // given Long articleId = 1L; Long commentId = 2L; Comment comment = createComment(articleId, commentId); given(commentRepository.findById(commentId)) .willReturn(Optional.of(comment)); given(commentRepository.countBy(articleId, commentId, 2L)).willReturn(2L); // when commentService.delete(commentId); // then verify(comment).delete(); } @Test @DisplayName("하위 댓글이 삭제되고, 삭제되지 않은 부모면, 하위 댓글만 삭제한다.") void deleteShouldDeleteChildOnlyIfNotDeletedParent() { // given Long articleId = 1L; Long commentId = 2L; Long parentCommentId = 1L; Comment comment = createComment(articleId, commentId, parentCommentId); given(comment.isRoot()).willReturn(false); Comment parentComment = mock(Comment.class); given(parentComment.getDeleted()).willReturn(false); given(commentRepository.findById(commentId)) .willReturn(Optional.of(comment)); given(commentRepository.countBy(articleId, commentId, 2L)).willReturn(1L); given(commentRepository.findById(parentCommentId)) .willReturn(Optional.of(parentComment)); // when commentService.delete(commentId); // then verify(commentRepository).delete(comment); verify(commentRepository, never()).delete(parentComment); } private Comment createComment(Long articleId, Long commentId) { Comment comment = mock(Comment.class); given(comment.getArticleId()).willReturn(articleId); given(comment.getCommentId()).willReturn(commentId); return comment; } private Comment createComment(Long articleId, Long commentId, Long parentCommentId) { Comment comment = createComment(articleId, commentId); given(comment.getParentCommentId()).willReturn(parentCommentId); return comment; } }
-
미해결웹소켓/STOMP 채팅서비스(spring, vue, redis)
CORS 설정 어떻게 하셨나요?
원래는 백엔드에서 진행 하는걸로 알고 있는데,간단하게 하기 위해서 프론트쪽에서 설정을 몇 번이고 진행 했는데도 불구하고 계속해서 cors 에러가 납니다.강의에서는 따로 cors 설정을 하셨던건안 나온거 같은데, cors 설정 어떻게 하셨는지 질문 드립니다.(vue.config.js)const { defineConfig } = require('@vue/cli-service'); module.exports = defineConfig({ transpileDependencies: true, devServer: { proxy: { member: { target: 'http://localhost:8080', changeOrigin: true, pathRewrite: { '^/member': '', }, }, }, }, });
-
미해결웹소켓/STOMP 채팅서비스(spring, vue, redis)
강의 내 1 번 방법에 대한 질문
강의 설명중 1 번 방법에서누가 서버에 커넥션을 맺고 있고 subscribe 하는지 서버에 메모리를 만들어서 관리하는 로직을 사용한다고 하셨는데 이전에 강의에서 배운내용에 따르면 스프링과 stomp 는 기본적으로 세션관리를 내부적으로 처리한다고 하셔서즉 저희가 직접 접근을 하지못하는데 이러면 이벤트 리스너로 따로 sessions라는 자료구조를 만든 것을 활용해서 코드를 작성해야 하잖아요 ? 그리고 세션은 랜덤으로 스프링에서 생성하는데 이러면 세션이 몇개인지 카운트 및 각각 세션id가 부여되긴하는데그게 어떤 사용자인지 구분이 안되기에 StompHandler에서 connect 맺을때 검증 후에 추가적으로 이메일정보를 String email = claims.getSubject();accessor.getSessionAttributes().put("email", email);로 설정해서 이벤트 리스너에 넘겨서 세션을 저장하는 식으로 생각했는데 맞을까요 ?이후 서버에서 처리할때 subscribe하면서 , 동시에 누가 서버에 커넥션을 맺고있는지 아닌지 여부를 파악하는 (다소 복잡한) 로직을 작성해서 처리할 수 있다 이게 맞는 흐름일까요 ?
-
미해결코드로 배우는 React 19 with 스프링부트 API서버
REST 방식 컨트롤러 만들기에서 익스플로러에 데이터 값이 출력 안됩니다
TodoController 파일 만들고 Api서버로 스프링 기동시키고 todo경로에 tno 값을 입력해도 익스플로러 화면에 제이슨데이터 값이 표시되지 않습니다 DB상에 있는 데이터로 입력을 해도 나오지 않는 걸 보면 제이슨 설정이 잘못된게 아닌가 싶은데 답변 부탁드립니다아래에 로그 남겨둡니다오전 11:13:21: 실행 중 ':org.zerock.apiserver.ApiserverApplication.main()'…Starting Gradle Daemon...Gradle Daemon started in 915 ms> Task :clean> Task :compileJava> Task :processResources> Task :classes> Task :org.zerock.apiserver.ApiserverApplication.main() . ____ _ __ _ _ /\\ / ___'_ __ _ ()_ __ __ _ \ \ \ \( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.4.1)2025-03-01T11:13:29.675+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.zerock.apiserver.ApiserverApplication : Starting ApiserverApplication using Java 21.0.5 with PID 12000 (C:\Users\zzamp\Desktop\apiserver\apiserver\build\classes\java\main started by zzamp in C:\Users\zzamp\Desktop\apiserver)2025-03-01T11:13:29.678+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.zerock.apiserver.ApiserverApplication : No active profile set, falling back to 1 default profile: "default"2025-03-01T11:13:29.704+09:00 INFO 12000 --- [apiserver] [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable2025-03-01T11:13:29.704+09:00 INFO 12000 --- [apiserver] [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'2025-03-01T11:13:30.098+09:00 INFO 12000 --- [apiserver] [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.2025-03-01T11:13:30.139+09:00 INFO 12000 --- [apiserver] [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 35 ms. Found 1 JPA repository interface.2025-03-01T11:13:30.495+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)2025-03-01T11:13:30.506+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]2025-03-01T11:13:30.506+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.34]2025-03-01T11:13:30.539+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext2025-03-01T11:13:30.539+09:00 INFO 12000 --- [apiserver] [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 835 ms2025-03-01T11:13:30.669+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]2025-03-01T11:13:30.725+09:00 INFO 12000 --- [apiserver] [ restartedMain] org.hibernate.Version : HHH000412: Hibernate ORM core version 6.6.4.Final2025-03-01T11:13:30.754+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.h.c.internal.RegionFactoryInitiator : HHH000026: Second-level cache disabled2025-03-01T11:13:30.942+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.s.o.j.p.SpringPersistenceUnitInfo : No LoadTimeWeaver setup: ignoring JPA class transformer2025-03-01T11:13:30.966+09:00 INFO 12000 --- [apiserver] [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...2025-03-01T11:13:31.039+09:00 INFO 12000 --- [apiserver] [ restartedMain] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection org.mariadb.jdbc.Connection@77e522372025-03-01T11:13:31.040+09:00 INFO 12000 --- [apiserver] [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.2025-03-01T11:13:31.082+09:00 INFO 12000 --- [apiserver] [ restartedMain] org.hibernate.orm.connections.pooling : HHH10001005: Database info: Database JDBC URL [Connecting through datasource 'HikariDataSource (HikariPool-1)'] Database driver: undefined/unknown Database version: 10.11.10 Autocommit mode: undefined/unknown Isolation level: undefined/unknown Minimum pool size: undefined/unknown Maximum pool size: undefined/unknown2025-03-01T11:13:31.519+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)2025-03-01T11:13:31.555+09:00 INFO 12000 --- [apiserver] [ restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'2025-03-01T11:13:31.810+09:00 WARN 12000 --- [apiserver] [ restartedMain] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning2025-03-01T11:13:32.040+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 357292025-03-01T11:13:32.059+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'2025-03-01T11:13:32.064+09:00 INFO 12000 --- [apiserver] [ restartedMain] o.zerock.apiserver.ApiserverApplication : Started ApiserverApplication in 2.638 seconds (process running for 2.905)2025-03-01T11:13:57.170+09:00 INFO 12000 --- [apiserver] [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'2025-03-01T11:13:57.170+09:00 INFO 12000 --- [apiserver] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'2025-03-01T11:13:57.171+09:00 INFO 12000 --- [apiserver] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 msHibernate: select t1_0.tno,t1_0.complete,t1_0.content,t1_0.due_date,t1_0.title from tbl_todo t1_0 where t1_0.tno=?Hibernate: select t1_0.tno,t1_0.complete,t1_0.content,t1_0.due_date,t1_0.title from tbl_todo t1_0 where t1_0.tno=?Hibernate: select t1_0.tno,t1_0.complete,t1_0.content,t1_0.due_date,t1_0.title from tbl_todo t1_0 where t1_0.tno=?
-
해결됨웹소켓/STOMP 채팅서비스(spring, vue, redis)
npm 한번에 추가하기
npm install vue-router && npm install axios && npm install vuetify@3 && npm install jwt-decode && npm install sockjs-client && npm install webstomp-client질문은 아니고 한번에 추가할수 있는 명령어 공유하면 좋을거 같아서 작성합니다!