fbfbf1의 등록된 링크

키자드에 등록된 총 1413개의 포스트를 확인하실 수 있습니다.

Naver Blog

[Spring Batch] AsyncItemProcessor, AsyncItemWriter

ItemProcssor에서 스텝의 전체 실행 속도를 느리게 만드는 경우가 있다면 새 스레드에서 스텝의 ItemProcssor 부분만 실행하게 만들 수 있다. AsyncItemProcessor ItemProcessor 구현체를 래핑하는 데코레이터 어떤 item이 데코레이터에 전달될 때 위임자의 호출은 새 스레드에서 실행 그런 다음에 itemProcessor의 실행 결과로써 반환된 Future가 AsyncItemWriter로 전달 AsyncItemWriter ItemWriter의 데코레이터 AsyncItemWriter는 Future를 처리해 그 결과를 위임 ItemWriter에 전달한다 AsyncItemProcessor와 AsyncItemWriter는 반드시 함께 사용해야한다. 그렇지 않으면 Future를 사용자가 직접 처리해 결과를 얻어야한다. build.gradle implementation 'org.springframework.batch:spring-batch-integration

Naver Blog

[Spring Batch] 배치 처리 테스트

@SpringBatchTest 자동으로 ApplicationContext에 테스트에 필요한 여러 유틸 Bean을 등록해 주는 어노테이션 JobLauncherTestUtils launchJob(), launchStep()과 같은 스프링 배치 테스트에 필요한 유틸성 메서드 지원 JobRepositoryTestUtils JobRepository를 사용해서 JobExecution을 생성 및 삭제 기능 메서드 지원 StepScopeTestExecutionListener @StepScope 컨텍스트를 생성해 주며 해당 컨텍스트를 통해 JobParameter 등을 단위 테스트에서 DI 받을 수 있음 JobScopeTestExecutionListener @JobScope 컨텍스를 생성해 주고 해당 컨텍스를 통해서 JobParameter 등을 단위 테스트에서 DI 받을 수 있다. JobLauncherTestUtils @SpringBatchTest 어노테이션을 통해서 주입받는 Util Class 실행

Naver Blog

[ElasticStack] 엘라스틱서치 index, document, bulk

엘라스틱 서치의 모든 기능은 REST API 형태 인덱스 document를 저장하는 논리적 구분자 document는 실제 데이터를 저장하는 단위 RDBMS의 테이블과 유사한 개념 동일한 인덱스에 있는 document는 동일한 스키마(매핑)을 갖는다. 모든 document는 반드시 하나의 인덱스에 포함 document document는 엘라스틱서치에서 데이터가 저장되는 기본 단위로 JSON 형태 하나의 document는 여러 필드와 값을 갖는다. 스키마에 따른 그룹핑 일반적으로 스키마(매핑)에 따라 인덱스를 구분함 관리 목적의 그룹핑 기본적으로 인덱스는 용량이나 숫자 제한 없이 무한대의 도큐먼트를 포함 가능 이론적으로 하나의 인덱스에 수억 개의 document 저장 가능 하지만 인덱스가 커지면 검색 시 많은 document를 참조해야 하기에 성능이 나빠짐 운용할 때 인덱스 용량 제한을 둠 특정 도큐먼트 개수에 도달하거나 특정 용량을 넘어서면 인덱스 분리 날짜/시간 단위로 분리 인덱스

Naver Blog

[Spring Batch] Step Flow

조건 로직 Spring batch의 Step은 잡내에서 StepBuilder의 Next 메서드를 이용해서 지정한 순서대로 실행됨 전이를 사용하면 다른 순서로 실행할 수 있다. 위 예제 코드는 firstStep의 실행 결과가 정상이면 successStep 실행 firstStep이 ExitStatus로 FAILED를 반환하면 failureStep을 실행 job의 On 메서드는 Step의 ExitStatus를 평가해서 어떤 일을 수행할지를 결정할 수 있다. BatchStatus, ExitStatus BatchStatus는 job이나 step의 현재 상태를 식별하는 JobExecution 또는 StepExecution의 애트리뷰트 ExitStatus는 job이나 step 종료 시 스프링 배치로 반환되는 값 스프링 배치는 어떤 스텝을 수행할지 결정할 때 이 값을 확인 문자열이기에 와일드카드 사용할 수 있다. ExitStatus를 확인해서 다음에 어떤 스텝을 진행할지 결정할 수 있지만 충분하지

Naver Blog

[Spring Batch] JobRepository와 메타데이터

JobRepository JobRepository 인터페이스, JobRepository 인터페이스를 구현해 데이터를 저장하는 데 사용되는 데이터 저장소의 의미를 가진다. 스프링 배치는 잡내에서 사용할 수 있는 두 가지 데이터 저장소를 제공한다. 하나는 인 메모리 저장소 하나는 관계형 데이터베이스 관계형 데이터베이스 크게 6개의 테이블이 존재한다. BATCH_JOB_INSTANCE 스키마의 시작점 잡의 논리적 실행을 나타냄 필드 설명 JOB_INSTANCE _ID 테이블의 기본 키 VERSION 낙관적인 락에 사용되는 레코드 버전 JOB_NAME 실행된 잡 이름 JOB_KEY 잡 이름과 잡 파라미터의 해시 값으로 JobInstance를 고유하게 식별하는 데 사용 BATCH_JOB_EXECUTION 필드 설명 JOB_EXECUTION_ID 테이블의 기본 키 VERSION 낙관적인 락에 사용되는 레코드 버전 JOB_INSTANCE_ID BATCH_JON_INSTANCE 외래 키 CREAT

Naver Blog

[Spring Batch] StepListener

스텝 리스너 스텝 리스너는 이벤트 시작 및 종료를 처리하고 잡 전체가 아닌 개별 스텝에서 이뤄짐 afterStep의 반환 값은 ExitStatus이다. Listener가 Step이 반환한 ExitStatus를 Job에 전달하기 전에 수정할 수 있다. 위 기능은 Listener가 Job 처리의 성공 여부를 판별하는 데 사용할 수 있다. StepExecutionListener와 ChunkListener 인터페이스를 사용한다. 각각 스텝과 청크의 시작과 끝에서 특정 로직을 처리할 수 있게 해줌 StepListener는 모든 스텝 리스너가 상속하는 마커 인터페이스이다. listener에 추가를 해주면 사용할 수 있다.

Naver Blog

[Spring Batch] tasklet Step, chunk Step

STEP 알아보기 스텝은 잡의 구성 요소를 담당 스텝은 독립적이고 순차적으로 배치 처리를 수행함 트랜잭션은 스텝 내에서 이루어짐 독립되도록 의도적으로 설계 배치 처리는 2가지도 나뉨 Tasklet 처리 Tasklet.execute 메서드가 RepeatStaus.FINISHED를 반환할 때까지 트랜잭션 범위 내에서 반복적으로 실행되는 코드 블록을 만들 수 있음 chunk 기반 최소한 2 ~ 3개의 컴포넌트로 구성 각 청크는 자체 트랜잭션으로 실행됨 마지막으로 성공한 트랜잭션 이후부터 다시 시작할 수 있다. Tasklet Step 만드는 방법에는 2가지가 있다. 사용자가 작성한 코드를 Tasklet step처럼 실행되도록 하는 것 MethodInvokingTaskletAdapter를 사용해서 정의 가능 이 구현체를 사용하면 기존에 존재하던 다른 클래스 내의 메서드를 잡내의 tasklet처럼 실행할 수 있다. Tasklet 인터페이스 구현 execute 메서드를 구현하며 처리 완료 이후에

Naver Blog

[Spring Batch] 배치 기본, Job, Step

JobRepository 다양한 배치 수행과 관련된 수치 데이터(시작 시간, 종료 시간, 상태, 읽기/쓰기 횟수) 관리 잡의 상태 관리 일반적으로 관계형 데이터베이스 사용 스프링 배치 내의 대부분의 주요 컴포넌트가 공유한다. 각 스텝이 실행되면 현재 상태로 갱신됨 실행된 스텝 현재 상태 읽은 아이템 및 처리된 아이템 수 등이 다 저장됨 jobLauncher 잡을 실행함 execute 메서드 호출 잡의 재실행 가능 여부 검증. 잡의 실행 방법(현재 스레드에서 수행할지 스레드 풀을 통해 실행할지) 파라미터 유효성 검증 스프링 부트가 즉시 잡 시작하는 기능 제공함 일반적으로 직접 다룰 필요는 없다. JobInstance, JobExecution JobInstance 잡의 이름, 잡의 논리적 실행을 위해 제공되는 고유한 식별 파라미터 모음으로써 유일하게 존재 잡이 다른 파라미터로 실행될 때마다 새로운 JobInstance가 생성된다. 실패한 이후 재실행하면 새로운 게 생성되지 않음 JobE

Naver Blog

[Spring Batch] job parameter 유효성 검증

잡 파라미터 유효성 검증 인터페이스를 구현하고 해당 구현체를 Job 내에서 구성하면 된다. DefaultJobParametersValidator 다만 DefaultJobParametersValidator를 기본적으로 제공함 requiresKey는 필수적인 파라미터 optionalKeys는 옵션이다. name과 age 이 외에 다른 파라미터 변수가 전달되면 유효성 검증에 실패한다. money를 추가하면 실패함 옵션 키가 구성되어있지 않고 필수 키만 구성되어 있다면 필수 키를 전달하기만 하면 어떤 키의 조합을 전달해도 유효성 검증 통과함. optional을 없애면 성공함 DefaultJobParametersValidator는 파라미터 존재 여부를 제외한 다른 유효성 검증을 수행하지 않는다. 더 강력한 게 필요하면 JobParameterValidator를 용도에 맞게 구현해야됨 다만 JobBuilder 의 메서드는 하나의 JobParameterValidator 인스턴스만 지정하게 되어 있

Naver Blog

[Spring Batch] RunIdIncrementer

RunIdIncrementer JobParametersIncrementer는 잡에서 사용할 파라미터를 고유하게 생성할 수 있도록 스프링 배치가 제공하는 인터페이스 기본적으로 run.id long 타입 파라미터의 값을 증가시킨다. validator의 옵셔널 키에 run.id를 추가해 주고 new RunIdIncrementer()를 사용해야 됨 JobParametesBuilder의 addDate 코드이다. Spring Batch에서 제공 커스텀 한 방식의 위와 같이 사용하면 된다. validator의 옵셔널키에 CurrentDate를 추가해 줘야 한다. 또한 Job에서도 custom 한 Class를 넣어줘야 한다. 실행을 하게 되면 currentDate가 바뀌는 걸 볼 수 있다.

Naver Blog

[Spring Batch] JobListener

잡 리스너 모든 잡은 생명주기를 갖는다. 스프링 배치는 생명주기의 여러 시점에 로직을 추가할 수 있는 기능 제공 잡과 관련이 있는 건 JobExecutionListener를 사용 JobExecutionListener beforeJob, afterJob 두 개의 콜백메서드 제공함 알림 초기화 : 잡 실행 전에 준비할 게 있다면 beforeJob 메서드에 해당 로직 추가 정리 : 잡 실행 이후에 정리 작업 수행할 때 사용 인터페이스를 상속받아서 beforeJob, afterJob 메서드에 구현을 하면 된다. afterJob 메서드는 잡의 완료 상태에 관계없이 호출이 된다. 그러므로 잡의 종료 상태에 따라 어떤 일을 수행할지 결정할 수 있다. Job에 리스너를 추가하면 된다. 실행하면 위와 같이 나오게 된다. afterJob에서 배치 종료 상태에 따라 로직을 작성할 수 있다. 인위적으로 에러를 발생시키면 if 문에 걸리게 된다. 또한 afterJob 잡의 완료 상태에 관계없이 호출이 되기

Naver Blog

[KAFKA] Consumer Offset Commit Strategies

enable.auto.commit True 오토 커밋을 true로 하게 되면 배치가 동시에 처리된다. 컨슈머 API를 사용할 때 오프셋이 정기적으로 커밋 된다. At Least Once가 특정 상황에서 기본적으로 활성화된다. poll 함수가 코드에 호출될 때 항상 커밋 된다. 그러면 auto.commit.interval.ms의 간격마다 오프셋을 비동기적으로 커밋 한다. 이때 poll을 호출하기 전에 모든 메시지를 처리해야 된다. 처리하지 못하게 되면 메시지가 손실이 된다. 커밋 한 오프셋부터 데이터를 읽기에 그전 오프셋에서 문제가 발생한 데이터는 읽지 못함 이를 위해서 enable.auto.commit을 비활성화한 다음에 어디까지 처리되었는지에 따라 commitSync or commitAsync를 호출해야 된다. https://www.conduktor.io/kafka/delivery-semantics-for-kafka-consumers/ 위와 같이 Poll을 한 뒤 시간이 지나면 비

Naver Blog

[KAFKA] Consumer Offset Reset Behavior

컨슈머 오프셋 재설정 동작 애플리케이션에 버그가 있으면 컨슈머가 중단될 수 있다. 기본적으로 kafka에는 7일의 데이터 리텐션(보유)이 있다. 즉 컨슈머가 7일 넘게 중단이 되면 읽으려 하는 오프셋이 무효화된다. 이럴 때 알아야 하는 게 컨슈머 오프셋 재설정 동작 latest 컨슈머가 로그 끝에서 읽도록 한다. auto.offset.reset=latest earliest 컨슈머가 로그 시작 부분에서 읽도록 한다. --from -beginning auto.offset.reset=earliest none 오프셋을 찾지 못했을 때 예외가 발생한다. auto.offset.reset=none 처리를 다시 시작하기 전에 데이터를 복구할 방법을 찾고 싶을 때 사용한다. offset.retention.minutes kafka 2.0 이전 버전에서는 하루 동안 새로운 데이터를 읽지 못 하면 오프셋 손실 kafka 2.0 보다 높은 버전에서는 컨슈머가 7일 동안 데이터를 읽지 못 하면 오프셋 손실

