묻고 답해요
160만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1
아키텍처 테스트에 대해 질문있습니다.
강의를 NestJS로 적용해 따라가고 있습니다. 마지막 “ArchUnit을 이용한 아키텍처 테스트” 파트에서 Node/NestJS 환경에서는 어떤 방식으로 아키텍처 규칙을 테스트/검증하는 것이 좋은지 궁금합니다.자바에서는 ArchUnit으로 레이어 규칙, 패키지 의존성, 순환 참조 등을 명시적으로 검사할 수 있는데, Node 진영에서는 유사한 도구로 무엇을 추천하실까요? 제가 찾은 것은 “ts-arch”였고, 폴더/슬라이스 의존성, 사이클 검사를 지원하는 것으로 보입니다. 적용을 하다가 실패를 했는데, 다른 방법이 있다면 조언 부탁드립니다. 😭😭😭
-
미해결토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1
Part 2 강의는 언제쯤 나오는지 궁금해요
안녕하세요, 강의 정말 잘보았습니다!!Part1을 전부 보고 나니까 part2가 언제쯤 나올지 궁금해서 질문남깁니다!
-
미해결자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
spring 개념적인 질문
스프링을 사용하는 이유 중 하나가 스프링 컨테이너를 통한 의존성 주입(DI)이라고 알고 있습니다.그러면 스프링 컨테이너가 Bean을 관리하기 때문에, 자동으로 싱글톤 패턴이 적용된다고 이해해도 될까요?
-
미해결스프링 핵심 원리 - 고급편
실무 멀티스레딩에 대한 궁금증
=========================================[질문 내용]안녕하세요, 영한님? 영한님의 자바와 스프링 전편의 로드맵을 수강 중인 개발자입니다. 항상 영한님의 강의를 들으며 스텝업하는 부분이 있기에 너무 감사하단 인사를 먼저 드리고 싶습니다. 본격적인 질문은 스레드 로컬을 포함한 멀티 스레딩 관련 내용입니다. 영한님의 유튜브 영상 중 초보 개===============================[질문 내용]안녕하세요, 영한님? 영한님의 자바와 스프링 전편의 로드맵을 수강 중인 개발자입니다. 항상 영한님의 강의를 들으며 스텝업하는 부분이 있기에 너무 감사하단 인사를 먼저 드리고 싶습니다. 영한님의 유튜브 영상 중 고민 많은 개발자가 찾아왔다 를 보고 저 역시 처음부터 높은 목표를 가지지 않고 당장 입사 가능한 회사에 들어가 1년간 업무를 해봤습니다. 그래서 그런지 몰라도 이전 회사에선 영한님 강의에서 배운 내용들을 10% 조차 적용하지 못해봤던 것 같고 그 부분에 회의를 조금 느낀 것인지 안주하지 않겠다는 생각을 가지고 퇴사 후 교육을 듣게 되었던 것 같습니다. 본격적인 질문은 스레드 로컬을 포함한 멀티 스레딩 관련 내용입니다. 자바 고급편에서 다뤄주신 executorService나 이번의 스레드 로컬과 같은 멀티스레드 관련 지식을 적용할만한 코드가 이전 회사에선 없었습니다. 기껏해야 비동기 API 구성시 Future를 사용한 것 정도일까요? 그래서 궁금해졌습니다. 스프링 부트에서는 기본적으로 대부분의 컴포넌트가 싱글톤 스코프로 관리되기 때문에, stateless하게 설계하면 일반적으로 스레드 안전성 문제가 드물다고 알고 있습니다.다만 실무에서는 의도치 않게 stateful한 코드가 들어가는 경우가 자주 발생하곤 하는데요.(그게 실수가 되었건 불가피하건 말이죠)> 실제로 규모가 있는 서비스 회사에서는 이런 문제를 사전에 방지하기 위해 클래스/컴포넌트 설계 가이드나 명세 단계에서 thread-safe 설계를 강제하는 편인가요?아니면 설계 때보단 코드 리뷰나 테스트 중 문제 발견 후 사후적으로 수정·보완하는 프로세스를 거치나요?
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
예제 궁금증
실제로 실행을 못해보는환경이라서 질문하는건데,JobLauncher를 활용한 REST API 구현의 예제같은경우 컨트롤러 하나를 생략없이 다 표현한거같은데 jobRegistry 는 di받지않았는데 어떻게 실행하는거임?빼먹은건가? job = jobRegistry.getJob(jobName);
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
TransactionManager 분리
TransactionManager 분리에 대해서 이해가 잘 가지 않는게 있어. 실제 운영 환경에서는 배치와 비즈니스 데이터 DB를 분리하는게 필수라고 했잖아?근데 이 분리의 단위가 배치용 메타데이터 저장만 분리를 하는게 맞는거야? 현재 사이드 프로젝트에서 멀티모듈 구조에 (MSA는 아님) API 모듈과 배치 모듈을 따로 분리한 상태야.유저 데이터에서 생일을 뽑아서 내일 생일인 유저에게 FCM 을 발송하는 배치를 만드는데,이때 만들어준 예제처럼 @BatchDataSource와 비즈니스 로직용 @Primary DataSource를 분리하게 되면,API 모듈용 DB Connnection을 배치에서도 똑같이 갖다 쓰는거 아니야 ?? 즉, 배치에서 API 쪽 커넥션을 가져다 써서 배치가 돌 때 커넥션이 고갈날 수 있지 않을까? 라는 생각이 들었어지금 이해한 바로는 @BatchDataSource, @BatchTransactionManager를 분리하고 주입해줘도 Reader -> Processor -> Writer 에는 @Primary 걸 쓰는것 같은데 맞아 ?나는 DB 분리와 함께, 비즈니스 로직에 대한 커넥션, 트랜잭션도 배치용으로 분리하고 싶은데 이럴땐 어떻게 해야해?특히나 배치에서도 JpaTransactionManager를 쓰고 싶은 경우에는 어떻게 해야해 ?원하는 바는, API 처리용 DB 커넥션은 커넥션대로 있고, 배치 메타데이터용 커넥션 따로, 배치에서 라이브 DB에서 유저 데이터를 가져오는 커넥션 따로 구성하고 싶어 (배치가 API 모듈 에 영향을 주지 않았으면 해서,,,) 혹시 내가 강의를 제대로 이해를 못한거라면 알려줘
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
오타(?) 발견
킬구형 강의 자료 중간에 이상한 문구 발견해서 제보해강의 회차: 5장. 작전4: Flow - 배치의 흐름을 지배하라 (분기점에서 생사를 쥐락펴락하라 ☠🏴☠)이상한 문장: 즉, Spring Batch의 암시적 전환 규칙 대상에서 제외된다는 뜻이다.재시도Claude는 실수를 할 수 있습니다. 응답을 반드시 다시 확인해 주세요.강의 자료 중간에 LLM에서 가져온 내용을 잘못 편집한 것 같아.
-
미해결토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1
코틀린에서 value class 적용 시 문제
안녕하세요 코틀린으로 현재 강의를 수강하고 있는 수강생입니다. 현재 자바로 작성된 코드를 보고 설명과 함께 어떤 이유로 이런 코드를 작성한 것인지 생각하며, 코틀린으로 이 개념을 적용하면 어떻게 작성할 수 있을지 DDD와 클린 아키텍처를 코틀린 문법 활용하여 구상하는 연습 중입니다. 현재 Member 도메인 코드 개선 강의에서 value class 적용하여 필드의 값이 바뀌는 문제(email자리에 nickname이 오더라도 같은 String이라 컴파일 에러가 안 남)를 해결하려 시도했습니다 package org.example.splearn.domain @JvmInline value class Email( val value: String, ) @JvmInline value class Nickname( val value: String, ) @JvmInline value class PasswordHash( val value: String, ) class Member private constructor( val email: Email, var nickname: Nickname, var passwordHash: PasswordHash, var status: MemberStatus, ) { fun activate() { check(status == MemberStatus.PENDING) { "회원이 PENDING 상태가 아닙니다" } this.status = MemberStatus.ACTIVATE } fun deactivate() { check(status == MemberStatus.ACTIVATE) { "회원이 ACTIVE 상태가 아닙니다" } this.status = MemberStatus.DEACTIVATED } fun verifyPassword( password: String, passwordEncoder: PasswordEncoder, ): Boolean = passwordEncoder.matches(password, this.passwordHash.value) fun changeNickname(nickname: String) { this.nickname = Nickname(nickname) } fun changePassword( password: String, passwordEncoder: PasswordEncoder, ) { this.passwordHash = PasswordHash(passwordEncoder.encode(password)) } fun isActive(): Boolean = this.status == MemberStatus.ACTIVATE companion object { fun create( memberCreateRequest: MemberCreateRequest, passwordEncoder: PasswordEncoder, ): Member = Member( email = memberCreateRequest.email, nickname = memberCreateRequest.nickname, passwordHash = PasswordHash( passwordEncoder.encode(memberCreateRequest.password.value), ), status = MemberStatus.PENDING, ) } } 강의대에서는 static 메소드인 of에서 MemberCreateRequest를 파라미터로 사옹하고 있습니다. 코틀린이라 companion object를 사용했구요 그러던 중 "헥사고날 아키텍처의 특성을 고려하면 의존성 외부 로직인 dto가 내부로 향해야 하고 따라서 도메인이 dto에 의존하는 것이 괜찮을까" 하는 의문이 들었습니다. companion object { fun create( email: Email, nickname: Nickname, password: String, passwordEncoder: PasswordEncoder, ): Member = Member( email = email, nickname = nickname, passwordHash = PasswordHash( passwordEncoder.encode(password), ), status = MemberStatus.PENDING, ) }그래서 코드를 수정해 보면 이런 식으로 수정해 볼 수 있을 것 같습니다. 이에 대해서 토비님 의견이 어떠신지 여쭙고 싶습니다
-
미해결Practical Testing: 실용적인 테스트 가이드
ERD 가장자리에 있는 도메인 테스트 질문
ERD 가장자리에 있는 도메인들은 선행적으로 존재해야하는 도메인들이 있다보니 테스트 코드 작성 시 given 부분이 너무 길어져요.어떻게 짜는게 좋은지 의견 부탁드립니다!!
-
해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
자바 map으로 put으로 넣을시 get으로 하는게 좋은 선택인지, 그냥 타자로 치는게 좋은 선택인지?
========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (모르겠음)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]안녕하세요. 강의를 보다가 궁금증이 생겨서 질문을 올립니다.강의 도중에 userA,userB를 map에 넣기 위해서, key값으로 String 으로 "userA", "userB"로 입력 하시 는 것을 보았습니다.(사진참조) 근데 어떤 때에는 get으로 값을 넣는 경우도 있는 것을 생각 할수 있었 습니다. (추가1: getName으로 넣어도 되는거 아닌가?라는 생각 때문에 다른 강의들에서 레파지토리는 어떻게 했는지 살펴봄)(예전 강의에서 save할때) 그래서 어떤 것이, 더 나은 선택 인지, 저는 모르겠습니다.그래서 어떤 때에는 get으로 값을 써야 하고,어떤 때에는 직접 타자로 값을 쳐서 입력해야 하는지 알고 싶습니다. 답변 부탁 드립니다.
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
오타 발견
가령 다음과 같이 getExecutionContextSerializer() 메서드를 오버라이드하면g에 볼드처리안됨--원시적 침투 예제의 BatchConfig에서 DefaultBatchConfiguration 상속을 제거하고@EnableBatchProcessing을 추가하자. 다음과 같이 말이다.예제밑의 예제가 그냥 기존 DefaultBatchConfiguration 방식만 나와있음아마 기존과 수정을 두개 다 표시하는식으로 하고싶었을거같음--JobContext/StepContext: Late-Binding의 최종 무기고키룩형 JobContext/StepContext가 존재하면 배치 스코프가 활성화된 상태라는 것은 알겠어. 근데 이 JobContext/StepSontext 대체 어디에 써먹는거지? 단순히 활성화를 의미하는게전부인가?키룩형 -> 갈매기가 되고싶은 내면의 소리일수있음괜찮음 주변에 돌멩이 지망생도 있고 독수리 지망생,딸기우유 지망생도 있어서 이해할수있음
-
미해결토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1
안녕하세요 코틀린으로 강의 수강 시 도메인 코드 질문드립니다
좋은 추석 보내고 계신가요?현재 코틀린으로 강의를 따라해 보고 있습니다. class Member private constructor( val email: String, var nickname: String, var passwordHash: String, var status: MemberStatus, ) { fun activate() { check(status == MemberStatus.PENDING) { "회원이 PENDING 상태가 아닙니다" } this.status = MemberStatus.ACTIVATE } fun deactivate() { check(status == MemberStatus.ACTIVATE) { "회원이 ACTIVE 상태가 아닙니다" } this.status = MemberStatus.DEACTIVATED } fun verifyPassword( password: String, passwordEncoder: PasswordEncoder, ): Boolean = passwordEncoder.matches(password, this.passwordHash) fun changeNickname(nickname: String) { this.nickname = nickname } fun changePassword(password: String) { this.passwordHash = password } companion object { fun create( email: String, nickname: String, password: String, passwordEncoder: PasswordEncoder, ): Member = Member( email, nickname, passwordEncoder.encode(password), MemberStatus.PENDING, ) } }이러한 식으로 작성하였는데 자바에서는 const로 선언한 객체나 변수가 아닌 이상 기본적으로 가변입니다. 그런데 코틀린에서는 val, var 키워드에 따라서 var로 선언해야 가변 타입이 됩니다. Member 도메인 모델 확장 챕터 수강하고 있는데 이 경우는 도메인에서 가변 속성을 미리 정의하고 해당 속성들을 var로 선언하는 것이 맞을지, 혹은 val을 통해 불변성을 확보하고 새 객체를 생성하여 변경을 처리하는 것이 적합할지 궁금합니다.코틀린에서 도메인 코드를 작성할 때 자바와 다른 문법&개념과 도메인 중심 설계가 종종 난해할 때가 있네요.
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
멀티모듈에서 DB 커넥션 풀 분리
DataSource에 대한 질문 배치를 적용중인데, 멀티모듈에서 배치용 Application을 따로두고, 배치용 yaml에서 datasource를 두었고, api쪽도 yaml에서 datasource를 보고 있다.이때 , 아래와 같이 Config에서 Bean을 통해 Datasource을 생성, JobRepository에 전달해주지 "않아도" 커넥션이 분리가 되는가?API 쪽 디비와, 배치 디비의 커넥션풀을 따로 쓰고싶은데 아래와 같이 별도 세팅 없이 yaml만으로 분리는 안되는지 궁금하다...@Configuration class JpaConfig { @Bean @ConfigurationProperties("spring.datasource") fun batchDataSource(): DataSource { return HikariDataSource() } @Bean fun jobRepository( batchDataSource: DataSource, transactionManager: PlatformTransactionManager, ): JobRepository { return JobRepositoryFactoryBean().apply { setDataSource(batchDataSource) setDatabaseType(DatabaseType.POSTGRES.name) setTransactionManager(transactionManager) afterPropertiesSet() }object } }
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
스프링 DB연결
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 자바부터 강의를 듣고있는데 언어가 이해가 되는부분이 있고 안되는 부분이있는데 이거는 앞에가서 다시 학습을 하고와야하나요!?지금 스프링입문은 여기서 다이해하고 다음 강의로 넘어가야 하는 건가요!?
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
오타 발견
SimpleStepHandler - Step 실행의 관리자Step의 실행은 StepHandler에 의해 의해 통제된다. Spring Batch는 기본 구현체로 SimpleStepHandler를 사용하는데, 이 컴포넌트가 Step 실행의 전체 라이프사이클을 관리한다.의해 의해 <-그리고 Step Squad 핵심 요약 있으니까 너무좋은데 Job Squad 에서도 핵심요약이 있었으면 더 좋았을거같음뭐 스탭이나 잡이나 내용이 거의 비슷비슷하긴한데(Execution 반드시 새거만들고,상태변경시 즉시 메타데이터저장소에 저장하고)그래도 실제 실행 따라가는 느낌이라 정리가 잘 안되는느낌이긴해서 마지막에 방점찍으면 보기 더 편할거같은느낌
-
미해결토비의 스프링 6 - 이해와 원리
WebApiExRateProvider 템플릿 콜백 패턴을 적용하면서 테스트 코드를 만들어보았습니다.
안녕하세요.우선 한푼도 아깝지 않은 명강의를 만들어주심에 진심으로 감사드립니다.WebApiExRateProvider를 템플릿 콜백 패턴을 적용한 구조로 변경하면서, 토비님께서는 실제 API를 호출하고 콘솔에 찍힌 결과를 보며 진행한 테스트 방식에 의문이 들어 한번 테스트 코드를 만들어보았는데요. 피드백을 받아보고 싶습니다.코드는 GitHub Repository에 Commit 내역에서 확인하실 수 있습니다. (Commit 내역 링크)의도에 대해 간단히 설명드리면 반드시 지정된 URL로 API 호출을 보내야 한다는 동작과 특정 스펙의 JSON을 파싱해서 환율 정보를 반환하는 동작을 테스트했습니다.이때 ApiExecutor 의 경우 단순히 API를 호출하고 그 응답을 반환하는 역할이므로 테스트 할 가치가 없다고 판단하여 배제했습니다.주로 궁금한 것은 다음과 같습니다.테스트하려는 기능에 대해 부족하거나 과함은 없는지?Mock을 활용한 테스트 방식에 대해서는 아쉬움이 없는지?아무래도 Mock을 활용한 테스트에는 찝찝함이 남아있는데, 어떻게 해소할 수 있을지?토비님이라면 어떤 식으로 테스트를 진행하셨을 지?다시 한번 좋은 강의 제공해주셔서 진심으로 감사합니다.
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
Read Committed 격리 수준 사용 관련 질문
Non-repeatable read가 발생 가능한 Read Committed 격리 수준에서 어떻게 비즈니스 로직의 정합성을 유지할 수 있는지 바로 이해하지 못했다가, 검색 및 추론을 통하여 아래 [1]과 같이 이해했습니다.질문제가 잘 이해했는지 확인하기 위해서 질문드렸습니다! 혹시 근본적으로 오해한 부분이 있을까 두렵습니다ㅠㅠ제가 잘 이해한 것이 맞다면, Read Committed 격리 수준을 사용할 때 데이터 정합성을 유지하기 위한 디테일들을 신경쓰면서 데이터 접근 계층의 로직을 작성하는지 궁금합니다.[1] 제가 이해한 Read Committed 격리 수준에서 데이터 정합성을 유지하기 위한 가정 및 필요조건JPA를 사용한다.RDBMS가 Read Committed 격리 수준을 구현할 때 MVCC를 사용한다.이유: JPA를 활용하여 비즈니스 로직을 작성할 때 데이터베이스 전역적으로 잘 정의된 일관적인 스냅샷이 존재한다고 가정하기 때문JPA로 작성한 코드가 항상 JPA의 1차 캐시를 cache hit하는 경우 Repeatable Read 격리 수준처럼 사용해도 무방하다.JPA에서 Lazy Loading을 사용한다면, 다른 MVCC 스냅샷의 데이터가 조회될 때에도 비즈니스 로직의 정합성이 깨지지 않는 맥락에서만 사용한다.
-
해결됨카카오 개발자와 함께하는 워크플로우 기반의 대용량 트래픽 처리 기법 [ By. 비전공자 & Kakao 개발자 ]
'서비스 개발자를 위한 Kafka 쉽고 깊게 알기' 학습자료 오류
자료를 다운로드 하면, 윈도우에서는 대부분의 압축파일 내에 파일이 없다고 나옵니다. Mac에서 작업하셔서 그런 것 같은데 확인 부탁드립니다.
-
미해결죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
writer retry 관련해서 궁금한 점이 있습니다.
반말은 조금 부끄러워서.. 존댓말로 질문드리겠습니다. ItemWriter에서 예외 발생 시 재시도 - 청크 단위로 재시도 관리 1. ItemWriter에서 예외 발생 시 ItemProcessor부터 처리가 재개된다.2. ItemProcessor에서와 달리, ItemWriter에서의 재시도 횟수는 청크 단위로 관리된다. 요 부분에서 실제로 배치를 돌려보니 writer부터 재시작하는 것을 확인 가능했습니다.. 관련해서 원인을 분석해보니, 아래 결론에 도달했는데 맞을까요? processorNonTransactional() 설정이 켜져있으면 Item 단위로 처리 결과를 캐시에 저장하기때문에 processor는 모두 완료 처리 -> writer부터 시작processorNonTransactional() 설정이 꺼져있으면 청크 단위로 완료 처리하기때문에 processor부터 다시 시작
-
해결됨죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.
청크 지향 처리 시 벌크 read 방법?
킬구형, 청크 지향 처리 시 벌크 read를 할 수 있는 방법이 있어?ItemReader 사용 시 소스에서 1건 씩 데이터를 읽어온다면, 단건 SELECT문이 매번 날아가거나 아니면 JDBC의 ResultSet next()를 사용하는 것 같은데,, 전자면 DB 부하가 너무 심하고 후자여도 네트워크 IO가 꽤 발생할 것 같은데..지금 수백? 수천만? 건 정도의 데이터를 마이그레이션 해야하는 업무를 받았는데, 청크 생성 시 DB 부하나 네트워크 트래픽을 좀 줄이고 싶은데 다건 SELECT를 통해 처리하는 방법이 있을까?