diff --git a/src/pages/routing/Create.tsx b/src/pages/routing/Create.tsx
index afadf5dddf0a3aadf7c1403a8c260c19a2200296..8011001f83f1625cf6c1e32d25072edfe61000fc 100644
--- a/src/pages/routing/Create.tsx
+++ b/src/pages/routing/Create.tsx
@@ -103,8 +103,13 @@ export default function RoutingCreate() {
     });
 
     if (!response.ok) {
-      console.error(response);
-      toast.error('라우팅 설정을 등록할 수 없습니다');
+      const { code } = await response.json();
+      if (code == 'DUPLICATED_DOMAIN_NAME') {
+        form.setError('domain', { type: 'custom', message: '이미 사용중인 도메인입니다' });
+        toast.error('이미 사용중인 도메인입니다');
+      } else {
+        toast.error('라우팅 설정을 등록할 수 없습니다');
+      }
     } else {
       toast.success('라우팅 설정을 등록합니다');
       navigate('/routing');
diff --git a/src/pages/routing/Edit.tsx b/src/pages/routing/Edit.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6a40926efb01c373ac5d727843d7b638c280af72
--- /dev/null
+++ b/src/pages/routing/Edit.tsx
@@ -0,0 +1,351 @@
+import { useEffect, useRef, useState } from 'react';
+import { Link, useNavigate, useParams } from 'react-router';
+import { useForm, useWatch } from 'react-hook-form';
+import { Check, X } from 'lucide-react';
+import { z } from 'zod';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { toast } from 'sonner';
+import { Button } from '@/components/ui/button';
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
+import { Input } from '@/components/ui/input';
+import { Switch } from '@/components/ui/switch';
+import { Separator } from '@/components/ui/separator';
+import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
+import { Skeleton } from '@/components/ui/skeleton';
+import {
+  Select,
+  SelectContent,
+  SelectGroup,
+  SelectItem,
+  SelectLabel,
+  SelectTrigger,
+  SelectValue,
+} from '@/components/ui/select';
+import { Certificate } from '@/types/certificate';
+import { useAuthStore } from '@/stores/authStore';
+import useDebounce from '@/hooks/useDebounce';
+
+const formSchema = z
+  .object({
+    name: z.string({ required_error: '서버 이름을 입력해주세요' }).min(1, { message: '서버 이름을 입력해주세요' }),
+    domain: z
+      .string({ required_error: '도메인 주소를 입력해주세요' })
+      .regex(/^(?=.{1,253}$)(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/, {
+        message: '올바른 도메인 주소를 입력해주세요',
+      }),
+    ip: z
+      .string({ required_error: '인스턴스 IP를 입력해주세요' })
+      .regex(/^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/, {
+        message: '올바른 IP 주소를 입력해주세요',
+      })
+      .startsWith('10.16.', { message: '인스턴스 IP는 10.16.0.0/16 대역을 사용해야 합니다' }),
+    port: z.coerce
+      .number({ invalid_type_error: '포트 번호를 입력해주세요' })
+      .min(1, { message: '포트 번호를 입력해주세요' })
+      .max(65535, { message: '올바른 포트 번호를 입력해주세요' }),
+    enableSSL: z.boolean(),
+    certificateId: z.coerce.number().optional(),
+    caching: z.boolean(),
+  })
+  .refine((data) => !data.enableSSL || (data.enableSSL && data.certificateId !== undefined), {
+    message: 'SSL 인증서를 선택해주세요',
+    path: ['certificateId'],
+  });
+
+export default function RoutingEdit() {
+  const navigate = useNavigate();
+  const { id } = useParams();
+  const { authFetch, selectedProject } = useAuthStore();
+  const form = useForm<z.infer<typeof formSchema>>({
+    resolver: zodResolver(formSchema),
+    defaultValues: {
+      name: undefined,
+      domain: undefined,
+      ip: undefined,
+      port: undefined,
+      enableSSL: false,
+      certificateId: undefined,
+      caching: false,
+    },
+  });
+  const domain = useWatch({ control: form.control, name: 'domain' });
+  const enableSSL = useWatch({ control: form.control, name: 'enableSSL' });
+  const debouncedDomain = useDebounce(domain, 500);
+  const [certificates, setCertificates] = useState<Certificate[]>([]);
+  const initData = useRef<z.infer<typeof formSchema> | null>(null);
+  const [isLoading, setIsLoading] = useState(true);
+
+  useEffect(() => {
+    authFetch(`/api/routing?routingId=${id}`)
+      .then((response) => {
+        if (!response.ok) {
+          console.error(response);
+          throw Error();
+        }
+
+        return response.json();
+      })
+      .then(({ name, domain, ip, port, certificateId, caching }) => {
+        initData.current = {
+          name,
+          domain,
+          ip,
+          port: parseInt(port),
+          enableSSL: certificateId ? true : false,
+          certificateId: certificateId || -1,
+          caching,
+        };
+
+        form.setValue('name', initData.current.name);
+        form.setValue('domain', initData.current.domain);
+        form.setValue('ip', initData.current.ip);
+        form.setValue('port', initData.current.port);
+        form.setValue('enableSSL', initData.current.enableSSL);
+        form.setValue('certificateId', initData.current.certificateId);
+        form.setValue('caching', initData.current.caching);
+
+        setIsLoading(false);
+      })
+      .catch((error) => {
+        console.error(error);
+        toast.error('라우팅 설정 정보를 조회할 수 없습니다.');
+      });
+  }, []);
+
+  useEffect(() => {
+    if (enableSSL) {
+      authFetch(`/api/certificates?projectId=${selectedProject?.id}&domain=${debouncedDomain}`)
+        .then((response) => {
+          if (!response.ok) {
+            toast.error('SSL 인증서 목록을 불러올 수 없습니다');
+            return { contents: [] };
+          }
+          return response.json();
+        })
+        .then(({ contents }) => {
+          setCertificates(contents);
+        });
+    }
+  }, [authFetch, enableSSL, selectedProject, debouncedDomain]);
+
+  async function onSubmit(values: z.infer<typeof formSchema>) {
+    if (!initData.current) return;
+
+    const payload: Partial<z.infer<typeof formSchema>> = {};
+    if (values.name !== initData.current.name) payload.name = values.name;
+    if (values.domain !== initData.current.domain) payload.domain = values.domain;
+    if (values.ip !== initData.current.ip) payload.ip = values.ip;
+    if (values.port !== initData.current.port) payload.port = values.port;
+    if (values.caching !== initData.current.caching) payload.caching = values.caching;
+    if (!values.enableSSL && values.enableSSL !== initData.current.enableSSL) payload.certificateId = -1;
+    if (values.enableSSL && values.certificateId !== initData.current.certificateId)
+      payload.certificateId = values.certificateId;
+
+    const response = await authFetch(`/api/routing?routingId=${id}`, {
+      method: 'PATCH',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(payload),
+    });
+
+    if (!response.ok) {
+      const { code } = await response.json();
+      if (code == 'DUPLICATED_DOMAIN_NAME') {
+        form.setError('domain', { type: 'custom' });
+        toast.error('이미 사용중인 도메인입니다');
+      } else {
+        toast.error('라우팅 설정 수정에 실패하였습니다');
+      }
+    } else {
+      toast.success('라우팅 설정이 수정되었습니다');
+      navigate('/routing');
+    }
+  }
+
+  return (
+    <div className="flex flex-1 flex-col gap-4 p-6">
+      <div className="mb-2">
+        <h1 className="scroll-m-20 text-3xl font-semibold first:mt-0">라우팅 설정 수정</h1>
+        <p className="mt-1 text-base text-gray-500">웹 프록시 서버의 기존 라우팅 설정을 수정합니다.</p>
+      </div>
+
+      <Form {...form}>
+        <form onSubmit={form.handleSubmit(onSubmit)}>
+          <Card className="mb-4">
+            <CardHeader>
+              <CardTitle className="text-xl">라우팅 기본 설정</CardTitle>
+            </CardHeader>
+            <CardContent className="space-y-4">
+              {isLoading ? (
+                <Skeleton className="h-[24rem] w-full" />
+              ) : (
+                <div className="grid grid-cols-1 gap-4">
+                  <FormField
+                    control={form.control}
+                    name="name"
+                    render={({ field }) => (
+                      <FormItem>
+                        <FormLabel required>서버 이름</FormLabel>
+                        <FormControl>
+                          <Input placeholder="웹 서버 이름" {...field} />
+                        </FormControl>
+                        <FormMessage />
+                      </FormItem>
+                    )}
+                  />
+
+                  <FormField
+                    control={form.control}
+                    name="domain"
+                    render={({ field }) => (
+                      <FormItem>
+                        <FormLabel required>도메인</FormLabel>
+                        <FormControl>
+                          <Input placeholder="example.ajou.app" {...field} />
+                        </FormControl>
+                        <FormDescription>
+                          *.ajou.app 도메인은 별도 설정 없이 자유롭게 사용할 수 있습니다
+                        </FormDescription>
+                        <FormMessage />
+                      </FormItem>
+                    )}
+                  />
+
+                  <FormField
+                    control={form.control}
+                    name="ip"
+                    render={({ field }) => (
+                      <FormItem>
+                        <FormLabel required>인스턴스 IP</FormLabel>
+                        <FormControl>
+                          <Input placeholder="10.16.x.x" {...field} />
+                        </FormControl>
+                        <FormDescription>인스턴스 IP는 10.16.0.0/16 대역을 사용합니다</FormDescription>
+                        <FormMessage />
+                      </FormItem>
+                    )}
+                  />
+
+                  <FormField
+                    control={form.control}
+                    name="port"
+                    render={({ field }) => (
+                      <FormItem>
+                        <FormLabel required>인스턴스 포트</FormLabel>
+                        <FormControl>
+                          <Input type="number" placeholder="8080" {...field} />
+                        </FormControl>
+                        <FormDescription>연결할 웹 서비스의 포트 번호를 입력해주세요</FormDescription>
+                        <FormMessage />
+                      </FormItem>
+                    )}
+                  />
+                </div>
+              )}
+            </CardContent>
+          </Card>
+
+          <Card className="mb-6">
+            <CardHeader>
+              <CardTitle className="text-xl">추가 설정</CardTitle>
+            </CardHeader>
+            <CardContent className="space-y-4">
+              {isLoading ? (
+                <Skeleton className="h-[8rem] w-full" />
+              ) : (
+                <>
+                  <FormField
+                    control={form.control}
+                    name="enableSSL"
+                    render={({ field }) => (
+                      <FormItem className="flex flex-row items-center justify-between">
+                        <div className="space-y-0.5">
+                          <FormLabel className="text-base font-medium">SSL 보안 연결</FormLabel>
+                          <FormDescription className="text-sm text-gray-500">
+                            HTTPS 프로토콜을 사용하여 보안 연결을 활성화합니다
+                          </FormDescription>
+                        </div>
+                        <FormControl>
+                          <div className="flex items-center space-x-2">
+                            {!field.value && <X className="h-4 w-4 text-gray-500" />}
+                            {field.value && <Check className="h-4 w-4" />}
+                            <Switch checked={field.value} onCheckedChange={field.onChange} />
+                          </div>
+                        </FormControl>
+                      </FormItem>
+                    )}
+                  />
+
+                  {form.watch('enableSSL') && (
+                    <FormField
+                      control={form.control}
+                      name="certificateId"
+                      render={({ field }) => (
+                        <FormItem>
+                          <Select onValueChange={field.onChange}>
+                            <FormControl>
+                              <SelectTrigger className="w-full">
+                                <SelectValue placeholder="SSL 인증서 선택" />
+                              </SelectTrigger>
+                            </FormControl>
+                            <SelectContent>
+                              <SelectGroup>
+                                {certificates.length === 0 ? (
+                                  <SelectLabel className="text-muted-foreground">
+                                    사용 가능한 SSL 인증서가 없습니다. &nbsp;
+                                    <Link to="/certificate/create" className="font-medium underline underline-offset-4">
+                                      추가하기
+                                    </Link>
+                                  </SelectLabel>
+                                ) : (
+                                  certificates.map((certificate) => (
+                                    <SelectItem value={certificate.id.toString()}>{certificate.domain}</SelectItem>
+                                  ))
+                                )}
+                              </SelectGroup>
+                            </SelectContent>
+                          </Select>
+                          <FormMessage />
+                        </FormItem>
+                      )}
+                    />
+                  )}
+
+                  <Separator />
+
+                  <FormField
+                    control={form.control}
+                    name="caching"
+                    render={({ field }) => (
+                      <FormItem className="flex flex-row items-center justify-between">
+                        <div className="space-y-0.5">
+                          <FormLabel className="text-base font-medium">정적 파일 캐싱 활성화</FormLabel>
+                          <FormDescription className="text-sm text-gray-500">
+                            빠른 응답을 위해 정적 파일에 대한 캐싱을 활성화합니다
+                          </FormDescription>
+                        </div>
+                        <FormControl>
+                          <div className="flex items-center space-x-2">
+                            {!field.value && <X className="h-4 w-4 text-gray-500" />}
+                            {field.value && <Check className="h-4 w-4" />}
+                            <Switch checked={field.value} onCheckedChange={field.onChange} />
+                          </div>
+                        </FormControl>
+                      </FormItem>
+                    )}
+                  />
+                </>
+              )}
+            </CardContent>
+          </Card>
+
+          <div className="flex justify-end gap-2">
+            <Button variant="outline" asChild>
+              <Link to="..">취소</Link>
+            </Button>
+            <Button type="submit">저장</Button>
+          </div>
+        </form>
+      </Form>
+    </div>
+  );
+}
diff --git a/src/routes.tsx b/src/routes.tsx
index 22bf2419cc730017b230de187ccaf13b6e39721c..1880f94bc398cf3355a267f991457a9419d9acc0 100644
--- a/src/routes.tsx
+++ b/src/routes.tsx
@@ -5,6 +5,7 @@ import Home from '@/pages/Home';
 import Login from '@/pages/Login';
 import RoutingList from '@/pages/routing/List';
 import RoutingCreate from '@/pages/routing/Create';
+import RoutingEdit from '@/pages/routing/Edit';
 import CertificateList from './pages/certificate/List';
 import CertificateCreate from './pages/certificate/Create';
 import ForwardingList from '@/pages/forwarding/List';
@@ -20,6 +21,7 @@ export default function AppRoutes() {
         <Route path="routing">
           <Route index element={<RoutingList />} />
           <Route path="create" element={<RoutingCreate />} />
+          <Route path="edit/:id" element={<RoutingEdit />} />
         </Route>
         <Route path="certificate">
           <Route index element={<CertificateList />} />