diff --git a/src/main/java/com/aolda/itda/config/WebConfig.java b/src/main/java/com/aolda/itda/config/WebConfig.java
index fd0080766c4816b4257be9c7c19dd0741d1da648..71e134bebee94ab01c47d0a032e6026d9929b62b 100644
--- a/src/main/java/com/aolda/itda/config/WebConfig.java
+++ b/src/main/java/com/aolda/itda/config/WebConfig.java
@@ -25,7 +25,7 @@ public class WebConfig implements WebMvcConfigurer {
 
     @Override
     public void addInterceptors(InterceptorRegistry registry) {
-        String[] excludeAuth = {"/error", "/api/auth/*" };
+        String[] excludeAuth = {"/error", "/api/auth/*", "/api/*" };
 
         registry.addInterceptor(authInterceptor)
                 .addPathPatterns("/**")
diff --git a/src/main/java/com/aolda/itda/controller/forwarding/ForwardingController.java b/src/main/java/com/aolda/itda/controller/forwarding/ForwardingController.java
index 19786bd5a3c7d08eaa8d691ceea2d95e0ee62d15..a6b67ecbd0090ce8f8460d3fd8b08def88d520a8 100644
--- a/src/main/java/com/aolda/itda/controller/forwarding/ForwardingController.java
+++ b/src/main/java/com/aolda/itda/controller/forwarding/ForwardingController.java
@@ -2,6 +2,7 @@ package com.aolda.itda.controller.forwarding;
 
 import com.aolda.itda.dto.forwarding.ForwardingDTO;
 import com.aolda.itda.service.forwarding.ForwardingService;
+import jakarta.validation.Valid;
 import lombok.RequiredArgsConstructor;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
diff --git a/src/main/java/com/aolda/itda/controller/routing/RoutingController.java b/src/main/java/com/aolda/itda/controller/routing/RoutingController.java
new file mode 100644
index 0000000000000000000000000000000000000000..894357188678e8f232a109e9aab99642ece56bce
--- /dev/null
+++ b/src/main/java/com/aolda/itda/controller/routing/RoutingController.java
@@ -0,0 +1,39 @@
+package com.aolda.itda.controller.routing;
+
+import com.aolda.itda.dto.routing.RoutingDTO;
+import com.aolda.itda.service.routing.RoutingService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/api")
+@RequiredArgsConstructor
+public class RoutingController {
+
+    private final RoutingService routingService;
+
+    @GetMapping("/routing")
+    public ResponseEntity<Object> view(@RequestParam Long routingId) {
+        return ResponseEntity.ok(routingService.getRouting(routingId));
+    }
+
+    @GetMapping("/routings")
+    public ResponseEntity<Object> lists(@RequestParam String projectId) {
+        return ResponseEntity.ok(routingService.getRoutings(projectId));
+    }
+
+    @PatchMapping("/routing")
+    public ResponseEntity<Object> edit(@RequestParam Long routingId,
+                                       @RequestBody RoutingDTO dto) {
+        routingService.editRouting(routingId, dto);
+        return ResponseEntity.ok().build();
+    }
+
+    @DeleteMapping("/routing")
+    public ResponseEntity<Object> delete(@RequestParam Long routingId) {
+        routingService.deleteRouting(routingId);
+        return ResponseEntity.ok().build();
+    }
+
+}
diff --git a/src/main/java/com/aolda/itda/dto/routing/RoutingDTO.java b/src/main/java/com/aolda/itda/dto/routing/RoutingDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..e95ab70e8763ab7c3db0a5e7d884d6e50662b1bf
--- /dev/null
+++ b/src/main/java/com/aolda/itda/dto/routing/RoutingDTO.java
@@ -0,0 +1,37 @@
+package com.aolda.itda.dto.routing;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class RoutingDTO {
+    @NotBlank
+    private String ip;
+    @NotBlank
+    private String domain;
+    @NotBlank
+    private String name;
+    @NotBlank
+    private String port;
+    private Long id;
+    @NotBlank
+    private Long certificateId;
+
+    private LocalDateTime createdAt;
+
+    private LocalDateTime updatedAt;
+
+    @NotNull
+    private Boolean caching;
+}
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 5ab56a9239325d5745e7255d00e79c9538a21698..188f05e106121abe6f26b70fde078e0bd8d50662 100644
--- a/src/main/java/com/aolda/itda/entity/certificate/Certificate.java
+++ b/src/main/java/com/aolda/itda/entity/certificate/Certificate.java
@@ -42,5 +42,7 @@ public class Certificate extends BaseTimeEntity {
 
     private String description;
 
-
+    public String formatDomain() {
+        return domain == null ? null : domain.replace("*", "_");
+    }
 }
diff --git a/src/main/java/com/aolda/itda/entity/log/Log.java b/src/main/java/com/aolda/itda/entity/log/Log.java
index fd8f460bba7940730772841c7451a8815412dd1b..fa78a6677f3cbb66322056a83dfd2a404eb5435c 100644
--- a/src/main/java/com/aolda/itda/entity/log/Log.java
+++ b/src/main/java/com/aolda/itda/entity/log/Log.java
@@ -35,6 +35,6 @@ public class Log extends BaseTimeEntity {
     @Enumerated(EnumType.STRING)
     private Action action;
 
-    private String metadata;
+    private String description;
 
 }
diff --git a/src/main/java/com/aolda/itda/entity/routing/Routing.java b/src/main/java/com/aolda/itda/entity/routing/Routing.java
index 0c6b2aab53b5cc4a4611aaff02316febad651257..be03dcd3edd27000c8c00aea2437ac65da1c72d5 100644
--- a/src/main/java/com/aolda/itda/entity/routing/Routing.java
+++ b/src/main/java/com/aolda/itda/entity/routing/Routing.java
@@ -1,5 +1,7 @@
 package com.aolda.itda.entity.routing;
 
+import com.aolda.itda.dto.forwarding.ForwardingDTO;
+import com.aolda.itda.dto.routing.RoutingDTO;
 import com.aolda.itda.entity.BaseTimeEntity;
 import com.aolda.itda.entity.certificate.Certificate;
 import com.aolda.itda.entity.user.User;
@@ -36,8 +38,38 @@ public class Routing extends BaseTimeEntity {
 
     private String instanceIp;
 
+    private String instancePort;
+
     private Boolean isDeleted;
 
-    private String description;
+    private Boolean caching;
+
+    private String name;
+
+    public RoutingDTO toRoutingDTO() {
+        return RoutingDTO.builder()
+                .id(routingId)
+                .name(name)
+                .port(instancePort)
+                .ip(instanceIp)
+                .certificateId(certificate == null ? null : certificate.getCertificateId())
+                .caching(caching)
+                .domain(domain)
+                .createdAt(getCreatedAt())
+                .updatedAt(getUpdatedAt())
+                .build();
+    }
+
+    public void edit(RoutingDTO dto, Certificate certificate) {
+        this.name = dto.getName() != null ? dto.getName() : this.name;
+        this.instanceIp = dto.getIp() != null ? dto.getIp() : this.instanceIp;
+        this.instancePort = dto.getPort() != null ? dto.getPort() : this.instancePort;
+        this.caching = dto.getCaching() != null ? dto.getCaching() : this.caching;
+        this.domain = dto.getDomain() != null ? dto.getDomain() : this.domain;
+        this.certificate = certificate;
+    }
 
+    public void delete() {
+        this.isDeleted = true;
+    }
 }
diff --git a/src/main/java/com/aolda/itda/exception/ErrorCode.java b/src/main/java/com/aolda/itda/exception/ErrorCode.java
index 443f3a10f7c7a2a5ac2f876187a2d88a2e911fe9..321bdaddd8b6eb5a3f523e8e56b5d738e3105319 100644
--- a/src/main/java/com/aolda/itda/exception/ErrorCode.java
+++ b/src/main/java/com/aolda/itda/exception/ErrorCode.java
@@ -15,12 +15,21 @@ public enum ErrorCode {
     INVALID_TOKEN(HttpStatus.BAD_REQUEST, "잘못된 토큰입니다"),
 
     // Forwarding
+    NOT_FOUND_FORWARDING(HttpStatus.BAD_REQUEST, "포트포워딩 파일이 존재하지 않습니다"),
+
+    // Routing
+    NOT_FOUND_ROUTING(HttpStatus.BAD_REQUEST, "라우팅 파일이 존재하지 않습니다"),
+
+    // Certificate
+    NOT_FOUND_CERTIFICATE(HttpStatus.BAD_REQUEST, "SSL 인증서가 존재하지 않습니다"),
+
+    // CONF File
     FAIL_CREATE_CONF(HttpStatus.BAD_REQUEST, "Conf 파일을 생성하지 못했습니다"),
     FAIL_UPDATE_CONF(HttpStatus.BAD_REQUEST, "Conf 파일을 수정하지 못했습니다"),
-    NOT_FOUND_FORWARDING(HttpStatus.BAD_REQUEST, "포트포워딩 파일이 존재하지 않습니다"),
     INVALID_CONF_INPUT(HttpStatus.BAD_REQUEST, "잘못된 입력이 존재합니다"),
     DUPLICATED_INSTANCE_INFO(HttpStatus.BAD_REQUEST, "중복된 인스턴스 IP와 포트입니다"),
     DUPLICATED_SERVER_PORT(HttpStatus.BAD_REQUEST, "중복된 서버 포트입니다"),
+    DUPLICATED_DOMAIN_NAME(HttpStatus.BAD_REQUEST, "중복된 도메인 주소입니다"),
 
     // Nginx
     FAIL_NGINX_CONF_TEST(HttpStatus.BAD_REQUEST, "Conf 파일 테스트에 실패했습니다"),
diff --git a/src/main/java/com/aolda/itda/repository/certificate/CertificateRepository.java b/src/main/java/com/aolda/itda/repository/certificate/CertificateRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..392c90b0aa31f7b445067f7db1ef490a379abf5d
--- /dev/null
+++ b/src/main/java/com/aolda/itda/repository/certificate/CertificateRepository.java
@@ -0,0 +1,7 @@
+package com.aolda.itda.repository.certificate;
+
+import com.aolda.itda.entity.certificate.Certificate;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface CertificateRepository extends JpaRepository<Certificate, Long> {
+}
diff --git a/src/main/java/com/aolda/itda/repository/routing/RoutingRepository.java b/src/main/java/com/aolda/itda/repository/routing/RoutingRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..046296c2df3937d920b4816734d16ce8267b6a1f
--- /dev/null
+++ b/src/main/java/com/aolda/itda/repository/routing/RoutingRepository.java
@@ -0,0 +1,14 @@
+package com.aolda.itda.repository.routing;
+
+import com.aolda.itda.entity.forwarding.Forwarding;
+import com.aolda.itda.entity.routing.Routing;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface RoutingRepository extends JpaRepository<Routing, Long> {
+    List<Routing> findByProjectIdAndIsDeleted(String projectId, Boolean isDeleted);
+    Optional<Routing> findByRoutingIdAndIsDeleted(Long routingId, Boolean isDeleted);
+    Boolean existsByDomainAndIsDeleted(String domain, Boolean isDeleted);
+}
diff --git a/src/main/java/com/aolda/itda/service/routing/RoutingService.java b/src/main/java/com/aolda/itda/service/routing/RoutingService.java
new file mode 100644
index 0000000000000000000000000000000000000000..9cfad7d4ec75d158fce65ced051f8036749ef5b2
--- /dev/null
+++ b/src/main/java/com/aolda/itda/service/routing/RoutingService.java
@@ -0,0 +1,325 @@
+package com.aolda.itda.service.routing;
+
+import com.aolda.itda.dto.PageResp;
+import com.aolda.itda.dto.routing.RoutingDTO;
+import com.aolda.itda.entity.certificate.Certificate;
+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;
+import com.aolda.itda.repository.routing.RoutingRepository;
+import com.aolda.itda.template.RoutingTemplate;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.Validation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.client.RestTemplate;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+
+@Service
+@Transactional
+@RequiredArgsConstructor
+@Slf4j
+public class RoutingService {
+
+    private final RoutingRepository routingRepository;
+    private final CertificateRepository certificateRepository;
+    private final RoutingTemplate routingTemplate;
+    private final RestTemplate restTemplate = new RestTemplate();
+
+    /* Routing 조회 */
+    public RoutingDTO getRouting(Long routingId) {
+        // project id 확인 필요
+        Routing routing = routingRepository.findByRoutingIdAndIsDeleted(routingId, false)
+                .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_ROUTING));
+        return routing.toRoutingDTO();
+    }
+
+    /* Routing 목록 조회 */
+    public PageResp<RoutingDTO> getRoutings(String projectId) {
+        // project id 확인 필요
+        return PageResp.<RoutingDTO>builder()
+                .contents(routingRepository.findByProjectIdAndIsDeleted(projectId, false)
+                        .stream()
+                        .map(Routing::toRoutingDTO)
+                        .toList()).build();
+    }
+
+    /* Routing 생성 */
+    public void createRouting(String projectId, RoutingDTO dto) {
+        /* 입력 DTO 검증 */
+        validateDTO(dto);
+
+        /* 중복 검증 */
+        if (routingRepository.existsByDomainAndIsDeleted(dto.getDomain(), false)) {
+            throw new CustomException(ErrorCode.DUPLICATED_DOMAIN_NAME);
+        }
+
+        /* SSL 인증서 조회 */
+        Certificate certificate = dto.getCertificateId() == -1 ? null :
+                certificateRepository.findById(dto.getCertificateId())
+                .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_CERTIFICATE)); // isDeleted 확인 필요
+
+        /* 라우팅 엔티티 생성 */
+        Routing routing = Routing.builder()
+                .isDeleted(false)
+                .projectId(projectId)
+                .name(dto.getName())
+                .instanceIp(dto.getIp())
+                .instancePort(dto.getPort())
+                .domain(dto.getDomain())
+                .certificate(certificate)
+                .caching(dto.getCaching())
+                .build();
+
+        routingRepository.save(routing);
+
+        /* nginx conf 파일 생성 및 예외 처리 */
+        String content = routingTemplate.getRouting(dto, certificate == null ? null : certificate.formatDomain());
+        String confPath = "/data/nginx/proxy_host/" + routing.getRoutingId() + ".conf";
+
+        File file = new File(confPath);
+        try {
+            Path path = Paths.get(confPath);
+            Files.createDirectories(path.getParent());
+            if (!file.createNewFile()) {
+                throw new CustomException(ErrorCode.FAIL_CREATE_CONF, "중복된 라우팅 Conf 파일이 존재합니다");
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new CustomException(ErrorCode.FAIL_CREATE_CONF);
+        }
+
+        /* conf 파일 작성 및 예외 처리 */
+        try {
+            BufferedWriter bw = new BufferedWriter(new FileWriter(file, false)); // 예외처리 필요
+            bw.write(content);
+            bw.flush();
+            bw.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+            if (file.delete()) {
+                throw new CustomException(ErrorCode.FAIL_DELETE_CONF);
+            }
+            throw new CustomException(ErrorCode.FAIL_CREATE_CONF, "포트포워딩 Conf 파일을 작성하지 못했습니다");
+        }
+
+        /* nginx test */
+        String url = "http://nginx:8081/nginx-api/test";
+        try {
+            restTemplate.getForEntity(url, String.class);
+        } catch (HttpServerErrorException.InternalServerError e) {
+            log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
+            if (file.delete()) {
+                throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)");
+            }
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
+        } catch (Exception e) {
+            log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage());
+            if (file.delete()) {
+                throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)");
+            }
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
+        }
+
+        /* nginx reload */
+        url = "http://nginx:8081/nginx-api/reload";
+        try {
+            restTemplate.getForEntity(url, String.class);
+        } catch (HttpServerErrorException.InternalServerError e) {
+            log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
+            if (file.delete()) {
+                throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)");
+            }
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
+        } catch (Exception e) {
+            log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage());
+            if (file.delete()) {
+                throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)");
+            }
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
+        }
+
+    }
+
+    /* Routing 수정 */
+    public void editRouting(Long routingId, RoutingDTO dto) {
+        Routing routing = routingRepository.findByRoutingIdAndIsDeleted(routingId, false)
+                .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_ROUTING));
+
+        /* 입력 DTO 검증 */
+        validateDTO(dto);
+
+        /* 중복 검증 */
+        if (dto.getDomain() != null && routingRepository.existsByDomainAndIsDeleted(dto.getDomain(), false)) {
+            throw new CustomException(ErrorCode.DUPLICATED_DOMAIN_NAME);
+        }
+
+        /* SSL 인증서 조회 */
+        Certificate certificate = (dto.getCertificateId() == null) || (dto.getCertificateId() == -1 ) ? null :
+                certificateRepository.findById(dto.getCertificateId())
+                        .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_CERTIFICATE)); // isDeleted 확인 필요
+
+        /* 파일 수정 */
+        routing.edit(dto, certificate);
+        String content = routingTemplate.getRouting(routing.toRoutingDTO(), certificate == null ? null : certificate.formatDomain());
+        String confPath = "/data/nginx/proxy_host/" + routing.getRoutingId() + ".conf";
+        File file = new File(confPath);
+        if (!file.exists()) {
+            throw new CustomException(ErrorCode.NOT_FOUND_FORWARDING, "Conf 파일이 존재하지 않아 수정할 수 없습니다");
+        }
+
+        Path backup;
+        try {
+            backup = Files.createTempFile("temp_", ".tmp");
+            Files.copy(Paths.get(confPath), backup, StandardCopyOption.REPLACE_EXISTING
+                    , StandardCopyOption.COPY_ATTRIBUTES);
+
+            BufferedWriter bw = new BufferedWriter(new FileWriter(file, false));
+            bw.write(content);
+            bw.flush();
+            bw.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "라우팅 Conf 파일을 수정하지 못했습니다");
+        }
+
+        /* nginx test */
+        String url = "http://nginx:8081/nginx-api/test";
+        try {
+            restTemplate.getForEntity(url, String.class);
+        } catch (HttpServerErrorException.InternalServerError e) {
+            log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
+            try {
+                Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING
+                        , StandardCopyOption.COPY_ATTRIBUTES);
+                Files.delete(backup);
+            } catch (IOException e1) {
+                throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(라우팅 Conf 파일 수정)");
+            }
+
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
+        } catch (RuntimeException e) {
+            log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage());
+            try {
+                Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING
+                        , StandardCopyOption.COPY_ATTRIBUTES);
+                Files.delete(backup);
+            } catch (IOException e1) {
+                throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(라우팅 Conf 파일 수정)");
+            }
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
+        }
+
+        /* nginx reload */
+        url = "http://nginx:8081/nginx-api/reload";
+        try {
+            restTemplate.getForEntity(url, String.class);
+        } catch (HttpServerErrorException.InternalServerError e) {
+            log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
+            try {
+                Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING
+                        , StandardCopyOption.COPY_ATTRIBUTES);
+                Files.delete(backup);
+            } catch (IOException e1) {
+                throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(라우팅 Conf 파일 수정)");
+            }
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
+        } catch (RuntimeException e) {
+            log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage());
+            try {
+                Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING
+                        , StandardCopyOption.COPY_ATTRIBUTES);
+                Files.delete(backup);
+            } catch (IOException e1) {
+                throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(라우팅 Conf 파일 수정)");
+            }
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
+        }
+
+        /* DB 정보 수정 */
+        routingRepository.save(routing);
+    }
+
+    /* Routing 삭제 */
+    public void deleteRouting(Long routingId) {
+        Routing routing = routingRepository.findByRoutingIdAndIsDeleted(routingId, false)
+                .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_ROUTING));
+
+        /* 파일 삭제 */
+        String confPath = "/data/nginx/proxy_host/" + routing.getRoutingId() + ".conf";
+        String deletePath = confPath + ".deleted";
+        try {
+            Files.move(Paths.get(confPath), Paths.get(deletePath));
+        } catch (IOException e) {
+            throw new CustomException(ErrorCode.FAIL_DELETE_CONF);
+        }
+
+        /* nginx test */
+        String url = "http://nginx:8081/nginx-api/test";
+        try {
+            restTemplate.getForEntity(url, String.class);
+        } catch (HttpServerErrorException.InternalServerError e) {
+            log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
+            try {
+                Files.move(Paths.get(deletePath), Paths.get(confPath));
+            } catch (IOException e1) {
+                throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(라우팅 Conf 삭제)");
+            }
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
+        } catch (Exception e) {
+            log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage());
+            try {
+                Files.move(Paths.get(deletePath), Paths.get(confPath));
+            } catch (IOException e1) {
+                throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(라우팅 Conf 삭제)");
+            }
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
+        }
+
+        /* nginx reload */
+        url = "http://nginx:8081/nginx-api/reload";
+        try {
+            restTemplate.getForEntity(url, String.class);
+        } catch (HttpServerErrorException.InternalServerError e) {
+            log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
+            try {
+                Files.move(Paths.get(deletePath), Paths.get(confPath));
+            } catch (IOException e1) {
+                throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(라우팅 Conf 삭제)");
+            }
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
+        } catch (Exception e) {
+            log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage());
+            try {
+                Files.move(Paths.get(deletePath), Paths.get(confPath));
+            } catch (IOException e1) {
+                throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(라우팅 Conf 삭제)");
+            }
+            throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
+        }
+
+        /* DB */
+        routing.delete();
+        routingRepository.save(routing);
+    }
+
+    private void validateDTO(RoutingDTO dto) {
+
+        for (ConstraintViolation<RoutingDTO> violation : Validation.buildDefaultValidatorFactory().getValidator().validate(dto)) {
+            throw new CustomException(ErrorCode.INVALID_CONF_INPUT, violation.getMessage());
+        }
+
+    }
+}
diff --git a/src/main/java/com/aolda/itda/template/OptionTemplate.java b/src/main/java/com/aolda/itda/template/OptionTemplate.java
index 3e1e92c77efaf1eebec1af4cc1b283255c501a0e..945b66609b565f62bb380e61e29952ea0e9cad9e 100644
--- a/src/main/java/com/aolda/itda/template/OptionTemplate.java
+++ b/src/main/java/com/aolda/itda/template/OptionTemplate.java
@@ -5,22 +5,22 @@ import org.springframework.stereotype.Component;
 @Component
 public class OptionTemplate {
 
-    public String getSSL(Long certificateId) {
+    public String getSSL(String certificateDomain) {
         return "\nconf.d/include/letsencrypt-acme-challenge.conf;\n" +
                 "include conf.d/include/ssl-ciphers.conf;\n" +
-                "ssl_certificate /etc/letsencrypt/live/npm-" + certificateId + "/fullchain.pem;\n" +
-                "ssl_certificate_key /etc/letsencrypt/live/npm-" + certificateId + "/privkey.pem;\n";
+                "ssl_certificate /data/lego/certificates/" + certificateDomain + ".crt;\n" +
+                "ssl_certificate_key /data/lego/certificates/" + certificateDomain + ".key;\n";
     }
 
     public String getAssetCaching() {
-        return "include conf.d/include/assets.conf;\n";
+        return "\ninclude conf.d/include/assets.conf;\n";
     }
 
     public String getBlockExploits() {
-        return "include conf.d/include/block-exploits.conf;\n";
+        return "\ninclude conf.d/include/block-exploits.conf;\n";
     }
 
     public String getForceSSL() {
-        return "include conf.d/include/force-ssl.conf;\n";
+        return "\ninclude conf.d/include/force-ssl.conf;\n";
     }
 }
diff --git a/src/main/java/com/aolda/itda/template/RoutingTemplate.java b/src/main/java/com/aolda/itda/template/RoutingTemplate.java
new file mode 100644
index 0000000000000000000000000000000000000000..46e6116ce6b1b9f6840a60cc9bd85d0fc8e8dde6
--- /dev/null
+++ b/src/main/java/com/aolda/itda/template/RoutingTemplate.java
@@ -0,0 +1,44 @@
+package com.aolda.itda.template;
+
+import com.aolda.itda.dto.routing.RoutingDTO;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class RoutingTemplate {
+
+    private final OptionTemplate optionTemplate;
+
+    public String getRouting(RoutingDTO dto, String certificateDomain) {
+        return "server { \n"
+                + "set $forward_scheme http;\n"
+                + "set $server \"" + dto.getIp() +"\";\n"
+                + "set $port "+ dto.getPort() +";\n"
+                + "\n"
+                + "listen 80;\n"
+                + "listen [::]:80;\n"
+                + (dto.getCertificateId() == -1 ? "" :
+                "listen 443 ssl;\n listen [::]:443 ssl;\n")
+                + "server_name " + dto.getDomain() + ";\n"
+                + (dto.getCertificateId() == -1 ? "" :
+                optionTemplate.getSSL(certificateDomain))
+                + (dto.getCaching() ? "" :
+                optionTemplate.getAssetCaching()
+        )
+                + "proxy_set_header Upgrade $http_upgrade;\n"
+                + "proxy_set_header Connection $http_connection;\n"
+                + "proxy_http_version 1.1;\n"
+                + "\n"
+                + "access_log /data/logs/proxy-host-" + dto.getId() + "_access.log proxy;\n"
+                + "error_log /data/logs/proxy-host-" + dto.getId() + "_error.log warn;\n"
+                + "location / { \n"
+                + "proxy_set_header Upgrade $http_upgrade;\n"
+                + "proxy_set_header Connection $http_connection;\n"
+                + "proxy_http_version 1.1;\n"
+                + "include conf.d/include/proxy.conf;\n"
+                + "}\n"
+                + "}\n";
+    }
+
+}