입사 후 온프레미스 환경에서 클라우드 환경으로 넘어오면서 AWS 인프라를 많이 활용해 보고 있다. 그 중에서도 리소스를 저장하기 위해 S3를 가장 많이 사용하고 있는데, 스프링부트에서 연동해서 사용하는 법을 알아보자. 주의!! 이 글은 S3 버킷을 생성하는 부분은 따로 언급하지 않았습니다. AWS S3란? Amazon Simple Storage Service(Amazon S3)는 업계 최고의 확장성, 데이터 가용성, 보안 및 성능을 제공하는 객체 스토리지 서비스입니다. 모든 규모와 업종의 고객은 Amazon S3를 사용하여 데이터 레이크, 웹 사이트, 모바일 애플리케이션, 백업 및 복원, 아카이브, 엔터프라이즈 애플리케이션, IoT 디바이스, 빅 데이터 분석 등 다양한 사용 사례에서 원하는 양의 데이터를..
그동안 서버에서 비동기 처리를 할 일이 많지 않았었는데 이번에 멀티쓰레드를 처음 사용해볼 기회가 생겼다. 다행히 스프링 부트는 멀티쓰레드 개발의 초심자인 사람도 편하게 사용할 수 있게끔 다양한 기능을 제공해 주고 있었다. 이 내용을 소개해 보려고 한다. 비동기(Asynchorous)란? 멀티 쓰레드가 필요한 이유. 비동기는 다른 곳에서도 많이 다루기 때문에 간단히 말하고 넘어가려고한다. 한줄 요약하면, 앞선 작업이 끝나기를 대기하며 수행(동기적)되는게 아니라 앞선 작업의 종료까지 대기하지 않고, 다음 작업을 바로 수행(비동기)한다는 의미이다. 다들 한번쯤 봤을 만한 그림을 첨부한다. @Async 이 어노테이션 하나면 비동기적으로 동작하게 코드를 구현할 수 있다. 자바에서 Thread를 상속받거나 Runn..
JPA를 사용해 DB insert를 하던 중 뜬금없이 아래와 같은 에러가 났다. java.sql.SQLException: The MySQL server is running with the --read-only option so it cannot execute this statement 흠 DB가 어떤 이유에서인지 read-only 설정이 되어 있군. 인프라 개발자에게 연락해야지. 라고 끝났으면 좋았겠지만, 인프라는 DB 설정을 변경한게 없다고 한다. 웃긴건, 같은 프로젝트의 다른 서비스 내에서의 DB insert는 정상적으로 수행되고 있다는 점이다. 다른 서비스와 차이점을 뜯어보던 중 @Transactional 이 빠져 있는걸 확인했다. @Transactional 어노테이션을 붙이니까 정상 동작했다. 그..
이직 후 맡은 첫 작업은 LOG 였다. 서비스 분석을 위해 코드를 처음 까봤을 때 굉장히 당황스러웠던 게 몇가지 있었는데, 그중 대표적인게 로그 부분이었다. 당황스럽게도, 남기고 있는 로그들은 전부 디버그 수준에서 남길만한 정보들만 남기고 있었다. if (oldUser != null) { log.info("이미 존재하는 사용자입니다. user : {} oldUser : {} ", user, oldUser); userResponseDTO.setCode(-1); userResponseDTO.setErrorMsg("이미 존재하는 사용자입니다."); return userResponseDTO; } 위와 같은 메시지들이 json 형태도 아닌 일반 cout 형태로 출력되고 있었다. 이런 로그들은 서비스를 운영하고 모..
이전 글에서 https://api.openai.com/v1/chat/completions API에 대해 간단히 다뤄보았다. 그런데 앞선 글이 너무 겉핥기라 정작 중요한 부분을 몇 가지를 놓친 것 같아서 추가적으로 정리해보려고 한다. 크게 두 가지 부분이 아쉬워서 내용을 보강해보려고 한다. 첫 번째는 GPT 프롬프트(Prompt)라고 알려진 메시지 프롬프트가 들어가는 message 배열 부분과 두 번째는 현재 GPT가 답변을 주는 것처럼 한 글자씩 내려주는 stream 부분이다. 하나씩 알아보자. 1. message 배열 먼저, user는 일반적인 사용자를 의미한다. 우리가 평소에 GPT를 사용할 때처럼 아래와 같이 작성하고 보내도, GPT는 정상적으로 답변을 보내준다. "messages": [ { "ro..
앞선 글에서는 캐시에 단순 String만 저장했다. 그런데 작업을 하다보면 한 줄의 단순한 String 보다는 더 많은 정보를 담고싶기 때문에 Object를 저장하고 싶을 것이다. 이 내용을 정리해봤다. 1. 저장하기 객체를 스트림으로 변환 후 Byte[] 형태로 저장한다. id는 기존 String을 저장하는 방식과 같이 UUID로 랜덤값을 생성했다. public String saveObjectCache(ObjectVo value) { Cache cache = cacheManager.getCache("myCache"); String id = UUID.randomUUID().toString(); byte[] bytes = null; try (ByteArrayOutputStream bos = new Byte..
앞선 글에서 캐시를 삭제하는 부분이 빠졌었다. 사실, 서버 입장에서는 캐시를 만드는 것 보다 캐시를 삭제하는게 더 중요하다. 캐시를 삭제하지않고 계속 쌓게되면 100% 확률로 서버는 언젠가 죽기 때문이다. 이를 방지하기 위해 캐시를 꼭 삭제해야한다. 캐시 삭제 전략 일단 캐시의 삭제 전략은 크게 세가지가 있다. (더 있으면 알려주세요..) 1. ID별로 만든 캐시를 하나씩 수동 삭제하기 2. 특정시간 마다 통으로 캐시 비우기 3. TTL(Time-to-Live)을 설정해 ID별 캐시가 살아있는 시간 설정 안정적으로 설계를 잘한다면 1번만으로 사용이 가능하겠지만, 예외 발생시 캐시를 삭제 안하고 넘어가는 경우가 분명 발생할 것이다. 때문에, 사용하지 않는 캐시를 주기적으로 삭제하는 2번 전략도 필요하다. ..
매번 데이터를 저장하기 위해 데이터베이스를 거치는 것은 번거롭고 오버헤드가 발생하는 작업이다. 때문에, DB의 부하도 줄일 겸해서 인메모리에 짧은 시간, 작은 크기의 데이터를 저장해서 사용하는 경우가 많다. 대표적인 예가 Redis를 사용해서 캐싱을 하는건데, 스프링 자체에서도 캐시 기능을 제공한다. 이전에 비슷한 내용의 글을 작성했는데, 스프링부트에서 굉장히 쉽게 구현이 가능해서 정리해봤다. 사용법 별도의 gradle 설정이 필요 없다. 라이브러리도 딱히 받을 필요없음. 1. Config 설정 - Map형식으로 사용하고 싶어서 ConcurrentMapCacheManager 사용함 @Configuration @EnableCaching public class CacheConfig { @Bean public..
- Total
- Today
- Yesterday
- serverless
- GIT
- S3
- AWS
- springboot
- cache
- AWS EC2
- docker
- openAI API
- CloudFront
- 스프링부트
- Elastic cloud
- MySQL
- JWT
- OpenFeign
- AOP
- EKS
- Spring
- OpenAI
- ChatGPT
- java
- 티스토리챌린지
- 후쿠오카
- terraform
- 람다
- 오블완
- elasticsearch
- Log
- lambda
- Kotlin
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |