728x90
반응형

Java 79

effectively final 및 lambda capturing에 대해 톺아보기

개요 당연하게 사용하던 Java의 람다 기능에 대해서 의문을 갖지 않고 막 써댔다. 그렇지만, 면접에서의 질문을 받았을 때 당황했다. 뜬금포로 final을 쓰고 안쓰고의 차이를 물어보셨는데 순간 답변을 하지 못했다. 그래서 정리해본다. 람다 캡쳐링에 대해서 알아보기 이전에 Effectively final에 대해 먼저 알아보자. Effectively Final 이란? 해당 단어를 deepL을 통해 해석해보면 사실상 최종 이라고 해석해준다. final을 선언한 상수와 같이 변경되지 않았다면 그와 같은 수준으로 컴파일러가 해석해준다. effectively final이 되려면 아래의 3가지 조건을 만족해야 한다. 아래 3가지 조건은 공식문서를 통해서 나와있는 정보들이다. 명시적인 final을 선언하지 않았다. ..

Java 2023.12.08

Stream 오류 제거

의문점 스크래핑 로직 실행 시간에 대해 의문을 가졌다. 평균 시간이 그럭저럭 다들 비슷한 수준에 머무는데, 이상하게 한 부분만 너무 느렸다. 증권사에 대한 스크래핑 내역이었는데, 특정 증권사만 중복 로그인이 감지되었을 경우 30초를 대기했다가 다시 수행할 수 있게 하는 로직이 들어있었고, 테스트 코드는 그에맞는 정말 30초를 기다리는지에 대한 여부를 테스트 하고 있었다. 🤔 그냥 30초를 기다리는것보단 특정한 법인이 아니라면 30초를 기다리지 않는다 를 테스트하면 되지 않을까? 이렇게 생각했던 이유는 30초를 테스트에서 기다리는 비용이 비싸다고 생각했고, 전체 테스트를 돌릴 때 이 부분때문에 30초를 더 기다려야 한다는 것이다. 그리고 milliseconds 차이값을 비교했기에 간헐적으로 실패하는 경우도..

디버깅 2023.04.21

FeignClient Logging level 디버깅

회사의 서비스들이 여러개로 쪼개져있다. 그래서 우리는 주로 FeignClient를 사용하는데, 애를 먹었던 로깅레벨에 대해 포스팅한다. 업무중에 삽질을 진행했었으며, 해당 내용으로 자바스럽게 고쳤던 경험을 좀 풀어본다.. 스프링 프레임워크를 사용하고 있기에 여기서 같이 제공해주는 Spring Cloud의 OpenFeign을 사용하였다. 아래는 사용하는 예시이다. 해당 예시처럼 나는 FeignClient를 구현했었다. 물론 @EnableFeignClients 는 별도의 Configuration 클래스 파일에 설정을 해주었었다! 여기까지는 일단 기본적인 설정이지만, 아래의 레벨 설명이 진짜다. Feing Logging Level은 총 4단계로 이루어져있다. NONE: 로깅 없음(Default) BASIC: ..

디버깅 2022.12.17

@Async 사용시 에러 해결

오랜만에 포스팅하는데 회사에서 그동안 앱 2.0 버전을 출시한다고 이래저래 바빴던 나날을 보냈다. 결과적으로는 만족스러운 출시..? 였던것 같다 ㅋㅋㅋ 버그도 많았고, QA 엔지니어께서 고생을 많이 하셨을 수도 있고 내가 구현한 메시지 플랫폼도 테스트하기가 정말 까다로웠다. 각설하고.. 해당 에러사항을 구현하는건 Kafka를 이용하지 않아도 되기 때문에 RestAPI로 구현했다. (+ 테스트코드로만) 모든 코드는 깃허브에 있다. 이번엔 무슨 버그였냐? 이런 에러가 쏟아져나왔다. 기존 레거시 푸시는 NHN Toast를 이용한 푸시서비스로 구성되어 있었다. 변경한다고 해도 과도기가 존재하기 때문에 바로 지울수는 없고 이전 앱을 사용하는 사용자들에게는 해당 푸시로 알림은 계속 받아야되기 때문이다. 왜 났던 에..

디버깅 2022.11.04

Kafka Offset Commit의 중요성