Naver Blog

[서평] 직장인을 위한 챗GPT 이안 클레이턴 지음, 김상유 옮김

이번에 한빛 미디어에서 받은 책은 직장인을 위한 챗 GPT입니다. Chat GPT가 나온 이후로 챗 GPT에게 "어떻게 질문을 하냐" 가 정말 중요하게 변한 것 같습니다. 이 책은 책 GPT를 어떻게 잘 활용하는 지를 알려주고 있습니다. 책의 앞부분과 뒷부분은 위와 같습니다. 깔끔한 초록색으로 나와져있었네요 챗 GPT 색깔이 초록색이라서 그런가봅니다. 책의 저자가 설명하는 책에 대한 설명입니다. 간단하게 요약하면 책 GPT 사용 방법입니다. 목차는 다음과 같습니다. 먼저 프롬프트가 무엇인지 설명합니다. 그리고 이제 산업별부터 시작해서 여러 분야에 대해서 챗 GPT를 어떻게 사용해야되는지 알려줍니다. 뒷부분에는 자기 계발과 관련된 프롬프트도 나와있습니다. 책의 6장에의 산업분야입니다. 프롬프트를 어떻게 활용하는 지 알려주고 어떤 산업 분야에서 활용할 수 있는 지 알려줍니다. 제 직업이 IT쪽이라서 IT쪽으로 가져와봤습니다. IT 분야엣서 활용할 만한 문제들을 알려줍니다. 또한 챗 GP

Naver Blog

Spring boot jdbc sql log 설정 추가

build.gradle // https://mvnrepository.com/artifact/org.bgee.log4jdbc-log4j2/log4jdbc-log4j2-jdbc4.1 implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16' log4jdbc 추가 application.yml url과 driver-class-name에 추가 log4jdbc.log4j2.properties 파일 추가 resource 폴더에 파일 추가 log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator log4jdbc.dump.sql.maxlinelength=0 해당 내용 추가 logback.xml 추가 resources에 logback.xml 추가 <configuration> <appender name="STDOUT" class="ch.qos.logback

Naver Blog

[Spring Batch] ExecutionContext

ExecutionContext 배치 처리는 특성상 상태를 가지고 있다. JobExecution은 상태를 저장하는 여러 곳 중 하나 잡이나 스텝이 진행될 떄 변경 잡 상태는 ExecutionContext에 저장된다. ExecutionContext는 배치 잡의 세션 키 - 값 쌍으로 보관 잡을 다루는 과정에서 여러 개의 ExecutionContext가 존재할 수 있다. 모든 것이 JobRepository에 저장됨 Job 범위 - 각 Job의 JobExecution에 저장되며 동일한 Job 내에서만 Step 간 데이터 공유가 가능 Step 범위 - 각 Step의 StepExecution에 저장되며 Step 사이에서는 데이터 공유 불가능 ExecutionContext 조작 JobExecution 또는 StepExecution 일부분 사용하려면 JobExecution 또는 StepExecution에서 가져와야 한다. 스텝 -> job으로 넘어가는 일이 필요하다. BATCH_JOB_EXEUCT

Naver Blog

[KAFKA] Consumer Group, Partition Rebalance, Static Group MemberShip

Partition Rebalance Consumer가 그룹에 합류하거나 나갈 때마다 파티션이 이동하게 된다. 이때 파티션이 컨슈머 사이에서 이동하는 상황을 리밸런싱이라고 한다. 리밸런싱은 컨슈머가 그룹을 나가거나 합류할 때마다 발생한다. 적극적 리밸런싱 파티션 3개가 있고 컨슈머 그룹에 컨슈머가 2개 있는 상황 이때 컨슈머가 기존 그룹에 합류하게 된다. 적극적 리밸런싱은 컨슈머가 그룹에 합류하게 되면 모든 컨슈머의 읽기 작업을 중단한다. 읽기 작업을 중단하고 파티션 멤버십을 포기한다. 즉 읽기를 진행하는 컨슈머도 없고 파티션도 없다는 의미이다. 모든 컨슈머가 다시 그룹에 합류해서 새로운 파티션을 무작위로 할당받는다. 전체 컨슈머 그룹이 처리를 멈추는 데 이걸 Stop the World 이벤트라고 한다. Stop the world로 인해서 컨슈머가 원래 있던 파티션으로 되돌아간다는 보장이 없다. 하나의 컨슈머에게 전과 같은 파티션을 할당해 주고 싶은데 해줄 수가 없고 일부 컨슈머가 같

Naver Blog

[KAFKA] Auto Offset Commit Behavior

Auto Offset Commit Behavior 자바 Consumer API에서는 Polling을 정규적으로 수행할 때마다 오프셋도 정규적으로 커밋 된다. 언제 Offset Commit 컨슈머에서 poll을 호출할 때마다 auto.commit.interval.ms 설정 시간이 경과된다. enable.auto.commit을 참으로 하면 설정 시간이 지나면 커밋 한다. 카프카 컨슈머를 자바에서 실행해 보면 interval는 기본으로 5000ms, enable auto commit은 true로 되어있는 걸 볼 수 있다. properties로 설정할꺼면 위와 같이 설정하면 된다. 위 코드에서 5초마다 Poll을 수행한다는 의미이다. 5초가 지난 다음에 다시 Poll을 호출하면 비동기적으로 오프셋을 커밋 한다는 의미다. 기록을 받아서 pll을 다시 호출하기 전에 오프셋 처리를 하기에 최소한 한 번으로 설정이 되어있다.

Naver Blog

[KAFKA] Producer Acknowledgement

ACK ack을 통해서 Producer는 브로커에 데이터를 전송할 때 데이터 쓰기 작업이 완료됐다는 응답을 받을 수 있다. ack은 0, 1, all(-1)이 있다. ACK 0 프로듀서가 확인 응답을 기다리지 않겠다는 의미. 데이터 손실 가능성이 있다. 프로듀서는 메시지가 전송된 순간 메시지 쓰기에 성공했다고 간주함 브로커가 수신하기까지 기다리지 않는다. 리더에게 데이터 전송 후 리더가 쓰기 작업을 하던 중에 브로커가 오프라인 상태가 되거나 예외가 발생해도 Producer 쪽에서는 문제가 발생한 걸 알 수가 없고 데이터는 손실된다. 메시지를 유실해도 괜찮을 때 사용 가능함 또한 설정값 중 처리량이 가장 많다. 오버헤드가 최소화된다. ACK 1 프로듀서는 리더 브로커에 확인 응답을 받을 때 쓰기가 성공했다고 간주함. 카프카 1.0 ~ 2.8까지 기본 값 프로듀서가 리더에 데이터를 보내면 리더가 쓰기 작업을 한 뒤 요청이 성공적이라고 응답한다. 하지만 리더가 요청을 받긴 하지만 데이터가

Naver Blog

[KAFKA] 멱등 프로듀서(Idempotent Producer)

상황 프로듀서가 아파치 카프카에 데이터를 전송할 때 네트워크 오류로 인해서 중복된 메시지가 전송될 수 있다. 정상 요청 카프카에 데이터를 생성하면 카프카가 로그에 데이터 커밋 그 후 프로듀서에게 수신 확인 전달 중복 요청 카프카에 데이터를 생성하면 카프카가 로그에 데이터 커밋 수신 확인 반환할 때 ACK을 프로듀서에게 전달하지 못한다. ACK을 받지 못한 프로듀서는 재시도를 하게 된다. 똑같은 메시지를 보내면 카프카는 새로운 요청으로 여겨서 로그에 중복 커밋 그 후 ACK을 보내게 된다. 프로듀서 입장에서는 두 개의 요청 중 하나만 성공했고 카프카가 수신 확인을 반환했지만 카프카는 실제로 메시지 두 개를 커밋 한 것이다. 멱등 프로듀서 위와 같은 문제를 해결하기 위해서 멱등 프로듀서를 사용한다. 네트워크 오류에도 중복을 허용하지 않는다. https://www.conduktor.io/kafka/idempotent-kafka-producer/ 중복 요청인 경우 카프카 쪽에서 중복 생성인

Naver Blog

[KAFKA] Message Compression, Linger.ms, batch.size

메시지 압축 프로듀서가 카프카에 데이터를 전송할 때 텍스트로 된 데이터 전송 Ex : Json 형식 압축을 하게 되면 메시지의 크기가 줄어들어서 카프카로의 전송 속도가 빨라지고 디스크 내 저장 공간을 적게 차지한다. 압축은 다양한 곳에서 할 수 있다. 프로듀서 압축, 브로커에서도 압축할 수 있다. 압축 과정에서 반복되는 값을 한 번에 압축하기에 메시지 배치의 크기가 클수록 압축률이 올라가서 효율 증가 압축 종류로는 none, gzip, lz4, snappy, zstd가 있다. 압축을 활성화하면 메시지 배치가 압축된 메시지의 배치로 압축된다. 크기가 줄어들기에 전송 속도 증가 요청 크기가 1/4 정도로 줄일 수 있기에 디스크 효율 증가 지연 시간이 줄어들고 처리량이 늘어나게 된다. 압축 단점 요즘은 거의 무의미 Producer가 CPU 사이클을 사용해서 계산과 압축을 수행 Consumer도 CPU 사이클을 사용해서 메시지 배치의 압축을 해제하고 읽어야 함 snappy와 lz4를 먼저

Naver Blog

[KAFKA] Default Partitioner, Sticky Partitioner

key Hashing 프로듀서에서 카프카로 메시지를 보낼 때 키가 null이 아니면 레코드는 파티셔너 로직을 거쳐서 어떤 파티션에 할당될지 결정된다. 이를 key Hashing이라고 한다. Default Partitioner 기본 파티셔너에서는 murmur2 알고리즘을 사용해서 키를 해싱 한다. 위 식을 통해서 동일한 키는 동일한 파티션에 할당이 된 게 만든다. 하지만 식의 오른쪽에 파티션의 개수가 있기에 기존 토픽에 파티션을 추가하면 식의 결괏값이 달라짐 따라서 동일한 키가 동일한 파티션에 할당된다는 보장이 없게 된다. 이럴 경우 파티션을 추가하는 대신 새로운 토픽을 만드는 것이 좋다 라운드 로빈 파티셔너 카프카 2.3까지는 기본이 Round Robin 방식이다. https://www.conduktor.io/kafka/producer-default-partitioner-and-sticky-partitioner/ 프로듀서가 6개의 메시지를 전송하고 파티션이 5개 있는 토픽 라운드 로

Naver Blog

[KAFKA] Delivery Sementics

At Most Once At Most Once 최대한 한 번인 경우이다. 이는 메시지 배치를 받자마자 오프셋이 커밋 되는 경우이다. https://www.conduktor.io/kafka/delivery-semantics-for-kafka-consumers/ 이 방법은 컨슈머에서 문제가 발생하면 다시 읽지 않기 때문에 메시지가 손실된다. 중요한 게 컨슈머 그룹의 컨슈머가 배치 읽고 바로 오프셋을 커밋 한다. 그 후에 데이터 처리를 시작한다. 위의 그림에서 일단 5번째까지 배치에 있는 데이터를 읽고 그다음에 처리 시작 이때 3번째까지 데이터를 처리하다가 4번째부터 문제가 생기게 되면 컨슈머는 다시 읽기를 시작한다. 다시 읽기 시작하면 마지막으로 커밋 된 부분부터 읽는다. 그렇기에 4번째와 5번째는 읽지 못하기에 데이터가 유실된다. 각 메시지를 최대한 한 번 보거나 처리하기 때문에 At Most Once이다. At Least Once 최소한 한 번 본다는 At Least Once 보통

Naver Blog

[KAFKA] Topic CLI

주키퍼 실행 zookeeper-server-start.sh 위 명령어를 사용하면 properties가 있어야 한다고 나온다. 이건 kafka/bin/config 폴더에 있다. zookeeper-server-start.sh /Users/a1101902/Desktop/kafka_2.13-3.4.0/config/zookeeper.properties kafka-server-start.sh /Users/a1101902/Desktop/kafka_2.13-3.4.0/config/server.properties 왼쪽 주키퍼 오른쪽 카프카 둘 중 하나가 정지되면 카프카가 멈춘다. 항상 주키퍼와 카프카를 실행시켜 놓고 있어야한다. 카프카 토픽 생성 카프카 토픽 생성 kafka-topics.sh --bootstrap-server localhost:9092 --topic first_topic --create 9092포트로 이름이 first_topic인 토픽을 생성한다. 카프카 파티션 설정 kafka-to

Naver Blog

[KAFKA] Producer CLI

