diff --git a/src/main/java/com/aolda/itda/aspect/CertificateLogAspect.java b/src/main/java/com/aolda/itda/aspect/CertificateLogAspect.java
index 61998c80c2383b070315e5b7068e15aacc7ce773..30df250f9ffd08dbf07b458750c7c464409faf82 100644
--- a/src/main/java/com/aolda/itda/aspect/CertificateLogAspect.java
+++ b/src/main/java/com/aolda/itda/aspect/CertificateLogAspect.java
@@ -23,6 +23,7 @@ import org.springframework.stereotype.Component;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
+import java.time.format.DateTimeFormatter;
 import java.util.Map;
 import java.util.Objects;
 
@@ -36,6 +37,8 @@ public class CertificateLogAspect {
     private final LogRepository logRepository;
     private final EntityManager entityManager;
 
+    private static final DateTimeFormatter LOG_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
     /* Create 로깅 */
     @AfterReturning(pointcut = "execution(* com.aolda.itda.service.certificate.*Service.*create*(..))"
             , returning = "result")
@@ -55,7 +58,7 @@ public class CertificateLogAspect {
         String description = "domain: " + certificate.getDomain() + "\n"
                 + "email: " + certificate.getEmail() + "\n"
                 + "challenge: " + certificate.getChallenge() + "\n"
-                + "expiresAt: " + certificate.getExpiresAt();
+                + "expiresAt: " + (certificate.getExpiresAt() != null ? certificate.getExpiresAt().format(LOG_DATE_FORMATTER) : "null");
 
         /* 로그 엔티티 저장 */
         logRepository.save(Log.builder()
@@ -89,7 +92,7 @@ public class CertificateLogAspect {
         String description = "domain: " + certificate.getDomain() + "\n"
                 + "email: " + certificate.getEmail() + "\n"
                 + "challenge: " + certificate.getChallenge() + "\n"
-                + "expiresAt: " + certificate.getExpiresAt();
+                + "expiresAt: " + (certificate.getExpiresAt() != null ? certificate.getExpiresAt().format(LOG_DATE_FORMATTER) : "null");
 
         /* 로그 엔티티 저장 */
         logRepository.save(Log.builder()
@@ -132,7 +135,8 @@ public class CertificateLogAspect {
         String description = "domain: " + old.getDomain() + (old.getDomain().equals(newObj.getDomain()) ? "" : " -> " + newObj.getDomain()) + "\n"
                 + "email: " + old.getEmail() + (old.getEmail().equals(newObj.getEmail()) ? "" : " -> " + newObj.getEmail()) + "\n"
                 + "challenge: " + old.getChallenge() + (old.getChallenge() == newObj.getChallenge() ? "" : " -> " + newObj.getChallenge()) + "\n"
-                + "expiresAt: " + old.getExpiresAt() + (old.getExpiresAt().equals(newObj.getExpiresAt()) ? "" : " -> " + newObj.getExpiresAt());
+                + "expiresAt: " + (old.getExpiresAt() != null ? old.getExpiresAt().format(LOG_DATE_FORMATTER) : "null")
+                + (old.getExpiresAt() != null && newObj.getExpiresAt() != null && !old.getExpiresAt().equals(newObj.getExpiresAt()) ? " -> " + newObj.getExpiresAt().format(LOG_DATE_FORMATTER) : "");
 
         /* 로그 엔티티 저장 */
         logRepository.save(Log.builder()
diff --git a/src/main/java/com/aolda/itda/controller/certificate/CertificateController.java b/src/main/java/com/aolda/itda/controller/certificate/CertificateController.java
index d08968bd39f0076c4ffcaf6d3881b792020f8c7c..26a0322cc29fb6c642ccafbf9dd5cce005030a9e 100644
--- a/src/main/java/com/aolda/itda/controller/certificate/CertificateController.java
+++ b/src/main/java/com/aolda/itda/controller/certificate/CertificateController.java
@@ -59,8 +59,18 @@ public class CertificateController {
     @GetMapping("/certificates")
     public ResponseEntity<PageResp<CertificateDTO>> lists(
             @RequestParam String projectId,
-            @RequestParam(required = false) String domain
+            @RequestParam(required = false) String domain,
+            @RequestParam(required = false) String query
     ) {
+
+        if (query != null) {
+            return ResponseEntity.ok(
+                    certificateService.getCertificatesWithSearch(
+                            projectId,
+                            query
+                    )
+            );
+        }
         return ResponseEntity.ok(
                 certificateService.getCertificates(projectId, domain)
         );
diff --git a/src/main/java/com/aolda/itda/dto/certificate/CertificateDTO.java b/src/main/java/com/aolda/itda/dto/certificate/CertificateDTO.java
index 23b9e95b71c2fbbcf5aaf86171f29b13d363b6d3..058fdd789d0f2c53bbda5ac10469bd9e72d6313b 100644
--- a/src/main/java/com/aolda/itda/dto/certificate/CertificateDTO.java
+++ b/src/main/java/com/aolda/itda/dto/certificate/CertificateDTO.java
@@ -16,7 +16,7 @@ import java.time.LocalDateTime;
 public class CertificateDTO {
 
     private Long id;          // 인증서 고유 ID
-//    private String projectId;            // 프로젝트 식별자
+    private String projectId;            // 프로젝트 식별자
     private String domain;               // SSL 인증받을 도메인 주소
     private String email;
     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")// 도메인 소유자의 이메일
diff --git a/src/main/java/com/aolda/itda/entity/certificate/Certificate.java b/src/main/java/com/aolda/itda/entity/certificate/Certificate.java
index 8ebc45449a7e18a768ea85f34f2d55f46ff3c83f..9161b45397475cd8555591d962df43f3c8684d78 100644
--- a/src/main/java/com/aolda/itda/entity/certificate/Certificate.java
+++ b/src/main/java/com/aolda/itda/entity/certificate/Certificate.java
@@ -34,6 +34,7 @@ public class Certificate extends BaseTimeEntity {
 
     @Setter
     @Column(columnDefinition = "DATETIME")
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
     private LocalDateTime expiresAt; //인증서 만료일
 
     @Enumerated(EnumType.STRING)
diff --git a/src/main/java/com/aolda/itda/repository/certificate/CertificateRepository.java b/src/main/java/com/aolda/itda/repository/certificate/CertificateRepository.java
index 6e0996b4ffadd631e3506332242de193f602b3ef..0f3c137a9795352e199bf81f2df8e081812a82cc 100644
--- a/src/main/java/com/aolda/itda/repository/certificate/CertificateRepository.java
+++ b/src/main/java/com/aolda/itda/repository/certificate/CertificateRepository.java
@@ -1,7 +1,9 @@
 package com.aolda.itda.repository.certificate;
 
 import com.aolda.itda.entity.certificate.Certificate;
+import com.aolda.itda.entity.routing.Routing;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
 
 import java.time.LocalDateTime;
 import java.util.List;
@@ -19,10 +21,13 @@ public interface CertificateRepository extends JpaRepository<Certificate, Long>
     //List<Certificate> findByExpiresAtBeforeAndIsDeleted(LocalDateTime date, Boolean isDeleted);
 
     // 1) domain 필터링용 메서드
-    List<Certificate> findByProjectIdAndDomainContainingIgnoreCaseAndIsDeleted(
+    List<Certificate> findByProjectIdAndDomainContainingAndIsDeleted(
             String projectId, String domain, Boolean isDeleted);
 
     // 3) 만료 30일 이내 대상 조회
     List<Certificate> findByExpiresAtBeforeAndIsDeleted(
             LocalDateTime date, Boolean isDeleted);
+
+    @Query("SELECT r FROM Routing r WHERE r.projectId = ?1 AND r.isDeleted = ?3 AND (r.domain LIKE %?2% OR r.instanceIp LIKE %?2% OR r.name LIKE %?2%)")
+    List<Certificate> findWithSearch(String projectId, String query, Boolean isDeleted);
 }
diff --git a/src/main/java/com/aolda/itda/service/certificate/CertificateService.java b/src/main/java/com/aolda/itda/service/certificate/CertificateService.java
index f8d8cfe69aceff9f00c99937293740446ab67b25..7f426709d5480a8ed5564376ec12616c3a8bb8e6 100644
--- a/src/main/java/com/aolda/itda/service/certificate/CertificateService.java
+++ b/src/main/java/com/aolda/itda/service/certificate/CertificateService.java
@@ -2,8 +2,10 @@ package com.aolda.itda.service.certificate;
 
 import com.aolda.itda.dto.PageResp;
 import com.aolda.itda.dto.certificate.CertificateDTO;
+import com.aolda.itda.dto.routing.RoutingDTO;
 import com.aolda.itda.entity.certificate.Certificate;
 import com.aolda.itda.entity.certificate.Challenge;
+import com.aolda.itda.entity.routing.Routing;
 import com.aolda.itda.exception.CustomException;
 import com.aolda.itda.exception.ErrorCode;
 import com.aolda.itda.repository.certificate.CertificateRepository;
@@ -12,6 +14,7 @@ import jakarta.validation.ConstraintViolation;
 import jakarta.validation.Validation;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -21,7 +24,10 @@ import java.io.IOException;
 import java.io.InputStreamReader;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
 
 @Service
 @Transactional
@@ -29,6 +35,8 @@ import java.util.List;
 @Slf4j
 public class CertificateService {
 
+    @Value("${spring.server.admin-project}")
+    private String adminProject;
     private final CertificateRepository certificateRepository;
     private final AuthService authService;
 
@@ -41,18 +49,67 @@ public class CertificateService {
         return toDTO(cert);
     }
 
+    /* Certificate 목록 조회 + 검색 */
+    public PageResp<CertificateDTO> getCertificatesWithSearch(String projectId, String query) {
+
+        /* 입력 검증 */
+        if (query == null || query.isBlank()) {
+            return PageResp.<CertificateDTO>builder()
+                    .contents(certificateRepository.findByProjectIdAndIsDeleted(projectId, false)
+                            .stream()
+                            .map(this::toDTO)
+                            .toList()).build();
+        }
+
+        /* 도메인 패턴 검증 */
+        String domainPattern = "^(\\*\\.)?([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}$";
+        if (Pattern.matches(domainPattern, query) && query.startsWith("*.")) {
+            query = query.substring(2);
+        }
+
+        return PageResp.<CertificateDTO>builder()
+                .contents(certificateRepository.findWithSearch(projectId, query, false)
+                        .stream()
+                        .map(this::toDTO)
+                        .toList()).build();
+    }
+
     /** 1) 목록 조회 (domain 필터 optional) **/
     public PageResp<CertificateDTO> getCertificates(String projectId, String domain) {
-        List<Certificate> list;
+        Set<Certificate> set = new HashSet<>();
+        // 도메인이 입력된 경우 처리
         if (domain != null && !domain.isBlank()) {
-            list = certificateRepository
-                    .findByProjectIdAndDomainContainingIgnoreCaseAndIsDeleted(
-                            projectId, domain, false);
+            // 서브도메인이 있는 경우 
+            if (domain.indexOf('.') != domain.lastIndexOf('.')) {
+                String wildcardDomain = "*." + domain.substring(domain.indexOf('.') + 1);
+                set.addAll(certificateRepository
+                        .findByProjectIdAndDomainContainingAndIsDeleted(
+                                projectId, wildcardDomain, false));
+                set.addAll(certificateRepository
+                        .findByProjectIdAndDomainContainingAndIsDeleted(
+                                projectId, domain, false));
+                set.addAll(certificateRepository
+                        .findByProjectIdAndDomainContainingAndIsDeleted(
+                                adminProject, wildcardDomain, false));
+                set.addAll(certificateRepository
+                        .findByProjectIdAndDomainContainingAndIsDeleted(
+                                adminProject, domain, false));
+            } else {
+                // 서브도메인이 없는 경우 일반 검색
+                set.addAll(certificateRepository
+                        .findByProjectIdAndDomainContainingAndIsDeleted(
+                                projectId, domain, false));
+                set.addAll(certificateRepository
+                        .findByProjectIdAndDomainContainingAndIsDeleted(
+                                adminProject, domain, false));
+            }
         } else {
-            list = certificateRepository
-                    .findByProjectIdAndIsDeleted(projectId, false);
+            set.addAll(certificateRepository
+                    .findByProjectIdAndIsDeleted(projectId, false));
+            set.addAll(certificateRepository
+                    .findByProjectIdAndIsDeleted(adminProject, false));
         }
-        List<CertificateDTO> dtos = list.stream()
+        List<CertificateDTO> dtos = set.stream()
                 .map(this::toDTO)
                 .toList();
         return PageResp.<CertificateDTO>builder()
@@ -171,6 +228,7 @@ public class CertificateService {
                 .updatedAt(cert.getUpdatedAt())
                 .isDeleted(cert.getIsDeleted())
                 .apiToken(cert.getApiToken())
+                .projectId(cert.getProjectId())
                 .build();
     }