본문 바로가기

사이드프로젝트

(21)
메모 ./gradlew test --tests "클래스명.메서드" --info 로 테스트를 실행시킬수있음테스트가 실행되면build/reports/tests/test/index.html경로에 테스트결과가 저장됨 ./gradlew test --tests "rkrk.whyprice.test.unit.KoreanStockTest.fetchDataSuccess" --info
이거왜오름?벡터검색(RAG)추가 작성중커서 테스트 실행//완스프링부트 버전업(ai버전이랑 맞춰야함)spring ai 버전업(https://docs.spring.io/spring-ai/reference/upgrade-notes.html)사용 api 임베딩과 모델 모두 openai로 통일(이건 모델은 생각해볼수있을듯)벡터 db설치뉴스api나 크롤링 테스트 배치로직 앞에 뉴스api로 가져와서청크로 나누고(이때 해당뉴스날짜도 모든청크에 표시)openai로 임베딩후벡터db에 넣는 로직 추가이후 springai로 벡터db검색 메서드추가 웹앱에도 똑같이 추가      api로 뉴스가져오기(퍼플북마크)  이떄 증분업데이트로 일정시간その後뉴스만 가져오기임베딩 변환벡터db에 담기 일정시간마다 자동으로 동작하게 트리거 현재 프롬프트로 rag 벡터db에 수..
이거왜오름?레포트생성부분 비동기(코루틴)처리하기 gpt를 통해서 api로 레포트를 가져오는부분이,동기식으로 처리되어있어서 최악의경우 각 레포트마다 10초,300초가 걸리는 문제가 있었다물론 이 문제가 있을거라는건 알고있었다(너무뻔한 문제니까)그래서 나중에 비동기로 변경하기쉽게 구현해뒀었고,일단 주기적으로 배치도 돌리는만큼 저정도까지 날 일은 거의없긴했지만,그래도 저런부분은 비동기로 처리하는게 좋은만큼,비동기로 변경하기로 마음먹었다 일단 나는 코틀린을 사용하니 코루틴을 사용해서 비동기처리를 할 예정이다거기다가 supervisorScope(supervisorJob)을 사용해서 어떤 한 대상에 문제가 생기더라도,무시하고 동작하게 만들생각이다 그렇게 어렵진않다일단 useCase의 해당부분을 suspend로 처리해주고interface CreateReportUs..
이거왜오름?레포트캐시 스프링배치 도커라이징하고 스케줄링하기 일단 이거도 도커라이징부터 하자도커라이징은 웹과 똑같은 도커파일을 사용하면된다# 빌드 스테이지FROM gradle:8.8-jdk17 AS buildCOPY --chown=gradle:gradle . /home/gradle/srcWORKDIR /home/gradle/srcRUN gradle build --no-daemon# 실행 스테이지FROM openjdk:17-slimEXPOSE 8080RUN mkdir /appCOPY --from=build /home/gradle/src/build/libs/*.jar /app/spring-boot-application.jarENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/spri..
이거왜오름?웹앱 도커라이징하기 이제 대충 다 만들어졌으니 도커라이징을 해야한다나는 구조를리눅스 미니pc에서 mysql,웹앱,배치와 배치스케줄러를 전부 돌릴생각임만약 미니pc는 웹앱과 배치가 localhost의 mysql을 참조하려면(해당 pc의 컨테이너가 아닌 mysql이 설치되어있다면), host.docker.internal:3306에 접근해야함(host.docker.internal은 도커의 컨테이너가 실행중인 컴퓨터의 localhost라고 보면됨) 이걸 생각해서 env파일을 만들면MYSQL_ID=IIIDDDDMYSQL_KEY=PASSWWWOOORRRDDDMYSQL_URL=jdbc:mysql://host.docker.internal:3306/projectName?serverTimezone=Asia/Seoul이렇게 만들면된다,이때 도..
이거왜오름?높은거래량 레포트 스프링배치로 미리만들어서 부하줄이기 거래량 상위 30개의 레포트를 요청하면,대략 2분정도걸리면서 타임아웃이 나는 문제가 있었다로직이 for돌리면서 하나씩 레포트를 생성해서 하는거라서 그렇다이걸 해결하는 방법으로 생각나는건비동기처리(코루틴사용)배치로 미리 만들어두기캐시만료를 없애고 무조건 마지막캐시레포트를 보내고,보낸뒤에 갱신요청이렇게 3가지가 생각났다캐시만료를 없애는건 딱봐도 문제가 많이생길거같아(하루전 레포트가 간다거나) 제외,비동기처리는 괜찮아보이는데,외부api를 사용해야하는 로직 특성상 한ip에서 갑자기 부하를 잔뜩걸어버리면 일정시간 ip밴을 때릴 가능성이 있어보이고,도큐먼트상에서도 분당 20회의 요청을 처리할수있다 라고 적혀있길래 제외결국 소거법으로 배치로 처리하기로 했다 배치 구조는api reader로 한투api에 접근해서 주식이..
이거왜오름? 헥사고날 리팩터링 할까말까 했는데,이럴때나 해보지 언제해보겠어 싶어서 헥사고날로 리팩터링을 하기로 했음 핵사고날의 핵심은 의존성역전이고(클린아키텍처가 다그렇긴하지만),외부와 내부의 분리가 핵심임나는 기본전략으로는 jpa엔티티와 도메인엔티티의 분리는 하지않을거고,컨트롤러입력모델과 도메인엔티티는 따로 둘거임,단 레포트의 경우 jpa엔티티와 도메인엔티티를 분리할거임또한 어플리케이션단에서는 도메인을 그냥 사용할예정즉 인포트의 입력모델과 출력모델만 있고,나머지는 다 도메인을 직접사용함 기본구성은 각 도메인(도메인보다 좀 더 큰 애그리거트라고 하는게 맞겠지만)마다 패키지를 두고이런식으로 분리하고,어댑터는 포트를 구현하고,인포트는 유스케이스,아웃포트에는 레포지토리인터페이스,api포트인터페이스 등이 들어갈예정임이런식으로 어댑터 패키지가..
이거왜오름? 테스트 작성 사실 이전부터 테스트는 계속 작성하고있었음꼭 테스트를 만들기위해서 라기보다는 도메인을 먼저 개발하고,서비스(유스케이스),포트,어댑터 순으로 만들면서,외부에서 진입해서 테스트할수있는곳이 없으니 스터디용 테스트(주로 외부통신어댑터)와,도메인 유닛테스트로 기능을 만들고 바로 테스트하는식으로 테스트했음 이렇게 하면 따로 외부 인커밍어댑터 없이도 만든기능을 테스트하며 진행할수있음어댑터는 스터디테스트로class BasicFetcherTest { @Test fun successFetch() { val basicFetcher = BasicFetcher(ApiHelperImpl()) val fetch = basicFetcher.fetch("1301110006246") As..