토픽에 데이터 생성 일단 토픽이 있어야 된다. kafka-topics.sh --bootstrap-server localhost:9092 --topic first_topic --create --partitions 1 그 후에 Producer CLI로 데이터 생성 kafka-console-producer.sh --bootstrap-server localhost:9092 --topic first_topic 위 명령어를 입력하면 메시지를 생성할 수 있다. 그만 만들고 싶으면 CTLG + C 누르면 된다. kafka-console-producer.sh --bootstrap-server localhost:9092 --topic first_topic --producer-property acks=all acks=all을 사용하면 모든 토픽이 데이터를 다 확인하게 만든다. 데이터 유실 방지 존재하지 않는 토픽에 데이터 생성 타임아웃이나 오류 발생 존재하지 않는 no_topic에 메시지를 입력하면 에

Naver Blog

[KAFKA] Consumer CLI

토픽 생성 kafka-topics.sh --bootstrap-server localhost:9092 --topic second_topic --create --partitions 3 Consumer CLI kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic second_topic 위 명령어로 생성된 second_topic을 Consume 하기 시작한다. 위가 Consumer 아래가 Producer이다. kafka-console-producer.sh --bootstrap-server localhost:9092 --producer-property partitioner.class=org.apache.kafka.clients.producer.RoundRobinPartitioner --topic second_topic 라운드 로빈 방식을 적용한 코드이다. 이 방식을 적용하지 않으면 계속 동일한 파티션에 데이터가 쌓이게 된다.

Naver Blog

[KAFKA] Consumer Group CLI

토픽 생성 kafka-topics.sh --bootstrap-server localhost:9092 --topic third_topic --create --partitions 3 3개의 파티션을 가지는 토픽 생성 Consumer kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic third_topic --group my-first-application Consumer를 실행하고 Consumer에 대해서 그룹 ID를 지정한다. my-first-application Producer kafka-console-producer.sh --bootstrap-server localhost:9092 --producer-property partitioner.class=org.apache.kafka.clients.producer.RoundRobinPartitioner --topic third_topic 또 다른 Consumer 위에서

Naver Blog

[KAFKA] JAVA 연동 및 CallBack, Partitioner

