<script>
export default {
    data() {
        return {
            productId: 0,
            productDetail: {},
            productImage: [],
            total: 0,
            totalPrice: 0
        };
    },
    created() {
        this.productId = this.$route.query.product_id;
        this.getProductDetail();
        this.getProductImage();
    },
    methods: {
        calculatePrice(cnt) {
            let total = this.total + cnt;
            if (total < 1) total = 1;
            this.total = total;
            this.totalPrice = this.productDetail.product_price * this.total;
        },
   
       
        async getProductDetail() {
            let productDetail = await this.$api("/api/productDetail", { param: [this.productId] });
            if (productDetail.length > 0) {
                this.productDetail = productDetail[0];
                this.totalPrice = this.totalPrice = this.productDetail.product_price * this.total;
            }
            console.log(this.productDetail);
        },
        async getProductImage() {
            this.productImage = await this.$api("/api/productMainImage", { param: [this.productId] });
        },
    }
};
</script>

 

  • data: productId, productDetail, productImage, total, totalPrice라는 데이터 속성을 초기화합니다. 각각은 현재 제품의 ID, 제품 상세 정보, 제품 이미지 목록, 수량, 총 가격을 나타냅니다.
  • created: Vue 인스턴스가 생성될 때 호출되는 라이프사이클 훅 중 하나입니다. productId를 현재 라우터의 쿼리에서 가져와 getProductDetail 및 getProductImage 메서드를 호출하여 제품의 상세 정보와 이미지를 가져옵니다.
  • methods: 컴포넌트에서 사용할 메서드들이 정의되어 있습니다.
    • calculatePrice: 수량이 변경될 때 호출되는 메서드로, 총 가격을 다시 계산합니다.
    • getProductDetail: API를 호출하여 제품의 상세 정보를 가져오는 메서드입니다. API에는 현재 제품의 ID가 매개변수로 전달됩니다.
    • getProductImage: API를 호출하여 제품의 이미지 목록을 가져오는 메서드입니다.

' > html' 카테고리의 다른 글

vue.js 를 이용한 웹 앱 구현 - 프론트엔드 구축(1)  (2) 2023.11.26
<template>

        <main class="mt-3">
            <div class="container">
                <div class="row mb-2">
                    <div class="col-12">
                        <select class="form-select">
                            <option selected>목록</option>
                            <option value="1">강아지</option>
                            <option value="2">고양이</option>
                            <option value="3">조류</option>
                        </select>
                    </div>
                </div>
                <div class="row g-3">

                    <!--첫번째 제품-->
                    <div class="col-xl-3 col-lg-4 col-md-6" :key="i" v-for="(product, i) in productList">
                        <div class="card" style="width: 18rem;">
                            <!--a href, onclick -> 해당 페이지로 이동-->
                            <a @click="goToDetail(product.id);" style="cursor:pointer;"><img :src="product.path" class="card-img-top" alt="..." onclick></a>
                            <div class="card-body">
                                <h5 class="card-title">{{ product.product_name }}</h5>
                                <p class="card-text">
                                    <span class="badge bg-dark text-white" style="margin-right: 8px;">{{ product.category1
                                    }}</span>
                                    <span class="badge bg-dark text-white" style="margin-right: 8px;">{{ product.category2
                                    }}</span>
                                    <span class="badge bg-dark text-white">{{ product.category3 }}</span>


                                </p>
                                <div class="d-flex justify-content-between align-items-center">
                                    <div class="btn-group" role="group" aria-label="Basic example">
                                        <button type="button" class="btn btn-sm btn-outline-secondary">장바구니 담기</button>
                                        <button type="button" class="btn btn-sm btn-outline-secondary">주문하기</button>
                                    </div>
                                    <small class="text-dark">{{ product.product_price }}원</small>
                                </div>

                            </div>
                        </div>
                    </div>





                </div>
            </div>
        </main>


   
</template>

