Răsfoiți Sursa

게시판 데이터 연동

송용우 2 luni în urmă
părinte
comite
6cfc0067c1

+ 18 - 0
.htaccess

@@ -9,6 +9,24 @@ RewriteEngine On
 RewriteCond %{REQUEST_METHOD} OPTIONS
 RewriteRule ^(.*)$ $1 [R=200,L]
 
+# Board routing - FAQ
+RewriteRule ^board_list/faq$ backend/index.php?/board_list/faq [L,QSA]
+
+# Board routing - Media (News, Press)
+RewriteRule ^board_list/media$ backend/index.php?/board_list/media [L,QSA]
+
+# Board routing - Media SNS
+RewriteRule ^board_list/media_sns$ backend/index.php?/board_list/media_sns [L,QSA]
+
+# Board routing - Technology (Patents)
+RewriteRule ^board_list/technology1$ backend/index.php?/board_list/technology1 [L,QSA]
+RewriteRule ^board_list/technology2$ backend/index.php?/board_list/technology2 [L,QSA]
+RewriteRule ^board_list/technology3$ backend/index.php?/board_list/technology3 [L,QSA]
+RewriteRule ^board_list/technology4$ backend/index.php?/board_list/technology4 [L,QSA]
+
+# Backend upload 이미지 접근 허용
+RewriteRule ^backend/upload/(.*)$ backend/upload/$1 [L]
+
 # /api/ 경로는 CodeIgniter로 라우팅
 RewriteCond %{REQUEST_URI} ^/api/(.*)$
 RewriteRule ^api/(.*)$ /api/index.php/$1 [L,QSA]

+ 1 - 1
app/composables/useApi.ts

@@ -17,7 +17,7 @@ const createApiClient = () => {
   // 요청 인터셉터
   client.interceptors.request.use(
     (config) => {
-      console.log('API Request:', config.method?.toUpperCase(), config.url)
+      //console.log('API Request:', config.method?.toUpperCase(), config.url)
       return config
     },
     (error) => {

+ 108 - 42
app/pages/contact/faq.vue

@@ -14,6 +14,7 @@
   </main>
 </template>
 <script setup>
+  import { ref, onMounted } from "vue";
   import TopVisual from "~/components/topVisual.vue";
 
   const className = ref("contact");
@@ -42,46 +43,111 @@
     },
   ]);
 
-  const faqContent = ref([
-    {
-      label: "바이오 플라스틱은 어떤 종류가 있어요?",
-      content:
-        "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
-    },
-    {
-      label: "생분해성 플라스틱이란 무엇인가요?",
-      content:
-        "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
-    },
-    {
-      label: "생분해성 플라스틱이 정말 친환경적인가요?",
-      content:
-        "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
-    },
-    {
-      label: "제품마다 생분해 되는 시간이 다른가요?",
-      content:
-        "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
-    },
-    {
-      label: "그린웨일글로벌 플라스틱은 어떻게 다르나요?",
-      content:
-        "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
-    },
-    {
-      label: "카사바란 무엇인가요?",
-      content:
-        "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
-    },
-    {
-      label: "정말 생분해되는지 어떻게 알 수 있나요?",
-      content:
-        "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
-    },
-    {
-      label: "물에 젖거나 가열하면 부패하나요?",
-      content:
-        "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
-    },
-  ]);
+  const loading = ref(true);
+  const faqContent = ref([]);
+
+  // HTML 태그 제거 함수
+  const stripHtmlTags = (html) => {
+    if (!html) return "";
+    const doc = new DOMParser().parseFromString(html, "text/html");
+    return doc.body.textContent || "";
+  };
+
+  // API에서 FAQ 데이터 가져오기
+  const fetchFaqList = async () => {
+    try {
+      loading.value = true;
+
+      // 공지사항과 동일한 방식으로 호출
+      const response = await $get(`/board_list/faq`, {
+        page: 1,
+        searchKind: "",
+        searchKeyword: "",
+      });
+
+      // 백엔드가 JSON으로 응답하는지 확인
+      if (response && typeof response === "object") {
+        // JSON 응답인 경우
+        if (response.success && response.list) {
+          // console.log("받은 FAQ 데이터:", response.list);
+          faqContent.value = response.list.map((item) => ({
+            label: item.title,
+            content: stripHtmlTags(item.contents),
+          }));
+          // console.log("변환된 FAQ 콘텐츠:", faqContent.value);
+        } else {
+          console.error("JSON 응답 형식이 올바르지 않습니다:", response);
+          // 기본 더미 데이터 사용
+          setDefaultFaqData();
+        }
+      } else if (typeof response === "string") {
+        // HTML 응답인 경우 (백엔드에서 AJAX 감지 실패시)
+        console.warn("HTML 응답을 받았습니다. AJAX 감지가 실패했을 수 있습니다.");
+        console.log("HTML 내용:", response.substring(0, 200) + "...");
+        // 기본 더미 데이터 사용
+        setDefaultFaqData();
+      } else {
+        console.error("예상하지 못한 응답 형식:", typeof response, response);
+        // 기본 더미 데이터 사용
+        setDefaultFaqData();
+      }
+    } catch (error) {
+      console.error("FAQ 데이터 로드 실패:", error);
+      // 에러시 기본 더미 데이터 사용
+      setDefaultFaqData();
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  // 기본 더미 데이터 설정
+  const setDefaultFaqData = () => {
+    faqContent.value = [
+      {
+        label: "바이오 플라스틱은 어떤 종류가 있어요?",
+        content:
+          "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
+      },
+      {
+        label: "생분해성 플라스틱이란 무엇인가요?",
+        content:
+          "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
+      },
+      {
+        label: "생분해성 플라스틱이 정말 친환경적인가요?",
+        content:
+          "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
+      },
+      {
+        label: "제품마다 생분해 되는 시간이 다른가요?",
+        content:
+          "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
+      },
+      {
+        label: "그린웨일글로벌 플라스틱은 어떻게 다르나요?",
+        content:
+          "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
+      },
+      {
+        label: "카사바란 무엇인가요?",
+        content:
+          "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
+      },
+      {
+        label: "정말 생분해되는지 어떻게 알 수 있나요?",
+        content:
+          "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
+      },
+      {
+        label: "물에 젖거나 가열하면 부패하나요?",
+        content:
+          "바이오플라스틱은 크게 생분해성 플라스틱(Biodegradable plastic), 바이오 베이스 플라스틱(Bio-based plastic), 그리고 산화생분해 플라스틱(Oxo-biodegradable plastic)으로 나뉩니다. 단 이 중 산화생분해 플라스틱은 최근에 마이크로플라스틱으로 분산될 뿐, 분해되지 않는다고 결론지어 친환경 플라스틱 종류에서 제외되었습니다.",
+      },
+    ];
+  };
+
+  // 컴포넌트 마운트 시 데이터 로드
+  onMounted(() => {
+    fetchFaqList();
+  });
 </script>

+ 67 - 179
app/pages/contact/notice.vue

@@ -16,7 +16,7 @@
             <NuxtLink
               v-for="news in paginatedNews"
               :key="news.id"
-              to="/contact/noticeView"
+              :to="news.link"
               class="notice"
             >
               <span class="news--index">{{ news.id }}</span>
@@ -52,10 +52,13 @@
   </main>
 </template>
 <script setup>
+  import { ref, computed, onMounted } from "vue";
   import TopVisual from "~/components/topVisual.vue";
+
   const searchItems = ref(["제목"]);
   const searchValue = ref("선택");
   const searchKeyword = ref("");
+  const loading = ref(true);
 
   const className = ref("contact");
   const title = ref("Contact");
@@ -83,184 +86,61 @@
     },
   ]);
 
