묻고 답해요
167만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결비전공자도 이해할 수 있는 쿠버네티스 입문/실전
실무 개발 환경
안녕하세요. 재밌고 좋은 강의를 해주셔서 감사합니다. 아직 70%정도 보고 있지만 궁금하게 있습니다.현재 백엔드 개발자로 근무하고 있는데 저희 환경은 aws의 ec2에 직접 올려백엔드 서버(spring-boot)를 운영하고 있습니다. 점차 쿠버네티스 환경으로 변경하려고인프라담당자들과 백엔드 개발자들이 스터디 및 환경 구축하고 있는데요. 만약 실무에서쿠버네티스 환경으로 바뀐다면 개발자들의 로컬 개발 환경은 어떻게 하시는지 궁금합니다.대부분 자바, 스프링 환경이면 인텔리제이등으로 개발 후 테스트를 해볼텐데 컨테이너에서 다른 개발자들과 다 같은 환경에서 테스트를 해보고 빌드해보고 해야 하지 않는가 싶어서요. 실무에선어떤식으로 개발자들이 개발하는지 개발, 테스트 , 운영 배포 까지 플로우가 어떻게 되는지 궁금합니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
RunWith
프로젝트 생성부분의 마지막 강의 수강중이고, 위와 같이 코드를 작성했을 때 다음과 같은 오류가 납니다https://drive.google.com/file/d/1g1uPQj8hZvNmWr3u9NBwMTuI_NOZWSKC/view?usp=sharing프로젝트 파일도 같이 첨부합니다
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
.ifPresent 사용법
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]멤버 삭제 기능을 만들려고 하는데 이렇게 하는게 맞을까요?한개의 멤버만 받아서 삭제하고 싶은데 어떻게 처리해야 할까요? public boolean deleteProduct(String productName){ List<Product> result = em.createQuery("select p from Product p where p.productName = :productName", Product.class) .setParameter("productName", productName) .getResultList(); return true; } getResultList 로 하니까 여러개 나올거 같은데 한개만 삭제하려면 어떻게 해야 하나요? 그리고 em.remove하면 되나요?
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
route 설정이 동작을 안하는거 같아요.
RouteLocator gatewayRoutes(RouteLocatorBuilder builder)이 메소드를 만들기 위해 implementation 'org.springframework.cloud:spring-cloud-starter-gateway' 이걸로 수정했을 했는데 이후 저 메소드를 주석 처리하고 applicatio.yml을로 설정을 대체 했을 때는 동작을 안하고 implementation 'org.springframework.cloud:spring-cloud-starter-gateway-mvc'mvc로 다시 변경해줘야 올바르게 동작하는데무슨 차이가 있을까요?
-
미해결웹소켓/STOMP 채팅서비스(spring, vue, redis)
안녕하세요 리프레시 토큰을 사용하면 대략적으로 어떤 점이 바뀌게 되는건가요??
안녕하세요 강사님. 혹시 Refresh Token 을 사용하면 프론트엔드 코드에서 대략적으로 어떤 점이 바뀌게 되는건가요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
이름에 유니크 제약 조건을 거는 것
[질문 내용]강의에서 회원의 이름으로 중복된 계정을 검증하고, DB에서 회원의 이름을 Unique 제약 조건으로 잡는 게 좋다고 하셨는데이건 이 예제에서의 가정인 거고, 현업에선 이름만으로 중복 계정을 검증하거나, 이름에 유니크 제약 조건을 거는 경우는 거의 없다고 봐도 되나요?
-
미해결개발자에게 필요한 로그 관리
표준출력보다 Slf4J가 느릴 때
저는 컴터 사양이 꽤나 좋아서 인지? 항상 표준출력이 더 빠르더군요.알아보니 로깅 프레임워크가 느린 이유에는 대략 이런 이유들이 있네요.로그 출력에 여러 과정을 거침. Logger → Appender → Encoder → Layout → OutputStream레벨 설정에 의한 필터링로그 포맷팅 처리분명 표준출력이 synchronized에 의해서 멀티 스레드 환경에서 취약한건 맞으나 현재 테스트에서는 그 부분이 로깅 프레임워크의 처리 과정보다는 빨랐던 것 같습니다.테스트 환경 변경그래서 테스트 환경을 바꿔서 테스트 해보았습니다.멀티스레드 환경. 스레드 10개. 각 스레드별 100000번 출력package kr.co.shortenurlservice.log; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @Slf4j public class SoutVsAsyncLoggingTest { private static final int THREAD_COUNT = 10; private static final int LOG_COUNT = 100_000; public static void main(String[] args) throws InterruptedException { // 1. System.out.println() 테스트 long sysoutTime = runTest(i -> System.out.println("[SYSOUT][" + Thread.currentThread().getName() + "] " + i) ); // 2. log.info() (AsyncAppender + Console) 테스트 long asyncLogTime = runTest(i -> log.info("[LOGGER][{}] {}", Thread.currentThread().getName(), i) ); // 결과 출력 Thread.sleep(5000); System.out.printf("System.out: %,d ms%n", sysoutTime); System.out.printf("Async log : %,d ms%n", asyncLogTime); } private static long runTest(StringConsumer task) throws InterruptedException { long start = System.currentTimeMillis(); ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT); CountDownLatch latch = new CountDownLatch(THREAD_COUNT); for (int t = 0; t < THREAD_COUNT; t++) { executor.submit(() -> { for (int i = 0; i < LOG_COUNT; i++) { task.accept(i); } latch.countDown(); }); } latch.await(); executor.shutdown(); long end = System.currentTimeMillis(); return end - start; } @FunctionalInterface interface StringConsumer { void accept(int value); } } 또한 test/resources/logback.xml 설정으로 포맷을 날짜 같은것 제외하고 표준출력과 똑같이 맞춰주고 AsyncAppender를 통해 멀티 스레드 환경에서 차별점이 있도록 비동기 Appender를 추가해줌.<configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <appender name="ASYNC_CONSOLE" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="CONSOLE"/> <queueSize>10240</queueSize> </appender> <root level="info"> <appender-ref ref="ASYNC_CONSOLE"/> </root> </configuration>이렇게 하니까 표준출력보다 빠르더군요.꼭 성능문제뿐 아니라 로그 관리체계 자체가 로깅 프레임워크가 넘사이기 때문에 안쓸 비교불가겠지만..성능적으로 보더라도 실무 환경이라면 메시지 출력 전후로 비즈니스 로직들이 있기 때문에 임계영역을 통해 스레드를 대시시키는 표준출력을 사용하는것보다는 로깅 프레임워크가 더욱 성능적으로 이점이 있을 것 같습니다.
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
댓글 수 구현에서 동시성 문제 해결 질문드립니다
학습 관련 질문을 최대한 상세히 남겨주세요!고민 과정도 같이 나열해주셔도 좋습니다.먼저 유사한 질문이 있었는지 검색해보세요.인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.안녕하세요 댓글 수 구현 강의를 해보다가 동시성 문제를 해결해보고 싶어서 비관적 락 for update를 사용하는 방법으로 한번 코드를 짜보고 테스트를 해보고 있습니다.코드는 아래처럼 짜보았습니다@Table(name = "article_comment_count") @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @ToString public class ArticleCommentCount { @Id private Long articleId; private Long commentCount; public static ArticleCommentCount init(Long articleId, Long commentCount) { ArticleCommentCount articleCommentCount = new ArticleCommentCount(); articleCommentCount.articleId = articleId; articleCommentCount.commentCount = commentCount; return articleCommentCount; } public void increase() { this.commentCount++; } public void decrease() { this.commentCount--; } }public interface ArticleCommentCountRepository extends JpaRepository<ArticleCommentCount, Long> { @Lock(LockModeType.PESSIMISTIC_WRITE) Optional<ArticleCommentCount> findLockedByArticleId(Long articleId); }@Service @RequiredArgsConstructor public class CommentService { private final CommentRepository commentRepository; private final Snowflake snowflake = new Snowflake(); private final ArticleCommentCountRepository articleCommentCountRepository; @Transactional public CommentResponse create(CommentCreateRequest request) { Comment parent = findParent(request); Comment comment = commentRepository.save( Comment.create( snowflake.nextId(), request.getContent(), parent == null ? null : parent.getCommentId(), request.getArticleId(), request.getWriterId() ) ); ArticleCommentCount articleCommentCount = articleCommentCountRepository.findLockedByArticleId(request.getArticleId()) .orElseGet(() -> { ArticleCommentCount newCount = ArticleCommentCount.init(request.getArticleId(), 0L); articleCommentCountRepository.save(newCount); return newCount; }); articleCommentCount.increase(); articleCommentCountRepository.save(articleCommentCount); return CommentResponse.from(comment); } private Comment findParent(CommentCreateRequest request) { Long parentCommentId = request.getParentCommentId(); if (parentCommentId == null) { return null; } return commentRepository.findById(parentCommentId) .filter(not(Comment::getDeleted)) .filter(Comment::isRoot) .orElseThrow(); } public CommentResponse read(Long commentId) { return CommentResponse.from(commentRepository.findById(commentId).orElseThrow()); } @Transactional public void delete(Long commentId) { commentRepository.findById(commentId) .filter(not(Comment::getDeleted)) .ifPresent(comment -> { if (hasChildren(comment)) { comment.delete(); } else { delete(comment); } }); } private boolean hasChildren(Comment comment) { return commentRepository.countBy(comment.getArticleId(), comment.getCommentId(), 2L) == 2; } private void delete(Comment comment) { commentRepository.delete(comment); articleCommentCountRepository.findLockedByArticleId(comment.getArticleId()) .ifPresent(articleCommentCount -> { articleCommentCount.decrease(); articleCommentCountRepository.save(articleCommentCount); }); if(!comment.isRoot()) { commentRepository.findById(comment.getParentCommentId()) .filter(Comment::getDeleted) .filter(not(this::hasChildren)) .ifPresent(this::delete); } } public CommentPageResponse readAll(Long articleId, Long page, Long pageSize) { return CommentPageResponse.of( commentRepository.findAll(articleId, (page - 1) * pageSize, pageSize).stream() .map(CommentResponse::from) .toList(), commentRepository.count(articleId, PageLimitCalculator.calculatePageLimit(page, pageSize, 10L)) ); } // 무한 스크롤 public List<CommentResponse> readAll(Long articleId, Long lastParentCommentId, Long lastCommentId, Long limit) { List<Comment> comments = lastParentCommentId == null || lastCommentId == null ? commentRepository.findAllInfiniteScroll(articleId, limit) : commentRepository.findAllInfiniteScroll(articleId, lastParentCommentId, lastCommentId, limit); return comments.stream() .map(CommentResponse::from) .toList(); } public Long count(Long boardId) { return articleCommentCountRepository.findById(boardId) .map(ArticleCommentCount::getCommentCount) .orElse(0L); } }@Test void concurrencyCountTest() throws InterruptedException { Long articleId = 24L; int threadCount = 10; ExecutorService executorService = Executors.newFixedThreadPool(threadCount); CountDownLatch latch = new CountDownLatch(threadCount); for(int i = 0; i < threadCount; i++) { final Long writerId = (long) (1000 + i); executorService.execute(() -> { try { createComment(new CommentCreateRequest(articleId, "concurrency test", null, writerId)); } catch (Exception e) { System.err.println("Exception in thread: " + Thread.currentThread().getName() + " -> " + e.getMessage()); } finally { latch.countDown(); } }); } latch.await(); Long commentCount = restClient.get() .uri("/v1/comments/articles/{articleId}/count", articleId) .retrieve() .body(Long.class); System.out.println("최종 commentCount = " + commentCount); assertThat(commentCount).isEqualTo(threadCount); }그런데 이렇게 했을때맨 처음 실행을 하면 1개의 데이터만 삽입되고 나머지 9개는 소실이됩니다그리고 한번더 실행하면 11개의 데이터가 저장되는데 맨처음 저장된 1개의 데이터 + 10개의 스레드가 저장한 10개의 데이터가 되어 11개가 됩니다.여기서 문제가 article_comment_count 테이블에 데이터가 아예 없을때 10개의 스레드가 동시에 insert문을 날리려고해서 Duplicate entry '24' for key 'article_comment_count.PRIMARY' 이런 문제가 나오지 않나 생각이 듭니다만.. create 메서드에 @Transactional(isolation = Isolation.READ_COMMITTED)로 격리 수준을 높여봤지만 여전히 문제가 해결되지 않습니다.혹시 제가 잘못 이해한 부분이 있을까요? 그리고 동시성 문제를 해결하려면 어떻게 해야할까요? gpt에 물어보거나 구글링해서 찾아봐도 해결이 되지 않아서 질문드립니다!
-
미해결코드로 배우는 React 19 with 스프링부트 API서버
안녕하세요 조회기능 구현에서 에러가 발생했습니다
vscode를 통해 npm start를 한 후, todo/read/숫자를 입력하니까 404에러가 발생했습니다. 그런데 vscode에서 컨트롤S를 눌렀더니 화면이 떴는데 익스플로러 상에서 새로고침을 하니까 다시 404에러가 발생하는데 이유를 모르겠습니다. 이미지를 첨부할 테니 혹시 더 필요하신 게 있으시면 답변해 주시면 감사드리겠습니다.
-
미해결1시간만에 끝내는 virtual thread in spring boot
ThreadPoolTaskExecutor에서의 가상스레드
안녕하세요! 너무 좋은 무료강의 감사합니다:)강의를 듣는와중에 궁금증이 생겼는데요. log.info("3) Service virtual true: {}", Thread.currentThread().isVirtual());현재 스레드가 가상스레드가 맞는지 확인 하는 위와 같은 코드를 심어 실행해 보았습니다. 컨트롤러의 경우 항상 true를 리턴했고, SimpleAsyncTaskExecutor의 경우에도 true를 리턴했습니다. 그러나 예제코드에서 세팅하신 ThreadPoolTaskExecutor의 설정으로는 false를 리턴하였습니다. 해당 현상을 gpt한테 100% 공식문서 기반으로 설명하라고 하자 ThreadPoolTaskExecutors는 VirtualThread와 상호작용 중이라는 힌트 정보를 붙인 것이다(?) 라는 답변을 하여 이해하기가 힘들었습니다. 일단 threadPoolTaskExecutor.setThreadFactory(Thread.ofVirtual().name("vthread-", 0).factory());와 같은 ThreadPoolTaskExecutors의 세팅을 추가해주니 isVirtual 에대한 true값이 나오긴 했습니다. 제 부족한 견문으로는 이해가 되지 않는 현상이라 강사님이 도움을 주실수 있나해서 문의드립니다 🙂
-
미해결카카오,구글 SNS 로그인(springboot3, vue3)
강의 내용 문의 입니당
안녕하세요수업 들으면서 동시에 코틀린으로 코딩하다보니 중간중간 놓치는 부분이 있어서 코드 제공이 가능할까요?코드 제공 주신 다는 내용은 들었는데 자료에 안보여서 동영상을 여기저기 반복 재생하니 진도가 느려지네요
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
조회수를 RDB에만 저장하고 있는 서비스에서 Redis 도입 관련해서 질문입니다.
안녕하세요. 쿠케님강의 너무나 잘 보고 있습니다. 쿠케님 질의응답 게시글 정독하고 있는데 1:1 멘토링 부럽지 않을만큼의 고퀄리티 답변 언제나 감사드립니다. (갬동갬동) 현재 회사에서 조회수를 RDB에만 저장하고 있습니다.이를 강의 내용처럼 'Redis 이전 & MySql 백업'을 적용 하고 싶은데 아래 흐름대로 적용 하면 될까요?1⃣ (개발) redis 저장 및 조회, mysql 백업 코드 작성2⃣ (개발) 기존 MySQL 데이터를 Redis에 저장하는 마이그레이션 코드 작성=> 이렇게 일회성 마이그레이션 같은 경우 테스트 코드로 한번만 돌리는데 쿠케님은 어떤 방식으로 하시나요?3⃣ (배포 전) 1번 코드 배포 직전에 2번 로직 실행4⃣ (배포) 1번 코드 배포 위 방식에서 발생할 수 있는 문제점1. 3번(마이그레이션)과 4번(배포) 사이에 조회수가 누락될 가능성- 마이그레이션 실행 후 MySQL에는 새로운 조회수가 계속 업데이트되지만, Redis는 아직 트래픽을 받지 않음.- 즉, 마이그레이션 실행 이후 MySQL에 새로 기록된 조회수는 Redis에 반영되지 않음 → 데이터 불일치 발생 가능.2. 처음 Redis로 전환할 때, Redis에 캐싱되지 않은 일부 조회수가 MySQL에 계속 쿼리될 가능성이 있음.- 처음 Redis로 전환할 때, Redis에 캐싱되지 않은 일부 조회수가 MySQL에 계속 쿼리될 가능성이 있음.- 특정 조회수가 빠르게 증가하면 Hot Key 이슈 발생 가능. 조회수 누락을 최소화 하는 방법1⃣ (개발) redis 저장 및 조회, mysql 백업 코드 작성2⃣ (개발) 기존 MySQL 데이터를 Redis에 저장하는 마이그레이션 코드 작성 및 실행3⃣ (1번 코드 배포 전) 더블 라이트(Double Write) 모드 개발하여 운영에 적용4⃣ (배포) 기존 MySQL 기반 조회수 코드 제거, Redis 기반으로 전환5⃣ (배포 후) MySQL 백업 로직 실행 및 기존 MySQL 조회 로직 완전히 제거제가 혹여나 놓친게 있거나 더 좋은 방법이 있으면 천천히 답변 부탁드립니닷! 출처: 내 뇌 + GPT 센세
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
Springdatamemberrepository
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요혹시 강사님 코드를 복붙해도 이상태인데 왜 이러는걸까요ㅠㅠ 저 springdpa말고는 다 작동 되었습니다!.
-
미해결Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
FeignErrorDecoder 질문
FeignErrorDecoder 에 대해서order_is_empty를 수정한뒤에127.0.0.1:8000/actuator/busrefresh 를 호출하면Keys refreshed [spring.cloud.bootstrap.enabled, order_service.exception.order_is_empty]로그는 정상적으로 뜨며디버깅 모드로 코드를 추가해서 실행한결과List<ResponseOrder> orders= orderServiceClient.getOrders(userId);코드전에env.getProperty("order_service.exception.order_is_empty") 를 확인해본 결과는정상적으로 리프레시되지만 이후에 오류를 터트리고 FeignErrorDecoder 처리 로직에서switch(response.status()){ case 400: break; case 404: if(methodKey.contains("getOrders")){ return new ResponseStatusException(HttpStatus.valueOf(response.status()),env.getProperty("order_service.exception.order_is_empty")); } break; default: return new Exception(response.reason()); }getProperty("order_service.exception.order_is_empty")이부분이 새로운 환경 변수가ErrorDecoder 에서는 반영 안되는것같아서 해결이 안되서 질문남깁니다 ! UserServiceImpl 에서는 정상적으로 바뀐값이 나오는거보면 ErrorDecoder 문제 같은데 정확히 모르겠습니다 @RefreshScope 이것도 해결책은 아닌것같아요 답변 부탁드립니다 !
-
미해결코드로 배우는 React 19 with 스프링부트 API서버
조회기능 구현 강의에서 에러가 발생했습니다
ReadComponent.js 파일을 만들고 ReadPage의 리턴 내용에 ReadComponent의 tno 값을 추가한 후에 npm start를 실행했는데 아래와 같은 에러가 발생했습니다. [eslint] src\components\menus\todo\ReadComponent.jsLine 13:29: 'useState' is not defined no-undefLine 16:9: 'getOne' is not defined no-undefSearch for the keywords to learn more about each error. ReadComponent.js의 useState와 getOne 로직 부분이 잘못 된 거 같아서 강의 영상을 다시 봤는데 틀린 부분이 없어 보여 어떤 게 문젠지 질문을 드리고 싶습니다.참고용으로 ReadComponent.js의 내용을 추가해놓겠습니다. import React, { useEffect } from 'react'; const initState = { tno:0, title:'', writer:'', dueDate: '', complete: false } function ReadComponent({tno}) { const [todo, setTodo] = useState(initState) useEffect(() => { getOne(tno).then(data => { console.log(data) setTodo(data) }) }, [tno]); return ( <div> </div> ); } export default ReadComponent;덧붙여서 툴은 vscode를 쓰고 있습니다. 잘 부탁드리겠습니다.
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
id관련
안녕하세요. 강의 잘 듣고 있습니다.제가 원래 질문이 많은데 개념을 이해가 잘 되도록 쉽게 설명해 주셔서 질문 드릴게 별로 없네요. 보통 api path에 id를 추가하시는거 같은데요.현업에서도 auto_increment나, snowflake id같은 db에서 쓰는 id를 그대로 넣고 사용하시나요?아니면 prefix등을 추가하여 조금 더 가공을 한다든지 하시나요?숫자만 들어가니 좀 밋밋해 보이기도 하고 알아보기도 힘들거 같기도 해서요.
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
csrf 토큰 생성 시점 및 방식에 대하여
강의 내용 중에 POST 와 같이 데이터를 변경하는 요청의 경우 csrf 토큰을 생성한다는 내용이 있는데 로그인 페이지 요청시 GET 으로 요청하는데 csrf 토큰이 input 태그에 포함되어 있는 걸로 보아 POST 와 같이 데이터틀 변경하는 요청의 경우 csrf 토큰을 생성하는 게 아니라 csrf 토큰을 검증하는 것이고, csrf 토큰은 모든 요청에 대해 반환해준다가 맞을까요? 또 csrf 토큰이 난수를 조합해 계속 변경해서 클라이언트에 반환한다고 들었는데제가 잘못 본 건지 모르겠지만 토큰을 디코딩할 때난수를 조합하는 코드를 보면 토큰의 길이로 난수를 만드는 것 같은데,토큰의 길이로 난수를 만든다고 하면토큰을 변하게 하지 않는 이상 인코딩된 토큰의 결과가 똑같을 것 같거든요. 그래서 세션당 고유 토큰 값은 똑같다고 한다면로그인 전에는 클라이언트에 반환하는 토큰이계속 바뀌고 (=익명 사용자 세션이니)로그인 이후에는 클라이언트에 반환하는 토큰이 일정한 게 아닐까 하는 물음이 생겼습니다.어느게 맞는 걸까요 ?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
오라클 사용시 GeneratedValue Strategy 지정방법..
안녕하세요오라클과 jpa를 사용중인데요..엔터티에서 id 지정할 때 .generatedValue.identity 옵션이 적용이 불가합니다그래서 auto나 다른 옵션으로 주면 테이블의 아이디값이 무작위로 나오는거 같은데요mysql처럼 1부터 순서대로 나오게 하고 싶으면 어떻게 해야 할까요?.. 아시는 분은 답변 주시면 감사하겠습니다
-
미해결RabbitMQ를 이용한 비동기 아키텍처 한방에 해결하기
스탭4 질문드립니다
안녕하세요, 스탭4 news 스크립트 코드가 궁금해 질문드립니다.우선 영상처럼 curl -X POST "http://localhost:8080/news/api/publish?newsType=ja"curl -X POST "http://localhost:8080/news/api/publish?newsType=sp"curl -X POST "http://localhost:8080/news/api/publish?newsType=vu"컬로 3번 찌르면 아래 사진과 같이 응답값이 찍히는데요스크립트 부분에서 connect 함수 실행시 현재 선택한 const newsType = document.getElementById("newsType").value; (java선택)값이 java이라subscribeToNews(newsType);이부분에 subscription = stompClient.subscribe(/topic/java, function (message) { alert(message.body); addMessageToDiv(message.body); }); 이렇게 /topic/java만 subscribe 할텐데 어떻게 spring , vue가 나왔는지 궁금합니다.curl 요청 -> restController -> publisher 에서 publishMessage 메서드를 통해 fanout으로 bindingBuilder가 설정된 큐에 send -> 클라이언트(html)에서 stomp를 이용해 구독 로직인것같은데클라이언트(html)에서 /topic/java만 구독한상태에서 다른 vue, spring을 받은지 궁금합니다
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
전부 단방향으로 구현해도 괜찮을까요?
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]야생형 로드맵 따라서 현재 활용 1편을 듣고 있습니다. 지금 팀 프로젝트 중이고 기본 편의 이론은 제대로 배우지 못했어서 이론을 정확히 알진 않습니다. 그런데 연관 관계 매핑할 때 전부 단방향으로 구현하는 것도 가능할까요? 양방향으로 구현하게 되면 연관 관계 메서드 만들 때 setter나 Builder 등을 쓰게 될 거 같은데, 단방향으로 구현하게 되면 그런 걸 신경 쓰지 않아도 될 것 같다는 생각이 듭니다. 물론 장단점이 있겠지만, 전부 단방향으로 구현해도 큰 상관이 없다면 일단 전부 단방향으로 구현해 보고, 나중에 양방향에 대해 제대로 공부하고 그때부터 단방향, 양방향을 고민해 볼까 하는데.. 단방향으로만 구현하는 게 문제가 될 수 있을까요?