toy/AgileHub 14

[이슈 #3] DB 설계 개선으로 끌어올린 코드 품질과 유지보수성

리팩토링을 시작하게 된 배경오래된 제 코드를 살펴보면서 리팩토링의 필요성을 느꼈습니다. 리팩토링을 하려는 이유는 숨겨진 버그나 취약점을 발견하고 수정하기 위함과 가독성을 높여 확장성을 향상시키기 위함 입니다. 리팩토링을 시작하려 했지만, 오래된 코드의 내용이 기억나지 않아서 먼저 코드를 보면서 어떤 요구사항이고 도메인이었는지 떠올려야 했습니다. 그러기 위해서는 먼저 테스트부터 작성할 필요성을 느꼈는데, 테스트 커버리지를 확인해보니 라인 커버리지가 25%에 불과했습니다. 제 생각엔 100%까지 목표로 잡지 않아도 핵심 비즈니스 로직에 대해 80%까지만 가도 충분히 리팩토링하는 데에는 도움이 될 것 같았습니다. 왜냐하면 커버리지가 높더라도 테스트 케이스가 부적절하게 작성되었다면 여전히 중요한 버그가 발생할 ..

toy/AgileHub 2025.03.06

[이슈 #2] 멤버 초대 이메일 발송 설계

기능 요구사항관리자는 이메일 주소를 입력하여 새로운 멤버를 초대할 수 있습니다.초대 이메일은 지정된 템플릿 형식으로 발송되어야 합니다.초대 링크는 10분간 유효합니다.초대 링크는 1회만 사용가능합니다.만료되거나 사용된 초대 링크는 더 이상 사용할 수 없습니다. 비기능 요구사항초대 링크는 추측할 수 없는 안전한 토큰을 사용해야 합니다.이메일 발송은 비동기로 처리되어야 합니다.시스템은 초대 상태를 추적하고 관리할 수 있어야 합니다. 멤버 초대 플로우프로젝트를 개설한 관리자는 본인 팀의 멤버들을 초대하기 위해 멤버 이메일을 작성하고 전송버튼을 누릅니다. 서버는 해당 이메일 받고, 그 이메일에 대한 초대토큰을 생성한 다음 템플릿에 담고 이메일 서비스를 사용해 해당 유저에게 이메일을 전달합니다.  유저는 이 이메..

toy/AgileHub 2024.12.23

[이슈 #1] 커넥션 풀 고갈 문제를 Redis Atomic 연산으로 개선하기

장애 상황이슈 생성 API의 부하 테스트를 통해 안정적인 서비스 제공과 우수한 성능을 달성하는 것을 목표로 설정했습니다.  그러기 위해서 대규모 조직(1000명 이상)에서 50~100명의 사용자가 동시에 이슈를 생성하는 상황을 가정했을 때, 다음과 같이 요청-응답 시간(MTT)은 1~2초 이내, TPS는 30~40, 에러율은 0.1% 이하, 테스트 시간은 1분 이내인 성능 지표를 목표로 삼았습니다 💡 TPS를 30~40으로 잡은 이유 (1000명 조직 기준 예상 시나리오)- 1인당 하루 평균 5-10개 이슈 생성 - 8시간 근무 기준: 1000명 × 10개 ÷ 8시간 ÷ 3600초 ≈ 0.34 TPS- 피크 타임(10배 부하) 고려: 약 3 TPS - 버퍼(10-20배)를 둬서 30-40 TPS 설정 ..

toy/AgileHub 2024.12.01

이슈 번호 생성의 동시성 문제와 커넥션 풀 최적화 여정

사전 지식 이슈란이슈란 팀이 프로젝트를 진행하면서 관리해야 할 모든 종류의 작업, 버그, 개선사항, 요청 등을 포괄합니다.1. 이슈 유형- 스토리(Story): 사용자 요구사항이나 기능 개발을 의미합니다.- 버그(Bug): 시스템 오류나 문제를 추적합니다.- 태스크(Task): 구체적인 작업 단위를 나타냅니다.- 에픽(Epic): 여러 스토리와 태스크를 포함하는 큰 단위의 작업입니다.2. 설명 및 요약(Description & Summary)- 작업의 목적, 세부 내용, 예상 결과 등을 기술합니다.  이슈번호(PROJECT-1 같은 형식)를 사용하는 이유- 커뮤니케이션 효율성짧고 명확한 참조: "PROJECT-123"처럼 간단히 이슈를 지칭할 수 있음구두 커뮤니케이션: 회의나 대화에서 쉽게 언급 가능"P..

toy/AgileHub 2024.11.09

Model has no value for 에러 발생

문제 사항컨트롤러에서 다음과 같이 redirectAttributes 로 리다이렉트를 한다.  직접 Postman으로 실행하면 정상적으로 리다이렉트 되지만MockMVC로 테스트를 하면 {key} 부분을 동적으로 변환을 하지 못해 실패를 한다. 에러 내용 고민한 방법디버깅먼저 key가 null로 들어가는 것이 확인 된다. RequestMappingHandlerAdapter 클래스에서 view 와 rediretModel 이 mavContainer에 담겨있는 것을 확인   DispatcherServlet 클래스까지 잘 전달되는게 확인 (물론 key는 null이라 이 부분을 확인해야한다) 그런데 DisPatcherServlet 클래스내에서 processDispatchResult 메서드가 실행된 후 예외 발생  M..

toy/AgileHub 2024.07.08

이슈 전체 조회 성능 개선하기

준비 사항프로젝트 1만개 생성멤버 1만개 생성프로젝트와 멤버 1대1 매칭예를들어 1번 프로젝트는 1번 멤버, 2번 프로젝트는 2번 멤버, n번 프로젝트는 n번 멤버가 속합니다.성능 비교를 위한 것은 프로젝트와 멤버가 아닌 이슈이기 때문에 최대한 간단하게 매칭 시켰습니다.EPIC 이슈는 100개 생성STORY 이슈는 에픽당 200개씩 총 2만개의 스토리 이슈 생성TASK 이슈는 스토리당 200개씩 총 4만개의 테스크 이슈 생성모든 이슈는 1번 프로젝트에 속하도록 합니다. 문제 사항1. 로직 리팩토링 더미데이터를 넣고 이슈 전체 조회 API를 요청 했지만 쿼리가 돌다가 응답이 오지 않고 멈췄습니다.(성능측정을 해야지하고 몇 초나 걸릴까를 생각했는데 그냥 아예 팅겨버린..)이유가 당연했습니다. 로직이 다음과 ..

toy/AgileHub 2024.07.06

배포 하는데 걸리던 시간 13분을 5분으로 줄이기

문제사항최근 애자일허브 프로젝트는 도커이미지를 만들어 DockerHub에 올리는 방식으로 배포를 하고 있습니다. Dockerfile을 만들어서 GitHub에 올려두고, GitHub Actions로 docker build와 push를 진행하는 방식입니다.  그런데 배포를 할때마다, 매번 빌드 시간이 10분 이상이었고, 코드가 조금만 추가되어도 1분씩 늘어나 최근에는 배포 한번 하는데 13분정도 걸립니다. 이정도의 시간은 매번 배포할때마다 다른 일을 해야하고, 나중에 테스트를 해보며 수정할게 생기면 다시 또 13분을 기다려야 하는 충분히 부담되는 시간입니다. 그리고 이런 사이클은 Continuous Deployment의 장점을 잘 살리지 못한다고 생각했습니다. 배경지식 - 도커 레이어와 캐시도커 빌드 속도에..

toy/AgileHub 2024.05.14

docker volume 제대로 설정하자

문제 사항애플리케이션 로그를 프롬테일을 이용해 로그들을 로키로 push 하는 과정에서 nginx와 system 로그는 제대로 로키가 받아오지만 애플리케이션 로그(ERROR 레벨)는 받지 못하는 상황이 발생했다.   먼저 프롬테일 config.yaml은 다음과 같이 작성했다.문제 해결 시도1. 로그 확인 먼저, 애플리케이션이 있는 서버 안의 프롬테일을 컨테이너로 띄었는데 이를 로그로 확인해봤다. 하지만 잘 로그 경로를 잘 찾아가서 탐지하고 있었다. 그렇다면, 모니터링 서버에 띄어놓은 로키의 컨테이너 로그를 확인해봤다. 대충 로그를 보면 200 status, 즉 프롬테일이 push 한 API를 로키가 잘 응답받아왔다는 것을 알 수 있다. 하지만 분명히 prod-log에 에러로그가 있음에도 불구하고 0B 즉,..

toy/AgileHub 2024.05.09

인증/인가 구현 및 리뷰과정에서 발생한 트러블 슈팅

팀원이 먼저 인증 API를 구현하고난뒤 함께 리뷰하면서 생겼던 트러블 슈팅을 적어보려 한다.- Spring Security 6.1- SpringBoot 3.2.3- Redis 5.0.7- java-jwt 4.4.0- oauth2-client 1. base 64 디코딩 에러 발생GitHub CLI gh로 PR을 로컬에 받고 테스트 도중 이상한 것을 발견했다. postman을 통해 api를 요청할 때 Authorization 헤더에 bearer: { accessToken } 을 넣고 API를 요청을 했다. e.g) /api/projects응답 결과는 다음과 같이 Token 유효성을 검사 도중 유효하지 않은 JSON format이라는 에러 메세지를 받았다.JwtUtil.verifyToken error: The..

toy/AgileHub 2024.04.29

간헐적으로 JUnit5 테스트가 깨지는 문제

문제 사항 테스트코드가 40개를 넘어가면서 갑자기 그 이후로 간헐적으로 깨짐이 발생했다. 처음 생겼던 에러는 다음과 같았다. org.hibernate.exception.JDBCConnectionException: Unable to release JDBC Connection [The database has been closed [90098-224]] [n/a] 문제해결 시도 해당 에러를 검색해보니 원인은 다양했다. 1. H2 데이터베이스 설정 확인 H2 데이터베이스가 테스트 하나 실행하고 닫지 않도록 DB_CLOSE_DELAY=-1; 을 추가했다. 테스트가 독립적으로 실행하니깐 H2에 필요로 하는 커넥션이 많아진것으로 예상이 되어 HikariCP maximum pool size을 100개로 늘렸다. dat..

toy/AgileHub 2024.04.01