<script>
export default {
    data() {
        return {
            productList: []

        };

    },
    created() {
        this.getProductList();

    },
    methods: {

        async getProductList() {
            this.productList = await this.$api("/api/productList", {});   //app.js 에 api타고 맞는 sql문 결과값 가져옴
            console.log(this.productList);
        },
        goToDetail(product_id){
            this.$router.push({path:'/detail', query:{product_id:product_id}})

        }
    }

}
</script>

 

  • data: productList라는 빈 배열을 초기화합니다. 이 배열은 제품 목록을 저장하는 데 사용됩니다.
  • created: Vue 인스턴스가 생성될 때 호출되는 라이프사이클 훅 중 하나입니다. getProductList 메서드를 호출하여 제품 목록을 가져와 productList에 할당합니다.
  • methods: 컴포넌트에서 사용할 메서드들이 정의되어 있습니다.
    • getProductList: API를 호출하여 제품 목록을 가져오는 메서드입니다. 비동기 함수로 선언되어 await 키워드를 사용하여 비동기적으로 데이터를 가져옵니다.
    • goToDetail: 제품 상세 페이지로 이동하는 메서드입니다. 라우터의 push 메서드를 사용하여 /detail 경로로 이동하고, query 매개변수에 제품 ID를 전달합니다.

 

import { createRouter, createWebHistory } from 'vue-router'

import ProductList from '../views/ProductList.vue'
import ProductDetail from '../views/ProductDetail.vue'
import ProductCreate from '../views/ProductCreate.vue'