저번 포스팅의 마지막 마무리가 바로 이 에러를 찾지 못했던 것이다. Kafka 에러를 고치게 된 시점 처음에 특정 Consumer만 consume을 못한다고 했었는데, 이는 당연 잘못된 것이었다!!! 그냥 로그를 좀 더 세세하게 찍고 검토를 더 열심히 했어야 했다! 우선 대략적으로 코드를 보면 아래와 같다. @KafkaListener(topics = "topic", properties = { "spring.kafka.consumer.properties.spring.json.type.mapping=com.github.lsj8367.MessageReq" }) public void consumeSomething(final MessageReq req, Acknowledgment acknowledgment) { ..

Spring/Kafka 2022.10.06

Spring Kafka 좀 더 공통 설정하기

일전에 카프카 에러 포스팅 에서 Configuration 설정을 자바 클래스에서 해주었다. 그것도 클래스별로!! 에러 포스팅과 더불어 This error handler cannot process 'SerializationException's directly; please consider configuring an 'ErrorHandlingDeserializer' in the value and/or key deserializer 이런 문구도 출력해줬었다. 근데 저 에러 포스팅을 보면서 좀 더 공통화할 수 없을까에서 찾아보다가 ErrorHandlingDeserializer 관련 검색을 해보다가 문서에서 찾게 되었던게 있는데, 기존의 설정을 이미지로 한번 가져와봤다. 그런데 이 방법을 Listener가 늘어나..

Spring/Kafka 2022.10.06

Spring Kafka Deserializer Class Not Found Exception

현재 회사에서 spring-kafka 를 이용해서 특정 서비스들의 푸시 메세지 이벤트를 받아서 전송해주는 서버를 구현하고 있다. (오늘 쿠버네티스에 배포까지 했다!! 모르는게 너무많은...) 로컬에서 내 맘대로 메세지 토픽을 발행해서 쏴도 잘 맞게 역직렬화를 수행을 해주길래 그냥 그런가보다. 하고 잘 넘어갔던 찰나에!!! Class Not Found Exception 왜? 이 에러가 났을까? 일단 나는 구독하는쪽 그러니까 Kafka에서는 Consumer 쪽 만을 구현해주었다. 내 지식이 부족했던 탓인지는 모르겠지만, 어쨌든 같은 JSON 형태라고 생각해서 클래스가 무엇이던 간에 JSON형식만 같다면 Consume해도 괜찮을 것이라고 처음 생각했었다. 그래서 발행 모델인 Producer쪽에서는 예를 들면 ..

Spring/Kafka 2022.09.16

@ModelAttribute, @RequestBody 커맨드 객체

ModelAttribute와 RequestBody의 커맨드 객체 파싱이 다른것을 확인했다. 한번 알아보자! ModelAttribute 동작과정은 덤이다. ModelAttribute 이 포스팅을 하는 이유는 인자가 많을 경우에 post방식으로 조회를 하는 식으로 구성을 했었는데, 코드리뷰중에 이런말이 나왔었다. get방식으로 다른 객체로 묶어서 한번에 받아보는건 어떤가요? 변수가 많아지면 많아질 수록 수정점이 늘어날것 같아요! 라고 받았다. 그래서 무의식적으로 평소에 하던방식처럼 post로 수정하여 커밋하고 수정했었다. 근데 post로 안바꾸고 get에서 @ModelAttribute 사용하면 객체로 파싱이 된다는것을 듣고 내가 부족했구나 싶었다. 이 글은 그 부분에서 나와 집에와서 따로 정리하여 포스팅한다..

Spring 2022.09.15

참조 유형

이펙티브 자바를 읽다가 약한참조에 대한 이야기가 나와서 포스팅한다. 참조에는 아래 4가지가 존재한다. Strong References (강한 참조) Soft References (소프트 참조) Weak References (약한 참조) Phantom References (팬텀 참조) 이 해당 참조 유형에 따라 GC 실행 대상여부, 시점이 달라진다. 강한참조 new 연산자를 사용하여 객체를 인스턴스화 하고 참조하는 방식. 참조가 해제되지 않으면 GC의 대상이 되지 않는다. Test test = new Test(); 해당 test라는 변수가 참조를 가지고 있다면 GC의 대상이 되지 않는다. test = null이 되는 순간 GC의 대상이 된다. 소프트참조 대상 객체의 참조가 SoftReference만 있다면..

Java 2022.09.12

변성

자바 변성 (Variance) 자바의 가변성에는 크게 공변, 무공변, 반공변이 존재한다. 제네릭을 잘 사용하려면 이 가변성에 대한 이해가 필요하다. 변성을 제대로 이해하려면 "타입 S가 T의 하위 타입일 때, Box[S]가 Box[T]의 하위 타입인가?" 라는 질문에서 시작하는게 좋다. 배열은 공변, 제네릭은 무공변이 기본이라고 다들 알고 있을 것이다. 무공변 (Invariance) or 불공변 기본적으로 제네릭은 무공변이다. 무공변이라고 하니 헷갈리는것 같다. 사전적으로 번역해보면 불공변으로 나오게 된다. 타입 S가 T의 하위 타입일 때, Box[S]와 Box[T] 사이에 상속 관계가 없는 것 쉽게 말하면 너는너, 나는 나 인 느낌이다. 그래서 선언한 유형만 들어갈 수 있게 코드를 구성할 수 있다. O..

Java 2022.08.11
728x90
반응형