간단한 영화 목록 조회입니다. 총 약 10000개의 데이터가 있습니다. redis를 적용하고 조회성능이 좋아진것은 맞지만 이상하게 redis를 적용하기 전에도 같은 조회를 계속해도 조회속도가 똑같이 빨라지는 현상을 겪고있습니다. 현재 이 movie는 MSA 의 여러 서비스 중 하나입니다. 혹시 MSA 아키텍쳐 자체가 문제가 될 수도 있나요? @Cacheable(cacheNames = "getMovies", key = "'movie:all'", cacheManager = "movieCacheManager") public List<Movie> getAllMovies() { return movieRepository.findAll(); } @GetMapping("/movies") public ResponseEntity<List<MovieDto>> getAllMovies() { List<Movie> allMovies = movieService.getAllMovies(); List<MovieDto> dtos = new ArrayList<>(); for (Movie movie : allMovies) { dtos.add(new ModelMapper().map(movie, MovieDto.class)); } return ResponseEntity.status(HttpStatus.OK).body(dtos); } @Configuration @EnableCaching // Spring Boot의 캐싱 설정을 활성화 public class RedisCacheConfig { @Bean public CacheManager movieCacheManager(RedisConnectionFactory redisConnectionFactory) { RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration .defaultCacheConfig() // Redis에 Key를 저장할 때 String으로 직렬화(변환)해서 저장 .serializeKeysWith( RedisSerializationContext.SerializationPair.fromSerializer( new StringRedisSerializer())) // Redis에 Value를 저장할 때 Json으로 직렬화(변환)해서 저장 .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( new GenericJackson2JsonRedisSerializer() ) ) // 데이터의 만료기간(TTL) 설정(1분) .entryTtl(Duration.ofMinutes(1L)); return RedisCacheManager .RedisCacheManagerBuilder .fromConnectionFactory(redisConnectionFactory) .cacheDefaults(redisCacheConfiguration) .build(); } } @Configuration public class RedisConfig { @Value("${spring.data.redis.host}") private String host; @Value("${spring.data.redis.port}") private int port; @Bean public LettuceConnectionFactory redisConnectionFactory() { return new LettuceConnectionFactory(new RedisStandaloneConfiguration(host, port)); } }
안녕하세요. TransactionMessage 부분에서 time을 기본값 LocalDateTime.now() 로 설정하실 때 val -> var로 변경하시는 것을 봤습니다. 실무에서 코틀린에서 기본값을 선언할때 관례적으로 var로 하는지 궁금합니다. (코틀린으로 서버를 개발해본적이 없어서 기초적인 질문 드려서 죄송합니다..) 감사합니다.
안녕하세요. KafkaProducer future.whenComplete에서 throw 하는 코드를 보고 질문 드립니다. 코드를 보니까 CompletableFuture로 구현되어 있던데 transactional.run 안에서 예외를 잡을 수가 있는지 궁금합니다. 코드만 보기로는 whenComplete가 비동기로 동작해서 저기서 예외를 던진다고 누가 받는지 잘 모르겠습니다. 제가 스프링 비동기를 구현해보지 않아서 질문드립니다. 감사합니다.
안녕하세요. 궁금한 점이 있어 질문드립니다. 코드를 보면 @Component private class Advice: Runner ... 이렇게 내부 클래스가 Private으로 되어 있는데 private으로 선언된 클래스도 component scan 대상이 되나요? 만약 1번에서 안된다면 인자로 받은 Runner가 프록시 빈으로 생성이 안될 것 같은데, 그렇다면 프록시가 제대로 동작하는게 맞는지 궁금합니다. private val advice : Runner = Advice() 코드를 보면 만약 빈으로 생성된 인자를 넣지 않는다면 기본 Advice() 를 생성해서 넣는다고 보이는데 이렇게 된다면 Advice 프록시가 자동으로 생성되지 않는다고 생각되고 그렇다면 aop가 작동되지 않을것 같은데 맞는지 궁금합니다.(그래서 기본값을 넣지 않는게 맞지 않나 궁금합니다.) 감사합니다.
학습 관련 질문을 최대한 상세히 남겨주세요! 고민 과정도 같이 나열해주셔도 좋습니다. 먼저 유사한 질문이 있었는지 검색해보세요. 안녕하세요? 강의 계속 잘 듣고 잇습니다. 이제거의 막바지에 이르렀네요 ㅎㅎ.. 게시글 목록조회 최적화와 관련하여 질문드리고자 합니다. 제가 처음에 이해한 바는 최신의 천개의 데이터를 레디스에 적재하고, 그 외의 데이터는 직접 articleServcie를 통해 가져오자 라고 이해를 했었습니다.(hot, cold Data) 그런데 이후의 결과적으로는 아래 두가지 캐시가 존재하게 되었더라구요 1.zset을 활용한 인기글 데이터 관리(목록 조회 최적화) 2.실제 데이터 queryModel(단건 조회 최적화) 이런 구조에서는 zset에서 천개의 데이터를 관리하긴 하지만 실제로 queryModel에는 데이터가 있을지 없을지 확신을 할 수 없는 상황이라는 생각이 듭니다. 즉 실제로 zset에 있는 데이터라 해도 하루가 지났다면 queryModel이 있을지 없을지 모르는 상황이라고 인지했습니다. 질문1) 제가 이해한바가 맞을까요? 맞다면 이 구조를 선택하신 이유가 조금 궁급합니다. 두 캐시를 합쳐서, queryModel자체를 하나의 캐시에서 천개의 데이터만 관리하면 되지않나? 라는 의문이 생겨가지구요 어차피 천개의 데이터만 관리한다면 메모리를 그렇게 크게 차지 하지 않을 것 같기도 하구요 질문2) 지금과 같은 구조에서는 zset을 활용한 article_id가 그렇게 큰 의미가 있는 부분인가? 라는 생각이 듭니다. - 어차피 최신순(1000개이하)의 데이터에 대해서 id를 추출하는거면 DB에서 offset을 세어도 그렇게 안느린 거 아닌가? 하는 생각이 들구요 - zset에 포함되어 있더라도, 실제 데이터(QueryModel)가 있는지 없는지 확답을 할 수 없는 상황이니 큰 의미가 있는건가? 하는 의문이듭니다. 차라리 최신 천개의 데이터에 대해서는 조회에 필요한 모든 데이터를 캐싱해둔다면 큰 의미가 있을거라고 생각이 드는데, 지금의 경우에 대해서는 잘 모르겠네요 ㅠㅠ -결론적으로, 현재 회사에서 RDB를 주로 쓰고 있는 주니어 개발자 입장에서 관련해서 레디스를 도입해본다면.. 아키텍처 복잡도가 올라가는 부분에 비해 엄청 크게 이득이 되는 부분이 있나?? 라는 생각이 많이 들었습니다. 질문3)추가로, 이거는 좀 다른 부분이긴 한데 read-service에서 like, unlike등 업데이트 이벤트 핸들러의 경우 동시요청에 대해서 lostupdate처럼 동작하는 부분이 있을 것 같은데 이부분은 배제하신건지, 혹은 제가 잘못생각하고 있는건지 궁금합니다. 양질의 강의 정말 감사드립니다
학습 관련 질문을 최대한 상세히 남겨주세요! 고민 과정도 같이 나열해주셔도 좋습니다. 먼저 유사한 질문이 있었는지 검색해보세요. 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. AssignedShard 클래스의 목적이 샤드를 균등하게 분배하는 것이라고 보이는데요 저는 처음에 스레드가 처리할 일을 분할해주는 거라고 생각했는데 찾아보니까 앱 인스턴스를 기준으로 샤드를 나누는 것이라고 하더라고요. 근데 앱 인스턴스는 말하자면 각각의 서버? 예를 들어서 포트 9000번을 A,B,C 서버에서 실행하면 그 각각을 앱 인스턴스라고 부른다고 봤습니다. 그리고 이렇게 각각 다른 서버에서 하나의 포트를 실행하려면 운영 환경에서 서버의 부담이 커질때 서버를 늘려주는 로드밸런싱?같은 기법을 쓸때 필요한 샤드 분배 기능같은데 나중에 운영환경에서 이런때를 대비해서 미리 구현하신건가요? 아니면 이런 지금 강의 환경 안에서도 이렇게 앱 인스턴스가 늘어나는? 상황이 있는건가요.. 아직 공부중이고 모르는 부분도 좀 있다보니 설명이 두서없었습니다 ㅠ
안녕하세요. 토큰 관련해서 레디스에 저장하는 게 리프레시 토큰이라고 하셨는데요. 액세스 토큰을 저장 안 하는 건지 궁금합니다. 리프레시 토큰은 액세스 토큰이 만료될 떄 필요하니까 상대적으로 사용 빈도가 낮고 매 요청 시에는 액세스 토큰이 쓰이는 걸로 알고 있어서요. 그렇다면 수시로 검증해야 하는 토큰은 액세스 토큰이 아닐까 해서요. 감사합니다.
안녕하세요 강사님, 좋아요 기능을 만드는 api를 반복하여 보고 있는데 궁금한 점이 생겨서 질문 드립니다. 좋아요 기능을 만들고 테스트중인데 좋아요가 중복처리 예를 들어, 10번 게시글에 15번의 사용자가 좋아요가 두 개를 눌러도 두 번 다 좋아요가 눌리는 상황인데 이에 대한 중복처리는 따로 해줘야 하는 것인가요?
1. 현재 학습 진도 몇 챕터/몇 강을 수강 중이신가요? 2-4 여기까지 이해하신 내용은 무엇인가요? 2. 어려움을 겪는 부분 어느 부분에서 막히셨나요? 코드의 어떤 로직이 이해가 안 되시나요? 어떤 개념이 헷갈리시나요? apllication.yml 파일에서 url 부분에 localhost로 적용하면 도커 컨테이너끼리 통신이 안되는 것으로 알고 있는데 문제 없이 작동하는 이유가 뭔가요?? 혹시 제가 잘못 알고 있는 것이면 말씀해주시면 감사하겠습니다. ㅎㅎ 3. 시도해보신 내용 문제 해결을 위해 어떤 시도를 해보셨나요? 에러가 발생했다면 어떤 에러인가요? 현재 작성하신 코드를 공유해주세요 이렇게 구체적으로 알려주시면, 더 정확하고 도움이 되는 답변을 드릴 수 있습니다!
1. 현재 학습 진도 몇 챕터/몇 강을 수강 중이신가요? 2-3강 여기까지 이해하신 내용은 무엇인가요? 워크플로우에 사용될 환경변수를 입력하는 중이다. 2. 어려움을 겪는 부분 어느 부분에서 막히셨나요? AWS_SECRET_ACCESS_KEY의 secret 값이 무엇인지 강의에는 안 나와 있습니다. 코드의 어떤 로직이 이해가 안 되시나요? 어떤 개념이 헷갈리시나요? 3. 시도해보신 내용 문제 해결을 위해 어떤 시도를 해보셨나요? 일단 dingco-terraform-user 사용자의 액세스 키를 입력했습니다. 이전의 AWS_ACCESS_KEY와 동일하게요. 에러가 발생했다면 어떤 에러인가요? 현재 작성하신 코드를 공유해주세요 이렇게 구체적으로 알려주시면, 더 정확하고 도움이 되는 답변을 드릴 수 있습니다! AWS_SECRET_ACCESS의 Secret 값을 입력하지 않으면 Repository secrets를 추가할 수 없는데 이 값으로 AWS_ACCESS_KEY에 입력했던 액세스 키를 동일하게 입력해주는 게 맞나요? 아니면 다른 값을 입력해야 하나요?
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.5.3.jar:3.5.3] Caused by: org.springframework.data.redis.listener.adapter.RedisListenerExecutionFailedException: org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis at org.springframework.data.redis.listener.RedisMessageListenerContainer.lazyListen(RedisMessageListenerContainer.java:383) ~[spring-data-redis-3.5.1.jar:3.5.1] at org.springframework.data.redis.listener.RedisMessageListenerContainer.start(RedisMessageListenerContainer.java:361) ~[spring-data-redis-3.5.1.jar:3.5.1] at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:405) ~[spring-context-6.2.8.jar:6.2.8] ... 19 common frames omitted Caused by: org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1858) ~[spring-data-redis-3.5.1.jar:3.5.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1789) ~[spring-data-redis-3.5.1.jar:3.5.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceC Redis 에러 (백엔드 에러는 이렇게 뜨고) 프론트 엔드 (로그인 하고 들어가는 거 잘됩니다. 채팅만 치면 저렇게 뜹니다.) EC2에서 redis 접속은 잘 됩니다. 프론트는 S3+cloudfront (도메인 적용 안함) 백엔드는 Redis(Elastic) + EC2+RDS +nginx 로 배포했고 몇시간 쨰 하는데 저 에러가 뜹니다. 혹시 프론트 배포가 잘 못 된건가요? 강사님 도와주세여ㅠㅠㅠ
Caused by: org.springframework.data.redis.listener.adapter.RedisListenerExecutionFailedException: org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis at org.springframework.data.redis.listener.RedisMessageListenerContainer.lazyListen(RedisMessageListenerContainer.java:383) ~[spring-data-redis-3.5.1.jar:3.5.1] at org.springframework.data.redis.listener.RedisMessageListenerContainer.start(RedisMessageListenerContainer.java:361) ~[spring-data-redis-3.5.1.jar:3.5.1] at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:405) ~[spring-context-6.2.8.jar:6.2.8] ... 19 common frames omitted Caused by: org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1858) ~[spring-data-redis-3.5.1.jar:3.5.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1789) ~[spring-data-redis-3.5.1.jar:3.5.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1586) ~[spring-data-redis-3.5.1.jar:3.5.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.lambda$getConnection$0(LettuceConnectionFactory.java:1566) ~[spring-data-redis-3.5.1.jar:3.5.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.doInLock(LettuceConnectionFactory.java:1527) ~[spring-data-redis-3.5.1.jar:3.5.1] 위에꺼는 백엔드 서버 에러이고 밑에는 프론트엔드 서버 에러입니다. 안녕하세요 강사님 채팅 서버와 프론트를 배포를 해서 Elastic Cache를 이용을 하고 있는데 EC2 랑 연결이 잘 되어 있으면서도 이런 에러가 뜹니다. 아무리 찾아봐도 더 해결사항이 보이지 않아 질문드립니다.
안녕하세요. 좋아요가 없는 경우 팩토리 메소드로 좋아요 객체를 생성하고 영속시키는 부분은 이해가 되었습니다. 그런데 비관적 락의 select for update 를 할 때 데이터가 없으면 row 도 없으니까 락이 안잡히지 않나요? row가 존재해야만 락이 생성되는게 아닌지 궁금합니다. 그리고 이 경우 신규 데이터를 생성할때 0으로 초기화 하고 1을 증가시켜 저장할 때 여러 요청이 있게 되면 다시 경쟁 상태에 놓이게 되는게 아닌가요?
안녕하세요 강사님, 강의 정말 잘 듣고 있습니다! 기존에는 항상 커버링 인덱스를 활용하셨었는데, comment_v2 인피니트 스크롤에서는 서브쿼리를 빼고 바로 전체 데이터를 조회하시더라구요. 혹시 특별한 이유가 있을까요? 커버링 인덱스를 일부러 포기한 구조인지, 아니면 path 기반 설계에서는 서브쿼리 자체가 필요 없어졌기 때문인지 궁금합니다.
안녕하세요~ 어뷰징 방지에 대한 질문을 드리고 싶습니다. 현재, 어뷰징 방지를 위해 분산락을 잡고 해당 유저가 특정 게시물에 대한 조회수를 10분 동안 1만 올릴 수 있도록 설계해주셨는데요. 레디스의 키-벨류 로도 충분히 위와 같은 어뷰징 방지를 설계할 수 있지 않나요? SETNX (key=유저+게시글, value=1, TTL=10분) 만약 이 값이 이미 존재한다면 조회수를 올리지 않는 방식으로 구현해도 충분할 거 같은데, 분산락으로 이 로직을 구현하신 이유가 궁금합니다. 감사합니다!
depth가 3이상인 댓글을 삭제했을 때 부모의 부모까지 삭제가 이루어져야 하는 경우가 있지 않나요? <삭제된 댓글> ---- depth 1 ㄴ <삭제된 댓글> ---- depth 2 ㄴ <삭제되지 않은 댓글> ---- depth 3 위 구조에서 depth 3의 댓글이 삭제되면 depth 1의 댓글도 삭제되어야 하지 않나요? 현재 delete 함수의 로직은 그렇게 작성되지 않은 것으로 이해했는데, 제가 이해한게 맞는지 궁금합니다. 감사합니다!
학습 관련 질문을 최대한 상세히 남겨주세요! 고민 과정도 같이 나열해주셔도 좋습니다. 먼저 유사한 질문이 있었는지 검색해보세요. 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 강의에서 만든 count 함수의 count 개념은 전체 게시글 수인 total count의 개념이 아니라 페이지의 번호를 위한 count인거죠?
@Test create 메소드 실행시 500에러 발생하였습니다. (게시판에 올라와잇는 해결방법은 다 해봤는데 해결되지 않았습니다.) 강사님 소스코드 다운받고 돌려도 동일하게 발생합니다.. org.springframework.web.client.HttpServerErrorException$InternalServerError: 500 Internal Server Error: "{"timestamp":"2025-07-15T14:25:26.527+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.ArticleApiTest.create(ArticleApiTest.java:27) at kuke.board.article.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)