코드 public class ProducerDemo { private static final Logger log = LoggerFactory.getLogger(ProducerDemo.class.getSimpleName()); public static void main(String[] args) { log.info("hello world"); // 프로듀서 설정 Properties properties = new Properties(); properties.setProperty("bootstrap.severs", "127.0.0.1:9092"); //브로커와 연결 properties.setProperty("key.serializer", StringSerializer.class.getName()); //직렬화 properties.setProperty("value.serializer", StringSerializer.class.getName()); // 프로듀서 생성 final KafkaP

Naver Blog

[KAFKA] Producer Key

Producer Key 메시지를 보낼 때 Key를 설정하면 동일한 키는 항상 동일한 파티션으로 들어가게 된다. ProducerRecord class에 인자로 key를 넣어줄 수 있다. 위와 같이 코드를 작성한다. 로그를 보게 되면 같은 아이디를 가지는 메시지는 같은 파티션으로 들어가는 걸 확인할 수 있다. 또한 비동기식으로 데이터를 보내는 것도 확인이 가능하다. 아이디가 순서대로 되어있지 않다.

Naver Blog

[KAFKA] Consumer Java API, Shutdown

코드 public class ConsumerDemo { private static final Logger log = LoggerFactory.getLogger(ConsumerDemo.class.getSimpleName()); public static void main(String[] args) { log.info("kafka Consumer"); String groupId = "java-app"; String topic = "demo_topic"; // 프로듀서 설정 Properties properties = new Properties(); properties.setProperty("bootstrap.servers", "127.0.0.1:9092"); //브로커와 연결 properties.setProperty("key.deserializer", StringDeserializer.class.getName()); //직렬화 properties.setProperty("value.deser

Naver Blog

[KAFKA] Consumer Groups

demo_topic-1 파티션을 할당받음 Consumer 를 실행하면 partition 1로만 데이터를 받는다. demo_topic-2 파티션을 할당받음 Consumer 를 실행시키면 파티션 2를 할당받은 건 파티션 2로만 읽는 걸 확인할 수 있다. 기존에 있던 Consumer 한 개를 종료하면 다른 Consumer가 파티션을 할당받게 된다. 기존에 한 개 더 켜놓고 있었음

Naver Blog

[JAVA] 컬렉션 팩토리 List, Set, Map

컬렉션 팩토리 기존에 리스트 생성 방법 리스트를 만들 때 위의 두 가지 방법을 이용해서 만들 수 있다. 다만 두 번째 방법은 고정 크기의 리스트를 만들었기에 요소 갱신은 가능하지만 새 요소를 추가하거나 요소를 삭제할 수는 없다. UnSupportedOperationException이 발생한다. 집합으로 바꾸면 오류가 발생하지 않는다. 하지만 불필요한 객체를 할당하기도 하고 List를 원하는 데 Set이 반환 결과다. 리스트 팩토리 자바 9에서부터는 List.of를 사용해서 리스트를 만들 수 있다. 하지만 add를 하게 되면 오류가 발생한다. List.of 또한 변경할 수 없는 리스트로 만들어진다. set 메서드를 사용해도 예외가 발생한다. Arrays.asList는 발생하지 않는다. List 인터페이스를 보면 of의 여러 개의 오버로드 버전이 있다. 다중 요소를 받을 수 있도록 API를 구현하지 않는 이유는 다음과 같다. 내부적으로 가변 인수 매개변수를 사용하면 추가 배열을 할당해서

Naver Blog

[JAVA] 자바 8 이후의 Map

맵 처리 자바 8에서는 Map 인터페이스 디폴트 메서드 추가 forEach 메서드 기존 방법으로는 위와 같이 구현을 해야 된다. default 메서드를 사용할 수 있다. 위와 같이 사용 가능하다. 정렬 Entry.comparingByValue Entry.comparingByKey 위의 두 메서드를 사용해서 각각 value와 key를 이용해서 정렬할 수 있다. forEachOrdered는 순서를 보장한다. getOrDefault Map에서 찾으려는 키가 없으면 기존에는 NPE가 발생한다. 이를 위해서 기본값을 반환하는 방식으로 이 문제를 해결할 수 있다. 위 삼항 연산자를 보면 key 값이 null이 아니거나 key를 포함하면 get(key) 값을 리턴하고 둘 다 false 이면 defaultValue를 리턴한다. 첫 번째 인수로는 키를, 두 번째 인수로 기본값을 받으며 맵에 키가 존재하지 않으면 두 번째 인수로 받은 기본값을 반환한다. 계산 패턴 맵에 키가 존재하는지에 따라 어떤 동

Naver Blog

[JAVA] Optional

Optional java.util.Optional<T> 자바 8에서부터 사용 가능 선택형 값을 캡슐화하는 클래스 값이 있으면 Optional 클래스는 값을 감싼다. 값이 없으면 Optional.empty 메서드로 Optional을 반환 null 참조와 Optional.empty()는 다르다. Optional의 역할은 더 이해하기 쉬운 API를 설계하도록 돕는 것이다. 메서드의 시그니처만 보고도 선택형 값인지를 구별할 수 있다. Optional이 등장해서 언랩해서 값이 없을 수 있는 상황에 적절하게 대응하도록 강제하는 효과가 있다. Optional.empty()를 이용하면 빈 Optional 객체를 얻을 수 있다. Optional.of로 null이 아닌 값을 포함하는 Optional을 만들 수 있다. 위와 같이 null을 넣게 되면 에러가 발생한다. of 정적 팩토리 메서드에 Objects.requireNonNull을 사용하고 있다. Optional.ofNullable로 null 값을

Naver Blog

[KAFKA] Topic, Producer, Consumer

토픽 토픽 : 카프카 클러스터에 있는 특정 스트림 데이터에 대한 검증이 없기에 여러 종류의 데이터를 저장할 수 있음 이름을 이용해서 토픽 구별 토픽 안에 있는 메시지 순서를 데이터 스트림이라고 부름 토픽을 통해 데이터 스트림을 만든다. 카프카 토픽에 데이터를 추가하기 위해서 producer 사용 데이터를 읽기 위해서 Consumer 사용 카프카에 쿼리를 할 수는 없다. 파티션 토픽은 여러 개의 파티션으로 분할된다. 각각의 파티션에 있는 메시지들은 순서대로 저장됨 오프셋이라는 증가하는 아이디를 가짐 카프카는 불변성임 데이터를 추가하고 난 뒤에 데이터를 삭제하거나 변경할 수 없음 파티션에 계속 기록 트럭이 20초마다 카프카에 위치를 전송함 (Producer) 대시보드나 알림 서비스에서 Consume 해서 사용함 중요 카프카에 있는 데이터는 불변성 카프카의 데이터는 시간이 지나면 사라짐 기본 7일 오프셋은 특정 파티션에만 의미가 있다. 오프셋 재사용은 안됨 오프셋의 순서는 한 파티션에서만

Naver Blog

[KAFKA] Consumer Groups, Offset, Brokers, Discovery, replica, Zookeeper

Consumer Groups 한 토픽이 여러 개의 파티션으로 나눠져 있다. 동일한 응용프로그램의 일부이므로 동일한 "논리적 작업"을 수행하는 컨슈머는 Kafka 컨슈머 그룹으로 그룹화할 수 있습니다. 각각의 컨슈머들이 다른 파티션을 읽기에 컨슈머 그룹이 카프카 토픽 전체를 읽게 된다. 브로커 하나에만(어떤 브로커든) 연결하고, 읽어 오고 싶은 토픽 이름만 제공하면 됩니다. 카프카가 호출을 적당한 브로커와 파티션으로 라우팅해 줍니다! 파티션보다 컨슈머가 많을 때 파티션보다 컨슈머가 많을 때는 읽을 파티션이 없는 컨슈머는 비활성화된다. 정상이다. 하나의 토픽에 여러 개의 컨슈머 그룹 하나의 토픽에 여러 개의 컨슈머 그룹이 있는 건 괜찮다. 각각의 그룹에서 모든 토픽을 다 읽는다. 그룹 3 같은 경우는 한 개의 컨슈머가 세 개의 파티션에서 데이터를 읽는다. Consumer Offset Consumer Offset을 사용해서 카프카에서 데이터를 어디까지 읽었는지 파악할 수 있다. 즉 카프카

Naver Blog

[1년 전 오늘] [1년 전 오늘] [1년 전 오늘] 1년 후

2022.4.3. 1년 전 오늘 [1년 전 오늘] [1년 전 오늘] 1년 후 1년 전 오늘의 1년 전 오늘 20년에는 21년에는 코로나가 잠잠해질 줄 알았는데 아니었다 ㅋ 21년에는 그래도 22년에는 코로나가 끝나있을 줄 알았는데 ㅋㅋㅋㅋ 말도 안 되는 상상이었다~ 2년 동안 코로나가 줄기는 커녕 계속 늘었다~~ 23년에는 끝나있겠지? ㅎ 음 후회 없도록 살려고 여전히 노력했으나 인간이 후회 없이 ... 류리상자 무려 1년 전 오늘의 1년 전 오늘의 1년 전 오늘.. 코로나는 거의 끝난 것 같고.. 저 글 쓰고 2개월 뒤에 취업했다. 아주 잘 살고 있다 ㅎ

Naver Blog

[Effective Java] 예외는 진짜 예외 상황에만 사용하라.

예외는 진짜 예외 상황에만 사용하라. try { int i = 0; while(true) range[i++].climb()' catch(ArrayIndexOutOfBoundsException e) {} 위 코드는 직관적이지 않다. 무한 루프를 돌다가 배열 끝에 도달하면 ArrayIndexOutOfBoundsException을 발생시킨다. for(Mountain m : range) { m.climb(); } 위와 같이 작성하면 개발자가 이해하기 더 쉬워진다. try ~ catch를 이용해서 예외를 잡을 필요도 없어지고 배열의 끝에 도달했을 때 예외를 발생시켜서 종료할 필요도 없어진다. 또한 위 코드가 성능도 더 좋다. JVM은 배열에 접근할 때마다 경계를 넘지 않는지 검사하는데 일반적인 반복문도 배열 경계에 도달하면 종료한다. try ~ catch를 명시하면 검사를 하는 일이 중복되므로 하나를 생략한 것이다. 위 try ~ catch 문의 문제점은 몇 가지가 있다. 코드를 try ~

Naver Blog

테스트 코드

TDD 테스트 코드 작성 순서 쉬운 것부터 예외 상황부터 중복 제거 일반적인 프로덕션 코드에서는 중복을 제거하는 것이 좋지만 테스트 코드에서는 스스로 무엇을 테스트하는 지 명확하게 설명할 수 있어야 하기에 중복 제거를 고민해야봐야된다. 파라미터 파라미터 개수는 적을수록 코드 가독성과 유지보수에 유리하기에 메서드의 파라미터 개수가 세 개 이상이면 객체로 바꿔 한 개로 줄이는 것을 고려해야한다. 테스트 목록 정리 TDD를 시작할 때 테스트할 목록을 미리 정리하면 좋다. 테스트 목록을 정리하고 어떤 테스트가 구현이 쉬울지 정하자. 다만 처음부터 모든 사례를 목록에 추가하지말자. 시작이 안 될 때는 단언부터 고민 검증하는 코드부터 작성하기 시작하면 테스트 코드를 짤 때 도움이 된다.

Naver Blog

EhCache

EhCache 단순 성능 자체는 Caffeine Cache가 가장 빠르나 분산 환경에서 사용할 수 없기에 EhCache 도입 EhCache는 분산환경에서 사용할 수 있음 Redis로도 Cache를 사용할 수 있지만 READ만 하기에 Redis는 오버스펙이라고 판단 또한 Network를 한 번 더 타야된다는 단점이 있음 @Cacheable(value = "getMembersCache", key = "{#memberNo, #pageNo, #limit}") public MemberDto getMembers(Long memberNo, long pageNo, long limit) { // ... } Value에는 cache 이름을 Key에는 cache에서 사용할 key를 입력 public class MemberDto implements Serializable { private MemberInfo memberInfo; } 응답값에는 Seriablizable 구현해줘야됨 MemberInfo cl

Naver Blog

동작 파라미터화 코드 전달하기

Predicate Member에서 사용할 Predicate를 만든다. 나이에 따라서 구별하기 위해 AgePredicate를 만들고 test 메서드를 구현한다. 성별에 따라서 구별하기 위해서 GenderPredicate를 만들고 test 메서드를 구현한다. 사용할 때는 위와 같이 하면 된다. filterMembers를 만들고 인자로 MemberPredicate interface를 받는다. 사용할 때는 구현체를 넘겨준다. 결과는 다음과 같다. 익명 클래스 익명 클래스를 사용할 수 있다. MemberPredicate interface를 파라미터로 넘겨주고 직접 구현하면 된다. 하지만 코드가 지저분해진다. 람다 람다를 사용하면 더 간결하게 줄일 수 있다. Generic 제너릭을 사용하면 더 일반화 시켜서 사용할 수 있다. 또한 오직 하나의 추상 메서드만 지정하기에 함수형 인터페이스다. 메서드를 인수로 전달 가능 결과도 똑같이 나온다. 정리 동작 파라미터화에서는 메서드 내부적으로 다양한 동작

Naver Blog

[JAVA] Stream 슬라이싱 takeWhile, dropWhile

정렬이 된 데이터에서 사용할 수 있는 Stream 슬라이싱 takeWhile 다음과 같이 나이로 정렬된 데이터가 있을 때 나이가 14살 이하인 멤버가 뽑는 코드는 위와 같이 filter를 이용해서 작성할 수 있다. 데이터가 정렬이 되어있다는 걸 이용해서 14살보다 큰 멤버가 나왔을 때 반복 작업을 중단할 수 있다. 이를 위해서 takeWhile를 이용할 수 있다 지금은 데이터 수가 적으니 성능 차이가 없겠지만 데이터가 많다면 성능 차이가 나게 된다. filter를 사용한 코드를 하나씩 찍어보면 아래와 같다. 일단 모든 데이터를 다 보게 된다. 나이가 16살인 것까지 다 본다. takeWhile로 바꾼 코드다. 나이가 15살인 것까지만 본다. dropWhile dropwhile을 사용하면 15살 이상인 멤버가 가져올 수 있다. 결과를 보면 15살부터 getAge() <= 14가 false가 나오기에 여기서부터 작업을 중단하고 남은 모든 요소를 반환한다.

Naver Blog

Collector

스트림값에서 최댓값과 최솟값 검색 Collectors.maxBy Collectors.minBy 위 두 개의 메서드를 사용해서 최댓값과 최솟값 계산할 수 있다. 스트림의 요소를 비교하는 데 사용할 Comparator를 인수로 받는다. 합계 Collectors.summingInt라는 특별한 요약 팩토리 메서드 제공 summingInt는 객체를 int로 매핑하는 함수를 인수로 받는다. summingInt의 인수로 전달된 함수는 객체를 int로 매핑할 컬렉터를 반환한다. summingInt가 collect 메서드로 전달되면 요약 작업을 수행 요약 summarizing~ 사용 문자열 연결 Joining을 사용할 수 있다 내부적으로 StringBuilder를 사용해서 문자열을 하나로 만든다. 범용 리듀싱 요약 연산 위에서 본 모든 컬렉터는 reducing 팩토리 메서드로 정의 가능 Collectors.reducing으로 구현 가능 그룹화 groupingBy를 통해서 그룹화 가능 여러 조건으로

Naver Blog

[JAVA] 병렬 스트림

병렬 스트림 1 ~ n 까지 모든 숫자를 반환하는 메서드 n이 커지면 병렬로 연산처리하는 게 좋다. 어떤 것부터 코드를 수정해야될까 결과 변수는 어떻게 동기화? 몇 개의 스레드를 생성 숫자는 어떻게 생성할까? 생성된 숫자는 누가 더 할까 병렬 스트림을 사용하면 위 고민없이 문제 쉽게 해결 가능 위 코드를 Stream으로 바꾸면 위와 같다. 이걸 병렬스트림으로 바꾸려면 parallel()을 사용하면 된다. 순차 스트림과 다른 부분은 스트림이 여러 청크로 분할된다는 것이다. 리듀싱 연산을 여러 청크에 병렬로 수행할 수 있다. 마지막으로 리듀싱 연산으로 생성된 부분 결과를 다시 리듀싱 연산으로 합쳐서 전체 스트림의 리듀싱 결과를 도출한다. 순차 스트림에 parallel()을 사용하면 parallel이 true로 설정된다. 병렬 스트림을 순차 스트림으로 바꾸면 parallel이 false로 된다. stream.parallel() .filter() .sequential() .map() .pa

Naver Blog

스프링 트랜잭션 REQUIRES_NEW

트랜잭션 복구 Service A에서 RepositoryB와 Repository C를 호출한다고 가정해 보자. Repository B는 정상 작동했지만 Repository C는 예외가 발생한 상황이다. 우리가 원하는 건 Repository C에서 예외가 발생해도 Repository B를 호출하는 로직은 정상 작동하는 것이다. 간단하게 생각하면 Repository C에서 발생하는 예외를 Service A에서 try ~ catch로 잡아서 처리해 주면 될 것 같다. 하지만 이 방법은 실패를 하게 된다. 실패 이유 Repository C에서 예외가 발생하면 신규 트랜잭션이 아니기에 롤백은 하지 않지만 트랜잭션 동기화 매니저에 롤백을 한다고 표시하기 때문이다. 그렇기에 Service A에서 try ~ catch로 예외를 잡는다고 해도 Repository C에서 이미 롤백을 한다고 표시되었기 때문에 롤백을 하게 된다. 롤백을 하기에 전체 물리 트랜잭션 자체가 롤백이 된다. 해결 방법 위의 문제

Naver Blog

프로토 타입 패턴

프로토 타입 패턴 기존 인스턴스를 복제해서 새로운 인스턴스를 만드는 방법 기존 객체를 복사해서 새롭게 만든 후 일부분만 변경해서 사용할 때 사용한다. DB Connection, Network는 한 번 생성할 때 많은 리소스가 사용이 된다. 그렇기에 매번 필요할 때마다 새롭게 생성하는 게 아니라 기존에 있는 걸 복사해서 필요한 부분만 변경해서 사용한다. 코드 public class Member { private String name; private int age; private String hotelName; public Member(final String name, final int age, final String hotelName) { this.name = name; this.age = age; this.hotelName = hotelName; } public String getName() { return name; } public void setName(final String n

Naver Blog

퍼사드 패턴

퍼사드 패턴 복잡한 서브시스템 의존성을 최소화할 때 사용하는 방법이다. 내가 생각하기에 클라이언트 코드에 호출하는 코드의 의존성을 줄이는 방법이라고 생각한다. 이를 위해서 각각의 역할에 맞는 클래스를 생성하고 이러한 클래스들을 호출하는 인터페이스나 서비스를 만드는 것이라고 생각한다. public class Client { public static void main(String[] args) { String to = "[email protected]"; String from = "[email protected]"; String host = "127.0.0.1"; Properties properties = System.getProperties(); properties.setProperty("mail.smtp.host", host); Session session = Session.getDefaultInstance(properties); try { MimeMessage message = new

Naver Blog

[JAVA] 어노테이션

어노테이션 자바 코드에서 @으로 작성되는 것을 Annotation이라 한다. 클래스 또는 인터페이스를 컴파일하거나 실행할 때 어떻게 처리해야 할 것인지를 알려주는 설정 정보 정의 인텔리제이에서 Annotation 타입으로 만들 수 있다. 다음과 같이 만들어지고 사용할 때는 @TestAnnotation으로 사용하면 된다. 속성 어노테이션도 속성을 가질 수 있다. 속성은 타입과 이름으로 구성되고 이름 뒤에 괄호를 붙인다. 속성의 기본 값은 default 키워드로 지정할 수 있다. 위와 같이 작성하면 TestAnnotation은 firstValue, secondValue 속성을 가지게 된다. secondValue는 기본 값으로 value를 가지게 된다. secondValue는 default 값이 있기에 작성하지 않아도 된다. 적용 대상 어노테이션을 사용할 때는 어떤 대상에 설정 정보를 적용할 것인지를 명시해야 된다. 자바에서는 ElementType 열거 상수로 정의되어 있다. Elemen

Naver Blog

어댑터 패턴

어댑터 패턴 클래스의 인터페이스를 클라이언트가 원하는 다른 인터페이스로 변환할 때 사용하는 패턴 호환성이 전혀 없는 인터페이스를 사용하는 클래스들이 호환되게끔 만들어준다. 클라이언트가 사용하는 인터페이스를 따르지 않는 기존 코드를 재사용할 수 있게 해준다. 구성요소 Target : 클라이언트가 사용하길 원하는 인터페이스 Adaptee : 클라이언트가 갖고 있는 인터페이스 (어댑터에서 사용하고자 하는 인터페이스) Adapter : Target 인터페이스를 구현하는 클래스로, Adaptee의 함수 사용 Client : Target 인터페이스를 사용하는 주체 예시 애플 회사의 CType 케이블이 있다고 하자. AppleCable interface를 상속받아서 AppleCTypeCable을 만들어서 사용하고 있다. 이때 삼성 케이블도 같이 사용하고 싶은데 애플 케이블의 코드를 변경하지 않고 활용해서 사용하고 싶다. 즉 애플과 삼성의 인터페이스를 함께 동작하게 만들고 싶다. 삼성 케이블 인터

Naver Blog

브릿지 패턴

브릿지 패턴 객체의 확장성을 향상하기 위한 패턴으로 객체의 동작을 처리하는 구현부와 확장을 위한 추상부를 분리해서 사용한다. 기능을 처리하는 클래스와 구현을 담당하는 추상 클래스로 구별해서 사용한다. Abstraction 기능 계층의 최상위 클래스 구현 부분에 해당하는 클래스를 인스턴스로 가지고 구현부 메서드를 호출 RefinedAbstraction 기능 계층에서 새로운 부분을 확장한 클래스 Implementor abstraction의 기능을 구현하기 위해서 사용하는 인터페이스 ConcreteImplement 실제 기능 구현 코드 abstraction에 해당하는 Shape이다. 여기서는 Color interface를 호출해서 구현부 메서드에 사용한다. Circle은 RefinedAbstraction이다. Color는 Implementator interface에 해당한다. Shape에서의 색칠하기 기능을 위해서 사용하는 인터페이스 Green과 Red는 ConcreteImplement

Naver Blog

전세 알아봐야될 것

최근에 전세를 알아보고 있는데 알아보기 귀찮아서 대충 알아보다가 피눈물 흘릴 뻔 했다. 요즘 깡통전세, 전세사기 전세 관련 말이 너무 많아서!!! 이제부터 제대로 알아봐야지!!! 계약 전 계약시 알아봐야 할 것 https://justdim.tistory.com/974 전세, 월세 계약시 주의사항 부동산을 알기 쉽게 설명해 드리는 '써니퍼니'입니다. 우리나라는 높은 집값때문에 아직 집을 가지고 있지 못한 사람들이 주변에 많이 있습니다. 혹은 집을 가지고 있지만 사정상 전세나 월세로 거주하고 있는 사람들도 있습니다. 신문이나 인터넷을 보면 임대차계약을 잘못해서 보증금을 돌려받지 못하는 경우들이 종종 보이곤 하는데 이번시간에는 전월세 계약시 주의할점에 대하여 알아보겠습니다. 조금만 조심하면 안전하게 집을 구할수 있는데 귀찮아 하거나 시간이 없다는 핑계로 대충 집을 선택해서 손해를 보는 경우가 많습니다. 천천히 읽어보시면 앞으로 ... justdim.tistory.com https://tw

Naver Blog

커넥션 풀, 데이터 소스

데이터베이스 커넥션 애플리케이션 로직은 DB 드라이버를 통해 커넥션을 조회한다. DB 드라이버는 DB와 TCP / IP 커넥션을 연결한다. 3 - way - handshake 같은 TCP / IP 연결을 위한 네트워크 동작 발생 DB 드라이버는 TCP / IP 커넥션이 연결되면 데이터베이스 접속에 필요한 ID, PASSWORD와 같은 정보를 DB에 전달한다. DB는 전달받은 ID, PASSWORD를 통해서 내부 인증을 완료하고 DB 내부에 DB Session을 생성한다. DB는 커넥션 생성이 완료되었다는 응답을 보낸다. DB 드라이버는 커넥션 객체를 생성해서 클라이언트에 반환한다. 이 과정은 복잡하고 시간도 많이 들고 TCP/IP 커넥션을 새로 생성하기 위한 리소스를 매번 사용해야 한다. 이를 위해서 커넥션을 미리 생성해두고 필요할 때마다 사용하는 커넥션 풀을 이용한다. 커넥션 풀 초기화 커넥션을 관리하는 공간이다. 커넥션 풀 초기화 과정이다. 애플리케이션을 시작하는 시점에 커넥션

Naver Blog

트랜잭션, 락

트랜잭션 데이터베이스에서 하나의 거래를 안전하게 처리하도록 보장해 주는 것 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 수행되어야 할 일련의 연산들을 의미한다. 커밋, 롤백 데이터베이스에서 모든 작업이 성공해서 데이터베이스에 정상 반영하는 것을 커밋 작업 중 하나라도 실패해서 거래 이전으로 되돌리는 것을 롤백 ACID 트랜잭션은 ACID를 보장해야 한다. Atomicity(원자성) 트랜잭션 내에서 실행한 작업들은 마치 하나의 작업인 것처럼 모두 성공하거나 실패해야 한다. Consistency (일관성) 모든 트랜잭션은 일관성 있는 데이터베이스 상태를 유지해야 한다. Isolation (격리성) 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않도록 격리한다. 동시에 같은 데이터를 수정하지 못하도록 해야 한다. 동시성과 관련된 성능 이슈로 인해 트랜잭션 격리 수준을 선택할 수 있다. 격리 수준 트랜잭션은 원자성, 일관성, 지속성을 보장한다. 격리성을

Naver Blog

체크 예외, 언체크 예외

자바 예외 계층 Object : 모든 객체의 최상위 부모는 Object 예외도 객체이다. Throwable : 최상위 예외 Error 애플리케이션에서 복구 불가능한 시스템 예외 개발자는 이 예외를 잡을 수 없다. 언체크 예외이다. Throwable로 예외를 잡게 되면 하위 클래스들도 다 잡을 수 있기에 Error 예외도 잡을 수 있어서 Throwable로 잡으면 안 된다. Exception 체크 예외 애플리케이션 로직에서 사용할 수 있는 실질적인 최상위 예외 RuntimeException을 제외하고 컴파일러가 체크하는 예외이다. 즉 체크 예외를 사용하면 throws 또는 try ~ catch를 반드시 사용해야 한다. RuntimeException 컴파일러가 체크하지 않는 예외이다. RuntimeException과 그 자식들은 모두 언체크 예외이다. 언체크 예외는 예외를 사용할 때 throws 또는 try ~ catch를 반드시 사용할 필요가 없다. 사용하고 싶으면 사용해도 된다. 예

Naver Blog

1월 첫째 주

점점 글쓰기가 귀찮아지네 자취방 알아보러 갔던 이수역..? 난생 처음 가보는데 엄청 좋다. 깜짝 놀랐다. 이수역에서 먹은 KFC.. 핸드폰 하다가 발견한 공감되는 짤.. 코로나로 몇 년이 순식간에 사라진 느낌이다. 이것도.. 아마 사당역 집 보다가.. 집 다 보고 먹은 돈가스 집 구하기 너무 어렵다!! 회사 베이글은 언제 먹어도 맛있어! 난생 처음 수염 왁싱을 해봤다. 나름 길러서 갔다고 생각했는데 이것도 짧다고 하신다. 나는 어느 정도 아플 줄은 알았는데 와 진짜 아팠다. 왁싱 중에서 턱이랑 인중이 제일 아프다고 한다. 브라질리언 왁싱보다 아프다고.. 아픈 만큼 효과는 확실하다. 지금 한 지 2주 되는 것 같은데 수염이 거의 안 자란다. ㅎㅎ 눈썹 왁싱도 저번에 했었다. 눈썹은 그래도 주기적으로 눈썹 칼 이용해서 밀어줬는데.. 왁싱 한 번 해보니.. 앞으로 왁싱만 해야겠다. 회사 출근해서 사수분이랑 간 수제버거 집 완전 맛있다. 여기는 저기 콜라 뒤에 있는 감자칩이 무료로 준다.

Naver Blog

1월 둘째 주

회사 복지 포인트가 아주 든든하게 들어와서.. 바로 스위치를 샀다~~~ 너무 좋아~~ 오랜만에 먹은 피자스쿨.. 옛날에 피자스쿨은 서민음식이었는데 이제 포테이토피자에 치즈크러스트 추가하면 14900원 나온다.. 엄청 비싸졌다! 둘째 주에는 내 생일이었다. ㅎ 꽃도 선물 받고! 가방도 선물 받았다! ㅎㅎ.. 가방 너무 이쁘고 마음에 든다!! 완전 감사합니다!!!! 카톡으로도 선물 많이 받았다. 축하해 주고 선물 준 모든 분들 감사합니다~ ㅎㅎ.. 생일이라고 위대하신 여자친구께서 오마카세를 데려가 주셨다. 진짜 엄청 맛있다. 음식 가짓수도 많이 있고, 너무 만족스럽다!!! 정말 알차게 나온다.. 버터 전복.. 맛있다.. 회도 많이 나오고 초밥도 많이 나온다. 크.. 이거 다시 먹고 싶네.. 마지막 후식까지 달달하게 나온다!!!!!! ㅎㅎ 생일선물 들고 한 컷! 회사 출근해서 새로 생긴 베트남 음식점 갔다. 이것도 시키고.. 갈비를 품은.. 쌀국수를 시켰다!! 맛있다! ㅎㅎ 생일 다음 날

Naver Blog

MSA 정리

Service Discovery 서비스 클라이언트가 서비스를 호출할 때 서비스의 위치 (즉 IP 주소와 포트)를 알아낼 수 있는 기능이 필요한데, 이것을 바로 서비스 디스커버리 (Service discovery)라고 한다. 즉 유레카 서버에 서버들의 주소를 저장해놓는다. 그러면 유레카 서버에 요청이 들어오면 유레카 서버가 라운드 로빈 방식으로 자체적으로 로드밸런싱을 진행해서 서버에 요청들을 할당해 준다. 유레카 서버는 전화번호부와 같다. 만일 유레카 서버를 쓰지 않으면 호출할 서버의 IP 주소들을 다 알고 있어야 된다. 유레카 서버에 IP 주소 대신에 서버의 이름으로 등록했기에 서버의 이름만 알고 있으면 된다. 사용 @EunableEurekaServer 유레카 서버가 되는 곳에서는 위 어노테이션 사용 @EnableDiscoverClient 유레카 서버에 등록이 되는 서버들은 위 어노테이션 사용 eureka: client: register-with-eureka : false or tr

Naver Blog

1장 객체 설계

객체 설계 public class Theater { private TicketSeller ticketSeller; public Theater(final TicketSeller ticketSeller) { this.ticketSeller = ticketSeller; } public void enter(Audience audience) { if (audience.getBag().hasInvitation()) { final Ticket ticket = ticketSeller.getTicketOffice().getTicket(); audience.getBag().setTicket(ticket); } else { final Ticket ticket = ticketSeller.getTicketOffice().getTicket(); audience.getBag().minusAmount(ticket.getFee()); ticketSeller.getTicketOffice().plusAmount(ti

Naver Blog

전셋집 알아보는 법 (부동산 가기 전까지)

부동산 가기 전에 해야 될 것들을 정리해 보자 매물 알아보기 https://new.land.naver.com/complexes?ms=37.4786337,126.9689174,16&a=APT:OPST&e=RETAIL&g=15000 네이버 부동산 네이버 부동산 new.land.naver.com 기본적으로 나는 네이버 부동산을 이용한다. 여기서 자기가 가고 싶은 곳을 필터링하자. 나는 아파트, 오피스텔 상단에서 필터링 가능하다. 자기가 가고 싶은 곳으로 설정하고, 전세 / 월세, 전세 보증금 가격 설정하면 된다. 그럼 위와 같이 뜨게 된다. 주거용 인지 알아보기 요즘같이 전세 사기가 많은 시기에 전세 보증 보험이 되는지 알아봐야 된다. 첫 번째로 볼 것이 주거용인지 확인하는 것이다. 마음에 드는 매물을 클릭하면 오른쪽에 용도가 뜨게 되는데 주거용인지 확인한다. 여기서 중요한 게 용도는 주거용인데 전입신고가 불가능한 곳이 있다. 전입신고가 불가능한 곳은 가지말자 주거용 + 전입신고 불가능

Naver Blog

2장 객체지향 프로그래밍

객체지향 프로그래밍 객체지향 패러다임으로의 전환은 클래스가 아닌 객체에 초점을 맞출 때에만 얻을 수 있다. 어떤 클래스가 필요한지를 고민하기 전에 어떤 객체들이 필요한지를 고민하자. 객체를 독립적인 존재가 아니라 기능을 구현하기 위해 협력하는 공동체의 일원으로 보자. 객체들의 모양과 윤곽이 잡히면 공통된 특성과 상태를 가진 객체들을 타입으로 분류하고 이 타입을 기반으로 클래스를 구현하자. 도메인 어떤 문제를 해결하기 위해 사용자가 프로그램을 사용하는 분야를 도메인이라고 한다. 클래스 구현 클래스는 내부와 외부로 구분되고 클래스 설계의 핵심은 어떤 부분을 외부에 공개하고 어떤 부분을 감출지를 결정하는 것이다. 내부와 외부를 구분하면 경계의 명확성이 객체의 자율성을 보장하기 때문이다. 자율적인 객체 객체가 상태와 행동을 함께 가지는 복합적인 존재 객체가 스스로 판단하고 행동하는 자율적인 존재 package com.example.oop.movie2; import java.math.BigD

Naver Blog

3장 역할, 책임, 협력

역할, 책임, 협력 객체지향의 본질은 협력하는 객체들의 공동체를 창조하는 것 설계의 핵심은 협력을 구성하기 위해 적절한 객체를 찾고 적절한 책임을 할당하는 과정에서 드러난다. 역할, 책임, 협력이 제자리를 찾지 못한 상태면 응집도 높은 클래스와 중복 없는 상속 계층을 구현한다고 하더라도 문제가 발생할 수 있다. 객체들이 애플리케이션의 기능을 구현하기 위해 수행하는 상호작용을 협력이라고 한다. 객체가 협력에 참여하기 위해 수행하는 로직을 책임 객체들이 협력 안에서 수행하는 책임들이 모여 객체가 수행하는 역할을 구성 협력 객체지향 시스템은 자율적인 객체들의 공동체 객체 사이의 협력은 하나의 객체가 다른 객체에게 메시지를 전송할 때 시작된다. 객체는 다른 객체의 상세한 내부 구현에 직접 접근할 수 없기에 오직 메시지 전송을 통해서만 자신의 요청을 전달할 수 있다. 메시지를 수신한 객체는 메서드를 실행해 요청에 응답한다. 상태는 객체가 행동하는 데 필요한 정보에 의해 결정되고 행동은 협력

Naver Blog

4장 설계 품질과 트레이드오프

객체지향 설계 핵심 객체지향 설계에 대한 두 가지 관점 객체지향 설계의 핵심이 책임 책임을 할당하는 작업이 응집도와 결합도 같은 설계품질과 깊이 연관되어 있다. 결합도와 응집도 합리적인 수준으로 유지하기 위해서는 객체의 행동에 초점을 맞추자. 책임은 객체의 상태에서 행동으로, 객체와 객체 사이의 상호작용으로 설계 중심을 이동시키고, 결합도가 낮고 응집도가 높으며 구현을 효과적으로 캡슐화하는 객체들을 창조할 수 있는 기반을 제공한다. 즉 설계를 할 때는 책임 중심으로 설계를 하자! 데이터 중심으로 설계를 하면 안 된다. 데이터 중심 시스템 객체지향 설계에서는 두 가지 방법을 이용해 시스템을 객체로 분할할 수 있다. 첫 번째는 상태를 분할의 중심축으로 삼는 것 객체는 자신이 포함하고 있는 데이터를 조작하는 데 필요한 오퍼레이션을 정의 객체의 상태에 초점을 맞춘다. 두 번째는 책임을 분할의 중심축으로 삼는 것 객체는 다른 객체가 요청할 수 있는 오퍼레이션을 위해 필요한 상태를 보관 객체의

Naver Blog

5장 책임 할당하기

책임 주도 설계 데이터보다 행동을 먼저 결정하라 협력이라는 문맥 안에서 책임을 결정하라. 두 원칙의 핵심은 설계를 진행하는 동안 데이터가 아니라 객체의 책임과 협력에 초점을 맞추는 것 데이터보다 행동을 먼저 결정하라. 객체에게 중요한 것은 데이터가 아니라 외부에 제공하는 행동 데이터는 객체가 책임을 수행하는 데 필요한 재료를 제공할 뿐 책임 중심 설계에세는 이 객체가 수행해야 하는 책임은 무엇인가? 책임을 수행하는 데 필요한 데이터는 무엇인가? 객체의 책임을 먼저 결정한 후에 객체의 상태를 결정한다. 협력이라는 문맥 안에서 책임을 결정하라. 객체에게 어떤 책임을 할당할지는 협력에서 찾을 수 있다. 책임은 객체의 입장이 아니라 객체가 참여하는 협력에 적합해야 한다. 협력을 시작하는 주체는 메시지 전송자이기에 협력에 적합한 책임은 메시지 수신자가 아니라 메시지 전송자에게 적합한 책임을 의미한다. 즉, 메시지를 전송하는 클라이언트의 의도에 적합한 책임을 할당해야 한다는 것 메시지를 결정한

Naver Blog

6장 메시지와 인터페이스

메시지와 인터페이스 객체지향의 흔한 실수 중 하나는 클래스에 집중하는 것 객체지향에서는 클래스가 아닌 객체에 집중해야 된다! 객체가 수행하는 책임에 초점을 맞춰야 한다 협력과 메시지 협력은 객체가 다른 객체에게 무언가를 요청할 때 시작함 메시지는 객체 사이의 협력을 가능하게 하는 매개체 협력의 관점에서 객체는 두 가지 종류의 메시지 집합으로 구성 객체가 수신하는 메시지 집합 외부의 객체에게 전송하는 메시지의 집합 함께 고려해야 한다. 메시지와 메시지 전송 메시지 객체들이 협력하기 위해 사용할 수 있는 유일한 의사소통 수단 한 객체가 다른 객체에게 도움을 요청하는 건 메시지 전송 또는 메시지 패싱 전송하는 객체를 메시지 전송자, 수신하는 객체를 메시지 수신자 메시지는 오퍼레이션명과 인자로 구성되고 메시지 전송은 메시지 수신자를 추가한 것 메시지와 메서드 메서드 메시지를 수신했을 때 실제로 실행되는 함수 또는 프로시저 메시지와 메서드의 구분은 메시지 전송자와 수신자가 느슨하게 결합될 수

Naver Blog

7장 객체 분해

프로시저 추상화 기능 분해 시스템을 분리하기 위한 기준으로 기능을 사용 기능 분해의 관점에서 추상화의 단위는 프로시저 시스템은 프로시저 단위로 분해 전통적인 기능 분해 방법은 하향식 접근법을 따른다. 시스템을 구성하는 가장 최상위 기능을 정의하고 최상위 기능을 좀 더 작은 단계의 하위 기능으로 분해해 나가는 방법을 의미 직원의 급여를 계산 사용자로부터 소득세율을 입력받는다. "세율을 입력하세요: "라는 문장을 화면에 출력한다. 키보드를 통해 세율을 입력받는다. 직원의 급여를 계산한다. 전역 변수에 저장된 직원의 기본급 정보를 얻는다. 급여를 계산한다. 양식에 맞게 결과를 출력한다. "이름: {직원명}, 급여: {계산된 금액}" 형식에 따라 출력 문자열을 생성한다. 기능 분해는 위와 같이 한다. 각 정제 단계는 이전 문장의 추상화 수준을 감소시켜야 한다. 기능을 중심으로 필요한 데이터를 결정한다. 하향식 기능 분해 방식의 문제점 하향식 기능 분해는 시스템을 최상위의 가장 추상적인 메인

Naver Blog

8장 의존성 관리하기

의존성 관리하기 객체지향 설계의 핵심은 협력을 위해 필요한 의존성은 유지하면서 변경을 방해하는 의존성은 제거 의존성 이해하기 어떤 객체가 협력하기 위해 다른 객체를 필요로 할 때 두 객체 사이에 의존성이 존재하게 된다. 의존성은 항상 단방향 실행 시점 : 의존하는 객체가 정상적으로 동작하기 위해서는 실행 시에 의존 대상 객체가 반드시 존재해야 한다. 구현 시점 : 의존 대상 객체가 변경될 경우 의존하는 객체도 함께 변경된다. 의존성은 변경에 의한 영향의 전파 가능성을 암시한다. 의존성 전이 의존성은 전이될 수 있다. A가 B에 의존하고 B가 C에 의존할 경우 A가 C에 의존하게 되는 것 의존성 전이는 캡슐화가 효과적으로 되어있다면 되지 않는다. 직접 의존성 한 요소가 다른 요소에 직접 의존하는 경우 코드에 명시적으로 들어남 간접 의존성 직접적인 관계는 존재하지 않지만 의존성 전이에 의해 영향이 전파되는 걸 의미 코드에 명시적으로 드러나지 않는다. 런타임 의존성과 컴파일 타임 의존성

Naver Blog

9장 유연한 설계

개방 폐쇄 원칙 소프트웨어 개체는 확장에 대해 열려 있어야 하고 수정에 대해서는 닫혀 있어야 한다. 확장에 대해 열려 있다 : 애플리케이션의 요구사항이 변경될 때 이 변경에 맞게 새로운 동작을 추가해서 애플리케이션의 기능을 확장할 수 있다. 수정에 닫혀 있다 : 기존 코드를 수정하지 않고 애플리케이션의 동작을 추가하거나 변경할 수 있다. 컴파일 타임 의존성을 고정시키고 런타임 의존성을 변경하라 개방 폐쇄 원칙은 런타임 의존성과 컴파일 타임 의존성과 관련 있다. 개방 -폐쇄 원칙의 핵심은 추상화에 의존하는 것! 추상화를 거치면 문맥이 바뀌더라도 변하지 않는 부분만 남게 되고 문맥에 따라 변하는 부분은 생략됨 개방 폐쇄 원칙에서 폐쇄를 가능하게 하는 것은 의존성의 방향이다. 모든 요소가 추상화에 의존해야 된다. 생성 사용 분리 결합도가 높아질수록 개방 폐쇄 원칙을 따르는 구조를 설계하기가 어려워진다. 생성자 내에서 인터페이스를 상속받는 구체적인 클래스 생성하는 경우 동일한 클래스 안에서

Naver Blog

10장 상속과 코드 재사용

상속과 코드 재사용 객체지향에서 클래스를 재사용하는 방법은 새로운 클래스를 추가하는 것 상속과 합성이 있다. 상속은 클래스 안에 정의된 인스턴스 변수와 메서드를 자동으로 새로운 클래스에 추가하는 기법 상속과 중복 코드 중복 코드는 변경을 방해한다. 중복 여부를 판단하는 기준은 변경이다. 요구사항이 변경됐을 때 두 코드를 함께 수정해야 한다면 이 코드는 중복이다. Dont' Repeat Yourself (DRY 원칙) -> 동일한 지식을 중복하지 마라. 중복과 변경 중복 코드는 새로운 중복 코드를 부른다. 민첩하게 변경하기 위해서는 중복 코드를 추가하는 대신 제거해야 한다. 상속을 이용해서 중복 코드 제거하기 이미 존재하는 클래스와 유사한 클래스가 필요하면 코드를 복사하지 말고 상속을 이용해 코드를 재사용하자. 다만 상속을 염두에 두고 설계되지 않은 클래스를 상속을 이용해 재사용하는 것은 쉽지 않다. 상속을 이용해 코드를 재사용하기 위해서는 부모 클래스의 개발자가 세웠던 가정이나 추론

Naver Blog

11장 합성과 유연한 설계

합성 합성은 전체를 표현하는 객체가 부분을 표현하는 객체를 포함해서 객체의 코드를 재사용 합성 관계는 has-a 합성은 구현에 의존하지 않는다. 합성은 내부에 포함되는 객체의 구현이 아닌 퍼블릭 인터페이스에 의존 상속 관계는 클래스 사이의 정적인 관계, 합성은 동적인 관계 코드 작성 시점에 결정한 상속 관계는 변경이 불가능하지만 합성 관계는 실행 시점에 동적으로 변경할 수 있다. 코드 재사용을 위해서는 객체 합성이 클래스 상속보다 더 좋다. 불필요한 인터페이스 상속 문제 해결 public class Stack<E> { private Vector<E> elements = new Vector<>(); public E push(E item) { elements.addElement(item); return item; } public E pop() { if(elements.isEmpty()) { throw new EmptyStackException(); } return elements.rem

Naver Blog

블로그 닉네임

From, 블로그씨 2023년에도 블로그 열심히 운영하고 계시나요? 내 블로그 닉네임 뜻에 대해 이야기해주세요~ 상자에 뭔가를 담아서 저장하는 것처럼 나도 내 블로그에 많은 걸 담아보자라는 의미로 류리상자로 지었다. 참고로 가수 유리상자한테 영감 얻었다. 닉값 제대로 하고 있다 ㅎ

Naver Blog

12장 다형성

상속을 코드 재사용을 위해서 사용하지 말자. 상속은 런타임 때 적합한 메서드를 동적으로 탐색해서 찾기 위한 일종의 탐색 경로를 클래스 계층의 형태로 구현하기 위한 방법 다형성을 위한 서브타입 계층 구축 다형성 하나의 추상 인터페이스에 대해 코드를 작성하고 이 추상 인터페이스에 대해 서로 다른 구현을 연결할 수 있는 능력 여러 타입을 대상으로 동작할 수 있는 코드 다형성은 아래와 같이 구분된다. 유니버설 매개변수 포함 임시 오버로딩 강제 강제 다형성 언어가 지원하는 자동적인 타입 변환이나 사용자가 직접 구현한 타입 변환을 이용해 동일한 연산자를 다양한 타입에 사용할 수 있는 방식 ex) "+" 이항 연산자 매개변수 제네릭 프로그래밍과 관련이 있다. 인스턴스 변수나 매개변수 타입을 임의의 타입으로 선언한 후 사용하는 시점에 구체적인 타입으로 지정하는 방식 포함 메시지가 동일하더라도 수신한 객체의 타입에 따라 실제로 수행되는 행동이 달라지는 능력 서브타입 다형성 객체지향에서의 일반적인 다

Naver Blog

13장 서브클래싱과 서브타이핑

상속 상속의 용도는 타입 계층을 구현하는 것 동일한 메시지에 대해 서로 다르게 행동할 수 있는 다형적인 객체를 구현하기 위해서는 객체의 행동을 기반으로 타입 계층을 구성해야 한다. 타입 사이의 관계를 고려하지 않은 채 단순히 코드를 재사용하기 위해 상속을 사용해서는 안 된다. 타입 개념 관점의 타입 우리가 인식하는 객체들에 적용하는 개념이나 아이디어를 가리켜서 타입이라고 한다. 어떤 대상이 타입으로 분류될 때 그 대상을 타입의 인스턴스 타입의 인스턴스를 객체 공통의 특징을 공유하는 대상들의 분류 프로그래밍 언어 관점의 타입 타입은 연속적인 비트에 의미와 제약을 부여하기 위해 사용 두 가지 목적을 위해 사용 1. 타입에 수행될 수 있는 유효한 오퍼레이션의 집합을 정의 2. 타입에 수행되는 오퍼레이션에 대해 미리 약속된 문맥을 제공 동일한 오퍼레이션을 적용할 수 있는 인스턴스들의 집합 객체지향 패러다임 관점의 타입 객체의 타입이란 객체가 수신할 수 있는 메시지의 종류를 정의하는 것 메시

Naver Blog

1월 끝

후. .점점 일상 쓰기가 귀찮아진다!! 그래도 1월 마지막이니 쓴다. 회사 점심을 먹은 도쿄스테이크.. 채끝살 정식 내 최애~~~~ 너무 맛있어~~ 퇴근하고 운동하고 지하에 있는 식당에서 먹은 제육볶음.. So so.. 요즘 딸기 많이 먹는다! 맛있어! 포켓몬도 진작에 엔딩 봤다.. 재밌어.. 문제는 엔딩 보고 나니 귀찮아서 잘 안 하는 중 ㅠ 드디어 나도 아바타 봤다! 롯데시네마 슈퍼플렉스에서 봤다 ㅎ 사진도 하나 찍어주고! 당연히 팝콘도 사고! 와우! 슈퍼플렉스 처음이었는데 엄청 커서 놀랐다. 영화관 엄청 크다. 3D로 봤는데 처음에 안경 불편했는데 어느 순간 안경 쓴 지도 모르면서 봤다. 3시간 엄청 길겠구나고 생각했는데 금방 지나가버렸다. 화장실 한 번도 안 갔다 ㅎ 영화 보고 배고파서 잠실역 맥도날드!! 금요일 출근해서 혼밥으로 먹은 연어 덮밥!! 이날이 설날 연휴 금요일 + 해피프라이데이여서 회사에 진짜 사람이 없었다. 원래 회사 카페에 사람 엄청 많은데 진짜 한 명도 없

Naver Blog

2월 계획

오브젝트 책 마무리 및 복습 15장 + 부록 A, B, C 있는데 현재 14장 보는 중 부록까지 다 보고 복습하기 김영한 DB 2 강의 보고 정리하기 대규모 시스템 설계 기초 책 3분의 2 이상 보기 Oracle 책 다 보기 위 4가지 하고 여기에 더 할 수 있으면 자바 책 다시 보기 욕심부리지 말자!

Naver Blog

14장 일관성 있는 협력

가능하면 유사한 기능을 구현하기 위해 유사한 협력 패턴을 사용하자. 기본 정책 확장 유사한 기능을 서로 다른 방식으로 구현해서는 안 된다! 설계에 일관성 부여하기 일관성 있는 설계를 만들기 위해서 다양한 설계 경험을 익히자. 디자인 패턴을 학습하자. 변하는 개념을 변하지 않는 개념으로부터 분리하자! 변하는 개념을 캡슐화하자! 클래스를 분리하기 위한 조건 가장 중요한 기준은 변경의 이유와 주기다.! 클래스는 명확히 단 하나의 이유에 의해서만 변경돼야 하고 클래스 안의 모든 코드는 함께 변경돼야 한다.! 단일 책임 원칙을 따르자 캡슐화 다시 살펴보기 데이터 은닉 오직 외부에 공개된 메서드를 통해서만 객체의 내부에 접근할 수 있게 제한함으로써 객체 내부의 상태 구현을 숨기는 기법 모든 인스턴스 변수 private으로 선언하고 해당 클래스의 메서드만이 인스턴스 변수에 접근할 수 있어야 한다. 캡슐화는 데이터 은닉 이상 캡슐화는 변하는 어떤 것이든 감추는 것 대표적인 예는 객체의 퍼블릭 인터

Naver Blog

15장 디자인 패턴과 프레임워크

디자인 패턴과 프레임워크 디자인패턴 소프트웨어 설계에서 반복적으로 발생하는 문제에 대해 반복적으로 적용할 수 있는 해결 방법 목적은 설계 재사용 특정한 변경을 일관성 있게 다룰 수 있는 협력 템플릿 제공 협력을 일관성 있게 만들기 위해 재사용할 수 있는 설계의 묶음 프레임워크 설계와 코드를 함께 재사용하기 위한 것 특정한 변경을 일관성 있게 다룰 수 있는 확장 가능한 코드 템플릿 제공 일관성 있는 협력을 제공하는 확장 가능한 코드 소프트웨어 패턴 패턴이란? 패턴은 반복적으로 발생하는 문제와 해법의 쌍으로 정의 패턴을 사용함으로써 이미 알려진 문제와 이에 대한 해법을 문서로 정리할 수 있고, 이 지식을 다른 사람과 의사소통할 수 있다. 패턴은 추상적인 원칙과 실제 코드 작성 사이의 간극을 메워주며 실질적인 코드 작성을 돕는다. 패턴 분류 아키텍처 패턴 소프트웨어의 전체적인 구조를 결정 분석 패턴 도메인 내의 개념적인 문제를 해결 디자인 패턴 특정한 설계 문제를 해결하는 것을 목적으로

Naver Blog

나는 리뷰어다 2023

한빛 미디어 나는 리뷰어다 2023에 선정됐다. 2022년에도 했었는데 2023년도... 잘 해보겠습니다!! 좋은 책 많이 걸리길~ 와 이번엔 귀신 같이 다 내가 필요한 것들만 있었다. nginx도 필요하고 MSA도 필요하고 코틀린도 필요하고!!!!!!!! 야호!!!!

Naver Blog

[JAVA] Thread, Runnable

자바의 멀티 스레드 기반의 프로그래밍을 위해 사용하는 Thread, Runnable Thread Thread 생성을 위해 Java에서 미리 구현해둔 클래스 sleep 현재 스레드 멈추는 기능 자원을 놓아주지 않고, 제어권을 넘겨주기에 데드락 발생 가능 interupt 다른 스레드를 깨워서 interruptedException 발생시킴 Interupt가 발생한 스레드는 예외를 catch 해서 작업할 수 있다. join 다른 스레드의 작업이 끝날 때까지 기다림 스레드의 순서를 제어할 때 사용 자바에서는 기본적으로 메인 스레드 1개에 의해서 프로그램이 실행된다. Main Thread도 만들어지고 ExThread에서 새로운 스레드가 생성이 된다. start() 메서드를 사용하게 되면 run 메서드가 실행된다. 중요한 게 run 메서드 직접 실행이 아니라 start 실행이다. 별도의 스레드에서 ExThread의 메서드를 실행하고 싶은 것인데 run을 직접 호출하면 메인 스레드에서 객체의 메서

Naver Blog

[JAVA] Callable, Future, Executor

Callable 기존의 Runnable 인터페이스는 결괏값을 반환할 수가 없다. run의 반환형이 void이다. Runnable의 발전된 형태로 제네릭을 사용해서 결과를 받을 수 있는 Callable이 만들어짐 제네릭 V가 응답 값이다. 위와 같이 사용할 수 있다. Future Callable 인터페이스의 구현체인 작업 Task는 가용 가능한 쓰레드가 없어서 실행이 미뤄질 수도 있고, 작업 시간이 오래 걸릴 수 있다. 이를 위해서 실행 결과를 바로 받지 못하고 미래의 어느 시점에 얻을 수 있는데, 미래에 완료된 Callable의 반환값을 구하기 위해서 사용되는 것이 Future이다. Future는 비동기 작업을 가지고 있어 미래에 실행 결과를 얻도록 도와준다. 비동기 작업의 현재 상태 확인, 기다리기, 결과를 얻는 법 제공 cancel 작업을 취소시키고 취소 여부를 반환함 cancel 후에 isDone()은 항상 true 반환 isDone 작업의 완료 여부를 반환 isCancelle

Naver Blog

[JAVA] CompletableFuture

CompletableFuture java8에 추가 Future의 한계 외부에서 완료시킬 수 없고, get의 타임아웃 설정으로만 작업 완료가 가능하다. get(블로킹 코드)를 통해서만 이후의 결과를 처리할 수 있다. 여러 Future를 조합하고 예외 처리할 수 없다. CompletableFuture Future을 외부에서 완료시킬 수 있어서 CompletableFuture CompletionStage 인터페이스도 구현하고 있다. 작업들을 중첩시키거나 완료 후 콜백을 위해 추가 몇 초 이내에 응답이 안 오면 기본값을 반환 같은 거 추가 가능 외부에서 작업을 완료 시킬 수 있고 콜백 등록 및 Future 조합 가능 비동기 runAsync 비동기이면서 반환 값이 없는 경우에 사용한다. 반환 값이 없기에 CompletableFuture<Void>를 반환한다. CompletableFuture는 별도의 스레드에서 작업이 실행된다. supplyAsync 리턴 값이 runAsync와 다르게 존재한다

Naver Blog

[JAVA] 멀티 스레드

멀티 프로세스, 멀티 스레드 운영체제는 실행 중인 프로그래밍을 프로세스 멀티 태스킹은 두 가지 이상의 작업을 동시에 처리 멀티 태스킹 != 멀티 프로세스 하나의 프로세스가 멀티 스레드를 통해서 두 가지 이상의 작업을 처리할 수 있다. 멀티 프로세스가 프로그램 단위의 멀티 태스킹 각 프로세스들은 독립적이기에 하나의 프로세스에서 오류가 발생해도 다른 프로세스에게 영향을 미치지 않는다. 멀티 스레드는 프로그램 내부에서의 멀티 태스킹 각 프로세스가 프로세스 내부에서 생성되기에 하나의 스레드가 예외를 발생하면 프로세스가 종료되기에 다른 스레드에게 영향을 미침. 멀티 스레드 애플리케이션 자바는 메인 스레드가 main 메서드를 실행하면서 시작 메인 스레드가 코드를 실행하면서 필요에 따라서 추가 스레드를 만들어서 실행 가능 멀티 스레드에서는 실행 중인 스레드가 하나라도 있으면 프로세스는 종료되지 않는다. 심지어 메인 스레드가 먼저 종료돼도 작업 스레드가 계속 실행 중이면 프로세스는 종료되지 않는다

Naver Blog

[JAVA] 스레드 동기화

스레드 동기화 멀티 스레드는 하나의 객체를 공유해서 작업 가능하다. 다른 스레드에 의해서 객체 내부 데이터가 변경될 수 있기에 다른 결과가 나올 수 있다. 이를 위해서 스레드 작업이 끝날 때가지 다른 스레드가 변경할 수 없도록 스레드 작업이 끝날 때까지 객체에 잠금을 걸면 된다. 다음과 같이 Lock을 걸면 Lock을 건 스레드만 접근 가능하고 다른 스레드는 접근할 수 없다. Lock을 걸지 않은 메서드는 접근 가능하다. synchronized 일반적인 set 메서드를 가지는 Total Class를 만들자. ExThread2에서는 total 값을 3333으로 바꾼다. ExThread1에서는 total 값을 9999으로 바꾼다. 실행해 보면 둘 다 3333으로 나오게 된다. Synchronized를 사용하게 되면 위와 같이 정상적으로 나오게 된다. wait()과 notify()를 이용한 스레드 제어 두 개의 스레드를 번갈아가면서 실행하기 위해서는 wait()와 notify()를 사용한

Naver Blog

[1년 전 오늘] 류리의 자취 일기 시즌 2

2022.2.14. 1년 전 오늘 류리의 자취 일기 시즌 2 2019년 9월 1일 ~ 2019년 12월 24일 자취 일기 시즌 1이 끝나고 다시는 자취 일기 안 쓸 줄 알았는데.. 이번 연도부터 자취하게 돼서 자취 일기 시즌 2 시작합니다!!!!!!!!!! 오예!!!!!!!!!!! 1학기 2학년 자취하고 2학년 1학기 집에서 2학년 2학기 ~ 3학년 2학기 겨울방학까지 기숙사에서 쭉 살다가 4학년부터는 혼자 살면... 류리상자 자취 일기를 쓸려고 했지만.. 그냥 일상으로 써버렸네 블챌도 하고!! 그리고!!! 다른 집도 계약완료했다!!!! 빨리 이사 가고 싶다!

Naver Blog

Spring boot Filter

일하면서 filter를 쓰게 되었는데 구글링하면서 급하게 쓰게 되니 개념들이 흩어져 있는 것 같아서 이 기회에 한 번 싹 정리하려고 한다. 목차 Filter란 무엇인가 Filter 사용법 GenericFilterBean OncePerRequestFilter Filter란 무엇인가 스프링 MVC 요청 라이프 사이클 그림 스프링에서 공통 작업을 처리할 수 있는 기능을 제공하는 데 그중 하나가 Filter이다. 위 그림에서 알 수 있듯이 Filter는 DispatcherServlet 앞에 위치하게 된다. DispatcherServlet 앞에 위치해서 HTTP 요청 전달 전후로 url 패턴에 맞게 공통 작업을 수행할 수 있게 한다. 이때 DistpatcherServlet은 스프링의 가장 앞단에 있는 프런트 Controller에 있기에 Filter는 스프링 밖에서 처리가 된다. Filter가 속한 패키지를 보면 servlet에 속하게 된다. 그렇기에 스프링과 무관하게 전역적으로 처리해야 하는

Naver Blog

[서평] 자바에서 코틀린으로 Java to Kotiln 코틀린으로 리팩터링하기 (덩컨 맥그레거, 냇 프라이스 지음, 오현석 옮김

이번에 한빛 미디어에서 받은 책은 자바에서 코틀린으로 Java to Kotiln 코틀린으로 리팩터링하기 책입니다. 앞표지에는 사향고양이의 일종인 하우사제넷이 그려져 있네요. 저는 한빛미디어 책에 이렇게 멸종 동물이 그려져 있는 게 좋더라고요 뒤표지에는 책을 요약한 부분이 써져있습니다. 이 책은 자바에서 코틀린으로 넘어가는 개발자를 위한 책입니다. 하지만 단순히 코틀린의 문법을 가르쳐 주는 책은 아니고 자바에서 코틀린으로 넘어갈 때 어떻게 코틀린 식으로 생각을 해야 되는지 코틀린으로 짰을 때의 장점이 무엇인지 코틀린 다운 코드가 무엇인지를 보여줍니다. 그리고 단계 단계별로 차근히 코드가 변환되는 과정을 보여줍니다. 챕터는 총 23장까지 있고 537쪽까지 있습니다. 책의 초반 부분에서는 어떻게 프로젝트를 세팅해야 되는지까지 친절하게 설명해 주고 있습니다. 책의 크게 자바 코드를 보여주고 코드를 설명해 준 다음에 이 코드를 어떻게 코틀린으로 변환하는지를 보여주고 있습니다. 먼저 옵셔널로

Naver Blog

[JAVA] 스트림

스트림 요소들이 하나씩 흘러가면서 처리된다는 의미를 가진다. Iterator와 Stream 왼쪽이 이터레이터 오른쪽이 Stream Stream은 내부 반복자이기에 처리 속도가 빠르고 병렬 처리에 효율적 람다식으로 다양한 요소 처리 정의 가능 중간 처리와 최종 처리를 수행하도록 파이프라인 형성 가능 내부 반복자 for 문과 iterator는 컬렉션의 요소를 컬렉션 바깥쪽으로 반복해서 가져와 처리한다. 이를 외부 반복자 컬렉션의 요소를 외부로 가져오는 코드와 처리하는 코드를 모두 개발자가 가지고 있어야 함 iterator의 hasNext를 통해서 있는지 확인하고 next()를 통해서 외부로 가져온 다음에 처리하는 코드가 있어야 함 스트림은 요소 처리 방법을 컬렉션 내부로 주입시켜서 요소를 반복 처리하는 것인데 이를 내부 반복자라고 한다. 개발자 코드에서 제공하는 데이터 처리 코드를 가지고 컬렉션 내부에서 요소를 반복 처리한다. 내부 반복자는 멀티 코어 CPU를 최대한 활용하기 위해 요소

Naver Blog

ElasticSearch

GET products/_search { "query": { "bool": { "must": [ { "match": { "name": "laptop" } }, { "range": { "price": { "gte": 500, "lte": 2000 } } } ], "must_not": [ { "term": { "discounted": true } } ], "should": [ { "term": { "brand.keyword": "Apple" } }, { "term": { "brand.keyword": "Samsung" } } ] } } } must 쿼리가 모두 참인 문서만 검색 AND 조건 must_not 쿼리가 모두 거짓인 문서만 검색 AND 조건 should 쿼리 중 하나만 만족하면 검색함 OR 조건 많은 쿼리가 만족할 수록 score 상승 filter 쿼리가 모두 참인 문서만 검색 AND 조건 must보다 속도가 빠르다. score를 산정하지 않는다. 캐시 가능

Naver Blog

2월

2월 한 방에 쓴다. 3월 초반에 한 번 1시간 정도 걸려서 썼는데 실수로 다 날아가버렸다.. 요즘 내 최애 음식 규카츠.. 존맛탱 꼭 먹어보세요~ 사수가 퇴사를 해서.. 송별회 할 겸 점심에 서울역 근처에 있는 이쁜 브런치 카페로 왔다. 4명이서 4개 시켰다. 음식 다 맛있다. 샐러드랑 피자도 맛있다. 같은 날 저녁에 먹은 돈까스 집.. 맨날 가보려다가 이번에 처음 가봤는데!! 완전 맛있다. 영화 바빌론 보러 간 날 영화 보러갈 때 마다 앤티앤즈 사가지고 간다. T1 팝업 스토어가 있어서 구경해봤다. 우리 롤드컵은 언제 우승하니..? 바빌론.. 한 영화에 여러 개의 에피소드로 구성된 느낌이다. 3시간의 런닝 타임인데 갠적으로 재밌게 봤다. 2월 7일에 집도 이사했다. 윽.. 지금 보니 엄청 작은 집에서 1년을 살았구나 짐 엄청 많다. 짐을 1층에 두고 계속 집을 청소 하고 있었는데 폐지 줍는 할머니분들이 계속 쓰레기인 줄 알고 가져가려고 해서 당황했다. 처량한 S.. ㅋㅋㅋㅋㅋㅋㅋ

Naver Blog

롯데월드 나들이

2월 26일에 롯데월드 갔다 왔다. 눈치게임은 실패했지만 재밌게 놀다 왔다. 내 기억으로 고등학교 1학년 때 온 게 마지막인 것 같다.. 11년 만에.. 온 롯데월드 이런 게 있었나.. 바로 혜성특급을 타러 갔다!!!! 혜성 특급 줄.. 내 평생 본 것 중 제일 길었다. 줄이 기니까 바로 맛있는 거 사 왔다. 혜성특급 앞 쪽에 130분이라 적혀 있는데 정말 귀신같이 130분 걸렸다 ㅋㅋㅋㅋㅋ 흑흑 줄 서서 여기까지 오는데 딱 130분.. 3분 정도 타는데.. 어지러웠지만 재밌었다.. 130분 혜성특급! 혜성특급 한 번 타보고 다른 거 타는 건 거의 불가능할 것 같다고 빠르게 판단해서 줄 별로 없는 것만 골라서 탔다. 어린이용 환타지 드림.. ㅎ 찰리와 초콜릿 공장 같은 느낌 어린이용답게 잘 꾸며져 있다. 출발!!!! 근데 개인적으로 좀 무섭게 느껴졌다. ㅋㅋㅋㅋㅋㅋ 지금 사진 보니 무섭네.. 그래도 실제로 보면 잘 꾸며져 있어서 이쁘다. 점심으로는 타코 먹었다. 존맛탱이긴하다. 점심

Naver Blog

문래역, 홍대입구역 나들이

문래역에 창작촌이 있다고 해서 가봤다. 금강산도 식후경이라고.. 일단 점심부터 먹었다. 분짜에 쌀국수 맛있다. 창작촌이라고 해서 기대하고 갔는데. 오잉~!~! 다나카 벽이 있길래.. 사진 하나 찍었다. 허허. . 창작촌.. 볼 게 없었다. 실제로 가서 보면.. 약간 좀비 영화에서 좀비 발생 후 10년 뒤의 모습이랄까.. 아포칼립스 느낌 그래도 #러스트베이커리 는 괜찮았다. 공장을 개조한 카페! 직접 가서 봤을 땐 몰랐는데 사진으로 보니 진짜 공장 같네 나름 잘 꾸며져있다. 빵은 맛있다. 푸딩이랑 에그타르트랑 하나 뭐였지.. 아.. 아이스아메키라노는 내가 지금까지 마셔본 것 중에서 제일 쓴맛이었다. 티라미슈 푸딩 맛있다. 이거 두 개도 맛있다. 오.. 이 사진 좀 느낌 있는데 맛있게 잘 먹고 갑니다. 문래역은 할 게 없어서 홍대입구역으로 가서 잠시 만화카페 갔다가 #또보겠지떡볶이 먹으러 갔다. 떡볶이 맛있다. 하지만!!!!!!! 이 감자튀김이 진짜 맛있다!!!!!!!!!!!!! 무조건

Naver Blog

싱글톤 패턴

싱글톤 패턴 인스턴스를 오직 한 개만 제공하는 클래스가 필요할 때 싱글톤 패턴이 필요하다. public class Setting { private Setting(){ } public static Setting getInstance() { return new Setting(); // 다르게 나와버림 } } 먼저 싱글톤 패턴을 하기 위해서는 외부에서 new 연산을 사용하지 못하게 만들어야 한다. 이를 위해서 private 기본 생성자를 만들어준다. Private를 하게 되면 외부에서 인스턴스를 생성할 수 없게 된다. 다만 위의 코드에서는 getInstance()에서 return new를 사용하고 있기에 매 생성할 때마다 다른 인스턴스가 나오게 된다. public class Setting { private static Setting instance; //static 선언으로 별도의 지정된 메모리 공간에만 존재. private Setting() { } public static Setting

Naver Blog

팩토리 메서드 패턴

팩토리 메서드 패턴 생성 패턴 중 하나로 객체를 생성할 때 어떤 클래스의 인스턴스를 만들지 서브 클래스에서 결정하게 된다. public class ShipFactory { public static Ship orderShip(String name, String email) { // validate if (name == null || name.isBlank()) { throw new IllegalArgumentException("배 이름을 지어주세요."); } if (email == null || email.isBlank()) { throw new IllegalArgumentException("연락처를 남겨주세요."); } prepareFor(name); Ship ship = new Ship(); ship.setName(name); // Customizing for specific name if (name.equalsIgnoreCase("whiteship")) { ship.setLogo

Naver Blog

스프링 트랜잭션

@Transactional @Transactional 애노테이션을 사용하면 트랜잭션 프록시가 트랙잰션 처리 로직을 모두 가져간다. 트랜잭션을 처리하는 프록시를 적용해 준다. @Transactional과 Proxy @Transactional 애노테이션이 있으면 트랜잭션 AOP는 Proxy를 만들어서 스프링 컨테이너에 등록 실제 서비스 객체 대신에 프록시를 스프링 컨테이너 빈에 등록한다. 프록시 내부에서는 실제 서비스를 참조하게 된다. Client에서 Service를 호출하면 트랜잭션을 사용할 수 있는지 확인을 하게 된다. 트랜잭션 애노테이션이 붙어 있으면 트랜잭션을 적용하고 붙어 있지 않으면 트랜잭션을 적용하지 않는다. 프록시 내부 호출 문제 @Transactional을 적용하면 프록시 객체가 요청을 먼저 받아서 트랜잭션을 처리하고 실제 객체를 호출 그렇기에 트랜잭션을 적용하려면 항상 프록시를 통해서 대상 객체를 호출해야 된다. 프록시를 거치지 않고 대상 객체를 직접 호출하게 되면 A

Naver Blog

스프링 트랜잭션 전파

스프링 트랜잭션 트랜잭션이 둘 이상 있을 때 스프링이 제공하는 트랜잭션 전파 개념을 사용할 수 있다. @Test void double_commit() { log.info("트랜잭션1 시작"); final TransactionStatus tx1 = transactionManager.getTransaction(new DefaultTransactionAttribute()); log.info("트랜잭션1 커밋 시작"); transactionManager.commit(tx1); log.info("트랜잭션2 시작"); final TransactionStatus tx2 = transactionManager.getTransaction(new DefaultTransactionAttribute()); log.info("트랜잭션2 커밋 시작"); transactionManager.commit(tx2); } 트랜잭션을 두 번 하는 코드이다. 첫 번째 트랜잭션에서 conn0 커넥션을 획득하고 커밋 한 다음

Naver Blog

추상 팩토리 패턴

추상 팩토리 패턴 구체적인 클래스에 의존하지 않고 서로 연관되거나 의존적인 객체들의 조합을 만드는 인터페이스를 제공하는 패턴 관련성이 있는 여러 종류의 객체를 일관된 방식으로 생성하는 경우에 유용하다. 클라이언트 코드에서 구체적인 클래스의 의존성을 제거한다. 팩토리 메서드 패턴과의 차이 팩토리 메서드 패턴은 팩토리를 구현하는 방법에 초점 팩토리 인터페이스를 구현하여 하나의 객체를 생성하는 데 사용이 된다. 추상 팩토리 패턴은 팩토리를 사용하는 방법에 초점 팩토리 객체가 아닌 다른 객체 내부에 구현되어 해당 객체에서 여러 타입의 객체를 생성하기 위해 사용된다. 추상 팩토리 코드 public interface ShipPartFactory { Anchor createAnchor(); Wheel createWheel(); } ShipPartFactory 인터페이스 하나에 Anchor와 Wheel을 만드는 코드가 정의되어 있다. Ship 1개가 아닌 Anchor, Wheel을 만든다. pub

Naver Blog

빌더 패턴

빌더 패턴 복합 객체의 생성 과정과 표현 방법을 분리해 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다. 말이 너무 어렵다. 그냥 복잡한 객체들을 단계별로 생성할 수 있게 만드는 디자인 패턴이다. 사용 예시 package me.whiteship.designpatterns._01_creational_patterns._04_builder._01_before; import java.time.LocalDate; import java.util.List; @Getter @Setter public class TourPlan { private String title; private int nights; private int days; private LocalDate startDate; private String whereToStay; private List<DetailPlan> plans; public TourPlan() { } public TourPlan(String t

Naver Blog

Optimistic Lock 이용 동시성 문제 해결

Optimistic Lock Lock을 이용하지 않고 Version을 이용해서 정합성을 맞추는 방법 데이터를 읽은 후에 update를 수행할 때 현재 내가 읽는 버전이 맞는지 확인해서 업데이트를 한다. 만약 읽은 버전에서 수정사항이 생겼을 경우 application에서 다시 읽은 후에 작업을 수행해야 됨 Optimistic Lock을 사용하기 위해서는 Entity에 @Version을 추가해줘야된다. OptimisticLockStockService를 추가해준다. @Lock(value = LockModeType.OPTIMISTIC)을 이용해서 사용할 수 있다. OptimisticLock을 사용할 때 실패 했을 때 재시작할 수 있는 로직을 추가해줘야한다. 개발자가 직접 추가 해야됨 테스트를 해보게 되면 성공한다. OptimisticLock을 Lock을 사용하지 않기에 비관적 락보다 성능상 이점이 있다. 충돌이 빈번하게 일어나면 비관적 락이 더 좋을 수 있다. MySQL을 사용한다면 Iso

Naver Blog

Named Lock 이용 동시성 문제 해결

Named Lock 이름을 가진 metadata Locking이다. 이름을 가진 Lock을 획득한 후 해제할 때까지 다른 세션은 이 Lock을 획득할 수 없도록 한다. 다만 Transaction이 종료될 때 Lock이 자동으로 해제되지 않는다. 별도의 명령어로 해제를 하거나 선점시간이 끝나면 해제된다. Named Lock을 사용하기 위해서 Repository를 만들어준다. get_lock을 이용해서 Lock을 얻어오고 release_lock을 통해서 Lock을 해제해준다. Named Lock을 활용할 떄는 데이터소스를 분리해야한다. 모든 Lock이 해제되지 않는다면 데이터소스가 부족해지는 현상이 발생할 수 있다. 특히 Named Lock은 커넥션을 2개 사용한다. lock 획득에 필요한 connection 1개, transaction에 필요한 커넥션 1개 같은 데이터베이스 소스를 사용한다면 커넥션 풀을 넉넉하게 잡아주자. Facade class를 만들어서 Get, release를 해

Naver Blog

Lettuce 이용 동시성 문제 해결

redis 활용 분산락 구현 트래픽이 많은 서비스에서는 redis를 사용하는 것이 가장 좋다. 인메모리데이터베이스라 굉장히 빠르기에 Lettuce setnx 명령어를 활용하여 분산락 구현 Setnx : set if not exist 키와 벨류를 Set 할 때 기존의 값이 없을 때만 set spin lock 방식 retry를 개발자가 직접 작성해줘야됨 lock을 획득하려는 thread가 반복적으로 확인하면서 lock을 획득하는 방식 Redis를 사용하기에 RedisRepository를 구현해준다. Facade를 만들어서 lock을 획득할 때까지 while문을 돌린다. spin Lock 방식이기에 Redis에 부하를 줄 수 있어서 sleep을 넣어줬다. lock을 획득하면 decrease 메서드를 수행하고 꼭 UnLock 한다. 테스트 코드를 작성하면 테스트가 정상 수행된다. 이때 redis를 킨 상태여야되고, redis에 해당 Key 값이 없어야된다. 출처 : 재고시스템으로 알아보는

Naver Blog

Redisson 이용 동시성 문제 해결

Redisson 락을 획득하지 못했을 때 Lettuce에 비해 재시도 횟수가 적어서 Redis에 부하가 적다. Redisson은 Lock 관련 Class를 제공하기에 별도로 class를 만들 필요가 없다. 로직 실행 전후로 Lock 획득, 해제는 해줘야 하기에 Class가 필요하다. Facade를 구현해 준다. redissonClient에서 getLock을 통해서 Lock을 얻을 수 있고 tryLock으로 시도해본다. Lock을 얻으면 decrease 메서드를 실행하고 꼭 마지막에 unLock 해준다. 테스트 코드를 실행해 보면 정상 작동한다. Lettuce vs Redisson Lettuce 구현이 간단하다. Spring-data-redis를 이용하기에 Lettuce가 기본 제공 Spin Lock 방식이기에 동시에 많은 Thread가 Lock 획득 대기 상태면 Redis에 부하가 갈 수 있다. Redisson Lock 획득 재시도를 기본으로 제공한다. Pub-Sub으로 구현되어 있

1 2 3 4 5 6 7 8 9 10