diff --git a/WebContent/WEB-INF/springapp-servlet.xml b/WebContent/WEB-INF/springapp-servlet.xml
index bdcc5db..f3a55c6 100644
--- a/WebContent/WEB-INF/springapp-servlet.xml
+++ b/WebContent/WEB-INF/springapp-servlet.xml
@@ -140,4 +140,5 @@
+
diff --git a/kjb-docs/apilog/log.md b/kjb-docs/apilog/log.md
new file mode 100644
index 0000000..ad82c85
--- /dev/null
+++ b/kjb-docs/apilog/log.md
@@ -0,0 +1,64 @@
+- url
+- 요청 clientId
+- 거래정보
+
+- 기존 샘플
+```
+{
+ "clientId": "8cd49ec6bdf82502e053030011ac7064",
+ "header": {
+ "x-request-id": "22617829,22617831,22617833,22617835",
+ "traceId": "8d41a04141794275abc3691b525cf2a9",
+ "content-length": "75194",
+ "x-forwarded-for": "117.52.3.143",
+ "x-user-no": "29024601",
+ "accept": "application/json, application/cbor, application/*+json",
+ "x-partner-id": "KWANGJU_BANK",
+ "via": "1.1 localhost:20443",
+ "authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkODBiMDJmZDVmYmM0MjNhOWYyZTk5YzY1MzgwODY5YyIsInNpbXBsZXEiOiJkYjJmODVmNTQ4ZmY3Njk3MmMwZTA2YjBiMWUwNDBmYWIyNjczNTI2ODI0ZjE1M2RiODAzNDQ4MzRhMDIzNzk3IiwidHJhY2VfaWQiOiJiMGU3MjNkOTY2NTM0N2QxYmFiZmYzZTIwYzZiMjIxYSIsImdyYW50X3R5cGUiOiJjbGllbnRfY3JlZGVudGlhbHMiLCJyZXNvdXJjZSI6IjhjZDViYTczMzgzOTJkNTdlMDUzMDMwMDExYWM4YmUxIiwic2NvcGUiOiJvb2IiLCJzaW1wbGUiOiIxZjNmODYwY2U4ODkxNTVkNDAxYWZjNmE5YTIxZjQ3OTYwNTczNzVhZjI3NzdkY2Y2YTMyZjQ3ZTAxOTc0ZGFiYWY5MTM0ODEzOGFkMTBjMDg3N2FkYTRmZDhhZmVhMmZkMDIzMjVkYTIzYTBkZThlNjMyODRjYzBhMjNjY2VlZjU0NDAyZjdhYzU2NmE5NmM0MmFjZDg4YjI0ZmE2NWQ2NWRiMzcwZDEyMTg2ZjY5ZDkzNmNhYjM0MTcyZDk1NzdkMzNlNDk2MTYxMzczMTY0YjJmMTdjMTk0YWRkZjYyMWIwZmJjNDViNWMzNjUyNzU5MTY2NWQ2NDg1NGE0OWUyYWNmNzM4NDdmZDVkYWZkNDY1Zjg3ZDU5ZTU1N2ZiNWNlN2Y3Njk1NGU2YTg4YjE1ZWFhN2JlNDhmODk5NmVmN2QxYmRjMDg1MjMwOGM5NDc1MzdmMDc1Y2JhZTBmYTM5OTBhZmYzMTY0ZGZlOGVmYTg3YmFlZDgyYjQyYjcyMDA3ZTg4YTM3NmU5MjUyMzZiMGIwZjE5MzM2MDNlN2ExMzNkMzI4YzBkM2JhNWY0OTExNjMyYWFlZmRkZjI5OTk4N2FmMjY3MjIyZTM2ZWI5ZmNlMzg0OWIyODNmN2Q3Yzc4NTQ0MjRlZWE2YTBmYzQ0ZWFmOTNiNzY1ZGQ2YWE5ZWQzNGFlOWEyNTU5OWFmZDM1NTkwOWQ3YjViNDUxYjM4NTc4OTdiMTM2ZjQyNmQ4ODkwZTljZWFiZTQ3NWRjYTEiLCJleHAiOjE3NjU5NjEwMDksInRva2VuX3R5cGUiOiJCZWFyZXIiLCJleHBpcmVzX2luIjozNjAwfQ.G-KC8DPeBBM40NoD7yQs6Y552PAExlz-V_DhehmqMuc",
+ "x-loan-token": "HOkND9Wb2PGjcV/h1pdpeMyVia8",
+ "x-forwarded-server": "localhost",
+ "x-forwarded-host": "apit.kjbank.com:20443",
+ "key-event-id": "BSST5OEP7G",
+ "host": "192.168.246.16:28184",
+ "content-type": "application/json;charset=UTF-8",
+ "connection": "Keep-Alive",
+ "accept-encoding": "gzip,deflate",
+ "user-agent": "Apache-HttpClient/4.5.13 (Java/17.0.12)"
+ },
+ "queryString": "",
+ "body": {
+ "data": {
+ "agreeIdentifyInfo": true,
+ "joinDate": "20191217",
+ "corporateNumber": "1248100998",
+ "agreePersonalCreditInfo": true,
+ "ci": "CI85100722580288510072258028851007225802885100722580288510072258028851007225802885100722",
+ "name": "박주희",
+ "salary": 33000000,
+ "jobType": "01",
+ "rrn": "8510072037827"
+ },
+ "requestProducts": [
+ {
+ "loanReqNo": "T000022617829",
+ "loanProductId": "01535"
+ },
+ {
+ "loanReqNo": "T000022617831",
+ "loanProductId": "0531"
+ },
+ {
+ "loanReqNo": "T000022617833",
+ "loanProductId": "0607"
+ },
+ {
+ "loanReqNo": "T000022617835",
+ "loanProductId": "0608"
+ }
+ ]
+ },
+ "exdata": "",
+ "txDate": "20251217"
+}
+```
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/ApiLogDTO.java b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/ApiLogDTO.java
new file mode 100644
index 0000000..618a124
--- /dev/null
+++ b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/ApiLogDTO.java
@@ -0,0 +1,17 @@
+package com.eactive.eai.rms.data.entity.onl.logger;
+
+import java.util.List;
+
+import lombok.Data;
+
+@Data
+public class ApiLogDTO {
+
+ private String apiServiceNumber;
+
+ private String txDate;
+
+ private List logs;
+
+ private Long totalProcessingTime;
+}
diff --git a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/ApiMessageLogDTO.java b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/ApiMessageLogDTO.java
new file mode 100644
index 0000000..793da46
--- /dev/null
+++ b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/ApiMessageLogDTO.java
@@ -0,0 +1,36 @@
+package com.eactive.eai.rms.data.entity.onl.logger;
+
+import java.util.List;
+import java.util.Map;
+
+import lombok.Data;
+
+@Data
+public class ApiMessageLogDTO {
+
+ private String apiServiceNumber;
+
+ private int processNumber;
+
+ private String txDate;
+
+ private String url;
+
+ private String queryString;
+
+ private String clientId;
+
+ private String method;
+
+ private Integer HttpStatus;
+
+ private String header;
+
+ private String body;
+
+ private String exdata;
+
+ private Long processingTime;
+
+ private String keymgtmsgctnt;
+}
diff --git a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogRepository.java b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogRepository.java
index 2b10fb0..b89448c 100644
--- a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogRepository.java
+++ b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogRepository.java
@@ -6,6 +6,7 @@ import org.springframework.data.domain.Pageable;
import com.eactive.eai.data.entity.onl.logger.EAILog;
import com.eactive.eai.data.entity.onl.logger.EAILogId;
+import java.util.List;
import java.util.Map;
public interface EAILogRepository {
@@ -16,4 +17,6 @@ public interface EAILogRepository {
Map countDetailedTransactions(Class extends EAILog> clazz, EAILogSearch eaiLogSearch);
+ List getApiLog(Class extends EAILog> class1, String apiServiceNumber);
+
}
diff --git a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogRepositoryImpl.java b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogRepositoryImpl.java
index fc78b9c..aad5b34 100644
--- a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogRepositoryImpl.java
+++ b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogRepositoryImpl.java
@@ -1,5 +1,19 @@
package com.eactive.eai.rms.data.entity.onl.logger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Repository;
+
import com.eactive.eai.data.entity.onl.logger.EAILog;
import com.eactive.eai.data.entity.onl.logger.EAILogId;
import com.eactive.eai.data.entity.onl.logger.QEAILog;
@@ -11,18 +25,6 @@ import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.EntityPathBase;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageImpl;
-import org.springframework.data.domain.Pageable;
-import org.springframework.stereotype.Repository;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
@Repository
public class EAILogRepositoryImpl implements EAILogRepository {
@@ -217,4 +219,14 @@ public class EAILogRepositoryImpl implements EAILogRepository {
.fetchOne();
}
+ @Override
+ public List getApiLog(Class extends EAILog> clazz, String apiServiceNumber) {
+ QEAILog qeaiLog = QEAILog.eAILog;
+ EntityPathBase> entityPathBase = new EntityPathBase<>(clazz, qeaiLog.getMetadata().getName());
+
+ return new JPAQueryFactory(em).select(qeaiLog).from(entityPathBase)
+ .where(qeaiLog.id.eaisvcserno.trim().eq(apiServiceNumber)).orderBy(qeaiLog.id.logprcssserno.asc())
+ .fetch();
+ }
+
}
diff --git a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogService.java b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogService.java
index 5742260..215687b 100644
--- a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogService.java
+++ b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogService.java
@@ -19,4 +19,6 @@ public interface EAILogService {
List selectLogList(HashMap paramMap);
Map getTransactionCounts(EAILogSearch eaiLogSearch);
+
+ ApiLogDTO getApiLog(String txDate, String apiServiceNumber);
}
diff --git a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogServiceImpl.java b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogServiceImpl.java
index 30a8d95..2782e65 100644
--- a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogServiceImpl.java
+++ b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/EAILogServiceImpl.java
@@ -1,55 +1,130 @@
package com.eactive.eai.rms.data.entity.onl.logger;
-import com.eactive.eai.data.RollingTable;
-import com.eactive.eai.data.entity.onl.logger.EAILog;
-import com.eactive.eai.data.entity.onl.logger.EAILogId;
-import com.eactive.eai.rms.common.util.CommonUtil;
-import com.eactive.eai.rms.data.entity.onl.apim.portalstatistics.PortalStatisticsVO;
-import lombok.RequiredArgsConstructor;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import com.eactive.eai.data.RollingTable;
+import com.eactive.eai.data.entity.onl.logger.EAILog;
+import com.eactive.eai.data.entity.onl.logger.EAILogId;
+import com.eactive.eai.data.entity.onl.logger.HttpAdapterExtraLog;
+import com.eactive.eai.rms.common.util.CommonUtil;
+import com.eactive.eai.rms.data.entity.onl.apim.portalstatistics.PortalStatisticsVO;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class EAILogServiceImpl implements EAILogService {
- private final EAILogRepository eaiLogRepository;
- private final ApplicationContext applicationContext;
- private final EAILogDAOForEMS eaiLogDAOForEMS;
+ private final EAILogRepository eaiLogRepository;
+ private final ApplicationContext applicationContext;
+ private final EAILogDAOForEMS eaiLogDAOForEMS;
+ private final HttpAdapterExtraLogService httpAdapterExtraLogService;
- @Override
- public Page findAll(Pageable pageable, EAILogSearch eaiLogSearch) {
- long time = CommonUtil.getCalendar(eaiLogSearch.getSearchStartTime()).getTimeInMillis();
- EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
- Page eaiLogDtos = eaiLogRepository.findAll(eaiLog.getClass(), pageable, eaiLogSearch);
- return eaiLogDtos;
- }
+ @Override
+ public Page findAll(Pageable pageable, EAILogSearch eaiLogSearch) {
+ long time = CommonUtil.getCalendar(eaiLogSearch.getSearchStartTime()).getTimeInMillis();
+ EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
+ Page eaiLogDtos = eaiLogRepository.findAll(eaiLog.getClass(), pageable, eaiLogSearch);
+ return eaiLogDtos;
+ }
- public Map getTransactionCounts(EAILogSearch eaiLogSearch){
- long time = CommonUtil.getCalendar(eaiLogSearch.getSearchStartTime()).getTimeInMillis();
- EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
- Map detailedCounts = eaiLogRepository.countDetailedTransactions(eaiLog.getClass(), eaiLogSearch);
- return detailedCounts;
- }
+ public Map getTransactionCounts(EAILogSearch eaiLogSearch) {
+ long time = CommonUtil.getCalendar(eaiLogSearch.getSearchStartTime()).getTimeInMillis();
+ EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
+ Map detailedCounts = eaiLogRepository.countDetailedTransactions(eaiLog.getClass(), eaiLogSearch);
+ return detailedCounts;
+ }
- @Override
- public EAILogDto getById(EAILogId eaiLogId) {
- long time = CommonUtil.getCalendar(eaiLogId.getMsgdpstyms()).getTimeInMillis();
- EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
- return eaiLogRepository.getById(eaiLog.getClass(), eaiLogId);
- }
+ @Override
+ public EAILogDto getById(EAILogId eaiLogId) {
+ long time = CommonUtil.getCalendar(eaiLogId.getMsgdpstyms()).getTimeInMillis();
+ EAILog eaiLog = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
+ return eaiLogRepository.getById(eaiLog.getClass(), eaiLogId);
+ }
+ public List selectLogList(HashMap paramMap) {
+ return eaiLogDAOForEMS.selectLogList(paramMap);
+ }
- public List selectLogList(HashMap paramMap) {
- return eaiLogDAOForEMS.selectLogList(paramMap);
- }
+ @Override
+ public ApiLogDTO getApiLog(String txDate, String apiServiceNumber) {
+
+ long time = CommonUtil.getCalendar(txDate).getTimeInMillis();
+ EAILog eaiLogTargetObject = (EAILog) applicationContext.getBean(RollingTable.class, EAILog.class, time);
+ List eaiLogs = eaiLogRepository.getApiLog(eaiLogTargetObject.getClass(), apiServiceNumber);
+ eaiLogs.sort((l1, l2) -> l1.getId().getEaisvcserno().compareTo(l2.getId().getEaisvcserno()));
+
+ ApiLogDTO apiLogDTO = new ApiLogDTO();
+ apiLogDTO.setApiServiceNumber(apiServiceNumber);
+ eaiLogs.stream().findFirst().ifPresent(log -> apiLogDTO.setTxDate(log.getId().getMsgdpstyms()));
+
+ List apiMessageLogDTOs = new LinkedList<>();
+
+ for (EAILog eaiLog : eaiLogs) {
+ ApiMessageLogDTO apiMessageLogDTO = new ApiMessageLogDTO();
+
+ apiMessageLogDTO.setApiServiceNumber(apiServiceNumber);
+ apiMessageLogDTO.setTxDate(eaiLog.getMsgprcssyms());
+ apiMessageLogDTO.setProcessNumber(Integer.parseInt(eaiLog.getId().getLogprcssserno()));
+ apiMessageLogDTO.setQueryString("");
+ apiMessageLogDTO.setClientId(eaiLog.getClientid());
+ apiMessageLogDTO.setKeymgtmsgctnt(eaiLog.getKeymgtmsgctnt());
+
+ String body = StringUtils.substringAfter(eaiLog.getBzwkdatactnt(), '|');
+ body = StringUtils.substringBeforeLast(body, "|");
+
+ apiMessageLogDTO.setBody(body);
+ apiMessageLogDTOs.add(apiMessageLogDTO);
+ }
+
+ Map extraLogs = httpAdapterExtraLogService.findByGuid(apiServiceNumber);
+ for (ApiMessageLogDTO apiMessageLogDTO : apiMessageLogDTOs) {
+ HttpAdapterExtraLog httpAdapterExtraLog = extraLogs.get(apiMessageLogDTO.getProcessNumber());
+
+ apiMessageLogDTO.setHeader(httpAdapterExtraLog.getHeaderContent());
+ apiMessageLogDTO.setMethod(httpAdapterExtraLog.getHttpMethod());
+ apiMessageLogDTO.setHttpStatus(httpAdapterExtraLog.getHttpStatus());
+ apiMessageLogDTO.setUrl(httpAdapterExtraLog.getUrl());
+ }
+
+ // 처리 시간 계산
+ for (int i = 0; i < apiMessageLogDTOs.size(); i++) {
+ ApiMessageLogDTO dto = apiMessageLogDTOs.get(i);
+ EAILog eaiLog = eaiLogs.get(i);
+
+ // msgprcssyms - msgdpstyms
+ long receivedTime = CommonUtil.getCalendar(eaiLog.getId().getMsgdpstyms()).getTimeInMillis();
+ long processedTime = CommonUtil.getCalendar(eaiLog.getMsgprcssyms()).getTimeInMillis();
+ long processingTime = processedTime - receivedTime;
+ dto.setProcessingTime(processingTime);
+ }
+
+ // 전체 처리 시간 계산 (첫 수신 시각 ~ 마지막 처리 시각)
+ if (!eaiLogs.isEmpty()) {
+ long firstReceivedTime = CommonUtil.getCalendar(eaiLogs.get(0).getId().getMsgdpstyms()).getTimeInMillis();
+ long lastProcessedTime = CommonUtil.getCalendar(eaiLogs.get(eaiLogs.size() - 1).getMsgprcssyms()).getTimeInMillis();
+ long totalProcessingTime = lastProcessedTime - firstReceivedTime;
+ apiLogDTO.setTotalProcessingTime(totalProcessingTime);
+ }
+
+ apiLogDTO.setLogs(apiMessageLogDTOs);
+ return apiLogDTO;
+ }
}
diff --git a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/HttpAdapterExtraLogService.java b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/HttpAdapterExtraLogService.java
index 2fa2c86..6441b7c 100644
--- a/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/HttpAdapterExtraLogService.java
+++ b/src/main/java/com/eactive/eai/rms/data/entity/onl/logger/HttpAdapterExtraLogService.java
@@ -1,16 +1,28 @@
package com.eactive.eai.rms.data.entity.onl.logger;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
import javax.transaction.Transactional;
import org.springframework.stereotype.Service;
import com.eactive.eai.data.entity.onl.logger.HttpAdapterExtraLog;
import com.eactive.eai.data.entity.onl.logger.HttpAdapterExtraLogId;
+import com.eactive.eai.data.entity.onl.logger.QHttpAdapterExtraLog;
import com.eactive.eai.data.jpa.AbstractDataService;
+import com.querydsl.core.types.dsl.BooleanExpression;
@Service
@Transactional
public class HttpAdapterExtraLogService
extends AbstractDataService {
+ public Map findByGuid(String guid) {
+ BooleanExpression predicate = QHttpAdapterExtraLog.httpAdapterExtraLog.id.guid.eq(guid);
+ return StreamSupport.stream(repository.findAll(predicate).spliterator(), false)
+ .collect(Collectors.toMap(log -> log.getId().getServiceProcessNumber(), log -> log));
+ }
+
}
diff --git a/src/main/java/com/eactive/ext/kjb/web/ApiLogUI.java b/src/main/java/com/eactive/ext/kjb/web/ApiLogUI.java
new file mode 100644
index 0000000..7572680
--- /dev/null
+++ b/src/main/java/com/eactive/ext/kjb/web/ApiLogUI.java
@@ -0,0 +1,17 @@
+package com.eactive.ext.kjb.web;
+
+import java.util.List;
+
+import lombok.Data;
+
+@Data
+public class ApiLogUI {
+
+ private String apiServiceNumber;
+
+ private String txDate;
+
+ private List logs;
+
+ private Long totalProcessingTime;
+}
diff --git a/src/main/java/com/eactive/ext/kjb/web/ApiMessageLogUI.java b/src/main/java/com/eactive/ext/kjb/web/ApiMessageLogUI.java
new file mode 100644
index 0000000..7e2989a
--- /dev/null
+++ b/src/main/java/com/eactive/ext/kjb/web/ApiMessageLogUI.java
@@ -0,0 +1,35 @@
+package com.eactive.ext.kjb.web;
+
+import java.util.Map;
+
+import lombok.Data;
+
+@Data
+public class ApiMessageLogUI {
+
+ private String apiServiceNumber;
+
+ private int processNumber;
+
+ private String txDate;
+
+ private String url;
+
+ private String queryString;
+
+ private String clientId;
+
+ private String method;
+
+ private Integer HttpStatus;
+
+ private Map header;
+
+ private Object body;
+
+ private String exdata;
+
+ private Long processingTime;
+
+ private String guid;
+}
diff --git a/src/main/java/com/eactive/ext/kjb/web/ApiTransactionLogController.java b/src/main/java/com/eactive/ext/kjb/web/ApiTransactionLogController.java
new file mode 100644
index 0000000..c18c317
--- /dev/null
+++ b/src/main/java/com/eactive/ext/kjb/web/ApiTransactionLogController.java
@@ -0,0 +1,142 @@
+package com.eactive.ext.kjb.web;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
+import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
+import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
+import com.eactive.eai.rms.data.entity.onl.logger.ApiLogDTO;
+import com.eactive.eai.rms.data.entity.onl.logger.ApiMessageLogDTO;
+import com.eactive.eai.rms.data.entity.onl.logger.EAILogService;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Controller
+@RequiredArgsConstructor
+public class ApiTransactionLogController implements InterceptorSkipController {
+
+ private final EAILogService eaiLogService;
+ private final ObjectMapper objectMapper = new ObjectMapper();
+
+ @GetMapping("/api/transaction/log.do")
+ @PostMapping("/api/transaction/log.do")
+ public ResponseEntity getApiLog(String txDate, String apiServiceNumber) {
+ DataSourceContextHolder.setDataSourceType(DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.APIGW));
+
+ // txDate가 없으면 오늘 날짜 설정
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
+ LocalDate searchDate;
+ if (StringUtils.hasText(txDate)) {
+ searchDate = LocalDate.parse(txDate, formatter);
+ } else {
+ searchDate = LocalDate.now();
+ }
+
+ // 최대 10일 전까지 조회 시도
+ ApiLogDTO dto = null;
+ for (int i = 0; i < 10; i++) {
+ String searchDateStr = searchDate.format(formatter);
+ dto = eaiLogService.getApiLog(searchDateStr, apiServiceNumber);
+
+ // 결과가 있으면 종료
+ if (dto != null && dto.getLogs() != null && !dto.getLogs().isEmpty()) {
+ break;
+ }
+
+ // 하루 전으로 이동
+ searchDate = searchDate.minusDays(1);
+ }
+
+ return ResponseEntity.ok(convertToUI(dto));
+ }
+
+ private ApiLogUI convertToUI(ApiLogDTO dto) {
+ ApiLogUI ui = new ApiLogUI();
+ ui.setApiServiceNumber(dto.getApiServiceNumber());
+ ui.setTxDate(dto.getTxDate());
+ ui.setTotalProcessingTime(dto.getTotalProcessingTime());
+
+ if (dto.getLogs() != null) {
+ List uiLogs = dto.getLogs().stream().map(this::convertMessageToUI)
+ .collect(Collectors.toList());
+ ui.setLogs(uiLogs);
+ }
+
+ return ui;
+ }
+
+ private ApiMessageLogUI convertMessageToUI(ApiMessageLogDTO dto) {
+ ApiMessageLogUI ui = new ApiMessageLogUI();
+ ui.setApiServiceNumber(dto.getApiServiceNumber());
+ ui.setProcessNumber(dto.getProcessNumber());
+ ui.setTxDate(dto.getTxDate());
+ ui.setUrl(dto.getUrl());
+ ui.setQueryString(dto.getQueryString());
+ ui.setClientId(dto.getClientId());
+ ui.setMethod(dto.getMethod());
+ ui.setHttpStatus(dto.getHttpStatus());
+ ui.setExdata(dto.getExdata());
+ ui.setProcessingTime(dto.getProcessingTime());
+ ui.setGuid(dto.getKeymgtmsgctnt());
+
+ // header: JSON 문자열 → Map
+ if (dto.getHeader() != null) {
+ try {
+ List