CloudWatch Alarm 활용한 ECS Fargate 스케일아웃

시간이 흐를수록 점점 분석 Batch 프로세스가 오래걸리기 시작하면서 점점 하루를 넘어가기 시작. 이를 해결하기 위해 ECS Service에 CloudWatch를 활용한 오토스케일링을 적용하였고 그 과정을 기록하였다.

2024년 7월 24일 · 3 분 · An Seongjin

MyBatis bind tag. 동적 SQL 구현

MyBatis에서 SQL을 동적으로 작성할 때 유용한 에 대해 간단하게 정리해보았다.

2024년 7월 11일 · 2 분 · An Seongjin

What to do about maven import errors

io.opentelemetry:opentelemetry-exporter-zipkin:jar:unknown was not found in https://repo.maven.apache.org/maven2 during a previous attempt. This failure was cached in the local repository and resolution is not reattempted until the update interval of central has elapsed or updates are forced

2024년 3월 20일 · 1 분 · An Seongjin

VM Proxy 설정에 대한 HttpURLConnection & HttpClient 차이

프록시 서버 구성을 하는 과정에서 알게된 Java 클래스 몇가지를 비교하여 정리하였다.

2024년 3월 17일 · 1 분 · An Seongjin

Spring Optimization: Refactoring Object-to-Map Conversion Methods

기존 Reflection 사용 방식 Object to Map 컨버팅 메서드의 성능 및 유지보수성 개선하기 위한 방법

2024년 3월 1일 · 2 분 · An Seongjin

Redis 세션 클러스터링 설정 (feat. Redisson)

How to Enable Session Clustering in “Low-level Spring Framework” and “Redis with Encryption”

2023년 10월 3일 · 2 분 · An Seongjin

Delimiter를 통한 다중 검색 처리

들어가며 현재 투입되어있는 프로젝트의 서비스 중에는 특정 데이터를 조회할 수 있는 화면이 있습니다. 그런데 이 화면을 사용하게되는 업무 특성상 데이터를 일일이 하나씩 조회하기가 번거롭다는 불편사항이있어 이를 한번에 다중 검색 가능하도록 수정 조치하였고, 당시 작업내용을 핵심부분만 간략하게 정리하였습니다. 기존 방식 mapper.xml <sql id="ticketSearch"> <if test="(method_info != null and method_info != '')"> <if test="method_id == 'gkId'"> AND GK_ID = #{method_info} </if> <if test="method_id == 'parentTicketId'"> AND UPPER(PRNT_TKT_ID) LIKE CONCAT('%',UPPER(REPLACE(#{method_info}, '_', '#_')),'%') ESCAPE '#' </if> <if test="method_id == 'ticketId'"> AND UPPER(TKT_ID) LIKE CONCAT('%',UPPER(REPLACE(#{method_info}, '_', '#_')),'%') ESCAPE '#' </if> <if test="method_id == 'guid'"> AND GUID LIKE CONCAT('%',#{method_info},'%') </if> </if> </sql> <select id="list" parameterType="map" resultMap="ticketVO"> SELECT 컬럼 1, 컬럼 2, 컬럼 3 FROM 테이블 A WHERE DEL_YN_FG = 'N' <include refid="ticketSearch"/> </select> ▲ 화면에서 입력한 문자열 1개를 포함하고있는 데이터를 “like” 검색을 통한 단일 조회 방식 ...

2023년 9월 25일 · 2 분 · An Seongjin

Autoscaling 적용을 위한 스케줄(@Scheduled) 로직 변경

