묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
사용된 어노테이션에 관한 질문
5:12분경 createdAt에서 @CreatedDate를 제외한 나머지 어노테이션들을 특별히 사용하신 이유가 있으실까요?
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
Redis 사용 방식에 대해서 질문 있습니다
안녕하세요 레디스를 공부하면서 궁금한게 있습니다.제가 토이프로젝트를 하면서 상품 검색 입력시 버튼 하나씩 누를때마다(이벤트 keyup 사용) 백엔드와 통신하여 입력창 하단에 자동완성 기능창을 만들려고 하고 있습니다.아무래도 버튼 하나씩 누를때마다 통신해야되니 빠르게 통신해야될 것 같아서 redis를 사용했습니다.상품 등록할 때 DB와 redis에 저장하고 (redis에는 상품 이름만 저장했습니다.)입력창 하단의 자동완성은 redis를 통해 상품 이름을 출력하고 출력된 상품이름을 선택시 DB를 통해서 상품 상세정보를 가져오는 식으로 했는데배운대로라면 Cache Aside 전략과 다른데 이럴때는 어떻게 구성해야되나요?아니면 SQL 튜닝만 잘해도 굳이 redis는 필요없는건지 궁금합니다.아무래도 버튼 누를때마다 통신하다보니 SQL은 느릴까봐 싶어 조바심이 나네요ㅠㅠ 알아보니 최근검색어나 인기검색어 같은 경우도 redis로 한다고하는데 이런것들도 굳이 출력하자면 DB로만 사용하여 출력이 될텐데 이게 Cache Aside 전략과 어떤 관계가 있는지 감이 안잡힙니다실무뛰면서 redis를 써본적이 없고 거의 db로만 해결하다보니 redis 사용예시를 잘 모르겠습니다
-
미해결레디스의 모든 것 (feat. Node.js)
systemctl restart redis-study 문제
[root@localhost system]# systemctl restart redis-studyJob for redis-study.service failed because a timeout was exceeded.See "systemctl status redis-study.service" and "journalctl -xeu redis-study.service" for details.systemctl restart redis-study를 실행하면 위와 같은 오류가 뜹니다. 이후 enable 도 안되어서 이 부분에서 걸려있는데, 로그를 확인해봐도 timeout때문에 실패했다는 문구만 뜹니다. 혹시 문제가 어디서 발생했을까요...? [메모리 테스트: redis-server --test-memory 2]Your memory passed this test.Please if you are still in doubt use the following two tools:1) memtest86: http://www.memtest86.com/2) memtester: http://pyropus.ca/software/memtester/ [conf 파일 체크: redis-server /redis/redis-stable/redis.conf --check-config] *** FATAL CONFIG FILE ERROR (Redis 7.4.1) ***Reading the configuration file, at line 2328>>> 'check-config'Bad directive or wrong number of arguments이걸 확인해보면 conf파일 문제인 것 같은데, 강의에서 conf 파일을 건드리는 부분이 없었던 걸로 기억합니다.
-
해결됨비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
aws elasticcache redis 툴 접속.
안녕하세요. 강의 잘 들었습니다.강의를 듣다보니 의문이 드는 점이 있어 질문드립니다.redis를 사용하다 보면 redisinsight같은 gui 툴을 통해 데이터를 확인하는데 운영관점에서 더 편한데요.aws elasticcache redis가 외부 로컬에서 접속이 안되면aws elasticcache는 데이터 확인을 툴로 못하는건가요? 실무에서 운영을 하다보면 분명 직접 데이터를 체크를 해야하는 케이스가 발생하는데 이걸 일일이 cli 명령어 찾는다는 것은 돈을 주고 aws 사용하는 고객입장에서는 너무 불편하다고 생각들어 문의드립니다.
-
해결됨대기업 근무하며 경험한 Redis를 야무지게 사용하는 방법 [이론편]
Redis SSD
안녕하세요 이미 커뮤니티에 올라온 글인데 제대로 이해를 못한 것 같아서요.redis를 사용할 때 기본적으로 메모리를 이용해 캐싱을 하고, AOF나 스냅샷을 저장하기 위한 용도로 SSD를 사용한다고 이해한 것이 맞을까요..? 강의 잘 듣고 있습니다 :) https://www.inflearn.com/community/questions/1400475/redis%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-%EC%A7%88%EB%AC%B8%EC%82%AC%ED%95%AD
-
해결됨대기업 근무하며 경험한 Redis를 야무지게 사용하는 방법 [이론편]
Redis Collection BitMaps
안녕하세요 강의를 듣다가 잘 이해가 안가는 부분이 있어서 질문드립니다.비트맵을 사용할 때, 사용자 수가 100만명인데 실제 사용자 수는 100명인 경우 메모리 낭비가 발생한다는 부분은 이해했습니다.이를 위해 구분자가 있는 데이터를 지정하고 활용하는 것이 좋다고 말씀하셨는데 구분자가 있는 데이터가 어떤 것인지 제대로 이해가 안 가서 질문드립니다.. 섹션3 - BitMaps Collectionshttps://www.inflearn.com/course/redis-%EC%95%BC%EB%AC%B4%EC%A7%80%EA%B2%8C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-%EC%9D%B4%EB%A1%A0%ED%8E%B8/unit/244780
-
미해결실습으로 배우는 선착순 이벤트 시스템
ApplyService 의 총 처리 시간이 궁금합니다.
Redis 로 문제점 해결하기 강의 7분 쯤에 나오는 설명으로, redis 는 싱글스레드 기반으로 동작하기 때문에 Thread 1 에서 10:00 에서 10:02 동안 incr coupon_count 메서드가 동작한다고 했을 때 10:02분에 끝나고나서 thread 2의 incr coupon_count 가 동작한다고 말씀하셨는데요 이는 딱 redis 가 싱글스레드로 동작하는 시간 만큼만이 lock 이 걸린 시간이라고 보면 될까요? 예컨데 ApplyService 의 apply 가 싱글 스레드, 단일 요청에 딱 2분이 걸리는 메서드라고 가정하고 그 안에 있는 couponCountRepository.increment() 가 1초가 걸린다고 가정하면 100개의 요청이 동시에 들어온 경우, 전체 요청이 모두 처리되는 시간이 2분 + 1*100초 = 3분 40초가 걸린다고 계산하는게 맞는거죠? 2분*100이 아니라요
-
해결됨대기업 근무하며 경험한 Redis를 야무지게 사용하는 방법 [이론편]
수업이랑 살짝 관계없는데 신경써주시면 좋을점입니다.
아키텍처 관련 설명하실때 듀퐁 라이터(?) 같은걸 열고 닫는 소리가 주기적으로나는데 생각보다 신경쓰여서요 다른 강의 예정이 있으시다면 영상 찍고나서 주변소음 관련해서 신경써주세요
-
해결됨실전! Redis 활용
장바구니 구현 관련
강의를 들으며 공부하다 궁금한 점이 생겨 질문 드립니다.초반 부분에서 Redis는 RAM에 데이터를 저장한다고 말씀해주셨습니다.그리고 장바구니 구현 설명에서 set을 활용하여 쉽게 구현하는 방법을 설명해주셨는데장바구니라는 것이 담기만 하고 실제 구매로 이어지지 않을 수 있어 데이터를 계속 가지고 있어야 할 필요가 있는 반영구적인 기능이라 생각하는데, TTL 설정을 따로 하지 않는 식으로 구현하면 될지 궁금합니다.또한, 사용자가 늘어나면 늘어날수록 Redis, 즉 RAM에 저장되는 데이터 또한 늘어날 것이라 생각하는데 이와 관련하여 발생할 수 있는 메모리 문제 같은 것은 없는지 궁금합니다.
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
Redis를 사용하는 이유
캐싱을 위해 Redis를 많이 사용한다고 생각하고 있었는데 SQL튜닝으로 해결되는 부분이 있는거군요! 그러면 일반적으로 현업에서 Redis를 사용하는 이유 중 어떤 이유로 가장 많이 사용하는지 여쭤볼 수 있을까요??
-
미해결실습으로 배우는 선착순 이벤트 시스템
쿠폰 생성 에러 처리에 관해서 질문이 있습니다.
안녕하세요 강사님 강의 잘 봤습니다.덕분에 kafka와 redis를 어떤식으로 사용할 수 있는지 많은 걸 엿볼 수 있는 느낌이었습니다.강의가 다 진행되고 난 후 궁금한 점이 하나 있습니다. 쿠폰 생성 에러 처리 관련되어서 질문이 있는데, 만약 메시지를 수신하는 쪽이 아니라 발송하는 쪽에서 문제가 생겼다면 어떻게 해야하나요? 예를들어 redis에서 increment로 수량에 대해서 가져왔지만, 만약 kafka에 메시지를 보내는 것이 실패 될 경우reids에 있는 값을 다시 하나 줄여야할 것 같습니다. 이런 경우 try catch 블럭으로 처리를 하는 지? 아니면 다른 방식으로 예외처리 하는지 궁금합니다.
-
미해결실습으로 배우는 선착순 이벤트 시스템
마지막에 하신 테스트 자체는 실패하는 게 맞는거죠??
Producer 에는 제대로 값이 찍히는데하지만 테스트 자체는 실패했는데요아마 mysql과 연결이 되지 않아서 생긴 오류라고 봐도 될까요?? 아직 뒷 강의는 진행하지 않았습니다!!
-
미해결AWS 배포 완벽가이드 (feat. Lightsail, Docker, ECS)
WSL에 설치한 Redis에 연결이 안 됩니다.
import express from "express"; import * as redis from "redis"; const PORT = 4000; const createApp = async () => { const app = express(); const client = redis.createClient({ url: "redis://localhost:6379" }); await client.connect(); app.use(express.json()); app.get("/", (req, res) => { res.status(200).send("hello from express"); }); return app; }; createApp().then((app) => { app.listen(PORT, () => { console.log(`App listening at port ${PORT}`); }); });Error: connect ECONNREFUSED 127.0.0.1:6379 [1] at createConnectionError (node:net:1647:14) [1] at afterConnectMultiple (node:net:1677:16) { [1] errno: -4078, [1] code: 'ECONNREFUSED', [1] syscall: 'connect', [1] address: '127.0.0.1', [1] port: 6379 [1] }WSL의 bind를 0.0.0.0으로 바꿔봄방화벽에서 6379 포트 허용함WSL의 ip를 localhost 대신에 넣어서 접속 시도이렇게 했는데 실행하면 계속 연결할 수 없다는 에러가 발생합니다. 혹시 해결 방법을 알 수 있을까요?
-
해결됨실습으로 배우는 선착순 이벤트 시스템
안녕하세요 질문 있습니다!
현재 카프카로 데이터를 보내기전에 redis를 사용하여 발급된 쿠폰 개수에 대한 동시성 처리를 해서 개수에 대한 검증 로직이 있다고 앞서 강의에서 얘기를 하셨습니다. 그러면 발급된 쿠폰 개수가 100개 되고 난 이후의 요청은 그냥 무시하면 되나요?쿠폰이 천개, 만개 이렇게 매우 많다면 쿠폰 발급에 대한 요청을 바로 DB에 저장을 하면 DB에 부하가 심해져서 카프카를 도입해 이러한 부하를 낮춘다고 이해를 했습니다. 궁금한 점은 DB에 대한 부하를 낮춰도 이벤트 시기에 수많은 사용자들의 요청으로 인해 서버 자체에 대한 부하는 굉장히 심할꺼 같은데 서버에 대한 부하를 낮추는 방법은 없나요?현재 흐름이 쿠폰 요청 -> 서버 -> reids에서 쿠폰 개수 확인 -> 카프카 -> 컨슈머 -> DB 인데 이러한 흐름을 요청 -> 서버 -> 카프카 -> 컨슈머 -> redis에서 쿠폰 개수 확인 -> DB 이렇게 바꾸는 방식은 어떤지 궁금합니다. 이런식으로 하면 서버쪽에서 카프카로 데이터를 비동기로 전송한다면 서버 자체에도 부하가 낮아지지 않을까 라는 생각이 들어서 여쭤 봅니다.redis streams나 래빗엠큐 같은 다른 기능들도 있는데 Kafka를 사용하신 이유가 궁금합니다.만약 쿠폰 발급이 100개처럼 적게 발급하는 시스템이라면 굳이 카프카를 도입을 할 필요가 없는건가요?publisher가 카프카로 데이터를 보내면 consumer가 바로 받아와서 DB에 처리를 하면 안되겠죠? 이렇게 처리를 하면 바로 DB에 저장을 하는 상황이니 DB에 부하가 심해진다고 생각합니다.현재 강사님이 알려주신 코드를 바탕으로 시스템을 구축하고 여기에 부하 테스트를 한다고 했을때 어떤 식으로 단계를 잡아서 부하 테스트를 하면 좋을지 조언을 해주실 수 있을까요 한번에 너무 많은 질문해서 죄송합니다.
-
미해결15일간의 빅데이터 파일럿 프로젝트
클라우데라 ERR_SSL_PROTOCOL_ERROR 문제
안녕하세요VM환경구성 중 클라우데라가 접속이 안되어 질문드립니다.기존에 잘 접속이 되었었는데,CPU와 메모리 문제로 가상서버 2개를 구동하면컴퓨터가 다운이 되어 작업이 불가능한 상태였습니다그래서 램16GB, SSD 1TB를 추가하였는데요이후에 가상서버를 실행 후 클라우데라 접속이 되지 않습니다ㅜㅜserver01.hadoop.com:7180입력 후 화면기존에 C드라이브에 프로젝트 서버 파일과 버츄얼박스를 깔아두었는데 D드라이브로 옮겨 실행하니 되지 않았습니다.다시 모두 지우고, C드라이브에 프로젝트파일, 버츄얼박스 설치후 실행하여도 동일하게 프로토콜 에러가 나네요ㅜ 구글링을 해보았지만 .. 초반에 디스크 공간이 부족한 상태에서도 클라우데라 매니저 접속이 되었던걸 생각하면 어떤게 무엇인지 잘 파악이 되지 않습니다.버츄얼박스 서버2개 실행후 컴퓨터 성능 현황은 아래와 같습니다 메모장으로 hosts 파일 수정도 완료한 상태입니다. 버츄얼박스는 커뮤니티에 이전분들이 올려주신 질의내용 참고하여 제일 최근 버전(VirtualBox-7.0.20)으로 사용하고 있습니다.
-
해결됨대기업 근무하며 경험한 Redis를 야무지게 사용하는 방법 [이론편]
Redis란 무엇인가? 질문사항
강의의 내용중 3:35 즈음에인메모리 같은 ssd 같은 메모리를 사용을 한다고 하셨는데궁금증이 생겼습니다.ssd는 제가 알기로는 디스크로 알고 있는데메모리라고 하셔서 궁금하고,ssd를 언급하신 이유는 지속성 옵션 관련해서 말씀 하신건지이 두 부분이 궁금하여 질문 올려봅니다:)
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
로컬에서 docker compose 명령어 실행 시
로컬에서 docker compose up --build -d 명령어 실행 시 아래와 같은 에러가 발생합니다.Cannot connect to the Docker daemon at unix:///Users/milaju/.docker/run/docker.sock. Is the docker daemon running?따로 설정을 해줘야 하는 부분이 있을까요?
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
EC2 서버 실행시키기 관련하여
# 스프링 프로젝트 경로로 들어가서 아래 명령어 실행$ ./gradlew clean build -x test $ cd build/libs$ java -jar -Dspring.profiles.active=prod {빌드된 jar 파일명}서버 실행시키기 명령어 단계에서 $ java -jar -Dspring.profiles.active=prod {빌드된 jar 파일명} 실행 시 ec2 터미널 창에서 아래와 같은 에러가 발생하게 됩니다. 현재 jar 파일은 그림과 같이 생성되었고 명령어는 java -jar -Dspring.profiles.activate=prod demo-0.0.1-SNAPSHOT.jar 이렇게 진행하였습니다.Failed to initialize JPA EntityManagerFactory: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)2024-10-03T16:57:37.160Z WARN 5523 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)2024-10-03T16:57:37.166Z INFO 5523 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]2024-10-03T16:57:37.213Z INFO 5523 --- [ main] .s.b.a.l.ConditionEvaluationReportLogger : Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.2024-10-03T16:57:37.243Z ERROR 5523 --- [ main] o.s.boot.SpringApplication : Application run failedorg.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1806) ~[spring-beans-6.1.13.jar!/:6.1.13] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) ~[spring-beans-6.1.13.jar!/:6.1.13] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.13.jar!/:6.1.13] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.13.jar!/:6.1.13] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.13.jar!/:6.1.13] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.13.jar!/:6.1.13] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.13.jar!/:6.1.13] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:954) ~[spring-context-6.1.13.jar!/:6.1.13] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.13.jar!/:6.1.13] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.4.jar!/:3.3.4] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.4.jar!/:3.3.4] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.4.jar!/:3.3.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.4.jar!/:3.3.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.4.jar!/:3.3.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.4.jar!/:3.3.4] at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[!/:0.0.1-SNAPSHOT] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:569) ~[na:na] at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:102) ~[demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:64) ~[demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:40) ~[demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:276) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.hibernate.boot.model.relational.Database.<init>(Database.java:45) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:189) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) ~[spring-orm-6.1.13.jar!/:6.1.13] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) ~[spring-orm-6.1.13.jar!/:6.1.13] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.1.13.jar!/:6.1.13] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.1.13.jar!/:6.1.13] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) ~[spring-orm-6.1.13.jar!/:6.1.13] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853) ~[spring-beans-6.1.13.jar!/:6.1.13] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802) ~[spring-beans-6.1.13.jar!/:6.1.13] ... 22 common frames omittedCaused by: org.hibernate.HibernateException: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided) at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:191) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:87) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentWithDefaults(JdbcEnvironmentInitiator.java:153) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:364) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
캐싱 객체 직렬화/역직렬화
안녕하세요! 강의를 수강하고 제 프로젝트에서 캐싱을 적용하고 싶어서 따라 적용해보고 있습니다. package com.ecommerceproduct.api.controller.product.dto.response; import com.ecommerceproduct.domain.product.repository.dao.ProductDetailDao; import com.ecommerceproduct.domain.product.type.OptionType; import com.ecommerceproduct.domain.product.type.ProductCategory; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import lombok.Builder; @Builder public record ProductDetailResponse( Long id, String name, StoreInfo store, int quantity, ProductCategory category, String thumbnailImgUrl, int basePrice, @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonDeserialize(using = LocalDateTimeDeserializer.class) LocalDateTime createdDateTime, List<ProductOptionInfo> options ) { public static ProductDetailResponse from(List<ProductDetailDao> daos){ List<ProductOptionInfo> options = new ArrayList<>(); daos.forEach(dao -> options.add(ProductOptionInfo.from(dao.option()))); ProductDetailDao dao = daos.get(0); return ProductDetailResponse.builder() .id(dao.id()) .name(dao.name()) .store(StoreInfo.from(dao.store())) .quantity(dao.quantity()) .category(dao.category()) .thumbnailImgUrl(dao.thumbnailImgUrl()) .basePrice(dao.basePrice()) .createdDateTime(dao.createdDateTime()) .options(options) .build(); } public record StoreInfo( Long storeId, String name ) { public static StoreInfo from(ProductDetailDao.StoreInfo daoStore){ return new StoreInfo(daoStore.storeId(), daoStore.name()); } } public record ProductOptionInfo( Long optionId, String name, int count, int price, OptionType optionType ){ public static ProductOptionInfo from(ProductDetailDao.ProductOptionInfo option){ return new ProductOptionInfo( option.optionId(), option.name(), option.count(), option.price(), option.optionType() ); } } } 해당 클래스를 반환하는 메서드에 @Cacheable을 적용하려고 합니다.@Cacheable(cacheNames = "getProduct", key = "'product:productId:' + #productId", cacheManager = "매니저이름") public ProductDetailResponse get(Long productId) { return ProductDetailResponse.from(productRepository.findWithOptions(productId)); }강의에서 알려주신 매니저와 동일하게 매니저를 bean으로 등록해서 사용해본결과직렬화/역질렬화가 안되는것으로 보입니다. 매니저에 설정을 serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer( new Jackson2JsonRedisSerializer<>(objectMapper, ProductDetailResponse.class)))처럼 명시적으로 타입을 지정해주면 문제가 없는 것 같은데 record여서 안되는 걸까 싶어서 class로 바꾸어도 되지는 않더라고요! 강의에서의 Board 클래스는 문제없이 직렬화/역직렬화가 되는데 제가만든 dto가 안되는 이유는 강의의 Board가 @Entity클래스여서 인걸까요??그렇다면 dto로 쓰려면 매니저를 각각의 dto마다 매니저를 하나씩 만들어주어야할까요?
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
@Cacheable key 속성에서 page, size 파라미터값 null
BoardService.class@Cacheable( cacheNames = "getBoards", key = "'boards:page:' + #page + ':size:' + #size", cacheManager = "boardCacheManager" ) public List<Board> getBoards(int page, int size) { log.info("page={},size={}", page, size); Pageable pageable = PageRequest.of(page - 1, size); Page<Board> pageOfBoards = boardRepository.findAllByOrderByCreatedAtDesc(pageable); return pageOfBoards.getContent(); }BoardController.class@GetMapping public List<Board> getBoards( @RequestParam(name = "page", defaultValue = "1") int page, @RequestParam(name = "size", defaultValue = "10") int size ) { log.info("page={}, size={}", page, size); return boardService.getBoards(page, size); }#page, #size 값에 모두 null이 저장되는 것 같습니다.위 코드에서처럼 BoardService.getBoards(), BoardController.getBoards() 두 메서드 전부 page, size 값을 로그로 출력해보니 각각 1, 10으로 여기서는 정상적으로 나오는데, 어디서 문제가 있는지 모르겠습니다.구글링을 해도 마땅한 답을 구할 수 없어서 질문 남깁니다!