묻고 답해요
169만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
Json 요청 처리
형 나 지금 너무 재밌어서 잘 따라하던중 별거 아닌거에서 막혀서 좀 힘들어형이 알려준 json 파라미터 넘기는 방법으로 해도 안되고 gpt 찾아서 진행 한거도 다 안돼는데 윈도우 환경에서 좀 힘든걸까 ?? 다른 수강생분이 올려준거도 봤는데 답변에 달아준 방법도 동작하지 않아 @Bean public JsonJobParametersConverter jobParametersConverter() { return new JsonJobParametersConverter(); } @Bean @StepScope public Tasklet terminatorTasklet( @Value("#{jobParameters['infiltrationTargets']}") String infiltrationTargets ) { return (contribution, chunkContext) -> { String[] targets = infiltrationTargets.split(","); log.info("⚡ 침투 작전 개시"); log.info("첫 번째 타겟: {} 침투 시작", targets[0]); log.info("마지막 타겟: {} 에서 집결", targets[1]); log.info("🎯 임무 전달 완료"); return RepeatStatus.FINISHED; }; }
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
로그아웃-logout()-2 강에서 겟방식 로그아웃 호출 후 화면이동 질문입니다.
8분 29초에서 /logoutProc 를 겟방식으로 호출했고 로그아웃은 성공했습니다.로그아웃 성공후 /logoutSuccess 로 이동해야 하고 해당 url 은 permitAll() 입니다. 그런데 왜 로그인화면이 표시되는지 궁금합니다.강의를 조금 더 보다보니, 궁금증은 해결됐습니다. 그런데 여전히 궁금한 점은 해당 소스에 맨 아래 permitAll() 의 역할입니다. 실제 아무일도 안하는건지 궁금합니다.
-
해결됨6주 완성! 백엔드 이력서 차별화 전략 4가지 - 똑같은 이력서 속에서 돋보이는 법
Build 관련 문제 (테스트 관련 문제)
다른 분들에게 도움이 될까 글을 작성합니다. 저는 윈도우 환경에서 InteliJ를 사용하고 CLI 화면이 편하기 때문에 WSL를 사용하여 도커를 사용했습니다. 해당 전에 문제 해결들은 자료가 없어서 해결 방안만 말씀드리겠습니다.cloud... gradle 문제 해당 프로젝트가 One Driver에 있기 때문에 클라우드 상에 있는 그레이들이 안되는 것으로 알고 있습니다. 만약 프로젝트가 One Driver에 있다면 One driver 밖으로 이동 시켜주세요WSL 도커를 실행해도 윈도우 환경에서는 컨테이너를 찾지 못하는 경우가 있기 때문에 Window 환경에서 도커를 실행 하세요 해당 예외들이 터진 후에 모든 테스트 로직에 대해 예외가 발생합니다.BackendportfolioApplicationTests > contextLoads() FAILED java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:143 Caused by: java.lang.IllegalStateException at LoadingCache.java:75 Caused by: java.lang.ExceptionInInitializerError at Class.java:-2 Caused by: java.lang.IllegalStateException at DockerClientProviderStrategy.java:277원래 전에는 build와 테스트가 잘 진행되었는데 무슨 일인지 Test에서 도커를 만들지 못하는 문제가 생겼나 봅니다. 저는 테스트에서 사용되는 DB Config들을 사용하는 곳에 주석 처리하고 도커 컴포즈로 DB를 주석 처리하고 테스트에서 사용되는 DB들은 Docker compose에 사용되는 DB를 켜서 사용했습니다. Docker Compose에서 사용되는 DB로 사용되기 싫으시다면 Docker 컨테이너로 따로 만드시면 될 것 같아요 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @SpringBootTest //@Import({TestDatabaseConfig.class, TestRedisConfig.class}) public @interface IntegrationTest { } docker compose up db redis -d build 관련 에러들은 어노테이션 설정, gradle 설정, 컴파일 설정 등 많은 이유가 있어 하루 종일 붙잡아도 문제 해결이 안되는 점이 많아 시간으 며칠 잡아 먹었네요 글을 깔끔하게 가독성 좋게 작성하지 못해 아쉽지만 다른 사람들이 똑같은 문제를 맞았을 때 해당 글이 도움이 되길 바랍니다.
-
해결됨카카오 면접관의 실무 밀착형 Spring Batch: 대용량 데이터 처리의 모든 것
job, step execution 관련 질문 드립니다.
안녕하세요.잡이 어떻게 스텝에서 사용하는 컨텍스트 값까지 가지고 있는지 잘 이해가 되지 않아 질문드립니다.분명 JobExecutionContext에 넣은 것이 아니라 StepExecutionContext에 값을 저장했는데, 확인해보니 JobExecutionContext에도 동일하게 저장된 것처럼 보여서 헷갈렸습니다.제가 이해한 바로는 JobExecutionContext와 StepExecutionContext는 서로 다른 영역이고,JobExecutionContext는 step 간 공유용, StepExecutionContext는 해당 step 전용으로 알고 있습니다.그런데 왜 StepExecutionContext에 넣은 값이 JobExecutionContext에도 같은 형태로 보이는지 잘 모르겠습니다.
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
이미지 업로드와 db 트랜잭션 묶는법
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]상품 리뷰 등록·수정·삭제 시 AWS S3 같은 외부 스토리지에 이미지 업로드/삭제가 함께 발생하는데,DB 트랜잭션(리뷰 저장/삭제)과 S3 작업(이미지 업로드/삭제)은 서로 다른 시스템이라 하나의 트랜잭션으로 묶기 어렵습니다. 실무에서는 리뷰 저장/수정/삭제와 이미지 업로드/삭제를 어떤 순서와 전략으로 설계하는지 궁금합니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
sdk 설정 오류
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.이렇게 오류가 떠서 jdk oracle을 다운 받고sdk도 설정하고IVM도 설정했습니다. 자바 스프링 버전은 최신 버전인 4.0.5 대신 강의 자료에서 3.x인 최신버전을 선택하라길래 3.5.13.을 선택했습니다. 무슨 문제일까요?
-
해결됨카카오 면접관이 알려주는 MSA 관점에서의 분산 트랜잭션 패턴
Orchestration SAGA 패턴 보상에 대한 질문입니다.
Orchestration SAGA 패턴 구현에 대해 고민하다가 질문이 생겨 남깁니다.보상을 요청하는 메서드가 명시적으로 나와있어 호출할 때(동기로 호출)만약 rollback을 요청하는 호출이 실패하게 된다면 이후의 순서대로 service에 보상 요청을 하는 동작을 멈춰야 할지 계속 진행하는 게 바람직할지 고민이 됩니다.예를 들어 서비스 1,2,3,4가 있고 center server가 orchestration 관리를 하고 1,2,3,4 순서대로 서비스 호출해서 관리를 진행한다고 했을 때 3에서 장애가 발생해서 2를 롤백하던 중 2 롤백에서 예외가 발생해서 롤백에 실패한 경우 orchestration에서 1에 대한 롤백을 진행해줘야 할지 아니면 일단 멈춰야 할지 고민입니다. 고민의 이유는 순서대로 롤백을 해주는 것은 앞에 작업이 뒤의 작업에 의존성이 있을 때만 그렇게 해주면 되나에 대한 고민이 있었습니다. 두 롤백 간에 데이터 의존성이 없다면 괜찮지 않을까 고민했습니다.다음으로 일단 1도 롤백을 한다면 어디서부터 어디까지 롤백이 진행됐는지 추적이 어려워지지 않을까 고민했습니다. 롤백을 어떤 것은 해주고 어떤 것은 안해준다면 어디까지 롤백했는지 추적이 힘들어지지 않을까 생각이 들었습니다.
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
[건의][6장][작전1] deprecated 메소드
형 ... @Bean public Step threatAnalysisStep( JpaPagingItemReader<Human> humanThreatDataReader, ItemProcessor<Human, TargetPriorityResult> threatAnalysisProcessor, FlatFileItemWriter<TargetPriorityResult> targetListWriter ) { return new StepBuilder("threatAnalysisStep") .<Human, TargetPriorityResult>chunk(10, transactionManager) .reader(humanThreatDataReader) .processor(threatAnalysisProcessor) .writer(targetListWriter) .taskExecutor(taskExecutor()) // deprecated 되어서 안씀 // .throttleLimit() .build(); } ... 에서 .throttleLimit() 부분이 5 이후로 deprecated 된다고 명시되어 있어. 관심사 분리로 인해서 taskExecutor 정의 부분에서 설정하라고 권장하는 것을 확인했거든. 현재 강의가 사실상 Spring Batch 5.x 까지의 기본 내용과 원리를 살펴봤잖아 ? 그렇다 하더라도 혼란을 줄 수 있기 때문에 해당 부분은 삭제하던지 아니면 추가 내용을 기재해야 할 것으로 보여.
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
[예제][3장][작전2] windows 에서 마지막 예제
... @Slf4j @Configuration @RequiredArgsConstructor public class LogProcessingJobConfig { private final JobRepository jobRepository; private final PlatformTransactionManager transactionManager; private final String BASE_PATH = "C:\\Users\\user\\Desktop\\batch\\section3\\flatfileitemwriter"; @Bean public Job logProcessingJob( Step createDirectoryStep, Step logCollectionStep, Step logProcessingStep ) { return new JobBuilder("logProcessingJob", jobRepository) .start(createDirectoryStep) .next(logCollectionStep) .next(logProcessingStep) .build(); } @Bean public Step createDirectoryStep(SystemCommandTasklet mkdirTasklet) { return new StepBuilder("createDirectoryStep", jobRepository) .tasklet(mkdirTasklet, transactionManager) .build(); } @Bean @StepScope public SystemCommandTasklet mkdirTasklet( @Value("#{jobParameters['date']}") String date ) { SystemCommandTasklet tasklet = new SystemCommandTasklet(); tasklet.setWorkingDirectory(BASE_PATH); String collectedLogsPath = "collected_ecommerce_logs\\" + date; String processedLogsPath = "processed_logs\\" + date; try { tasklet.setCommand("cmd.exe", "/c", "mkdir", collectedLogsPath, processedLogsPath); tasklet.setTimeout(3000); } catch (Exception e) { log.error("mkdirTasklet error: ", e); } return tasklet; } @Bean public Step logCollectionStep(SystemCommandTasklet scpTasklet) { return new StepBuilder("logCollectionStep", jobRepository) .tasklet(scpTasklet, transactionManager) .build(); } @Bean @StepScope public SystemCommandTasklet scpTasklet( @Value("#{jobParameters['date']}") String date ) { SystemCommandTasklet tasklet = new SystemCommandTasklet(); tasklet.setWorkingDirectory(BASE_PATH); String processedLogsPath = "collected_ecommerce_logs\\" + date; StringJoiner commandBuilder = new StringJoiner(" & "); for (String host : List.of("localhost")) { // Windows 환경에서 해당 코드를 적용하려면 ssh 관련 설정들을 찾아야 해서 주석 처리 // String command = String.format("scp %s:~/ecommerce_logs/%s.log %s\\%s.log", host, date, processedLogsPath, host); String sourcePath = BASE_PATH + "\\ecommerce_logs\\" + date + ".log"; String command = String.format("copy %s %s\\%s.log", sourcePath, processedLogsPath, host); commandBuilder.add(command); } tasklet.setCommand("cmd.exe", "/c", commandBuilder.toString()); tasklet.setTimeout(10000); return tasklet; } @Bean public Step logProcessingStep( MultiResourceItemReader<LogEntry> multiResourceItemReader, LogEntryProcessor logEntryProcessor, FlatFileItemWriter<ProcessedLogEntry> processedLogEntryJsonWriter ) { return new StepBuilder("logProcessingStep", jobRepository) .<LogEntry, ProcessedLogEntry>chunk(10, transactionManager) .reader(multiResourceItemReader) .processor(logEntryProcessor) .writer(processedLogEntryJsonWriter) .build(); } @Bean @StepScope public MultiResourceItemReader multiResourceItemReader( @Value("#{jobParameters['date']}") String date ) { MultiResourceItemReader<LogEntry> resourceItemReader = new MultiResourceItemReader<>(); resourceItemReader.setName("multiResourceItemReader"); resourceItemReader.setResources(getResources(date)); resourceItemReader.setDelegate(logFileReader()); return resourceItemReader; } private Resource[] getResources(String date) { try { String formattedBasePath = BASE_PATH.replace("\\", "/"); String location = "file:///" + formattedBasePath + "/collected_ecommerce_logs/" + date + "/*.log"; PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); return resolver.getResources(location); } catch (IOException e) { throw new RuntimeException("Failed to resolve log files", e); } } @Bean public FlatFileItemReader<LogEntry> logFileReader() { return new FlatFileItemReaderBuilder<LogEntry>() .name("logFileReader") .delimited() .delimiter(",") .names("dateTime", "level", "message") .targetType(LogEntry.class) .build(); } @Bean public LogEntryProcessor logEntryProcessor() { return new LogEntryProcessor(); } @Bean @StepScope public FlatFileItemWriter<ProcessedLogEntry> processedLogEntryFlatFileItemWriter( @Value("#{jobParameters['date']}") String date ) { String outputPath = Paths.get(BASE_PATH, "processed_logs", date, "processed_logs.jsonl").toString(); ObjectMapper objectMapper = new ObjectMapper(); JavaTimeModule javaTimeModule = new JavaTimeModule(); javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"))); objectMapper.registerModule(javaTimeModule); return new FlatFileItemWriterBuilder<ProcessedLogEntry>() .name("processedLogEntryJsonWriter") .resource(new FileSystemResource(outputPath)) .lineAggregator(item -> { try { return objectMapper.writeValueAsString(item); } catch (JsonProcessingException e) { throw new RuntimeException("Error Converting item to JSON", e); } }) .build(); } @Data public static class LogEntry { private String dateTime; private String level; private String message; } @Data public static class ProcessedLogEntry { private LocalDateTime dateTime; private LogLevel level; private String message; private String errorCode; } public enum LogLevel { INFO, WARN, ERROR, DEBUG, UNKNOWN; public static LogLevel fromString(String level) { if (level == null || level.trim().isEmpty()) { return UNKNOWN; } try { return valueOf(level.toUpperCase()); } catch (IllegalArgumentException e) { return UNKNOWN; } } } public static class LogEntryProcessor implements ItemProcessor<LogEntry, ProcessedLogEntry> { private static final DateTimeFormatter ISO_FORMATTER = DateTimeFormatter.ISO_DATE_TIME; private static final Pattern ERROR_CODE_PATTERN = Pattern.compile("ERROR_CODE\\[(\\w+)]"); @Override public ProcessedLogEntry process(LogEntry item) throws Exception { ProcessedLogEntry processedLogEntry = new ProcessedLogEntry(); processedLogEntry.setDateTime(parseDateTime(item.getDateTime())); processedLogEntry.setLevel(parseLevel(item.getLevel())); processedLogEntry.setMessage(item.getMessage()); processedLogEntry.setErrorCode(extractErrorCode(item.getMessage())); return processedLogEntry; } private LocalDateTime parseDateTime(String dateTime) { return LocalDateTime.parse(dateTime, ISO_FORMATTER); } private LogLevel parseLevel(String level) { return LogLevel.fromString(level); } private String extractErrorCode(String message) { if (message == null) { return null; } Matcher matcher = ERROR_CODE_PATTERN.matcher(message); if (matcher.find()) { return matcher.group(1); } // ERROR 문자열이 포함되어 있지만 패턴이 일치하지 않는 경우 if (message.contains("ERROR")) { return "UNKNOWN_ERROR"; } return null; } } } 윈도우즈에서는 scp 명령어 관련해서 windows 서비스에서 open-ssh-server 실행현재 사용하고 있는 사용자(windows 사용자) 가 관리자 권한을 보유 할 경우 programdata/sshd_config 파일 수정 필요기타 파일 권한 정리 필요로 인하여 scp 프로그램을 windows 환경의 intellij idea 에서 id, 비번치게끔 ide 콘솔에서 지원하지 않는거 같아. 그래서 제미니가 추천해준대로 실습 환경에서 scp 접속 단을 copy 로 그냥 퉁치는 것으로 바꿔놨어. 나처럼 windows 환경인 사람들이 있으면 혹시나 참고했으면 좋겠네. ObjectMapper, JavaTimeModule 같은 경우는 org.springframework.boot:spring-boot-starter-json 의존성 추가 필요
-
해결됨서버개발자 과제전형 완벽가이드 - 1편
NaverBookRepository.class 의 위치에 따른 모듈간의 의존성에 대해 질문드립니다.
학습관련 질문을 남겨주세요! 상세히 작성주시면 더 좋아요 🙂 안녕하세요, 강사님 🙂이번 질문도 혼자 먼저 구현 후, 강사님의 강의를 들으며 리팩토링을 진행하며 궁금증이 하나 생겨 질문 드립니다. 저는 search-api 모듈의 com.library.repository의 NaverBookRepository.class 위치를 강사님과 다르게 external:naver-client 에 위치시켰습니다.(NaverBook/KakaoBook은 external 에 종속된 구현체라고 생각) 그러다 보니, naver-client 모듈이 search-api 모듈에 있는 BookRepository, PageResponse, SearchResponse 를 알아야 했으며, naver-client 모듈이 search-api 모듈을 implementation('...') 으로 의존?참조? 하게 되었습니다. // search-api 모듈 public interface BookRepository { PageResponse<SearchResponse> search(...); } 이렇게 external -> search-api 로 흘러가는 의존 방향에 이질감이 듭니다.(외부 API 가 app 을 안다..?) 그래서 모듈간 의존 방향이 search-api -> external 되도록 강사님 강의처럼 NaverBookRepository 를 search-api 모듈에 위치 시켜도 NaverClient 때문에 search-api에 feign 종속성이 생긴 다는 것이 모듈간 의존성 격리가 되지 않아서 멀티모듈의 장점이 퇴색되었다고 생각합니다. 강사님은 과제가 아닌 실무에서 search-api 와 external 간의 모듈 격리를 어떻게 하시며, 의존 방향을 어떻게 하시는지 궁금합니다. 저의 부족한 지식을 확장할 수 있게 강사님의 인사이트 공유해주시면 감사하겠습니다!
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
Could not resolve org.springframework.boot:spring-boot-starter-validation:2.4.4
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]eclipse 환경에서 validation 예제를 따라가고 있었는데 Bean Validation 강의부터 라이브러리가 다운받아지지 않습니다.Could not resolve: org.springframework.boot:spring-boot-starter-validation:2.4.4위와 같은 메세지가 출력되면서 외부 의존성 라이브러리를 확인해봤을 때, jakarta.validation-apihibernate-validator 라이브러리가 추가되지 않는 것을 확인했습니다. 검색해도 해결방안을 찾지 못해 질문 남깁니다. 어떻게 해결할 수 있을까요? 추가로 Eclipse는 4.16.0 버전 사용중입니다.
-
미해결
클로드 보안 설정
안녕하세요 클로드를 회사에서 사용하려고 하는데요 웹프롬프트및 CLI에 보안설정을 하려고 하는데 제가 한 방법이 맞는지 모르겠어서요 혹시 보통은 보안설정을 어떻게 설정하고 계신지 궁금합니다
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
REQUIRES_NEW 해결 방법에 대해서 질문있습니다!!
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]전체 롤백을 방지하기 위해 REQUIRES_NEW를 사용하면 된다고 하셨는데 그럼 Service의 트랜잭션과는 완전히 분리되는건가요??MemberRepository가 롤백이 발생해서전체 서비스가 롤백되야 하지만서비스가 호출한 LogRepository가 커밋을 하는 경우도 발생하지 않나요??
-
해결됨서버개발자 과제전형 완벽가이드 - 1편
패키지 vs 모듈 선택 기준
학습관련 질문을 남겨주세요! 상세히 작성주시면 더 좋아요 🙂 안녕하세요, 재밌는 강의 만들어주셔서 감사합니다! 저는 먼저 구현 후, 강사님의 강의를 보며 리팩토링을 진행하고 있습니다. 제가 궁금한 것은 강사님은 external 모듈에서 naver/kakao 를 하위 모듈로 분리하셨는데, 저는 external 하위에 kakao 패키지, naver 패키지로 분리했었습니다. 그래서, 모듈로 분리하신 이유가 무엇인질 고민하다가 naver 와 kakao 의 수정되는 주기가 달라서 빌드/배포에 이점이 있겠다는 생각이 들었는데 강사님은 어떤 기준으로 모듈과 패키지를 선택하시는지 질문 드립니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
오탈자 - @Transactional
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]안녕하세요. 영한님.프로젝트 환경설정 - JPA와 DB 설정, 동작확인 오탈자 제보합니다.강의에서는 Spring을 사용하고 있기 때문에Spring의 org.springframework.transaction.annotation.Transactional을 사용하셨지만수업자료는 jakarta.transaction.Transactional을 사용하고 있습니다.[1. 프로젝트 환경설정 | JPA와 DB 설정, 동작확인]import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.Rollback; import org.springframework.transaction.annotation.Transactional;import문 수정 내용입니다. 감사합니다.
-
미해결제로부터 Kotlin으로 Claude Code 만들기
타입스크립트
타입스크립트도 듣고 싶습니다.혹시 이전 할인 가격으로 구매할 수 있을까요? ㅠ
-
해결됨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 및 조회 성능을 처리하는지 궁금합니다.
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
..
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 지금 영상 따라 진행하던도중 막혔는데 최신 버전 설명도 읽어봤으나 무슨 말인지도 하나도 모르겠습니다.. 계속 오류만 뜨고 화면도 전혀 다르고...
-
해결됨[Lv1] 면접에서 설명할 수 있는 Spring Boot - 경험으로 답변하는 백엔드 개발
색깔구분
11:41분 때 처럼 저런Run창에 Debug 혹은 WARN처럼 색깔을 입혀 구분하게 하고 싶은데 어떻게 해야하나용..?
-
미해결재고시스템으로 알아보는 동시성이슈 해결방법
레디선 테스트코드에서 채널이름은 없어도 되는건가요?
안녕하세요.레디선을 CLI 에서 테스트할 때는 채널명이 있었는데,자바소스로 옮겨서 테스트 할 때는 채널명을 지정하지 않은 것 같아서요.. 이 부분이 이해가 안되서 질문드립니다.