들어가며 현재 투입되어있는 프로젝트에서는 최근 기존의 인프라 구성에서 많은 부분 전환된 일정이 있었습니다. 그 당시 Autoscaling을 적용하기 위해서 예상되는 문제점은 무엇이 있었는지, 그리고 그것을 어떻게 극복했는지 다음과 같이 정리하였습니다. 기존 환경 Autoscaling이 적용되어있지 않은 was EC2 2개 운영 해당 서버의 Spring Framework 애플리케이션 내에는 @Scheduled 어노테이션을 통한 스케줄잡 사용 일부 스케줄 관련 코드 : @Scheduled(cron = "0 30 9 ? * *", zone = "GMT+9:00") public void notifyLongTermNoUseAdmin() { if("1".equals(GkConstant.WAS_NUMBER)) { // STG, PRD 의 1번 서버인 경우에만 Batch 실행 try { List<LongTermNoUseAdminVO> notifyAdminDataList = longTermNoUseAdminSvc.getNotifyAdminDataList(); for (LongTermNoUseAdminVO voNotifyAdmin : notifyAdminDataList) { try { List<String> mailReceiverIDList = new ArrayList<>(Arrays.asList(voNotifyAdmin.getAccountId())); // 메일 수신인 리스트에 장기 미사용자의 이메일 주소만 추출해 추가 // 대상자별 mail template parameter 가 다르기 때문에 for 문을 통해 개별 메일 발송 awssesClient.sendEmail(mailReceiverIDList, "[" + ospAppConfig.getGkServerType() + "]" + MailEnum.NOTIFICATION.getMailSubject(), setMailHtmlBody(MailEnum.NOTIFICATION, voNotifyAdmin), null); LOG.info("##### SUCCESS Sending Notification Email : {}, {}", voNotifyAdmin.getSaGuid(), voNotifyAdmin.getAccountId()); } catch (Exception e) { e.printStackTrace(); LOG.info("##### FAIL Sending Notification Email : {}, {}", voNotifyAdmin.getSaGuid(), voNotifyAdmin.getAccountId()); } } LOG.info("##### SUCCESS notifyLongTermNoUseAdmin Batch"); } catch (Exception e) { e.printStackTrace(); LOG.info("##### FAIL notifyLongTermNoUseAdmin Batch"); } } } 위와 같이 “코드가 실행되는 두대의 서버 중 vm option의 특정 시스템 프로퍼티가 ‘1’로 되어있는 서버에서만 동작”하도록 조건이 설정 (if("1".equals(GkConstant.WAS_NUMBER))) 문제점 Autoscaling을 적용하게되면 서버가 동적으로 생성 및 삭제되기 때문에 어느서버가 1번 서버인지 기준이 사라지는 상황. 따라서 기존의 Scheduled 로직이 여러 서버에서 중복으로 실행되거나 혹은 전혀 실행될 수 없는 로직 ...

2023년 9월 21일 · 4 분 · An Seongjin

Tomcat 배포 방식의 올바른 이해와 구조적 분석

Tomcat 서버의 애플리케이션 배포는 웹 애플리케이션 운영에서 가장 기본적인 영역이면서도, 실제로는 많은 개발자들이 정확한 동작 원리를 놓치고 있는 부분이다. 최근 고객사 운영 서버의 server.xml 설정을 분석하던 중, <Context> 태그와 <Host>의 appBase 속성이 혼재된 구성에서 WAR 파일 배포 과정에 대한 오해를 발견했다. 기존의 배포 설정 운영 중인 서버의 server.xml 설정: <Host name="localhost" appBase="/home/manager/eps/webapps" unpackWARs="true" autoDeploy="true"> <Context path="" docBase="/home/manager/eps/webapps/legacy" reloadable="false" /> <Context path="/v5" docBase="/home/manager/eps/webapps/ui5" reloadable="false" /> <!-- ... AccessLogValve 설정 ... --> </Host> 이 설정에서 명시적인 <Context> 배포와 appBase를 통한 자동 배포가 공존하고 있었음.. 그런데 여기서 문제가 발생. 새로운 버전의 ui5.war 파일을 배포하려 할 때, 기존 관리자는 다음과 같은 절차를 따르고 있었다. ...

2023년 5월 11일 · 4 분 · An Seongjin