728x90
반응형

Spring 26

Slack Slash Commands(슬랙 슬래시 커맨드) 사용하기

회사에서 어떻게 하면 좀 더 편하게 어떤 기능을 사용하게 할 수 있을까? 라는 생각이 계속해서 들었는데, 좋은 기회가 생겼다. 회사에서 영업을 하시는분들이 컨퍼런스, 세미나 등등을 많이 참석하여 홍보하고 고객을 유치하는 과정에서 기회가 생겼다. 그것은 회사의 카드를 발급을 받았는지에 대한 여부 확인을 따로 할 수 없었다는 것인데, 당연히 그럴 것이 회원가입할 때 법인 유무를 체크하지는 않으니 말이다. 그래서 종이로든 아니면 엑셀시트던 특정 자료를 세미나 전에 준비해서 가는 부분이 매우 불편해보였다. (갈 때마다 추가 법인이 있으니까 매번 정리해야 된다.) 자! 그래서 슬랙에서 /법인찾기 법인명 하면 우리에게 가입된 법인인지를 찾는 기능을 구현하고 싶었다. 그래서 데모로 슬래시 커맨드를 만드는 법을 데모로..

Spring 2023.07.06

분산 락

분산 락 회사에서 스크래핑 작업을 수행하다가 분산락을 구현하게 되어 너무 잦은 야근으로 인해 이제야 포스팅을 끄적여본다. 한번의 스크래핑요청은 곧바로 비용 + 시간이 요구된다. 비용이 요청때마다 들고, 내가 구현했던 정부기관의 스크래핑 시간은 길면 15초까지 걸리는 작업도 있다. (의존도가 너무 높은것도 사실이다) 이런 비용과 시간이 드는 스크래핑 작업을 동시 다발적으로 같은 작업을 수행해준다? 이것도 문제가 있을 것이다. 한번의 스크래핑 데이터를 계속해서 돌려쓰면 되지않을까? 이러한 스크래핑 데이터를 공유자원이라 생각했고 이미 요청중인 작업이 있다면 이미 작업중인 스크래핑이 있다고 오류를 내려주는게 오히려 적합하다고 생각했다. Synchronized 우선 Java에서 제공해주는 synchronized ..

Spring 2023.04.15

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

배치 에러 개선기

업무에서 Spring Batch로 세미나를 진행하고, 앱 푸시 기능을 배치로 전환하는 작업을 진행했다.여기에 저장하면서 글로만 보던 것들을 직접 경험해보면서 겪었던 일들을 기록하려고한다.첫번째 에러우리 푸시 배치 서버의 구조는 스프링 스케줄러 서버에서푸시 서버의 api를 호출해서 해당 job들을 돌려주는 방식으로 구성이 되어있다.물론 이 부분을 새롭게 개편해야 하는것은 맞다ㅋㅋㅋ그래서 특정 시간이 되면 해당 job api로 호출을 하는데여기서 대략 총 데이터가 100,000건 정도 되는데 전부 동기 + 블록킹처리로 진행했다.그래서 스케줄러가 api를 쏘고 요청값이 최대 오래걸려도 limit을 30분을 잡았었다.그런데 100,000건의 데이터를 여러 로그를 쌓고, 푸시를 하는데까지 1시간이 넘게 걸렸었다...

Spring 2022.08.11

@Valid, @Validated 차이

@Valid @Validated 차이 @Valid @Valid는 JSR-303표준 스펙이다. org.hibernate.validator.internal.constraintvalidators 안에 구현된 여러 Validator 구현체들로 인해 값을 검증해준다. 이의 핵심은 LocalValidatorFactoryBean 이며, 나는 스프링 부트를 사용하였기 때문에 자동으로 구성이 된다. 동작 원리 기본적으로 컨트롤러에서 @Valid가 없더라도 유효성 검증을 처리하는 로직을 지나간다. 이유는?? InvocableHandlerMethod는 적절한 파라미터 처리기를 찾으려고 HandlerMethodArgumentResolverComposite로 보낸다. 얘가 처리해줄 resolver를 찾는데 getArgument..

Spring 2022.08.10

AOP

예제는 깃허브에 있다. AOP (Aspect Oriented Programming) AOP는 스프링의 핵심 구성요소중 하나이다. 관점지향 프로그래밍은 프로그램 구조에 대한 또 다른 사고방식을 제공하며 객체 지향 프로그래밍을 보완해준다. OOP의 모듈화 핵심 단위 클래스 AOP의 모듈화 단위 관점 (aspect) AOP는 횡단 관심사의 분리를 허용해주어 모듈성을 높이는 것을 목표로 하는 패러다임이다. 코드 자체를 수정하지 않고 기존 코드에 추가 동작을 추가해서 수행한다. 개념 그리고 용어 Aspect 여러 클래스에 중복되어 있는 관심사의 모듈화 대표적인 예로 트랜잭션 관리가 있다. Spring AOP 에서는 @Aspect를 사용한다. JoinPoint 메소드 실행이나 예외 처리와 같은 프로그램 실행중인 지..

Spring 2022.08.10

@ExceptionHandler

@ExceptionHandler 예외 처리기가 어떻게 동작하는지에 대해서 궁금했어서 업무중에 돌려보게 되었다. (예제코드는 다시 작성할 예정) 일단 동작과정은 DB에서 해당 id를 찾아 검색했을 때 없을 경우 예외를 던져주게 하는 예시 간단하게 보면 public class UserService { private final UserRepository userRepository; public User findById(final int id) { return userRepository.findById(id) .orElseThrow(() -> new NotFoundException("해당 유저를 찾을 수 없습니다")); } } 라고 로직을 구성했을 때 이 로직의 예외에 대한 핸들러 동작을 파보게 되었다. 일단 ..

Spring 2022.08.10
728x90
반응형