const routes = [
  {
    path: '/',
    name: 'home',
    component: ProductList
  },
  {
    path: '/create',
    name: 'Create',
    component: ProductCreate
  },
  {
    path: '/detail',  // 또는 '/ProductDetail'로 수정 가능
    name: 'ProductDetail',
    component: ProductDetail
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

 

 

  • createRouter: Vue Router의 createRouter 함수를 사용하여 라우터 인스턴스를 생성합니다.
  • createWebHistory: 브라우저 히스토리를 사용하는 라우터를 생성합니다. createWebHistory 함수는 HTML5 History API를 기반으로 브라우저 히스토리를 다룹니다.
  • routes: 라우터의 경로와 컴포넌트를 정의하는 배열입니다. ProductList, ProductCreate, ProductDetail 컴포넌트를 각각 /, /create, /detail 경로에 매핑하고 있습니다.

 

import {createStore} from 'vuex'

const store = createStore({

    state(){
        return{
            user:{}
        }
    },
    mutations:{

            user(state,data){

                state.user = data;
            }
    }
})

export default store;

 

vue.js의 상태 관리를 구성하는부분

  • state: 애플리케이션의 상태를 저장하는 객체입니다. 여기에서는 user 속성을 정의하여 사용자 정보를 저장합니다.
  • mutations: 상태를 변경하는 로직이 정의된 객체입니다. 여기에서는 user 뮤테이션을 정의하여 state.user를 업데이트합니다.
//axios 클라이언트 - 서버로 데이터를 주고받을때 사용하는 모듈, 공통모듈 파일

import axios from 'axios';
export default {
    methods: {
        async $api(url, data) {
            return (await axios({
                method: 'post',
                    url,
                    data
            }).catch(e => {
                console.log(e)
            })).data;


        }
    }

}

axios 사용 모듈

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import mixins from './mixins'
//부트스트랩 임포
//import 'bootstrap'
//import 'bootstrap/dist/css/bootstrap.min.css'
import store from './store'
//해당 모듈 import 후 use를 꼭 사용해야 사용할 수 있다.
createApp(App).use(router).mixin(mixins).use(store).mount('#app')
 
//카카오 SDK초기화 
window.Kakao.init("93e035de88e6057997f1e7856b13e079");
 

 

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import mixins from './mixins'
// 부트스트랩 임포트
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
import store from './store'

// 카카오 SDK 초기화
window.Kakao.init("93e035de88e6057997f1e7856b13e079");

createApp(App).use(router).mixin(mixins).use(store).mount('#app')

const { query } = require("express")

module.exports ={
    productList: {                  //Productlist : 상품 리스트 가져오는 쿼리
    query : 'select t1.*, t2.path, t3.category1, t3.category2, t3.category3 from t_product t1, t_image t2, t_category t3 where t1.id = t2.product_id and t2.type =1 and t1.category_id =t3.id'

    },
    productDetail:{

    query : 'select t1.*, t2.path, t3.category1, t3.category2, t3.category3 from t_product t1, t_image t2, t_category t3 where t1.id =? and t1.id = t2.product_id and t2.type=3 and t1.category_id=t3.id'
    }, //상품 상세정보 가져오는 쿼리

    productMainImage: { //상품 사진들 (썸네일 X)

        query : 'select * from t_image where product_id =? and type =2'
    },

    sellerList: {
    query: 'select * from t_seller'

    },

    productInsert: { //로그인한 사용자만 이 쿼리 가능, 쿼리안에서 로그인했는지 체크 코드 추가해야됨
    query: 'INSERT INTO `dev_class`.`t_product` (`id`, `product_name`, `product_price`, `delivery_price`, `add_delivery`, `tags`, `outbound_days`, `created_date`, `seller_id`, `category_id`) VALUES (?, ?, ?, ?, ?, ?, ?, ? ,?)'

    },
    productImageInsert: {
        query: 'insert into t_image (product_id,type,path) values (?,?,?)'
    },
   
    sellerList : {
        query: 'select 8 from t_seller'
       

},
    signUp:{
        query:'insert into t_user set ? on duplicate key update ?'

    }
}

//product_create.html 쿼리

sql.js 파일을 따로 생성후 DB 로 넘겨질 sql문 작성

 

// 필요한 모듈을 가져옵니다
const express = require('express');
const app = express();
const session = require('express-session');
const fs = require('fs');

// 세션 미들웨어 설정
app.use(session({
  secret: 'secret code',
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: false,
    maxAge: 1000 * 60 * 60
  }
}));

// JSON 미들웨어 설정 (크기 제한 증가)
app.use(express.json({
  limit: '50mb'
}));

// 데이터베이스 구성
const db = {
  database: "dev_class",
  connectionLimit: 10,
  host: "127.0.0.1",
  user: "root",
  password: "1234",
  port: "3306"
};

const dbPool = require('mysql').createPool(db);
let sql = require('./sql.js');  // 동적 SQL 쿼리

// 데이터베이스 요청 함수
const req = {
  async db(alias, param = [], where = '') {
    return new Promise((resolve, reject) => {
      // SQL 쿼리 실행
      dbPool.query(sql[alias].query + where, param, (error, rows) => {
        if (error) {
          if (error.code !== 'ER_DUP_ENTRY') {
            console.log(error);
          }
          resolve({
            error
          });
        } else {
          resolve(rows);
        }
      });
    });
  }
};

// 보호된 API 경로 (로그인 필요)
app.post('/apirole/:alias', async (request, response) => {
  if (!request.session.email) {
    return response.status(401).send({ error: "로그인이 필요합니다." });
  }
});

// 사용자 로그인 API
app.post('/api/login/', async (request, response) => {
  try {
    // 로그인 로직 수행
    await req.db('signUp', request.body.param);

    // 로그인이 성공했는지 확인
    if (request.body.param.length > 0) {
      for (let key in request.body.param[0]) {
        request.session[key] = request.body.param[0][key];
      }
      response.send(request.body.param[0]);
    } else {
      response.send({ error: "다시 시도하거나 시스템 관리자에게 문의하십시오." });
    }
  } catch (err) {
    response.send({
      error: "DB 액세스 오류"
    });
  }
});

// 사용자 로그아웃 API
app.post('/api/logout/', async (request, response) => {
  // 로그아웃 로직
  request.session.destroy();
  response.send('OK');
});

// 일반 API 경로 (로그인 필요 없음)
app.post('/api/:alias', async (request, response) => {
  try {
    // 데이터베이스 요청 실행
    response.send(await req.db(request.params.alias, request.body.param));
  } catch (err) {
    response.status(500).send({
      error: err
    });
  }
});

// 서버 시작
const server = app.listen(3000, () => {
  console.log('서버 시작. 포트 3000.');
});

// SQL 파일 변경 감지
fs.watchFile(__dirname + '/sql.js', (curr, prev) => {
  console.log("SQL 변경시 재시작 없이 반영");
  delete require.cache[require.resolve('./sql.js')];
  sql = require('./sql.js');
});
  • 산업제어시스템 구성 요소 문제들HMI : 휴먼인터페이스로 운영자가 컨트롤러와 상호작용 할 수 있는 하드웨어 혹은 소프트웨어다.센서 : 물리적 속성 값을 계측한다.다수 네트워크 프로토콜
      1. 제어 루프 동작 프로시저 서술.
      2. 센서로 계측 → PLC 로 해석 및 명령 생성 → 액추에이터가 수행
      3. 원격진단 및 유지보수 : 비정상 작동 식별, 방지
      4. 액추에이터 : 시스템을 동작시키는 장치

산업제어시스템 설계 요구 사항이 아닌것은?

    • 계층 구조
    • 제어 복잡성
    • 가용성
    • 결함 영향
    • 안전
    • 제어타이밍
    • 지리적 분산 정도
    • 정보보호학과를 아는지~ 왁왁왁
    • 마산대 물리치료과는 알아요

  1. 산업시스템 물리구성요소 중 RTU와 PLC의 차이점을 서술해라.
    • 로컬 (RTU/PLC) → 제어 서버 → HMI

[RTU /  PLC]

자체로직 X (외부 장치 제어 X) 자체로직O(직접 논리를 처리해 외부장치 제어)
먼 지역 가까운 지역
SCADA, DCS 와 액추에이터,센서 사이에 위치해있으며 센서 계측값을 전송가능한 데이터 형식으로 변환한 후 중앙 센터로 전송 PLC 구성 - 센서 값을 입력으로 받아들이고 순차적으로 논리를 처리한 후 외부 장치를 제어한다.
  • 데이터 이력 저장 장치 : 제어시스템의 상태정보HMI 를 통해 전달된 제어 명령에 대한 로그 정보
    1. 산업시스템 종류 3가지를 나열하고 각 서술해라.
    • SCADA는 ( 제어시스템을 모니터링하는 것 )이 주 목적이며 제어시스템의 상태를 감시하고, 지리적으로 ( 넓게 ) 분산되어 있다.
    • DCS는 ( 제어용도로 )로 사용되며 공정과정이 복잡해 ( 많은양의 데이터 ) 를 처리하기 위해 사용한다. 지리적으로 ( ) 현장에서 사용한다.
    • PLC는 단일 지엽적(소규모 공정)에서 공정이 단순하고 빠른 불연속(?뭔말)에 적용
  • 스카다 시스템과 분산제어시스템의 종속관계 차이점을 서술하시오.
    • 스카다 시스템은 (PLC와 RTU등의 요소) - (HMI, 제어서버) 간의 종속성이 낮아 원하는 코드를 제작하여 사용하는게 가능
    • 분산제어시스템은 특정 제조사가 (네트워크 컴포넌트) 전체를 공급해 사전에 정의된 코드를 사용 하도록한다.
  • PLC 기반 구성 방식에서 스카다 시스템, 분산제어시스템 과 차이점을 서술하시오.
    • PLC 는 폐쇄형 제어 루프를 사용한다는점
    • 폐쇄형 제어 루프 - 목표, 기준치를 달성하도록 시스템 안정을 위한 것
  • Purdue 모델 6-레벨에 대해 서술하고 3,4단계 사이에 IDMZ 운용목적이 무엇인지 서술하시오.
    • IDMZ는 위험성이 현저히 차이나는 IT네트워크와 OT 네트워크 간 정보 교환의 중간 매개 역할로 IT영역과 OT 영역 네트워크 경계 역할을 수행한다. 이는 IT → OT 으로의 직접적 공격을 방지하기 위해 운용된다.
    • 5레벨 ( ) - 산업 제어시스템 대규모 네트워크
    • 4레벨 ( ) - 5레벨에 데이터 제공
    • 3레벨 ( ) - HMI, 제어 운영실
    • 2레벨 ( ) - 3레벨과 유사
    • 1레벨 ( ) - 컨트롤러

'정보처리기능사' 카테고리의 다른 글

정보처리기능사 - 산업제어시스템  (0) 2023.10.22
위에 말만 기억하면 쉽다. 산업시스템(가용) IT시스템(자산)
보안우선순위 가용>  > 기밀 기밀 >  > 가용
요구하는 성능 실시간 실시간
가용성 기계 하나멈추는 게 굉장히어려움 .  높은가용성을 요구 IT시스템 재시작?   어렵지않음
보호대상 프로세스,필드 장치 IT 정보 자산
시스템 운영체제 전용 운영체제(기업/국가) 개방 운영체제(Enterprise)
생애주기 길다(규모가 크니까) 짧다(노트북 생각)
통신 전용 프로토콜 표준(TCP/IP)
SW 변경 계획된 정지(운영 정지해야되니까) 자동 적용(휴대폰도 알아서 업뎃되니까)
접근용이 넓은 영역 일정 범위
  • 1. 산업제어시스템과 일반 IT시스템과의 차이
    • “산업제어시스템” 은 피해가 발생하더라도 운영 지연/중단이 없이 유지되어야한다는 차이가 있다. (그 이유는 국가/사회 운영기관이기 때문)
  • 2. 산업제어시스템에 S/W 변경관리가 IT시스템보다 어려운 이유 서술
    • 산업제어시스템은 운영 지연/ 중단이 되면 안되고 보안 및 안전 요구 사항이 복잡,민감 하기 때문이다.
  • 3. 에너지 배급업 vs 제조업 제어시스템
    • 에너지 배급 : 장거리통신(장거리로 인한 데이터 손실 문제해결에 초점), 무선
    • 제조업 : 연속공정(등급 구분) , 일괄제조(재료수량에따라 뚜렷한 공정단계)
  • 4. 개별 산업제어시스템의 사고는 다른 인프라에 영향을 따로 주지 않는 독립적인 구조이다. (O/X)
  • 5. 스턱스넷에 공격흐름이다. 빈칸을 써넣어라.
    • [공격흐름]>> ( 감연된pc에서 씨앤씨 서버로 감염시스템정보 전송 )>>>>( 악성코드 생성및 전송 )
    • >> 메인 PC와 내부 네트워크 PC 공격 명령 공유
    • >> 내부 네트워크 감염
    • >> 스턱스넷 감염된 PC에서 USB로 PLC 제어하는 PC 감염
    • 폐쇄망으로 운용되는 대규모 산업시설을 주 타겟으로 제작된 악성코드이다.
  • 6. 암기 : 산업제어시스템 주요 잠재 취약점 3가지
    • Inherent lack of security
    • 보안이 취약
    • The “air -gap” facllacy - 에어 갭 오류 및 식별되지 않은 ICS(산업제어세스템) 네트워크 접근 경로 존재
    • Continued use of outdated hardware and software - 노후화된 하드웨어와 소프트웨어
  • 7. 암기 : 산업제어시스템 주요 보안 목표가 아닌 것은?
    • 산업제어시스템 네트워크 및 네트워크 활동에 대한 논리적 접근 제한
    • 네트워크 트래픽이 산업제어시스템 네트워크 사이를 통과하는 것을 방지 =>
    • 단방향 게이트웨이, 방화벽과 경계 네트워크구간 DMZ를 사용
    • 산업제어시스템 네트워크 및 장치에 대한 물리적접근제한 필요
    • 데이터 무단 변경 금지
    • 산업제어시스템 구성요소 변경
    • 보안 사건 및 사고 감지
    • 시스템 복원
    • 악조건안에서 기능유지(반장, 부반장)

'정보처리기능사' 카테고리의 다른 글

정보처리기능사 - 산업제어시스템(2)  (0) 2023.10.22

+ Recent posts