Java & Kotlin102 Redis를 데이터베이스 답게 사용하는 다양한 방법 안녕하세요. POD 백엔드팀 고희광입니다.이전에 redis를 이용한 분산락 적용으로 이벤트 참여 동시성 이슈를 개선한 것과 더불어 다양한 방법으로 redis를 활용하는 방법을 소개하고자 합니다.먼저 사내에서 redis를 사용하는 사례에는 대표적으로 세가지가 있습니다.JWT 토큰 저장캐시 저장분산락흔히 redis가 뭔지 물어보면 메모리기반이라 빠르다, 싱글스레드이다 등의 답변을 받습니다.하지만 redis가 휘발성 데이터만 저장한다 생각하며 NoSQL 데이터베이스라는 성격을 띄고있는 것에 관심가지지 않는 것 같아 몇가지 사례를 예로 들고자 합니다.이벤트 중복 참여 제한하기이벤트 중복 참여의 경우 분산락을 통해 중복참여 체크 로직에서 걸러지게 되어있습니다.하지만 락을 사용하지 않은 경우 한 회원의 연속된 쿠폰.. 2025. 1. 23. S3 파일업로드, 어떻게 하고 계세요? 안녕하세요.지난 2년이 넘는 기간동안 이미지, PDF 리소스를 중심으로 서비스를 제공하며 겪었던 문제를 AWS에서 제공하는 pre signed url로 해결한 경험을 공유하고자 합니다.기술 스택SpringBootS3IDC, AWS EC2, AWS ECS문제먼저 기존의 파일 업로드 과정은 다음과 같습니다. 이러한 형태의 파일 업로드는 가장 일반적으로 사용하는 파일 업로드 과정이며 MultipartFile 등을 이용해 백엔드 서버에서 S3 스토리지로 직접 업로드를 수행합니다.저희 서비스의 경우 이미지를 주로 다루며 고해상도 이미지 사용과 PDF 업로드를 제공하기 위해 파일 업로드 용량 제한을 크게 설정해 두었습니다.그리고 다음과 같은 장애가 간헐적으로 발생했습니다.대용량 파일을 연속적으로 업로드하는 경우 g.. 2025. 1. 23. Feign에서 multipart/form-data json 조금 더 잘 다루기 업무 중 외부 API 호출이 필요한 상황이 생겼습니다. 이미 사용하고 있던 ClientAPI는 FeignClient였고, 평소 Get, Post 그리고 application/json 형식의 요청을 주로 사용했습니다. 하지만 이번 경우에는 Multipart/form-data 형태의 요청 그리고 File과 json을 함께 전송하는 것을 필요로 했습니다. (예시) 외부 API의 컨트롤러 형태는 다음과 같습니다. Post 요청의 consumes는 Multipart/form-data 이며, 각각의 mapVlues, longValues, fileValue는 모두 @RequestPart로 요청받고 있습니다. 단순히 생각했을 때, 이 API를 feignClient로 요청한다면 아마 다음과 같은 interface를 구성.. 2024. 3. 10. 백엔드 서비스 운영시 고려해야할 점 지난 한 해 동안 사내에서 신규 서비스를 개발 및 오픈하게 되었습니다.🎉 보통 주니어 개발자는 입사 후 아래와 같은 상황인 경우가 많을 것이라 생각됩니다. 기존 운영되고 있던 서비스를 운영 개인(토이) 프로젝트 개발 -> 때에 따라 실제 서비스 오픈 (하지만 서비스 이용자가 많이 없어 배포까지만 완료하는 경우가 많음) 시니어 개발자가 프로젝트 설정 후 API 개발만을 담당함 저 또한 같은 주니어 개발자 입장이지만 팀 내 프로젝트 개발 표준 구성 데브옵스 & 인프라 구성 를 모두 담당하게 되면서 단순히 API 개발만 했더라면 알지 못하고 넘어갔을 내용들을 정리하여 공유하려 합니다. Java + Springboot 환경을 기준으로 작성합니다👋 요청 당 로그 트레이싱 서비스를 오픈하고 운영하는 단계 또는 그 .. 2024. 1. 21. 스프링부트 커넥션 설정도 체크하자 Issue 배치를 통해 async로 호출하는 API에서 응답시간이 60초 또는 30초, 심지어 에러까지 발생해서 정상 응답하지 않는 문제가 발생했습니다. 위 내용을 보면 HikariPool에서 커넥션을 30초동안 얻지 못해 생긴 에러임을 알 수 있습니다. TroubleShooting 첫 번째 의심 API 요청에 대한 응답이 너무 느려 타임아웃이 나는건가? 아닙니다. 직전 요청이 외부 서비스에 주문상태를 전달하는 Feign 요청이지만, 그렇다면 우리의 DB에서 커넥션을 얻지 못한다는 내용을 이렇게 상세하게 추적할 수 있을 리가 없습니다. 두 번째 의심 우리 DB가 문제가 있나? 아닙니다. 에러로그도 없고 데이터베이스 헬스체크 실패에 대한 로그도 없을 뿐더러, 동시간대 같은 API에 요청이 정상 응답한 경우.. 2024. 1. 21. ELK 스택을 사용해 Springboot 로그 수집하기 ELK 스택을 사용해 Springboot 로그 수집하기 분산환경을 사용해 서버를 운영하고 있다면, 몇 개 또는 수십개의 서버의 로그를 한번에 보기 힘든 상황이 나타납니다. 예를 들면 터미널을 여러 개로 분할해서 각 서버에 접속 후 로그를 찾는다거나… (제가 그러고 있었죠…) 물론, cloudWatch와 같이 서버의 console에 출력되는 로그의 내용을 한번에 조회할 수 있지만, 이것 또한 불편함이 굉장히 많습니다. 이런 불편함을 해결하고자 미루고 미루던 분산된 Springboot 로그를 ELK스택을 이용해 수집하고, 조회해보고자 합니다. ELK 구축 각각의 서비스의 로그를 수집하는 방법에는 여러가지 방법이 있습니다. 그중 Logstash로 로그를 수집해 ElasticSearch 에 전달, Kibana를.. 2023. 11. 5. [Spring] ExceptionHandlerLoggedImpl 에러가 나타난다면 ExceptionHandlerLoggedImpl 에러가 나타난다면? 저는 start.spring.io를 이용해 스프링 프로젝트를 생성하고 있습니다. 현재 최신 springboot version은 2.7.3이며, 프로젝트 생성 후 H2DB에 ddl-auto=create 옵션 사용중 이러한 에러를 확인했습니다. GenerationTarget encountered exception accepting command : Error executing DDL 위 에러는 Hibernate 버전과 H2DB 스키마 사이의 에러로 확인되는데 springboot 2.7.3에서 사용하는 Hibernate는 5.6.10 버전입니다. 과거에도 자주 나타났던 에러이고, 최근 진행했던 다른 프로젝트에서 Springboot 2.6.8 .. 2022. 8. 24. [Spring] AOP Joinpoint의 getThis()와 getTarget() AOP Joinpoint의 getThis()와 getTarget() 김영한님의 Spring 고급편을 수강하면서 수강하시는 분의 질문을 보고 작성하는 포스팅입니다. 커뮤니티의 질문을 보면 aspectj의 joinPoint를 통해 조회한 getThis()와 getTarget()의 결과가 같다는 질문이 있습니다. eclipse aspectJ doc을 확인해보면, getThis()의 경우 현재 실행중인 개체(proxy 객체)를 반환하고, getTarget()의 경우 대상 개체(class 객체)를 반환한다고 나와있습니다. @Around("com.heekng.aop.order.aop.Pointcuts.orderAndService()") public Object doTransaction(ProceedingJoinPo.. 2022. 8. 20. [Spring] kotlin spring lazy loading 삽질기 Kotlin spring lazy loading 삽질기 kotlin+spring 시작하기에 이어 기존에 만들었던 crud 위중의 프로젝트를 kotlin+spring 프로젝트로 변경하던 중 JPA와 Jackson 그리고 Jpa의 LazyLoading으로 인해 몇 시간 동안 붙잡게 되었습니다. 이를 해결하기 위해 진행했던 방법, 결과적으로 잘못되었던 점에 대해 짚어보려 합니다. allOpen 옵션 열어두기 먼저 kotlin의 open에 대해 알아보면, java와 다르게 kotlin의 클래스는 기본적으로 final으로 설정되어 있습니다. hibernate에서 사용하는 CGLIB는 상속을 기반으로 프록시 기술을 사용하기 떄문에 코틀린 클래스에 대해 상속을 열어두어야 프록시 기술을 사용할 수 있습니다. 기존의 b.. 2022. 8. 13. 이전 1 2 3 4 ··· 12 다음