-  // 뉴스 데이터 배열 생성
-  const newsData = ref([
-    {
-      id: 1,
-      title: "그린플라스틱연합, ESG친환경대전서 '자원순환 탄소중립 GPA 컨퍼런스' 개최",
-      date: "2025.07.11",
-      image: "/img/img--news.png",
-      link: "/",
-    },
-    {
-      id: 2,
-      title: "친환경 플라스틱 기술 개발 동향",
-      date: "2025.07.10",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 3,
-      title: "탄소중립 실현을 위한 플라스틱 재활용 기술",
-      date: "2025.07.09",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 4,
-      title: "바이오플라스틱 시장 전망과 기술 동향",
-      date: "2025.07.08",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 5,
-      title: "플라스틱 감축을 위한 정부 정책 변화",
-      date: "2025.07.07",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 6,
-      title: "순환경제와 플라스틱 재활용 산업",
-      date: "2025.07.06",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 7,
-      title: "해양 플라스틱 오염 해결을 위한 혁신 기술",
-      date: "2025.07.05",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 8,
-      title: "친환경 포장재 개발 현황",
-      date: "2025.07.04",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 9,
-      title: "플라스틱 대체재 소재 연구 동향",
-      date: "2025.07.03",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 10,
-      title: "ESG 경영과 플라스틱 감축 전략",
-      date: "2025.07.02",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 11,
-      title: "글로벌 플라스틱 규제 동향",
-      date: "2025.07.01",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 12,
-      title: "생분해성 플라스틱 상용화 전망",
-      date: "2025.06.30",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 13,
-      title: "플라스틱 없는 일주일 캠페인",
-      date: "2025.06.29",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 14,
-      title: "재활용 플라스틱 품질 향상 기술",
-      date: "2025.06.28",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 15,
-      title: "플라스틱 순환경제 구축 방안",
-      date: "2025.06.27",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 16,
-      title: "친환경 소재 개발 투자 확대",
-      date: "2025.06.26",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 17,
-      title: "마이크로플라스틱 저감 기술",
-      date: "2025.06.25",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 18,
-      title: "플라스틱 재활용률 제고 방안",
-      date: "2025.06.24",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 19,
-      title: "바이오매스 기반 플라스틱 개발",
-      date: "2025.06.23",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 20,
-      title: "환경친화적 플라스틱 산업 전망",
-      date: "2025.06.22",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 21,
-      title: "플라스틱 폐기물 감축 정책",
-      date: "2025.06.21",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 22,
-      title: "지속가능한 포장재 솔루션",
-      date: "2025.06.20",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 23,
-      title: "플라스틱 리사이클링 혁신 기술",
-      date: "2025.06.19",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 24,
-      title: "친환경 플라스틱 인증 시스템",
-      date: "2025.06.18",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 25,
-      title: "탄소 발자국 감축을 위한 플라스틱 대안",
-      date: "2025.06.17",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-  ]);
+  // 뉴스 데이터 배열 - API에서 받아올 것
+  const newsData = ref([]);
+
+  // API에서 공지사항 데이터 가져오기
+  const fetchNoticeList = async (page = 1) => {
+    try {
+      loading.value = true;
+
+      // CodeIgniter 방식으로 호출 (/controller/method/param)
+      const response = await $get(`/board_list/notice`, {
+        page: page,
+        searchKind: searchValue.value,
+        searchKeyword: searchKeyword.value,
+      });
+
+      // 백엔드가 JSON으로 응답하는지 확인
+      if (response && typeof response === "object") {
+        // JSON 응답인 경우
+        if (response.success && response.list) {
+          // 전체 개수와 현재 페이지를 기준으로 번호 계산
+          const totalCount = response.totalCount || 0;
+          const currentPageNum = page || 1;
+          const pageSize = 20; // 백엔드의 페이지 사이즈와 동일
+
+          newsData.value = response.list.map((item, index) => {
+            // 번호 = 전체개수 - ((현재페이지-1) * 페이지크기 + 인덱스)
+            const displayNumber = totalCount - ((currentPageNum - 1) * pageSize + index);
+
+            return {
+              id: displayNumber, // 순차적인 번호로 표시
+              title: item.title,
+              date: item.regdate,
+              link: `/contact/noticeView?idx=${item.board_idx}`, // 실제 링크는 board_idx 사용
+            };
+          });
+        } else {
+          console.error("JSON 응답 형식이 올바르지 않습니다:", response);
+          newsData.value = [];
+        }
+      } else if (typeof response === "string") {
+        // HTML 응답인 경우 (백엔드에서 AJAX 감지 실패시)
+        console.warn("HTML 응답을 받았습니다. AJAX 감지가 실패했을 수 있습니다.");
+        console.log("HTML 내용:", response.substring(0, 200) + "...");
+        newsData.value = [];
+      } else {
+        console.error("예상하지 못한 응답 형식:", typeof response, response);
+        newsData.value = [];
+      }
+    } catch (error) {
+      console.error("공지사항 데이터 로드 실패:", error);
+      // 에러시 기본 더미 데이터 사용
+    } finally {
+      loading.value = false;
+    }
+  };
 
   // 페이지네이션 로직
   const currentPage = ref(1);
@@ -276,18 +156,26 @@
   const goToPage = (page) => {
     if (page >= 1 && page <= totalPages.value) {
       currentPage.value = page;
+      fetchNoticeList(page);
     }
   };
 
   const nextPage = () => {
     if (currentPage.value < totalPages.value) {
       currentPage.value++;
+      fetchNoticeList(currentPage.value);
     }
   };
 
   const prevPage = () => {
     if (currentPage.value > 1) {
       currentPage.value--;
+      fetchNoticeList(currentPage.value);
     }
   };
+
+  // 컴포넌트 마운트 시 데이터 로드
+  onMounted(() => {
+    fetchNoticeList(1);
+  });
 </script>

+ 103 - 20
app/pages/contact/noticeView.vue

@@ -2,50 +2,133 @@
   <main>
     <section class="">
       <div class="sub--container type4">
-        <div class="view--wrap">
+        <div class="view--wrap" v-if="!loading">
           <div class="view--title">
-            <h3>2025년 정기주주총회</h3>
+            <h3>{{ noticeData.title }}</h3>
             <div class="view--info">
-              <p>그린웨일글로벌(주)</p>
+              <p>{{ noticeData.name }}</p>
               <span class="bar"></span>
-              <p>2025-03-17 09:03:14</p>
+              <p>{{ noticeData.regdate }}</p>
               <span class="bar"></span>
-              <p>조회수 : 304</p>
+              <p>조회수 : {{ noticeData.viewcnt }}</p>
             </div>
           </div>
           <div class="view--cont">
-            <p>
-              그린웨일 글로벌 주식회사 (‘www.greenwhaleglobal.com’이하 '그린웨일 글로벌')은(는) 「개인정보 보호법」 제30조에 따라 정부주체의 개인정보를 보호하고 이와 관련한 고충을 신속하고 원활하게 처리할 수 있도록 하기 위하여 다음과 같이 개인정보 처리방침을 수립·공개합니다. <br /><br />
-              이 개인정보처리방침은 2022년 11월 01일부터 적용됩니다. <br /><br />
-              제1조(개인정보의 처리 목적) <br /><br />
-              그린웨일 글로벌은 다음의 목적을 위하여 개인정보를 처리합니다. 처리하고 있는 개인정보는 다음의 목적 이외의 용도로는 이용되지 않으며 이용 목적이 변경되는 경우에는 「개인정보 보호법」 제18조에 따라 별도의 동의를 받는 등 필요한 조치를 이행할 예정입니다. <br /><br />
-              재화 또는 서비스 제공: 맞춤 서비스 제공을 목적으로 개인정보를 처리합니다.
-            </p>
+            <div v-html="noticeData.contents"></div>
           </div>
           <div class="btn--wrap">
             <NuxtLink to="/contact/notice">목록</NuxtLink>
           </div>
           <div class="link--wrap">
-            <NuxtLink to="/" class="link">
-              <p>Preview</p>
-              <h5>2025년 정기주주총회</h5>
-              <span>2025.07.11</span>
+            <NuxtLink v-if="prevData && prevData.board_idx" :to="`/contact/noticeView?idx=${prevData.board_idx}`" class="link">
+              <p>이전글</p>
+              <h5>{{ prevData.title }}</h5>
+              <span>{{ prevData.regdate || '-' }}</span>
             </NuxtLink>
-            <NuxtLink to="/" class="link">
-              <p>Next</p>
-              <h5>2025년 정기주주총회</h5>
-              <span>2025.07.11</span>
+            <div v-if="!prevData || !prevData.board_idx" class="link">
+              <p>이전글</p>
+              <h5>이전글이 없습니다.</h5>
+              <span>-</span>
+            </div>
+            <NuxtLink v-if="nextData && nextData.board_idx" :to="`/contact/noticeView?idx=${nextData.board_idx}`" class="link">
+              <p>다음글</p>
+              <h5>{{ nextData.title }}</h5>
+              <span>{{ nextData.regdate || '-' }}</span>
             </NuxtLink>
+            <div v-if="!nextData || !nextData.board_idx" class="link">
+              <p>다음글</p>
+              <h5>다음글이 없습니다.</h5>
+              <span>-</span>
+            </div>
           </div>
         </div>
+        <div v-else class="loading">
+          <p>로딩 중...</p>
+        </div>
       </div>
     </section>
   </main>
 </template>
 <script setup>
+import { ref, onMounted, onUnmounted, watch } from 'vue'
+
+const route = useRoute()
+const idx = route.query.idx
+
+console.log("현재 라우트:", route)
+console.log("받은 idx:", idx)
+
+const loading = ref(true)
+const noticeData = ref({
+  title: '',
+  name: '',
+  regdate: '',
+  viewcnt: 0,
+  contents: ''
+})
+const nextData = ref(null)
+const prevData = ref(null)
+
 let scrollObserver = null
 
+// 공지사항 상세 데이터 가져오기
+const fetchNoticeDetail = async () => {
+  try {
+    loading.value = true
+    
+    const currentIdx = route.query.idx
+    if (!currentIdx) {
+      throw new Error('게시글 ID가 없습니다.')
+    }
+    
+    // POST 방식으로 파라미터 전달 (수정됨 - 2025-01-17)
+    console.log('POST 요청 전송 중:', {boardId: 'notice', boardIdx: currentIdx})
+    const response = await $postForm('/board_view', {
+      boardId: 'notice', 
+      boardIdx: currentIdx
+    })
+    
+    console.log("받은 상세 데이터:", response)
+    
+    if (response && response.success && response.view) {
+      noticeData.value = {
+        title: response.view.title || '',
+        name: response.view.name || '그린웨일글로벌(주)',
+        regdate: response.view.regdate || '',
+        viewcnt: response.view.viewcnt || 0,
+        contents: response.view.contents || ''
+      }
+      
+      // 이전글/다음글 데이터
+      nextData.value = response.next
+      prevData.value = response.prev
+      
+      console.log("nextData:", nextData.value)
+      console.log("prevData:", prevData.value)
+    } else {
+      throw new Error('게시글을 찾을 수 없습니다.')
+    }
+  } catch (error) {
+    console.error('공지사항 상세 데이터 로드 실패:', error)
+    alert('게시글을 불러올 수 없습니다.')
+    navigateTo('/contact/notice')
+  } finally {
+    loading.value = false
+  }
+}
+
+// URL 파라미터 변경 감지를 위한 watcher 추가
+watch(() => route.query.idx, (newIdx) => {
+  if (newIdx) {
+    fetchNoticeDetail()
+  }
+})
+
 onMounted(() => {
+  // 데이터 로드
+  fetchNoticeDetail()
+  
+  // 헤더 스타일 처리
   const header = document.querySelector('.header--wrap')
   if (header) {
     header.classList.add('white')

+ 99 - 188
app/pages/media/news.vue

@@ -11,10 +11,12 @@
         </div>
         <div class="news--wrap">
           <div class="news--list">
-            <NuxtLink
+            <a
               v-for="news in paginatedNews"
               :key="news.id"
-              :to="news.link"
+              :href="news.link"
+              target="_blank"
+              rel="noopener noreferrer"
               class="news"
             >
               <div class="news--title--wrap">
@@ -24,7 +26,7 @@
               <div class="news--thumb--wrap">
                 <img :src="news.image" alt="" />
               </div>
-            </NuxtLink>
+            </a>
           </div>
           <div class="pagination--wrap">
             <UButton
@@ -54,6 +56,7 @@
   </main>
 </template>
 <script setup>
+  import { ref, computed, onMounted } from "vue";
   import TopVisual from "~/components/topVisual.vue";
 
   const className = ref("media");
@@ -80,189 +83,79 @@
     },
   ]);
 
-  // 뉴스 데이터 배열 생성
-  const newsData = ref([
-    {
-      id: 1,
-      title: "그린플라스틱연합, ESG친환경대전서 '자원순환 탄소중립 GPA 컨퍼런스' 개최",
-      date: "2025.07.11",
-      image: "/img/img--news.png",
-      link: "/",
-    },
-    {
-      id: 2,
-      title: "친환경 플라스틱 기술 개발 동향",
-      date: "2025.07.10",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 3,
-      title: "탄소중립 실현을 위한 플라스틱 재활용 기술",
-      date: "2025.07.09",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 4,
-      title: "바이오플라스틱 시장 전망과 기술 동향",
-      date: "2025.07.08",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 5,
-      title: "플라스틱 감축을 위한 정부 정책 변화",
-      date: "2025.07.07",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 6,
-      title: "순환경제와 플라스틱 재활용 산업",
-      date: "2025.07.06",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 7,
-      title: "해양 플라스틱 오염 해결을 위한 혁신 기술",
-      date: "2025.07.05",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 8,
-      title: "친환경 포장재 개발 현황",
-      date: "2025.07.04",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 9,
-      title: "플라스틱 대체재 소재 연구 동향",
-      date: "2025.07.03",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 10,
-      title: "ESG 경영과 플라스틱 감축 전략",
-      date: "2025.07.02",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 11,
-      title: "글로벌 플라스틱 규제 동향",
-      date: "2025.07.01",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 12,
-      title: "생분해성 플라스틱 상용화 전망",
-      date: "2025.06.30",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 13,
-      title: "플라스틱 없는 일주일 캠페인",
-      date: "2025.06.29",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 14,
-      title: "재활용 플라스틱 품질 향상 기술",
-      date: "2025.06.28",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 15,
-      title: "플라스틱 순환경제 구축 방안",
-      date: "2025.06.27",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 16,
-      title: "친환경 소재 개발 투자 확대",
-      date: "2025.06.26",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 17,
-      title: "마이크로플라스틱 저감 기술",
-      date: "2025.06.25",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 18,
-      title: "플라스틱 재활용률 제고 방안",
-      date: "2025.06.24",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 19,
-      title: "바이오매스 기반 플라스틱 개발",
-      date: "2025.06.23",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 20,
-      title: "환경친화적 플라스틱 산업 전망",
-      date: "2025.06.22",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 21,
-      title: "플라스틱 폐기물 감축 정책",
-      date: "2025.06.21",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 22,
-      title: "지속가능한 포장재 솔루션",
-      date: "2025.06.20",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 23,
-      title: "플라스틱 리사이클링 혁신 기술",
-      date: "2025.06.19",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 24,
-      title: "친환경 플라스틱 인증 시스템",
-      date: "2025.06.18",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 25,
-      title: "탄소 발자국 감축을 위한 플라스틱 대안",
-      date: "2025.06.17",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-  ]);
+  const loading = ref(true);
+  const newsData = ref([]);
+  const totalCount = ref(0);
+
+  // API에서 뉴스 데이터 가져오기
+  const fetchNewsList = async (page = 1) => {
+    try {
+      loading.value = true;
+
+      // 공지사항과 동일한 방식으로 호출
+      const response = await $postForm(`/board_list/media`, {
+        boardId: 'news',
+        page: page,
+        searchKind: "",
+        searchKeyword: "",
+      });
+
+      // 백엔드가 JSON으로 응답하는지 확인
+      if (response && typeof response === "object") {
+        // JSON 응답인 경우
+        if (response.success && response.list) {
+          // 전체 개수와 현재 페이지를 기준으로 번호 계산
+          totalCount.value = response.totalCount || 0;
+          const currentPageNum = page || 1;
+          const pageSize = 20; // 백엔드의 페이지 사이즈와 동일
+
+          console.log("뉴스 API 응답:", {
+            totalCount: totalCount.value,
+            listCount: response.list.length,
+            currentPage: currentPageNum,
+            pageSize
+          });
+
+          newsData.value = response.list.map((item, index) => {
+            // 번호 = 전체개수 - ((현재페이지-1) * 페이지크기 + 인덱스)
+            const displayNumber = totalCount.value - ((currentPageNum - 1) * pageSize + index);
+
+            return {
+              id: displayNumber, // 순차적인 번호로 표시
+              title: item.title,
+              date: item.regdate,
+              image: item.main_file1
+                ? `http://green.interscope.co.kr/backend${item.main_file1}`
+                : "/img/img--cycle--center.png", // 기본 이미지
+              link: item.etc1 || "#", // etc1 필드에 외부 링크 저장
+            };
+          });
+        } else {
+          console.error("JSON 응답 형식이 올바르지 않습니다:", response);
+          // 에러시 기본 더미 데이터 사용
+        }
+      } else if (typeof response === "string") {
+        // HTML 응답인 경우 (백엔드에서 AJAX 감지 실패시)
+        console.warn("HTML 응답을 받았습니다. AJAX 감지가 실패했을 수 있습니다.");
+        console.log("HTML 내용:", response.substring(0, 200) + "...");
+        // 기본 더미 데이터 사용
+      } else {
+        console.error("예상하지 못한 응답 형식:", typeof response, response);
+        // 기본 더미 데이터 사용
+      }
+    } catch (error) {
+      console.error("뉴스 데이터 로드 실패:", error);
+      // 에러시 기본 더미 데이터 사용
+    } finally {
+      loading.value = false;
+    }
+  };
 
   // 페이지네이션 로직
   const currentPage = ref(1);
-  const itemsPerPage = 10;
-  const totalPages = computed(() => Math.ceil(newsData.value.length / itemsPerPage));
+  const itemsPerPage = 10; // 프론트엔드에서 10개씩 표시
+  const backendPageSize = 20; // 백엔드는 20개씩 가져옴
+  const totalPages = computed(() => Math.ceil(totalCount.value / itemsPerPage));
 
   const paginatedNews = computed(() => {
     const start = (currentPage.value - 1) * itemsPerPage;
@@ -270,21 +163,39 @@
     return newsData.value.slice(start, end);
   });
 
-  const goToPage = (page) => {
+  // 백엔드에서 필요한 데이터가 있는지 확인하고 필요시 API 호출
+  const needToFetchData = (targetPage) => {
+    const startIndex = (targetPage - 1) * itemsPerPage;
+    const endIndex = startIndex + itemsPerPage - 1;
+    return endIndex >= newsData.value.length && newsData.value.length < totalCount.value;
+  };
+
+  const goToPage = async (page) => {
     if (page >= 1 && page <= totalPages.value) {
       currentPage.value = page;
+      
+      if (needToFetchData(page)) {
+        // 백엔드 페이지 계산: 프론트 페이지를 백엔드 페이지로 변환
+        const backendPage = Math.ceil(page * itemsPerPage / backendPageSize);
+        await fetchNewsList(backendPage);
+      }
     }
   };
 
-  const nextPage = () => {
+  const nextPage = async () => {
     if (currentPage.value < totalPages.value) {
-      currentPage.value++;
+      await goToPage(currentPage.value + 1);
     }
   };
 
-  const prevPage = () => {
+  const prevPage = async () => {
     if (currentPage.value > 1) {
-      currentPage.value--;
+      await goToPage(currentPage.value - 1);
     }
   };
+
+  // 컴포넌트 마운트 시 데이터 로드
+  onMounted(() => {
+    fetchNewsList(1);
+  });
 </script>

+ 380 - 236
app/pages/media/press.vue

@@ -12,63 +12,41 @@
         <div class="sns--wrap">
           <h3>SNS</h3>
           <div class="sns--list">
-            <NuxtLink class="sns" to="/">
-              <div
-                class="img--wrap"
-                style="background-image: url('/img/img--sns1.png')"
-              ></div>
-              <div class="txt--wrap">
-                <h4>
-                  그린웨일글로벌, 녹색인프라 수출펀드 첫 투자기업 선정. 그린웨일글로벌
-                </h4>
-                <span>바로가기<i class="ico"></i></span>
-              </div>
-            </NuxtLink>
-            <NuxtLink class="sns" to="/">
-              <div
-                class="img--wrap"
-                style="background-image: url('/img/img--sns2.png')"
-              ></div>
-              <div class="txt--wrap">
-                <h4>
-                  그린웨일글로벌, 녹색인프라 수출펀드 첫 투자기업 선정. 그린웨일글로벌
-                </h4>
-                <span>바로가기<i class="ico"></i></span>
-              </div>
-            </NuxtLink>
-            <NuxtLink class="sns" to="/">
-              <div
-                class="img--wrap"
-                style="background-image: url('/img/img--sns3.png')"
-              ></div>
-              <div class="txt--wrap">
-                <h4>
-                  그린웨일글로벌, 녹색인프라 수출펀드 첫 투자기업 선정. 그린웨일글로벌
-                </h4>
-                <span>바로가기<i class="ico"></i></span>
-              </div>
-            </NuxtLink>
-            <NuxtLink class="sns" to="/">
-              <div
-                class="img--wrap"
-                style="background-image: url('/img/img--sns4.png')"
-              ></div>
-              <div class="txt--wrap">
-                <h4>
-                  그린웨일글로벌, 녹색인프라 수출펀드 첫 투자기업 선정. 그린웨일글로벌
-                </h4>
-                <span>바로가기<i class="ico"></i></span>
-              </div>
-            </NuxtLink>
+            <swiper
+              :slides-per-view="4"
+              :space-between="20"
+              :loop="true"
+              :autoplay="{
+                delay: 3000,
+                disableOnInteraction: false,
+              }"
+              :navigation="false"
+              :modules="[Autoplay]"
+            >
+              <swiper-slide v-for="sns in snsData" :key="sns.id">
+                <a class="sns" :href="sns.link" target="_blank" rel="noopener noreferrer">
+                  <div
+                    class="img--wrap"
+                    :style="`background-image: url('${sns.image}')`"
+                  ></div>
+                  <div class="txt--wrap">
+                    <h4>{{ sns.title }}</h4>
+                    <span>바로가기<i class="ico"></i></span>
+                  </div>
+                </a>
+              </swiper-slide>
+            </swiper>
           </div>
         </div>
         <div class="news--wrap">
           <h3>기사</h3>
           <div class="news--list">
-            <NuxtLink
+            <a
               v-for="news in paginatedNews"
               :key="news.id"
-              :to="news.link"
+              :href="news.link"
+              target="_blank"
+              rel="noopener noreferrer"
               class="news"
             >
               <div class="news--title--wrap">
@@ -78,7 +56,7 @@
               <div class="news--thumb--wrap">
                 <img :src="news.image" alt="" />
               </div>
-            </NuxtLink>
+            </a>
           </div>
           <div class="pagination--wrap">
             <UButton
@@ -108,6 +86,10 @@
   </main>
 </template>
 <script setup>
+  import { ref, computed, onMounted } from "vue";
+  import { Swiper, SwiperSlide } from "swiper/vue";
+  import { Autoplay } from "swiper/modules";
+  import "swiper/css";
   import TopVisual from "~/components/topVisual.vue";
 
   const className = ref("media");
@@ -134,189 +116,332 @@
     },
   ]);
 
-  // 뉴스 데이터 배열 생성
-  const newsData = ref([
-    {
-      id: 1,
-      title: "그린플라스틱연합, ESG친환경대전서 '자원순환 탄소중립 GPA 컨퍼런스' 개최",
-      date: "2025.07.11",
-      image: "/img/img--news.png",
-      link: "/",
-    },
-    {
-      id: 2,
-      title: "친환경 플라스틱 기술 개발 동향",
-      date: "2025.07.10",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 3,
-      title: "탄소중립 실현을 위한 플라스틱 재활용 기술",
-      date: "2025.07.09",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 4,
-      title: "바이오플라스틱 시장 전망과 기술 동향",
-      date: "2025.07.08",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 5,
-      title: "플라스틱 감축을 위한 정부 정책 변화",
-      date: "2025.07.07",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 6,
-      title: "순환경제와 플라스틱 재활용 산업",
-      date: "2025.07.06",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 7,
-      title: "해양 플라스틱 오염 해결을 위한 혁신 기술",
-      date: "2025.07.05",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 8,
-      title: "친환경 포장재 개발 현황",
-      date: "2025.07.04",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 9,
-      title: "플라스틱 대체재 소재 연구 동향",
-      date: "2025.07.03",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 10,
-      title: "ESG 경영과 플라스틱 감축 전략",
-      date: "2025.07.02",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 11,
-      title: "글로벌 플라스틱 규제 동향",
-      date: "2025.07.01",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 12,
-      title: "생분해성 플라스틱 상용화 전망",
-      date: "2025.06.30",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 13,
-      title: "플라스틱 없는 일주일 캠페인",
-      date: "2025.06.29",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 14,
-      title: "재활용 플라스틱 품질 향상 기술",
-      date: "2025.06.28",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 15,
-      title: "플라스틱 순환경제 구축 방안",
-      date: "2025.06.27",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 16,
-      title: "친환경 소재 개발 투자 확대",
-      date: "2025.06.26",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 17,
-      title: "마이크로플라스틱 저감 기술",
-      date: "2025.06.25",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 18,
-      title: "플라스틱 재활용률 제고 방안",
-      date: "2025.06.24",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 19,
-      title: "바이오매스 기반 플라스틱 개발",
-      date: "2025.06.23",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 20,
-      title: "환경친화적 플라스틱 산업 전망",
-      date: "2025.06.22",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 21,
-      title: "플라스틱 폐기물 감축 정책",
-      date: "2025.06.21",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 22,
-      title: "지속가능한 포장재 솔루션",
-      date: "2025.06.20",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 23,
-      title: "플라스틱 리사이클링 혁신 기술",
-      date: "2025.06.19",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 24,
-      title: "친환경 플라스틱 인증 시스템",
-      date: "2025.06.18",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-    {
-      id: 25,
-      title: "탄소 발자국 감축을 위한 플라스틱 대안",
-      date: "2025.06.17",
-      image: "/img/img--cycle--center.png",
-      link: "/",
-    },
-  ]);
+  const loading = ref(true);
+  const newsData = ref([]);
+  const snsData = ref([]);
+  const totalCount = ref(0);
+
+  // API에서 보도자료 데이터 가져오기
+  const fetchPressList = async (page = 1) => {
+    try {
+      loading.value = true;
+
+      // 공지사항과 동일한 방식으로 호출
+      const response = await $postForm(`/board_list/media`, {
+        boardId: "media",
+        page: page,
+        searchKind: "",
+        searchKeyword: "",
+      });
+
+      // 백엔드가 JSON으로 응답하는지 확인
+      if (response && typeof response === "object") {
+        // JSON 응답인 경우
+        if (response.success && response.list) {
+          // 전체 개수와 현재 페이지를 기준으로 번호 계산
+          totalCount.value = response.totalCount || 0;
+          const currentPageNum = page || 1;
+          const pageSize = 20; // 백엔드의 페이지 사이즈와 동일
+
+          // console.log("보도자료(media) API 응답:", {
+          //   totalCount: totalCount.value,
+          //   listCount: response.list.length,
+          //   currentPage: currentPageNum,
+          //   pageSize,
+          // });
+
+          newsData.value = response.list.map((item, index) => {
+            // 번호 = 전체개수 - ((현재페이지-1) * 페이지크기 + 인덱스)
+            const displayNumber =
+              totalCount.value - ((currentPageNum - 1) * pageSize + index);
+
+            return {
+              id: displayNumber, // 순차적인 번호로 표시
+              title: item.title,
+              date: item.regdate,
+              image: item.main_file1
+                ? `/backend${item.main_file1}`
+                : "/img/img--cycle--center.png", // 기본 이미지
+              link: item.etc1 || "#", // etc1 필드에 외부 링크 저장
+            };
+          });
+        } else {
+          console.error("JSON 응답 형식이 올바르지 않습니다:", response);
+          // 에러시 기본 더미 데이터 사용
+          setDefaultPressData();
+        }
+      } else if (typeof response === "string") {
+        // HTML 응답인 경우 (백엔드에서 AJAX 감지 실패시)
+        console.warn("HTML 응답을 받았습니다. AJAX 감지가 실패했을 수 있습니다.");
+        console.log("HTML 내용:", response.substring(0, 200) + "...");
+        // 기본 더미 데이터 사용
+        setDefaultPressData();
+      } else {
+        console.error("예상하지 못한 응답 형식:", typeof response, response);
+        // 기본 더미 데이터 사용
+        setDefaultPressData();
+      }
+    } catch (error) {
+      console.error("보도자료 데이터 로드 실패:", error);
+      // 에러시 기본 더미 데이터 사용
+      setDefaultPressData();
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  // API에서 SNS 데이터 가져오기
+  const fetchSnsList = async () => {
+    try {
+      const response = await $postForm(`/board_list/media_sns`, {
+        boardId: "media_sns",
+        page: 1,
+        searchKind: "",
+        searchKeyword: "",
+      });
+
+      if (response && typeof response === "object") {
+        if (response.success && response.list) {
+          //console.log("SNS API 응답:", response.list);
+
+          snsData.value = response.list.map((item) => ({
+            id: item.board_idx,
+            title: item.title,
+            image: item.main_file1
+              ? `http://green.interscope.co.kr/backend${item.main_file1}`
+              : "/img/img--sns1.png",
+            link: item.etc1 || "#", // etc1 필드에 외부 링크 저장
+          }));
+        } else {
+          console.error("SNS JSON 응답 형식이 올바르지 않습니다:", response);
+          setDefaultSnsData();
+        }
+      } else {
+        console.error("SNS 예상하지 못한 응답 형식:", typeof response, response);
+        setDefaultSnsData();
+      }
+    } catch (error) {
+      console.error("SNS 데이터 로드 실패:", error);
+      setDefaultSnsData();
+    }
+  };
+
+  // 기본 SNS 더미 데이터 설정
+  const setDefaultSnsData = () => {
+    snsData.value = [
+      {
+        id: 1,
+        title: "그린웨일글로벌, 녹색인프라 수출펀드 첫 투자기업 선정. 그린웨일글로벌",
+        image: "/img/img--sns1.png",
+        link: "#",
+      },
+      {
+        id: 2,
+        title: "그린웨일글로벌, 녹색인프라 수출펀드 첫 투자기업 선정. 그린웨일글로벌",
+        image: "/img/img--sns2.png",
+        link: "#",
+      },
+      {
+        id: 3,
+        title: "그린웨일글로벌, 녹색인프라 수출펀드 첫 투자기업 선정. 그린웨일글로벌",
+        image: "/img/img--sns3.png",
+        link: "#",
+      },
+      {
+        id: 4,
+        title: "그린웨일글로벌, 녹색인프라 수출펀드 첫 투자기업 선정. 그린웨일글로벌",
+        image: "/img/img--sns4.png",
+        link: "#",
+      },
+    ];
+  };
+
+  // 기본 더미 데이터 설정
+  const setDefaultPressData = () => {
+    newsData.value = [
+      {
+        id: 1,
+        title: "그린플라스틱연합, ESG친환경대전서 '자원순환 탄소중립 GPA 컨퍼런스' 개최",
+        date: "2025.07.11",
+        image: "/img/img--news.png",
+        link: "/",
+      },
+      {
+        id: 2,
+        title: "친환경 플라스틱 기술 개발 동향",
+        date: "2025.07.10",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 3,
+        title: "탄소중립 실현을 위한 플라스틱 재활용 기술",
+        date: "2025.07.09",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 4,
+        title: "바이오플라스틱 시장 전망과 기술 동향",
+        date: "2025.07.08",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 5,
+        title: "플라스틱 감축을 위한 정부 정책 변화",
+        date: "2025.07.07",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 6,
+        title: "순환경제와 플라스틱 재활용 산업",
+        date: "2025.07.06",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 7,
+        title: "해양 플라스틱 오염 해결을 위한 혁신 기술",
+        date: "2025.07.05",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 8,
+        title: "친환경 포장재 개발 현황",
+        date: "2025.07.04",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 9,
+        title: "플라스틱 대체재 소재 연구 동향",
+        date: "2025.07.03",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 10,
+        title: "ESG 경영과 플라스틱 감축 전략",
+        date: "2025.07.02",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 11,
+        title: "글로벌 플라스틱 규제 동향",
+        date: "2025.07.01",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 12,
+        title: "생분해성 플라스틱 상용화 전망",
+        date: "2025.06.30",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 13,
+        title: "플라스틱 없는 일주일 캠페인",
+        date: "2025.06.29",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 14,
+        title: "재활용 플라스틱 품질 향상 기술",
+        date: "2025.06.28",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 15,
+        title: "플라스틱 순환경제 구축 방안",
+        date: "2025.06.27",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 16,
+        title: "친환경 소재 개발 투자 확대",
+        date: "2025.06.26",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 17,
+        title: "마이크로플라스틱 저감 기술",
+        date: "2025.06.25",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 18,
+        title: "플라스틱 재활용률 제고 방안",
+        date: "2025.06.24",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 19,
+        title: "바이오매스 기반 플라스틱 개발",
+        date: "2025.06.23",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 20,
+        title: "환경친화적 플라스틱 산업 전망",
+        date: "2025.06.22",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 21,
+        title: "플라스틱 폐기물 감축 정책",
+        date: "2025.06.21",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 22,
+        title: "지속가능한 포장재 솔루션",
+        date: "2025.06.20",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 23,
+        title: "플라스틱 리사이클링 혁신 기술",
+        date: "2025.06.19",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 24,
+        title: "친환경 플라스틱 인증 시스템",
+        date: "2025.06.18",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+      {
+        id: 25,
+        title: "탄소 발자국 감축을 위한 플라스틱 대안",
+        date: "2025.06.17",
+        image: "/img/img--cycle--center.png",
+        link: "/",
+      },
+    ];
+  };
 
   // 페이지네이션 로직
   const currentPage = ref(1);
-  const itemsPerPage = 10;
-  const totalPages = computed(() => Math.ceil(newsData.value.length / itemsPerPage));
+  const itemsPerPage = 10; // 프론트엔드에서 10개씩 표시
+  const backendPageSize = 20; // 백엔드는 20개씩 가져옴
+  const totalPages = computed(() => Math.ceil(totalCount.value / itemsPerPage));
 
   const paginatedNews = computed(() => {
     const start = (currentPage.value - 1) * itemsPerPage;
@@ -324,21 +449,40 @@
     return newsData.value.slice(start, end);
   });
 
-  const goToPage = (page) => {
+  // 백엔드에서 필요한 데이터가 있는지 확인하고 필요시 API 호출
+  const needToFetchData = (targetPage) => {
+    const startIndex = (targetPage - 1) * itemsPerPage;
+    const endIndex = startIndex + itemsPerPage - 1;
+    return endIndex >= newsData.value.length && newsData.value.length < totalCount.value;
+  };
+
+  const goToPage = async (page) => {
     if (page >= 1 && page <= totalPages.value) {
       currentPage.value = page;
+
+      if (needToFetchData(page)) {
+        // 백엔드 페이지 계산: 프론트 페이지를 백엔드 페이지로 변환
+        const backendPage = Math.ceil((page * itemsPerPage) / backendPageSize);
+        await fetchPressList(backendPage);
+      }
     }
   };
 
-  const nextPage = () => {
+  const nextPage = async () => {
     if (currentPage.value < totalPages.value) {
-      currentPage.value++;
+      await goToPage(currentPage.value + 1);
     }
   };
 
-  const prevPage = () => {
+  const prevPage = async () => {
     if (currentPage.value > 1) {
-      currentPage.value--;
+      await goToPage(currentPage.value - 1);
     }
   };
+
+  // 컴포넌트 마운트 시 데이터 로드
+  onMounted(() => {
+    fetchPressList(1);
+    fetchSnsList();
+  });
 </script>

+ 195 - 33
app/pages/technology/patents.vue

@@ -11,42 +11,26 @@
           </h2>
         </div>
         <div class="tab--wrap">
-          <NuxtLink to="/" class="active">전체</NuxtLink>
-          <NuxtLink to="/" class="">특허증</NuxtLink>
-          <NuxtLink to="/" class="">인증서</NuxtLink>
-          <NuxtLink to="/" class="">성적서</NuxtLink>
-          <NuxtLink to="/" class="">MSD&TDS</NuxtLink>
+          <a @click="filterByCategory('all')" :class="{ active: selectedCategory === 'all' }" href="javascript:void(0)">전체</a>
+          <a @click="filterByCategory('technology1')" :class="{ active: selectedCategory === 'technology1' }" href="javascript:void(0)">특허증</a>
+          <a @click="filterByCategory('technology2')" :class="{ active: selectedCategory === 'technology2' }" href="javascript:void(0)">인증서</a>
+          <a @click="filterByCategory('technology3')" :class="{ active: selectedCategory === 'technology3' }" href="javascript:void(0)">성적서</a>
+          <a @click="filterByCategory('technology4')" :class="{ active: selectedCategory === 'technology4' }" href="javascript:void(0)">MSD&TDS</a>
         </div>
         <div class="patents--wrap">
           <div class="patents--list">
             <UModal
+              v-for="patent in paginatedPatents"
+              :key="patent.id"
               v-model:open="isModalOpen"
               title="특허 / 인증 크게보기"
               :close="false"
             >
-              <UButton @click="openModal('/img/img--patents.png')" class="patents">
+              <UButton @click="openModal(patent.image)" class="patents">
                 <div class="img--wrap">
-                  <img src="/img/img--patents.png" alt="" />
+                  <img :src="patent.image" alt="" />
                 </div>
-                <h4>플라스틱 감축 소재 인증서</h4>
-              </UButton>
-              <template #content>
-                <UButton @click="isModalOpen = false" class="modal--close--btn"></UButton>
-                <div class="modal--img--container">
-                  <img :src="selectedImage" alt="" />
-                </div>
-              </template>
-            </UModal>
-            <UModal
-              v-model:open="isModalOpen"
-              title="특허 / 인증 크게보기"
-              :close="false"
-            >
-              <UButton @click="openModal('/img/top_ban_technology.jpg')" class="patents">
-                <div class="img--wrap">
-                  <img src="/img/top_ban_technology.jpg" alt="" />
-                </div>
-                <h4>플라스틱 감축 소재 인증서</h4>
+                <h4>{{ patent.title }}</h4>
               </UButton>
               <template #content>
                 <UButton @click="isModalOpen = false" class="modal--close--btn"></UButton>
@@ -57,15 +41,26 @@
             </UModal>
           </div>
           <div class="pagination--wrap">
-            <UButton class="prev--btn" disabled></UButton>
+            <UButton
+              @click="prevPage"
+              class="prev--btn"
+              :disabled="currentPage === 1"
+            ></UButton>
             <div class="numbs">
-              <UButton class="active">1</UButton>
-              <UButton>2</UButton>
-              <UButton>3</UButton>
-              <UButton>4</UButton>
-              <UButton>5</UButton>
+              <UButton
+                v-for="page in totalPages"
+                :key="page"
+                @click="goToPage(page)"
+                :class="{ active: currentPage === page }"
+              >
+                {{ page }}
+              </UButton>
             </div>
-            <UButton class="next--btn"></UButton>
+            <UButton
+              @click="nextPage"
+              class="next--btn"
+              :disabled="currentPage === totalPages"
+            ></UButton>
           </div>
         </div>
       </div>
@@ -73,11 +68,17 @@
   </main>
 </template>
 <script setup>
+  import { ref, computed, onMounted } from "vue";
   import TopVisual from "~/components/topVisual.vue";
 
   const className = ref("technology");
   const title = ref("Technology");
   const isModalOpen = ref(false);
+  const loading = ref(true);
+  const patentsData = ref([]);
+  const totalCount = ref(0);
+  const selectedCategory = ref('all');
+  const allPatentsData = ref([]); // 전체 데이터 저장용
   const navigation = ref([
     {
       name: "Technology",
@@ -102,8 +103,169 @@
 
   const selectedImage = ref("/img/img--patents.png");
 
+  // 전체 데이터 가져오기 (4개 API 합쳐서)
+  const fetchAllPatents = async () => {
+    try {
+      loading.value = true;
+      const apis = ['technology1', 'technology2', 'technology3', 'technology4'];
+      let allData = [];
+      
+      for (const api of apis) {
+        const response = await $postForm(`/board_list/${api}`, {
+          boardId: api,
+          page: 1,
+          searchKind: "",
+          searchKeyword: "",
+        });
+        
+        if (response && response.success && response.list) {
+          const categoryName = getCategoryName(api);
+          const categoryData = response.list.map((item, index) => ({
+            id: `${api}_${item.board_idx || index}`,
+            title: item.title,
+            category: categoryName,
+            image: item.main_file1
+              ? `http://green.interscope.co.kr/backend${item.main_file1}`
+              : "/img/img--patents.png",
+          }));
+          allData = [...allData, ...categoryData];
+        }
+      }
+      
+      patentsData.value = allData;
+      totalCount.value = allData.length;
+    } catch (error) {
+      console.error("전체 데이터 로드 실패:", error);
+      setDefaultPatentsData();
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  // 카테고리별 데이터 가져오기
+  const fetchPatentsByCategory = async (category) => {
+    try {
+      loading.value = true;
+
+      const response = await $postForm(`/board_list/${category}`, {
+        boardId: category,
+        page: 1,
+        searchKind: "",
+        searchKeyword: "",
+      });
+
+      if (response && typeof response === "object") {
+        if (response.success && response.list) {
+          totalCount.value = response.totalCount || response.list.length;
+          const categoryName = getCategoryName(category);
+
+          patentsData.value = response.list.map((item, index) => ({
+            id: `${category}_${item.board_idx || index}`,
+            title: item.title,
+            category: categoryName,
+            image: item.main_file1
+              ? `http://green.interscope.co.kr/backend${item.main_file1}`
+              : "/img/img--patents.png",
+          }));
+        } else {
+          console.error("JSON 응답 형식이 올바르지 않습니다:", response);
+          setDefaultPatentsData();
+        }
+      } else {
+        console.error("예상하지 못한 응답 형식:", typeof response, response);
+        setDefaultPatentsData();
+      }
+    } catch (error) {
+      console.error("특허/인증 데이터 로드 실패:", error);
+      setDefaultPatentsData();
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  // 카테고리 이름 맵핑
+  const getCategoryName = (apiName) => {
+    const categoryMap = {
+      'technology1': '특허증',
+      'technology2': '인증서', 
+      'technology3': '성적서',
+      'technology4': 'MSD&TDS'
+    };
+    return categoryMap[apiName] || '기타';
+  };
+
+  // 기본 더미 데이터 설정
+  const setDefaultPatentsData = () => {
+    patentsData.value = [
+      {
+        id: 1,
+        title: "플라스틱 감축 소재 인증서",
+        image: "/img/img--patents.png",
+      },
+      {
+        id: 2,
+        title: "플라스틱 감축 소재 인증서",
+        image: "/img/top_ban_technology.jpg",
+      },
+    ];
+  };
+
+  // 카테고리별 필터링 함수
+  const filterByCategory = async (category) => {
+    selectedCategory.value = category;
+    currentPage.value = 1;
+    
+    if (category === 'all') {
+      await fetchAllPatents();
+    } else {
+      await fetchPatentsByCategory(category);
+    }
+  };
+
+  // 페이지네이션 로직 
+  const currentPage = ref(1);
+  const itemsPerPage = 8;
+  const backendPageSize = 20;
+  
+  const totalPages = computed(() => Math.ceil(totalCount.value / itemsPerPage));
+
+  const paginatedPatents = computed(() => {
+    const start = (currentPage.value - 1) * itemsPerPage;
+    const end = start + itemsPerPage;
+    return patentsData.value.slice(start, end);
+  });
+
+  const needToFetchData = (targetPage) => {
+    const startIndex = (targetPage - 1) * itemsPerPage;
+    const endIndex = startIndex + itemsPerPage - 1;
+    return endIndex >= patentsData.value.length && patentsData.value.length < totalCount.value;
+  };
+
+  const goToPage = (page) => {
+    if (page >= 1 && page <= totalPages.value) {
+      currentPage.value = page;
+    }
+  };
+
+  const nextPage = async () => {
+    if (currentPage.value < totalPages.value) {
+      await goToPage(currentPage.value + 1);
+    }
+  };
+
+  const prevPage = async () => {
+    if (currentPage.value > 1) {
+      await goToPage(currentPage.value - 1);
+    }
+  };
+
   const openModal = (imagePath) => {
     selectedImage.value = imagePath;
     isModalOpen.value = true;
   };
+
+  // 컴포넌트 마운트 시 데이터 로드
+  onMounted(() => {
+    fetchAllPatents(); // 초기에는 전체 데이터 로드
+  });
 </script>

+ 1 - 1
nuxt.config.ts

@@ -50,7 +50,7 @@ export default defineNuxtConfig({
   },
   runtimeConfig: {
     public: {
-      apiBase: process.env.NUXT_PUBLIC_API_BASE || 'http://localhost'
+      apiBase: process.env.NUXT_PUBLIC_API_BASE || 'http://green.interscope.co.kr'
     }
   }
 })

+ 0 - 2
package-lock.json

@@ -9697,7 +9697,6 @@
       "integrity": "sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg==",
       "devOptional": true,
       "license": "MIT",
-      "peer": true,
       "dependencies": {
         "chokidar": "^4.0.0",
         "immutable": "^5.0.2",
@@ -10268,7 +10267,6 @@
           "url": "http://opencollective.com/swiper"
         }
       ],
-      "license": "MIT",
       "engines": {
         "node": ">= 4.7.0"
       }