묻고 답해요
169만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결비전공자도 이해할 수 있는 Redis 중급/실전
mysql 의 bitmap
bitmap은 db 테이블에서 정보가 보이지 않던데 , redis 명령어로만 확인이 가능한 건가요??
-
미해결15일간의 빅데이터 파일럿 프로젝트
주제영역3 데이타 조회 문의
주제영역3 데이타 조회 문의 입니다. 저는 쿼리문장을 날리면건수가 10개만 조회가됩니다.managed_smartcar_drive_info 테이블를 전체데이타 건수는43000건 정도나옵니다.주제영역4는 실행하면 33건이 나오고있습니다.질문은 주제영역3는 결과가 94건인데..저는 10건이라서 제가 어떤 부분을 잘못한건지?아니면 저사향이고 랜덤으로 자바파일 로그 데이타 생성이므로 문제가 없는 건지 질문드립니다.또한 , 10건이여도 7장이후 분석에서 문제가 없는지 질문합니다.
-
해결됨6주 완성! 백엔드 이력서 차별화 전략 4가지 - 똑같은 이력서 속에서 돋보이는 법
인덱스 관련 질문 있습니다.
안녕하세요. 인덱스를 활용한 조회 성능 개선을 공부하던 중 궁금한 점이 생겨 질문드립니다.현재 저는 OFFSET 기반 pagination을 사용하는 서비스를 개발하고 있으며, 다음과 같은 환경에서 성능 테스트를 진행했습니다.데이터: 약 1,000만 건서버: EC2 t3.smallDB: RDS t4g.microk6 vus1001. 문제 상황초기에는 OFFSET 제한 없이 마지막 페이지까지 이동 가능하도록 구현했습니다.하지만 데이터가 1,000만 건 수준으로 증가하자, 깊은 페이지로 갈수록 조회 속도가 급격히 느려지는 문제를 확인했습니다.2. 고민 및 제약일반적으로 이 문제는 Keyset Pagination(커서 기반)으로 해결하라고 많이 알려져 있습니다.하지만 제 서비스는👉네비게이션 바를 통한 페이지 직접 이동 (ex. 1, 10, 100 페이지 클릭)이 필요하기 때문에 Keyset 방식만으로는 요구사항을 만족시키기 어렵다고 판단했습니다.3. 적용한 개선 방법다음과 같은 방식으로 성능 개선을 진행했습니다.OFFSET 최대 범위를 제한 (최대 10,000 페이지 / OFFSET 100,000)커버링 인덱스 적용조회 방식 개선먼저 ID만 조회 → 이후 필요한 10건만 상세 조회전체 게시글 수(count)는 캐싱 처리4. 성능 개선 결과[Page 10] avg: 1.4s → 700ms p95: 4.5s → 1.8s [Page 100] avg: 17s → 1.18s p95: 24s → 3.3s [Page 1000] avg: 32.1s → 1.7s p95: 59s → 4.27s5. 추가 제약사항로그인 사용자와 비로그인 사용자의 조회 결과가 다름(사용자별 구독 게시글이 포함됨)따라서 캐시는 비로그인 사용자에만 적용위 성능 수치는 로그인 사용자 기준6. 현재 고민위와 같이 개선했지만,👉 여전히 성능이 충분하지 않다고 느끼고 있습니다.특히 궁금한 점은 다음과 같습니다.7. 질문OFFSET 기반 pagination을 유지하면서👉추가로 성능을 개선할 수 있는 방법이 있을까요?다음과 같은 방법들을 고려했는데, 방향성이 맞는지 궁금합니다.RDS를 2개를 사용하여 조회 성능 데이터를 각각 2개의 db가 처리하도록 한다?Keyset + OFFSET 혼합 방식 (일반적인 페이지 이동은 Keyset Pagination을 사용하고,사용자가 특정 페이지를 직접 입력하거나 점프하는 경우에만제한적으로 OFFSET 기반 조회를 사용하는 혼합 방식)RDS 스펙 업그레이드또한 에펨코리아(https://www.fmkorea.com/)와 같은 대형 커뮤니티는 제가 원하는 페이지 네이션 방식을 사용하면서 깊은페이지(최대 1만)도 지원하고동시접속자 수십만페이지 수천~수만대량 데이터환경에서도 빠른 조회 성능을 유지하는데👉이러한 서비스들은 어떤 방식으로 pagination 및 조회 성능을 처리하는지 궁금합니다.
-
해결됨6주 완성! 백엔드 이력서 차별화 전략 4가지 - 똑같은 이력서 속에서 돋보이는 법
비관적 락 구현 방식 문의 건
1. 현재 학습 진도몇 챕터/몇 강을 수강 중이신가요? 여기까지 이해하신 내용은 무엇인가요?강사님 안녕하세요 :)현재 4-9 낙관적 락, 비관적 락 강의를 수강하는 중이며, 단일 행에 대해 배타 락을 거는 방식을 학습한 후 관련 문의 드립니다. 2. 어려움을 겪는 부분어느 부분에서 막히셨나요?코드의 어떤 로직이 이해가 안 되시나요?어떤 개념이 헷갈리시나요?만약비관적 락(PESSIMISTIC_WRITE) 방식으로 한 테이블의 여러 행에 락을 걸어야 한다면, 아래 두 방식 중 어느 방식이 적절한지 궁금합니다.N번의 DB 조회를 방지하기 위해 아래 1번 방식을 고려했으나, 관련 케이스가 많지 않아 제가 놓치는 부분이 있는지 여쭤보고 싶습니다. 더불어 실무에서는 어떤 방식으로 접근하시는지도 궁금합니다. :) 3. 시도해보신 내용문제 해결을 위해 어떤 시도를 해보셨나요?에러가 발생했다면 어떤 에러인가요?현재 작성하신 코드를 공유해주세요1. IN절 조회 후 락 걸기@Lock(LockModeType.PESSIMISTIC_WRITE)@Query("select p from Product p where p.productNumber in :productNumbers")List<Product> findAllByProductNumberIn(@Param("productNumbers") List<String> productNumbers);만약 1번 방식이 적절하다면, 데드락 방지를 위해 ORDER BY 정렬이 필수인지 궁금합니다.2. 루프를 돌며 조회 후 락 걸기for (String productNumber : productNumbers) { Product product = productRepository.findByProductNumberWithLock(productNumber) .orElseThrow( ··· ); ··· }@Lock(LockModeType.PESSIMISTIC_WRITE)@Query("SELECT p FROM Product p WHERE p.productNumber = :productNumber")Optional<Product> findByProductNumberWithLock(@Param("productNumber") String productNumber); 이렇게 구체적으로 알려주시면, 더 정확하고 도움이 되는 답변을 드릴 수 있습니다!
-
미해결2026년! 백엔드 개발자를 위한 Redis 실전 가이드: 기초부터 실무 패턴까지
백엔드 서버 코드 변경에서 프론트엔드 서버가 값을 파싱하지 못하는 문제
stream_notices 내부의 event_generator 함수 코드에서 yield f"data: {data}\\n\\n"위의 개행 문자에 이스케이프가 두번 들어가서 메시지가 정상적으로 전송되어도 파싱 오류로 화면에 표시되지 않는 문제가 있는것 같습니다.해결책은 이스케이프 문자를 하나만 사용하면 개행도 정상적으로 되고 문자열도 올바르게 출력됩니다.yield f"data: {data}\n\n"
-
미해결2026년! 백엔드 개발자를 위한 Redis 실전 가이드: 기초부터 실무 패턴까지
강사님 GETDEL 관련해서 질문 있습니다
# Redis 6.2 이상일 경우 GETDEL 사용 권장 # saved_code = await rd.getdel(cache_key)이 코드 사용을 권장하셨는데 입력 값 비교 검증까지 통과하기 전에 값을 가져와서 바로 지워버리면 사용자가 실수로 인증번호 입력을 실패해도 다시 요청하도록 해야하는데 이를 감안하고서라도 GETDEL을 사용해야 한다면 이는 verify_code 함수의 원자성을 지키기 위한 권장 사항인가요?혹은 verify_code 함수에 트랜잭션 관련 설정을 하고 GET과 DEL 호출을 쪼개서 하거나 Redis Functions을 사용하는 것을 고려하는게 더 나은지 궁금합니다.
-
미해결2026년! 백엔드 개발자를 위한 Redis 실전 가이드: 기초부터 실무 패턴까지
비밀번호를 걸고 실행된 레디스 서버에 lua 스크립트를 등록하는 경우
docker exec -i my-redis redis-cli -x FUNCTION LOAD REPLACE < coupon_logic.lua위의 기존 코드를 실행시키면 NOAUTH Authentication required 라는 오류가 발생합니다. 이 경우에는 docker exec -i my-redis redis-cli -a <비밀번호> -x FUNCTION LOAD REPLACE < coupon_logic.lua와 같은 형식으로 입력하시면 정상 등록됩니다.경고가 뜨긴 하는데 커맨드라인에 비밀번호를 직접 입력하지 말라고 하는거네요.
-
미해결2026년! 백엔드 개발자를 위한 Redis 실전 가이드: 기초부터 실무 패턴까지
보안 설정을 한 수강생들은 Connection Settings에 비밀번호를 넣어야 추가되네요
보안 설정이 걸려 있어서 그런지 바로 목록에 로컬 레디스가 보이는건 아니고 Connect existing database 누르고 세팅에서 비밀번호를 입력한 후에 add를 해야 정상적으로 목록에 표시됩니다.
-
해결됨2026년! 백엔드 개발자를 위한 Redis 실전 가이드: 기초부터 실무 패턴까지
Redis Container 해킹
안녕하세요. 좋은 강의 감사합니다! docker container로 redis 실습 중 모든 키가 제거되고 backup1,backup2 와 같은 키가 남아있는 현상을 확인했는데 서칭 결과 크롤링 봇에 의한 해킹이라고 진단했습니다.해킹 원인은 public ip를 사용하는 pc에서 포트를 ip 제한 없이 열어서 그런 것으로 추측했습니다.그래서 기존 컨테이너 생성 코드container run --name my-redis -p 6379:6379 redis에서docker run -d \ --name my-secure-redis \ -p 127.0.0.1:6379:6379 \ --restart always \ redis:latest \ redis-server --requirepass "비밀번호" --appendonly yes로 변경하여 local ip 지정 뿐만 아니라 권한 설정, 데이터 백업 등이 설정 된 새로운 컨테이너를 생성했습니다.수정 후 지금까지는 키가 삭제 현상이 다시 나타나지 않았는데 혹시 잘못된 부분이 있으면 지적 부탁 드립니다. 감사합니다!
-
해결됨초당 500,000+건 트래픽을 처리하는 카카오 면접관의 Redis
Redis Hash
강의 내용을 듣고 생각했을때 ,대부분의 경우 Redis String 보다 Redis Hash 사용하는게 대부분 이득일것 같다 생각이 들던데...어떻게 사용하고 계시나요 ?? 사실 저는 Redis String 으로 Json 으로 많이 사용했었습니다. 그리고 큰 장애를 경험하지 못했는데요 아무래도 트래픽에 대한 차이인것 같네요
-
해결됨초당 500,000+건 트래픽을 처리하는 카카오 면접관의 Redis
Redis 큐
강의 잘 들었습니다.Redis 주로 그냥 일반적으로 메모리에 저장하고 호출하는 정도로만 사용을 하고 있는데요BLPOP ,RPUSH job_queue job1 와 같은 기능은 언제 사용하게 되나요 ??
-
해결됨비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
redis VS valkey
최근에 Redis 의 개발사가 라이선스 정책을 변경하면서, 더 이상 완전한 무료 오픈소스로 부르기 애매해지는 사건이 있었습니다. 이에 반발한 AWS, 구글 등 빅테크 기업들이 모인 Linux Foundation 에서 기존 Redis 코드를 그대로 복사해서(포크해서) 만든 진짜 100% 무료 오픈소스가 바로 Valkey 입니다.라고 제미나이가 그러던데... 요즘은 Valkey를 선택하는 게 대세인가요?
-
해결됨6주 완성! 백엔드 이력서 차별화 전략 4가지 - 똑같은 이력서 속에서 돋보이는 법
외부 api 처리 방안에 대하여 궁금한 점이 있습니다.
수업 예시에서는 외부 api가 실패할 경우 스케쥴러를 활용해서 후보정 로직을 통하여 결과적 일관성을 맞추고 있습니다. 만약에 자리를 지정하는 콘서트를 위와 같이 처리할 경우 (예약은 성공, 외부 api는 실패), 후보정 로직이 동작하기 전 다른 예약 시스템에서 해당 자리를 예약한 경우 더욱 큰 문제가 발생할 수 있을 것으로 보입니다. 이러한 경우 (좌석처럼 한정된 자원을 예약하는 경우), 외부 API 실패 시 후보정 로직을 통한 비동기 처리 대신 동기적으로 처리하는 것이 올바른 방식인 것 같은데, 강사님은 어떻게 생각하시는지 궁금합니다!
-
해결됨초당 500,000+건 트래픽을 처리하는 카카오 면접관의 Redis
강의에서 작성한 코드 제공 문의
강의에서 작성된 코드를 제공해주시는 것 같은데 어디서 볼 수 있나요?
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 캐시 전략
23강 5:38 부분 질문 있습니다!
m=32MB짜리 10개와 m=512MB짜리 1개의 경우를 비교해주셨습니다.그런데 이는 샤딩을 통해서 메모리 효율적으로 됐다기 보다는 메모리 총량이 512MB->320MB로 감소했기 때문에 오차율이 조금 증가하는 대신 메모리를 덜 쓸 수 있는 것 아닌가요?예를 들어 320MB 짜리 1개인 경우와 32MB짜리 10개인 경우의 오차율이 똑같지 않나 하는 생각이 들어서 질문드립니다!
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 캐시 전략
23강 17초 부분 질문있습니다~
"Split 전략에서 항상 모든 Split을 조회한다."요 부분이 이해가 가지 않아서 질문드립니다!findSplitIndex로 계산한 split에만 접근하는 것 아닌가요?아니면 모든 스플릿이 단일 redis 내에 존재하는 것이 문제라는 의도로 말씀하신걸까요?
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 캐시 전략
Split 전략 강의 중 질문 있어요
@Slf4j @SpringBootTest class SplitBloomFilterRedisHandlerTest extends RedisTestContainerSupport { @Autowired SplitBloomFilterRedisHandler splitBloomFilterRedisHandler; @Test void mightContain() { SplitBloomFilter splitBloomFilter = SplitBloomFilter.create("testId", 1000, 0.01); List<String> values = IntStream.range(0, 1000).mapToObj(idx -> "value" + idx).toList(); for (String value : values) { splitBloomFilterRedisHandler.add(splitBloomFilter, value); } for (String value : values) { boolean result = splitBloomFilterRedisHandler.mightContain(splitBloomFilter, value); assertThat(result).isTrue(); } for (int i = 0; i < 1000; i++) { String value = "notAddedValue" + i; boolean result = splitBloomFilterRedisHandler.mightContain(splitBloomFilter, value); if (result) { log.info("value={}", value); } } } } 위 코드는 SplitBloomFilterRedisHandlerTest 인데요.강의 중 코드입니다 1000 크기에 0.01 오차율의 Bloom Filter 를 만들고1000개의 데이터를 넣고 False Positive 까지 검증해보는 코드인데요.질문입니다Split 전략을 배우기 전에순수한 Bloom Filter 구현 강의에서도 위와 동일한 테스트 코드가 있는데요이 때, 순수한 Bloom Filter 의 한계로써생성한 Bloom Filter 크기를 초과하여 데이터를 넣으면 비트 1이 많아져 오차율이 증가하고그로 인해 False Positive 데이터가 많이 조회되는 현상을 살펴보거든요.그리고 그 해결책으로처음부터 큰 Bloom Filter 를 만드는 것 이외에Split / Sharding / Sub Filter 전략이라고 말씀하시는데요근데 위 Split 전략의 테스트 코드에서 BloomFilter 크기는 1000으로 만들고 데이터를 훨씬 초과하여 2000개 만들어 넣어보면순수한 Bloom Filter 때처럼 False Positive 데이터가 많이 조회됩니다.저는 PC 가 느려서 False Positive 를 1000번으로 조회하였고오차율 (0.01) 에 의하면 약 10개의 False Positive 가 나와야 하는데데이터 1000개를 저장했을 때는 오차율에 맞게 8개로 떨어지는데데이터 2000개를 저장했을 때는 오차율을 훨씬 넘어갑니다제가 코드를 잘못 따라 친건지.. Split 도 원래 그런건지..제 질문 의미가 전달될지는 모르겠지만.. 명확하게 개념 정리가 되지 않아 질문드립니다
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
정렬, 필터, 검색 등의 조건이 붙을 경우 최적화할 수 있는 방법이 무엇이 있을까요?
안녕하세요.게시판 관련 강의를 듣는 도중 궁금한 점이 있어 질문을 남깁니다.강의에서는 Snowflake 기반 단순 정렬을 기준으로 커버링 인덱스를 설명해주셨는데요,실무에서는 여러 정렬 조건과 필터, 검색 조건이 함께 붙는 경우가 많습니다.✅ 이런 복합적인 조회 패턴에서도 커버링 인덱스를 중심으로 설계하는 것이 적절한지,아니면 다른 전략을 어떻게 사용해야 하는지 궁금합니다.(설명이 길어질 경우 간단한 힌트라도 부탁드립니다.)💥 걱정하는 부분정렬되는 컬럼 전부에 대해 인덱스를 걸면 더 문제가 발생할 것 같아요.검색 %검색어%의 경우에는 결국엔 full_scan이어서 성능 최적화가 불가능하다.
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 캐시 전략
질문이 있습니다!!
강의를 보다가 궁금한 부분들이 생겨 질문드립니다!!1. RateLimit Boundary Burst 관련RateLimit을 설명해주시는 부분을 보면서 한 가지 의문이 들었습니다.예를 들어 1초에 100개로 제한을 두었을 때,0.9초 시점에 100개 요청이 들어오고 1초가 되자마자 다시 100개가 들어온다면실제로는 매우 짧은 시간 안에 200개의 요청이 처리될 수 있지 않을까 하는 생각이 들었습니다.찾아보니 이러한 문제를 Boundary Burst라고 부른다는 것을 알게 되었습니다.이를 해결하기 위해:Sliding WindowSliding Window CounterToken BucketLeaky Bucket등의 방식이 있다는 것을 확인했습니다.실무 관점에서는 이런 경계 구간 Burst 문제를 어떤 방식으로 해결하는지 궁금합니다.2. Request Collapsing 관련Request Collapsing을 설명해주신 부분을 보면서,여러 요청을 하나로 모아서 처리하는 방식으로 Golang의 SingleFlight 패턴을 응용하는 방법도 가능하지 않을까 생각해보았습니다.이와 관련해서 아래와 같은 예제 코드도 작성해 보았습니다.private final StringRedisTemplate redisTemplate; private final Map<String, CompletableFuture<?>> singleFlightMap = new ConcurrentHashMap<>(); @Override public <T> T fetch(String key, Duration ttl, Supplier<T> supplier, Class<T> clazz) { String cached = redisTemplate.opsForValue().get(key); if (cached != null) { return DataSerializer.deserializeOrNull(cached, clazz); } CompletableFuture<T> newFuture = new CompletableFuture<>(); CompletableFuture<T> existing = (CompletableFuture<T>) singleFlightMap.putIfAbsent(key, newFuture); if (existing != null) { // 다른 스레드가 실행 중 → 기다림 return existing.join(); } // 내가 실행자 (락 없이 실행) try { T result = refresh(key, ttl, supplier); newFuture.complete(result); return result; } catch (Throwable t) { newFuture.completeExceptionally(t); throw t; } finally { singleFlightMap.remove(key, newFuture); } } private <T> T refresh(String key, Duration ttl, Supplier<T> dataSourceSupplier) { T result = dataSourceSupplier.get(); put(key, ttl, result); return result; }이 방식은 분산 락이나 폴링 방식 없이도 동일 인스턴스 내 요청을 모을 수 있다는 장점이 있다고 생각했습니다.물론 이 방법은 모든 분산 서버 간 요청을 하나로 모으는 것은 아니기 때문에, 서버 인스턴스 수만큼은 요청이 발생할 수 있다는 한계가 있다고 생각합니다.하지만 인스턴스 수가 많지 않다면, 분산 락으로 인한 오버헤드나 복잡성을 줄이면서도 어느 정도 트래픽을 제어할 수 있는 현실적인 선택지가 될 수 있지 않을까 하는 생각이 들었습니다.실무 관점에서는 이런 방식에 대해 어떻게 평가하시는지 궁금합니다.3. Write Through 방식에서의 장애 처리Write Through 방식에서는 일반적으로:DB에 먼저 저장동일 데이터를 Redis에도 저장하는 구조로 이해하고 있습니다.그런데 만약:DB에는 쓰기 성공Redis에는 쓰기 실패하는 상황이 발생한다면, 이 경우를 트랜잭션 실패로 간주해야 하는지 궁금합니다.Redis 장애로 인해 캐시 반영이 실패했을 때,핵심 트랜잭션(DB 쓰기)까지 롤백해야 하는지아니면 캐시는 보조 저장소로 보고 DB 성공을 기준으로 처리해야 하는지두 저장소 간 원자성을 반드시 보장해야 하는 설계인지 실무에서는 어떤 기준으로 판단하는지 궁금합니다.
-
해결됨AI 다루는 백엔드 설계 기본 - SpringBoot SNS 편
질문 드립니다!
혹시 선생님께서 수업 중 사용하신 ppt 파일이 있으실까요? 복습할 때 꼭 필요해서 질문드립니다!