묻고 답해요
156만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
TransactionManager 분리/통합 사용 시 이해가 가지 않는 상황 발생
안녕 킬구횽. 정성 가득한 강의 감사한 마음으로 공부하고 있다. 고맙다.다름이 아니라, 해당 작전에서 설명한대로 TransactionManager을 분리해서 사용하고 있었는데, 이때 이해가 가지 않는 상황이 있다.글이 조금 길어서, 요약을 먼저 하겠다.요약비즈니스용 트랜잭션 매니저(JPA)과 메타데이터용 트랜잭션 매니저(JDBC)을 분리한 경우, UnexpectedRollbackException이 발생한 후에 OptimisticLockingFailureException까지 추가로 발생한다.그러나 트랜잭션 매니저를 분리하지 않은 경우, UnexpectedRollbackException은 발생하지만 OptimisticLocking 예외는 발생하지 않는다.이유가 궁금하다.상황 설명다음은 @Configuration 클래스다. @Bean @Primary @ConfigurationProperties("spring.datasource.service") public DataSource dataSource() { return DataSourceBuilder.create() .type(HikariDataSource.class) .build(); } @Bean @BatchDataSource @ConfigurationProperties("spring.datasource.batch") public DataSource batchDataSource() { return DataSourceBuilder.create() .type(HikariDataSource.class) .build(); } @Bean @Primary public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); } @Bean @BatchTransactionManager public PlatformTransactionManager batchTransactionManager(@BatchDataSource DataSource dataSource) { return new JdbcTransactionManager(dataSource); }다음은 job을 구성하는 (잘못 작성된) tasklet이다. 트랜잭션 전파 속성은 Propagation.REQUIRED를 사용하고 있다.class TestTasklet implements Tasklet{ private final TestRepository testRepository; @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { try{ // testRepository의 @Transactional method 호출 // but @Transactional method에서 RuntimeException을 throw } catch(RuntimeException e){ // sucess process logic } return RepeatStatus.FINISHED; }위 코드에서, 예외를 캐치하는 것으로 예외를 처리한 것은 나의 실수였다.런타임 예외를 던지는 트랜잭션은 rollback-only 마킹 처리되어 해당 트랜잭션이 커밋될 수 없었기 때문이다. 이해가 가지 않는 지점은 지금부터다. 이를 설명하기 위해 내가 파악한 흐름을 정리해봤다. 오류가 있을 수 있다. (비즈니스: JPA / 메타 데이터: JDBC) 트랜잭션 매니저를 분리하는 경우TransactionTemplate의 execute 메서드 실행 doInTransaction 메서드 실행 시작 TestTasklet의 execute메서드의 실행 * transaction from JPAexecute메서드 내부에서 런타임 예외가 발생하는 트랜잭션 메서드 호출 -> 트랜잭션에 rollback-only 마킹됨내부적으로 정상 처리하였으므로 RepeatStatus.FINISHED 반환StepExecution update (version 1 -> version 2) 커밋 * 메타데이터용 DB 커넥션 사용하는 것을 확인함doInTransaction 메서드 실행 완료TransactionTemplate의 execute 메서드에서 커밋 시도 * transaction from JPAUnexpectedRollbackException발생 * rollback-only 마킹으로 인함롤백 시작version 1 -> version 2로 StepExecution update 시도이때 다음 예외가 발생한다.OptimisticLockingFailureException: Attempt to update step execution id=4 with wrong version (1), where current version is 2 반면, 트랜잭션 매니저를 분리하지 않으면 OptimisticLocking 예외가 발생하지 않는데,왜 OptimisticLocking 예외가 발생하지 않는지 궁금하다. (비즈니스, 메타 데이터: JPA ) 트랜잭션 매니저를 분리하지 않는 경우TransactionTemplate의 execute 메서드 실행 doInTransaction 메서드 실행 시작TestTasklet의 execute메서드의 실행execute메서드 내부에서 런타임 예외가 발생하는 트랜잭션 메서드 호출 -> 트랜잭션에 rollback-only 마킹됨내부적으로 정상 처리하였으므로 RepeatStatus.FINISHED 반환StepExecution update (version 1 -> version 2) 커밋doInTransaction 메서드 실행 완료TransactionTemplate의 execute 메서드에서 커밋 시도UnexpectedRollbackException 발생롤백 시작version 1 -> version 2로 StepExecution update 시도OptimisticLock 예외가 터지지 않고 정상적으로 버전 업데이트가 완료된다.이때 OptimisticLocking 예외가 발생하지 않았다는 것은, 현재 stepExecution의 버전이 1이라는 것으로 받아들여진다.의문인 점은, StepExecution update (version 1 -> version 2)이 커밋되는 것을 디버깅을 통해 확인했는데, 어째서 롤백 시점에서 stepExecution의 버전이 1이냐는 것이다.무언가 엔티티 매니저와 관련이 있는 것 같은데, 잘모르겠다.도움이 될까하여, 로그 일부를 첨부한다.트랜잭션 매니저 분리하는 경우2025-07-27T22:16:13.626+09:00 TRACE 141032 --- [server] [ main] o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 1, parameter value [28], value class [java.lang.Long], SQL type unknown 2025-07-27T22:16:13.626+09:00 TRACE 141032 --- [server] [ main] o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.batch.core.repository.support.SimpleJobRepository.update] 2025-07-27T22:16:13.626+09:00 DEBUG 141032 --- [server] [ main] o.s.jdbc.support.JdbcTransactionManager : Initiating transaction commit 2025-07-27T22:16:13.626+09:00 DEBUG 141032 --- [server] [ main] o.s.jdbc.support.JdbcTransactionManager : Committing JDBC transaction on Connection [HikariProxyConnection@33286612 wrapping org.postgresql.jdbc.PgConnection@6ae1d5f1] 2025-07-27T22:16:13.627+09:00 DEBUG 141032 --- [server] [ main] o.s.jdbc.support.JdbcTransactionManager : Releasing JDBC Connection [HikariProxyConnection@33286612 wrapping org.postgresql.jdbc.PgConnection@6ae1d5f1] after transaction 2025-07-27T22:16:13.627+09:00 DEBUG 141032 --- [server] [ main] o.s.jdbc.support.JdbcTransactionManager : Resuming suspended transaction after completion of inner transaction 2025-07-27T22:16:13.627+09:00 DEBUG 141032 --- [server] [ main] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit 2025-07-27T22:16:13.627+09:00 DEBUG 141032 --- [server] [ main] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(858762286<open>)] 2025-07-27T22:16:13.630+09:00 INFO 141032 --- [server] [ main] o.s.batch.core.step.tasklet.TaskletStep : Commit failed while step execution data was already updated. Reverting to old version. 2025-07-27T22:16:13.630+09:00 DEBUG 141032 --- [server] [ main] o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(858762286<open>)] after transaction 2025-07-27T22:16:13.630+09:00 DEBUG 141032 --- [server] [ main] o.s.batch.repeat.support.RepeatTemplate : Handling exception: org.springframework.transaction.UnexpectedRollbackException, caused by: org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only 2025-07-27T22:16:13.631+09:00 DEBUG 141032 --- [server] [ main] o.s.batch.repeat.support.RepeatTemplate : Handling fatal exception explicitly (rethrowing first of 1): org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only 2025-07-27T22:16:13.633+09:00 ERROR 141032 --- [server] [ main] o.s.batch.core.step.AbstractStep : Encountered an error executing step switchAliasTargetStep in job addressIndexingJob분리하지 않는 경우2025-07-27T22:18:22.239+09:00 TRACE 114800 --- [server] [ main] o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 1, parameter value [8], value class [java.lang.Long], SQL type unknown 2025-07-27T22:18:22.240+09:00 TRACE 114800 --- [server] [ main] o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.batch.core.repository.support.SimpleJobRepository.update] 2025-07-27T22:18:22.240+09:00 DEBUG 114800 --- [server] [ main] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit 2025-07-27T22:18:22.240+09:00 DEBUG 114800 --- [server] [ main] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(707576293<open>)] 2025-07-27T22:18:22.241+09:00 INFO 114800 --- [server] [ main] o.s.batch.core.step.tasklet.TaskletStep : Commit failed while step execution data was already updated. Reverting to old version. 2025-07-27T22:18:22.242+09:00 DEBUG 114800 --- [server] [ main] o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(707576293<open>)] after transaction 2025-07-27T22:18:22.242+09:00 DEBUG 114800 --- [server] [ main] o.s.batch.repeat.support.RepeatTemplate : Handling exception: org.springframework.transaction.UnexpectedRollbackException, caused by: org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only 2025-07-27T22:18:22.242+09:00 DEBUG 114800 --- [server] [ main] o.s.batch.repeat.support.RepeatTemplate : Handling fatal exception explicitly (rethrowing first of 1): org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only 2025-07-27T22:18:22.246+09:00 ERROR 114800 --- [server] [ main] o.s.batch.core.step.AbstractStep : Encountered an error executing step switchAliasTargetStep in job addressIndexingJob
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
Spring Batch에서의 비즈니스 로직 처리 관련 질문
13. jpa reader,writer 까지만 보고 질문드립니다.JpaPagingItemReader, JpaItemWriter를 사용해서 JPA 기반으로 DB에 직접 접근해 처리할때, Writer나 Processor에서 복잡한 비즈니스 로직이 필요한 경우에는 어떻게 설계하는 것이 좋은지 궁금합니다.만약 주문을 처리하는 배치가 있다고 했을 때배치 작업에서 주문을 조회 (JpaPagingItemReader-Entity 리턴)writer에서주문 상태 변경주문 내역 추가배송 테이블에 적재 등 여러 도메인을 걸치는 비즈니스 로직 수행 필요이렇게 되면 reader에서 조회한 것을 processor에서 command와 같은 객체로 변환해서 writer에서는 service 로직을 호출하는 것이 좋을까요?
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
application.yaml 설정
프로젝트 수행시에 itemReader로 데이터 조회가 안된다면, application.yaml 설정에 data: mongodb: database: cyberops추가해보세요~🤔
-
해결됨죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
JobLauncherTestUtils 의존성 주입
킬구형, 테스트 할 때 JobLauncherTestUtils 빈을 주입받는 부분에서 궁금한 게 있어. @Autowired private JobLauncherTestUtils jobLauncherTestUtils;spring batch 테스트를 할 때 JobLauncherTestUtils 을 AutoWired 를 사용해서 필드 주입을 받으면 테스트가 잘 동작하는데, @RequiredArgsConstructor class InFearLearnStudentsBrainWashJobConfigTest { private final JobLauncherTestUtils jobLauncherTestUtils;생성자 주입으로 받으려고 하면 아래처럼 에러가 나는 이유가 뭘까?No ParameterResolver registered for parameter [final org.springframework.batch.test.JobLauncherTestUtils jobLauncherTestUtils] in constructor ~~그리고 AutoWired 로 필드 주입을 받으면 동작은 잘 하지만, IDE에서 Could not autowire. No beans of 'JobLauncherTestUtils' type found. 이렇게 빨간 줄이 뜨는 건 왜일까? 인터넷 서칭해봐도 플러그인 설치를 통한 해결 방법은 있지만 해답은 못 찾았고, 지피티 설명은 이해가 안돼서 여기에 물어봐.미리 고마워!
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
구분자로 분이된 형식의 파일 읽기 소스 오류 문의
☠ 질문 가이드 ☠ " 시스템 종결자의 지령이다. 질문하기 전에 이 규칙들을 숙지하도록. " 1. 코드 실행에 문제가 있다고?전체 코드를 보여줘라. 단편적인 에러 메시지만으로는 아무것도 알 수 없다.실행 환경도 알려달라. JDK 버전, 스프링 버전 등을 함께. 2. 오타를 발견했나?즉시 제보하도록. 자네같은 날카로운 눈을 가진 동료가 필요하다. 3. 질문은 자유롭게"이런 걸 물어봐도 될까요?" 같은 소심한 멘트는 불필요하다. 궁금한 건 바로 물어봐라. 배치 시스템에 소심한 건 없다. 4. 검색은 기본비슷한 질문이 있는지 먼저 확인하도록.하지만 이해가 안 된다면? 주저하지 말고 추가 질문해라.GPT가 거짓말친다고? 나에게로 오라. 💀 5. 서로 존중하라여기는 모두가 시스템을 지배하고자 하는 동료들이다.서로를 이해하고 돕는 문화를 만들어가자. ⛔ 인프런 서비스 자체에 대한 문의는 1:1 문의하기로.💀그쪽 서버는 막강한 CTO가 있어 건드리지 않는 게 좋을 거다 💀- KILL-9 올림 구분자로 분리된 형식의 파일 읽기org.springframework.batch.item.file.FlatFileParseException: Parsing error at line: 2 ... ... Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'severity' of bean class [com.system.batch.onego_batch.config.SystemFailureJobConfig$SystemFailure]: Bean property 'severity' is not writable or has an invalid setter method.위와 같은 에러가 나는데 여기서 아래 소스 보면 set method가 없어서 그러는데 위에 @Data를 추가하면 될거 같아요! public static class SystemFailure { private String errorId; private String errorDateTime; private String severity; private Integer processId; private String errorMessage; // setter, toString() rm -rf }P.S.존댓말로 질문하면 rm -rf를 시전한다. 편하게 물어보도록.강의에서 놓친 부분이나 더 보충하면 좋을 내용도 자유롭게 제보하라. 너희의 피드백이 이 강의를 더 강력하게 만든다. 🔥 시스템을 함께 진화시켜 나가자.🔥
-
해결됨강의 하나로 끝내는 백엔드 모든 지식!
강의 자료 PDF 제공 가능 여부 문의
안녕하세요 어제 강의를 신청하여 시작하였습니다. 노션으로 강의자료를 제공해주시던데.. 혹시 PDF 자료로 일괄적으로 제공이 가능하신가요? 인쇄물로 공부하고 싶어서 그렇습니다. 안녕하세요! 수강 중 궁금한 점이 생겼을 때, 어떻게 질문해야 원하는 답변을 더 빠르고 정확하게 얻을 수 있을까요? 여러분의 소중한 질문이 더 효과적으로 해결될 수 있도록, 몇 가지 질문 방법을 안내해 드릴게요!1. 무엇이 궁금한지 명확하게 알려주세요! 🎯어떤 강의 내용에 대한 질문인가요?예: "섹션 3, 챕터 11: 인증과 인가 제대로 알기 강의 내용 중 JWT 토큰 발급 과정에서 궁금한 점이 있습니다."어떤 목표를 달성하고 싶으셨나요? / 어떤 결과를 예상하셨나요?예: "서버에서 토큰을 정상적으로 발급받아 클라이언트에 전달하는 것을 목표로 했습니다."2. 충분한 정보를 함께 공유해주세요! 💾시도해본 내용 (중요! ⭐):이 문제를 해결하기 위해 어떤 노력을 해보셨는지 알려주세요.예: "구글에 'JWT 토큰 만료 해결 방법'을 검색해서 몇 가지 글을 읽어봤지만, 제 상황에 적용하기 어려웠습니다." 또는 "강의 노트를 다시 살펴보며 OOO 개념을 이해하려고 했는데, XXX 부분이 명확하지 않습니다."여러분이 이해하고 있는 내용 (개념 질문 시):단순히 "OOO이 뭐예요?" 보다는, "OOO은 XXX라고 이해했는데, 그렇다면 YYY 상황에서는 어떻게 적용되나요?" 와 같이 여러분의 생각을 함께 공유해주시면 더 깊이 있는 답변이 가능합니다.3. 질문은 명료하고 간결하게! ✨한 번에 한 가지 핵심 질문을 중심으로 작성해주세요. 여러 질문이 있다면 나눠서 질문해주시는 것이 좋습니다.가급적 맞춤법과 띄어쓰기를 지켜주시면 질문을 이해하는 데 큰 도움이 됩니다.질문 제목은 내용을 유추할 수 있도록 명확하게 작성해주세요.나쁜 예: "질문있습니다ㅠㅠ"좋은 예: "섹션5 챕터22 도커 이미지 빌드 시 COPY 명령어 오류 문의"4. 질문 전, 혹시 이미 답변이 있지는 않을까요? 🔍강의 Q&A 게시판이나 관련 커뮤니티에서 비슷한 질문이 이미 있었는지 검색해보는 센스!
-
미해결예제로 뿌수는 코틀린 Kotlin 76제
Null 안정성 관련 질문
Null 을 다루는 방법에 대해서 말씀하신 예제에서는 자바에서도 동일하게 실행할 수 있는데 이 코드가 왜 코틀린에서 우아하게 대처할 수 있는 기능이라고 말씀하셨는지가 궁금합니다.
-
해결됨[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core
로그인 엔드포인트 관련 질문
안녕하세요 코팩님 강의 정말 유용하게 듣고 있습니다 강의를 완강하고 난뒤 코드를 분석하고 있는 중 이상하다고 느낀 부분이 있어 질문드립니다 @Post('login/email') @IsPublic() @UseGuards(BasicTokenGuard) postLoginEmail( @Headers('authorization') rawToken: string, ) { // email:password -> base64 // asdkljoijzxlxck;vjaosi;dfjawe;lkrj -> email:password const token = this.authService.extractTokenFromHeader(rawToken, false); const credentials = this.authService.decodeBasicToken(token); return this.authService.loginWithEmail(credentials); } 이 부분에서 이미 Guards(BasicTokenGuard)가 사용자를 식별하고 심지어 인증까지 맡아 요청 부분에 user 정보까지 넣어둡니다. 그러면 이미 BasicTokenGuard가 로그인의 역할을 다 했는데 왜 한번 더 검증하는지 궁금해서 질문 남깁니다.단순히 Guards의 예제를 위해서인지, 아니면 다른 이유가 있는지 설명해 주시면 정말 감사하겠습니다
-
해결됨Real MySQL 시즌 1 - Part 1
복합 index 문의
안녕하세요, 강의 잘 듣고 있습니다. 04 페이징 쿼리 작성 강의 > 데이터 개수 기반 방식 (동등 조건 사용 시) (9:36 부근) 에 나온 예시에 대한 질문입니다. KEY index_userid_id (user_id, id)로 인덱스가 있는데요, user_id +id 가 아닌, user_id만 인덱스로 걸어도 N회차 쿼리가 잘 동작 할까요? where 절에 user_id, id를 사용하고, ORDER BY 에 id가 있기 때문에 user_id + id 인덱스가 필요한 걸까요? 조금 더 자세히 알려주시면 감사하겠습니다.
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
예제 실행 명령어 오류
SystemDeathJobConfig 예제 실행 명령어가> ./gradlew bootRun --args='--spring.batch.job.name=recordSystemKillJob inputFile=/path-to-kill-batch-system/system_death.jsonl' ... SystemDeath[command=destroy, cpu=99, status=memory overflow] SystemDeath[command=explode, cpu=100, status=cpu meltdown] SystemDeath[command=collapse, cpu=95, status=disk burnout] ...로 되어 있는데job.name이 recordSystemKillJob -> systemDeathJob으로 바껴야 할 것 같습니다🫡JsonRecordSeparatorPolicy 예제도 함께 바꿔야 할 것 같아요🫡
-
해결됨Real MySQL 시즌 1 - Part 1
강의
안녕하세요, ppt 자료제공이 안되는 건가요?일년 전 문의 글이 있어보니, 문제가 있어 당장에 공개를 안하고 있다고 하신글을 봤늗네 아직도 해결 되지 않으신걸까요?구매하였는데, 당황스럽네요...
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
[분산 서버 로그 처형 작전] 중 scp 오류
[작전명: 분산 서버 로그 처형 작전] [상황설명]: 코드 작성 후 최종 실행시, 비밀번호 입력 프롬프트 없이 아래 에러 발생org.springframework.batch.core.step.tasklet.SystemCommandException: Execution of system command failed with exit code 255 at org.springframework.batch.core.step.tasklet.SystemCommandTasklet.execute(SystemCommandTasklet.java:129) ~[spring-batch-core-5.2.2.jar:5.2.2][환경]: mac, intellij [분석]: 터미널에서는 scp localhost 하면 비밀번호 프롬프트가 잘 떴으나, 배치실행시에만 에러가 발생[추가시도]ssh-keygen -t rsa -b 4096 으로 키쌍 생성 후ssh-copy-id -i ~/.ssh/id_rsa.pub localhost 공개키를 등록 후ssh localhost 하여 비밀번호 없이 접근 확인 이후 정상 처형 확인 완료
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
jobConfiguration 구성 질문
안녕하세요, 강의를 보던 중 문득 궁금한 점이 생겨 문의드립니다. Spring Batch에서 Job 설정 클래스를 구성할 때, 아래와 같이 두 가지 스타일이 혼용되는 것을 자주 보게 되는데요.🥔 PotatoJobConfiguration (생성자 주입 방식)@RequiredArgsConstructor public class PotatoJobConfiguration { private final JobRepository jobRepository; private final PlatformTransactionManager transactionManager; @Bean public Job potatoJob() { return new JobBuilder("potatoJob", jobRepository) .start(potatoStep()) .build(); } @Bean public Step potatoStep() { return new StepBuilder("potatoStep", jobRepository) .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED, transactionManager) .build(); } }🥬 KimchiJobConfiguration (메서드 파라미터 주입 방식)@RequiredArgsConstructor public class KimchiJobConfiguration { @Bean public Job kimchiJob( final JobRepository jobRepository, final Step kimchiStep ) { return new JobBuilder("kimchiJob", jobRepository) .start(kimchiStep) .build(); } @Bean public Step kimchiStep( final JobRepository jobRepository, final PlatformTransactionManager transactionManager ) { return new StepBuilder("kimchiStep", jobRepository) .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED, transactionManager) .build(); } }강의를 보다 보면 예시마다 사용되는 경우가 다르던데,어떤 기준에 따라 생성자 주입 방식과 메서드 파라미터 주입 방식을 구분해서 사용하시는지 궁금합니다. 실무에서도 보통 이 둘을 혼용하는 편인지,아니면 상황에 따라 선호되는 방식이 명확히 나뉘는지 조언 부탁드립니다. 감사합니다.
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
jobExecutionContext 에 접근하는 방법
치치직...1장 작전 3에서,키보드는 꽉 잘 잡았는데 궁금한게 발생했다. jobExecutionContext 에 접근/수정할 때chunkContext 를 통해서 접근하는 방법과 contribution 을 통해서 접근하는 방법 두가지를 알게 되었다. 일부러 두가지 침투 방식 을 알려준 것 같으나 두 방식의 차이가 있는지, 무엇이 더 선호되는지 아니면 취향의 문제인지 궁금하다.
-
미해결하루만에 배우는 AWS OpenSearch
Semantic Search 관련 문의
다음과 같은 양식으로 남겨주세요.질문을 한 배경 : Semantic Search는 어떻게 가능한가요?질문내용 : Semantic Search는 어떻게 가능한가요? 허깅페이스에서 외부 모델을 가져와서 한국어 시멘틱 검색이 가능하도록 만들려 하는데 한국어 형태소 분석만 존재해서 이 부분을 물어보고 싶습니다.
-
미해결[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core
yarn으로 express 다운 후 node 2_server.js 실행 안되는 경우
저는 yarn node 2_server.js 로 실행하니 되네요![코드팩토리 디스코드]https://bit.ly/3HzRzUM - 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
강의 자료를 PDF로 받아볼 수 없나요?
강의 자료를 PDF로 받아볼 수 없나요?? 제목이 곧 질문입니다!
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
오타 확인
☠ 질문 가이드 ☠ " 시스템 종결자의 지령이다. 질문하기 전에 이 규칙들을 숙지하도록. " 1. 코드 실행에 문제가 있다고?전체 코드를 보여줘라. 단편적인 에러 메시지만으로는 아무것도 알 수 없다.실행 환경도 알려달라. JDK 버전, 스프링 버전 등을 함께. 2. 오타를 발견했나?즉시 제보하도록. 자네같은 날카로운 눈을 가진 동료가 필요하다.StepExecution stepExecution = contribution.getStepExecution(); ExecutionContext stepExecutionContext = stepExecution.getExecutionContext(); Integer infiltrationCount = (Integer) stepContext.get("infiltrationCount"); JobExecution jobExecution = stepExecution.getJobExecution(); jobExecution.getExecutionContext().put("totalInfiltrations", infiltrationCount);혹시 stepExecutionContext가 stepContext인데 이름이 오타가 난게 맞는지??7강 자료에서 찾은것이다. 3. 질문은 자유롭게"이런 걸 물어봐도 될까요?" 같은 소심한 멘트는 불필요하다. 궁금한 건 바로 물어봐라. 배치 시스템에 소심한 건 없다. 4. 검색은 기본비슷한 질문이 있는지 먼저 확인하도록.하지만 이해가 안 된다면? 주저하지 말고 추가 질문해라.GPT가 거짓말친다고? 나에게로 오라. 💀 5. 서로 존중하라여기는 모두가 시스템을 지배하고자 하는 동료들이다.서로를 이해하고 돕는 문화를 만들어가자. ⛔ 인프런 서비스 자체에 대한 문의는 1:1 문의하기로.💀그쪽 서버는 막강한 CTO가 있어 건드리지 않는 게 좋을 거다 💀- KILL-9 올림 P.S.존댓말로 질문하면 rm -rf를 시전한다. 편하게 물어보도록.강의에서 놓친 부분이나 더 보충하면 좋을 내용도 자유롭게 제보하라. 너희의 피드백이 이 강의를 더 강력하게 만든다. 🔥 시스템을 함께 진화시켜 나가자.🔥
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
JobParameter의 JSON 표기법 명령어 오류
JSON 표기법 실습을 진행중이다. 아래 명령어를 실행하는데, 에러가 난다. json 문자열 속 쌍따옴표를 백슬래시로 이스케이프 하는게 안 먹혀서 그런 것 같다. 견문이 부족하여 스스로 해결 못 하였다. GPT가 알려주는 대로도 해봤지만 따옴표가 문자열에 들어가지 않는다. 문자열이 어떻게 입력되는지는 아래에 있는 에러코드에서 확인 가능하다. 혹시나 답을 알 수 있을까 질문한다. window 환경, 스프링부트 3.5.2, jdk 17이고, 인텔리제이에서 실습중이다.intellij 로컬 터미널과, git bash등에서 아래 명령어를 실행했으나 실패하였다. ./gradlew bootRun --args="--spring.batch.job.name=terminatorJob infiltrationTargets='{\"value\":\"판교서버실,안산데이터센터\",\"type\":\"java.lang.String\"}'" ./gradlew bootRun --args="--spring.batch.job.name=terminatorJob infiltrationTargets={\"value\":\"판교_서버실,안산_데이터센터\",\"type\":\"java.lang.String\"}" package com.system.batch.killbatchsystem.JobParameter; import lombok.extern.slf4j.Slf4j; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.converter.JobParametersConverter; import org.springframework.batch.core.converter.JsonJobParametersConverter; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import org.springframework.transaction.PlatformTransactionManager; @Configuration @Slf4j public class SystemTerminatorConfig { @Bean public Job processTerminatorJob(JobRepository jobRepository, Step terminationStep){ return new JobBuilder("terminatorJob", jobRepository) .start(terminationStep) .build(); } @Bean public Step terminationStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, Tasklet terminatorTasklet ){ return new StepBuilder("terminationStep", jobRepository) .tasklet(terminatorTasklet, transactionManager) .build(); } // @Bean // @StepScope // public Tasklet terminatorTasklet(@Value("#{jobParameters['terminatorId']}")String terminatorId, // @Value("#{jobParameters['targetCount']}") Integer targetCount){ // return (contribution, chunkContext) -> { // log.info("시스템 종결자 정보:"); // log.info("ID: {}", terminatorId); // log.info("제거 대상 수: {}", targetCount); // log.info("🎇 SYSTEM TERMINATOR {} 작전을 개시합니다", terminatorId); // log.info("👻 {}개의 프로세스를 종료합니다.", targetCount); // // for(int i =1; i<=targetCount; i++){ // log.info("👻 프로세스 {} 종료 완료!", i); // } // // log.info("🎯 임무 완료: 모든 대상 프로세스가 종료되었습니다."); // return RepeatStatus.FINISHED; // }; // } @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; }; } @Bean public JobParametersConverter jobParameterConverter() { return new JsonJobParametersConverter(); } } 오류 내용(명령어를 intellij 로컬 터미널에서 실행)PS C:\Users\Desktop\study\스프링배치\kill-batch-system> ./gradlew bootRun --args="--spring.batch.job.name=terminatorJob infiltrationTargets={\"value\":\"판교서버실,안산데이터센터\",\"type\":\"java.lang.String\"}" . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.5.2) 2025-06-23T10:10:06.623+09:00 INFO 36520 --- [kill-batch-system] [ main] c.s.b.k.KillBatchSystemApplication : Starting KillBatchSystemApplication using Java 17.0.15 with PID 36520 (C:\Users\Bistelligence\Desktop\study\스프링배치\kill-batch-system\build\classes\java\main started by Bistelligence in C:\Users\Bistelligence\Desktop\study\스프링배치\kill-batch-system) 2025-06-23T10:10:06.625+09:00 INFO 36520 --- [kill-batch-system] [ main] c.s.b.k.KillBatchSystemApplication : No active profile set, falling back to 1 default profile: "default" 2025-06-23T10:10:07.436+09:00 INFO 36520 --- [kill-batch-system] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2025-06-23T10:10:07.577+09:00 INFO 36520 --- [kill-batch-system] [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:bc0bd0fe-d717-4e43-908b-4ee615d3746b user=SA 2025-06-23T10:10:07.579+09:00 INFO 36520 --- [kill-batch-system] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2025-06-23T10:10:07.834+09:00 INFO 36520 --- [kill-batch-system] [ main] c.s.b.k.KillBatchSystemApplication : Started KillBatchSystemApplication in 1.634 seconds (process running for 1.953) 2025-06-23T10:10:07.836+09:00 INFO 36520 --- [kill-batch-system] [ main] o.s.b.a.b.JobLauncherApplicationRunner : Running default command line with: [infiltrationTargets={\value\:\판교서버실,안산데이터센터\,\type\:\java.lang.String\}] 2025-06-23T10:10:07.884+09:00 INFO 36520 --- [kill-batch-system] [ main] .s.b.a.l.ConditionEvaluationReportLogger : Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. 2025-06-23T10:10:07.898+09:00 ERROR 36520 --- [kill-batch-system] [ main] o.s.boot.SpringApplication : Application run failed org.springframework.batch.core.converter.JobParametersConversionException: Unable to decode job parameter {\value\:\판교서버실,안산데이터센터\,\type\:\java.lang.String\} at org.springframework.batch.core.converter.JsonJobParametersConverter.decode(JsonJobParametersConverter.java:121) ~[spring-batch-core-5.2.2.jar:5.2.2] at org.springframework.batch.core.converter.DefaultJobParametersConverter.getJob ~~~~ ~~~~ Git Bash에서 명령어를 실행할 경우 데이터는 아래처럼 입력되었다. org.springframework.batch.core.converter.JobParametersConversionException: Unable to decode job parameter {value:판교_서버실,안산_데이터센터,type:java.lang.String} ~~~~ > Task :bootRun FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':bootRun'. > Process 'command 'C:\Program Files\Eclipse Adoptium\jdk-17.0.15.6-hotspot\bin\java.exe'' finished with non-zero exit value 1 * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. > Get more help at https://help.gradle.org. BUILD FAILED in 3s
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
외부 API 호출 적재 방법
외부 API를 호출해서 DB에 적재하는 배치를 구성을 하려고한다. 이때까지 문서 내용을 바탕으로는 Chunk가 아닌 Tasklet으로 해도 문제가 없다고 판단이든다. 하지만 공공 데이터 API를 1번 호출 할 때 10건씩만 데이터를 조회해야한다는 단점이있다. 평소에 하루에 1번 호출하겠지만 지난 3달의 데이터를 일단 적재를 해야한다. 이런 상황에서도 RepeatStatus.CONTINUABLE이 아닌 while문으로 계속 호출하고 끝나면 RepeatStatus.FINISHED로 반환해도 되는 지 궁금하다. 또한 외부API를 호출 할 때 PageNo도 명시를해줘야하는데 pageNo을 1씩 증가시키다가 특정 pageNo일때 오류가나면 해당 pageNo일때 부터 동작하도록 하려면 Jenkins의 매개변수 값을 설정해서 다시 batch를 돌리려고한다.하지만 아래처럼 PAGE_NO을 정수로하고싶었는데 String으로 해야한다는 점이있어, 리스너에서 해당 매개변수를 Integer 또는 Long 타입으로 변경을 해야하는 과정을 추가해야 할 지 아니면 더 수월한 방법이 있는 지 궁금하다. 💀 [시스템 인텔리전스]일반적으로 Tasklet에서 DB 트랜잭션 관리가 필요한 않은 경우가 많지는 않다. 모든 Tasklet이 데이터베이스 작업을 포함하는 것은 아니기 때문이다. 예를 들어, 파일을 정리하거나, 외부 API를 호출하거나, 단순한 알림을 보내는 작업이라면 DB트랜잭션을 고려할 필요가 없다. 그러므로 반복이 필요할 경우 작업의 성격을 잘 판단해서 while문으로 처리할지, RepeatStatus로 처리할지 현명하게 선택하라. 모든 반복을 RepeatStatus로 처리하는 것이 능사는 아니다.