반응형

오늘은 자바스크립트 ES6에서 추가된 주요 기능 중 화살표함수( => )에 대해 알아보겠습니다. 

 

[ 목차 ]

     

    1. 화살표 함수

    기존의 function으로 함수를 표현하는 방식을 좀 더 간결하게 표현하기 위해 화살표( => ) 함수가 도입되었습니다. 아래의 두 함수는 모두 동일한 역할을 하는 함수입니다.

    const test1 = function(a,b){
    	return a+b;
    }
    
    const test2 = (a,b) => {
    	return a+b;
    };
    
    const test3 = (a,b) => a+b;

     

    2. 화살표 함수 주의점(this)

    일반적인 자바스크립트 함수에서의 this는

       - 전역 객체

       - 메소드 호출시 호출한 해당 객체

    를 나타냅니다.

    // 일반 함수
    const obj1 = {
      name: '홍길동',
      func1(){
        console.log(this.name);
      }
    };
    obj1.func1();
    // 홍길동
    
    const obj2 = {
      name: '홍길동',
      func1: function() {
        const func2 = function() {
          console.log(this.name);
        }
        func2();
      }
    };
    
    obj2.func1();	
    // undefined

    위 두번째 obj2에서 this는 함수를 호출했을 때 지정되지 않았습니다. 곧 전역객체인 Window를 가리킵니다. 하지만 전역 객체 Window에 name이란 속성이 존재하지 않아서 undefined가 나타납니다.

     

    반면 화살표 함수에는 this는 현재 환경에서 그 변수가 없으면 바로 상위 환경을 검색하고, 해당 스코프에서 없으면 다시 또 상위를 검색합니다.

    // 화살표 함수
    const obj2 = {
      name: '이순신',
      func1: function() {
        const func2 = ()=> {
          console.log(this.name);
        }
        func2();
      }
    };
    
    obj2.func1();	// 이순신

     

    javascript에서의 this는 상당히 헷갈리고 어려운 개념으로 가볍게 다루기엔 좀 부담되는 주제이긴 합니다. 자세한 사용법은 다음에 공부해서 포스팅 하도록 하고, 오늘은 이만 마치겠습니다.

     

     

    (ps) 참고로 메서드 축약선언

    var obj = {
      foo: function() {},
      bar: function() {}
    };
    
    // 이를 아래로 줄일 수 있습니다:
    
    var obj = {
      foo() {},
      bar() {}
    };




    반응형
    반응형

    자바스크립트 filter 메소드에 대해 알아보겠습니다. Filter 메소드는 배열 내부를 순환하면서 특정 조건에 부합하는 요소들을 새로운 배열에 담아 반환합니다.

     

    1. 기본사용법

    result = my_array.filter (a => {
        return [조건];
    });

     

    const my_array = [1,2,3,4,5,6,7,8,9,10]
    
    const result = my_array.filter(a => {
      return a % 2 == 0; // a중 2로 나눈 나머지가 0(즉, 짝수)인 요소
    });
    
    console.log(result);
    
    // [ 2, 4, 6, 8, 10 ]

     

     

    2. 객체 다루기

    const my_array = [
        {name:'홍길동', age:28},
        {name:'이순신', age:37},
        {name:'유관순', age:18}
    ];
    
    const result = my_array.filter(a => {
      return a.age > 20; // 20세 이상인 요소
    });
    
    console.log(result);
    
    // [ { name: '홍길동', age: 28 }, { name: '이순신', age: 37 } ]

     

    3. Map, Reduce로 filter 구현하기

     

    map, reduce함수로도 filter를 구현할 수 있습니다.

    [map 예시]

    const my_array = [
        {name:'홍길동', age:28},
        {name:'이순신', age:37},
        {name:'유관순', age:18}
    ];
    
    const result = my_array.map(a=>{
      if(a.age>20){
        return a;
      }
    })
    console.log(result);
    
    // [ { name: '홍길동', age: 28 }, { name: '이순신', age: 37 }, undefined ]

    그런데 이 경우 마지막에 undefined가 들어갑니다. map과 filter의 특성이 다르니 상황에 따라 적절히 사용하면 좋을 것 같습니다.

     

    [reduce 예시]

    const my_array = [
        {name:'홍길동', age:28},
        {name:'이순신', age:37},
        {name:'유관순', age:18}
    ];
    
    result = my_array.reduce((acc, cur) => {
      if (cur.age > 20) acc.push(cur);
      return acc;
    }, []);
    
    console.log(result);
    
    // [ { name: '홍길동', age: 28 }, { name: '이순신', age: 37 } ]

     

    오늘은 이름과 같이 직관적으로 사용할 수 있어서 자주사용하게되는 filter메소드에 대해 간단한 사용법 몇가지, 그리고 참고로 map과 reduce를 사용하여 filter 구현하는 법을 알아보았습니다.

    반응형
    반응형

    reduce 함수는 자바스크립트에서 배열 또는 리스트 안의 요소들을 정렬하거나 특정 조건에 부합하면 합계나 평균 등을 계산하는데 사용되는 함수입니다.  개인적으로 자주 쓰지는 않지만 잘 알고있으면 많이 유용하게 쓸 수 있을것 같아서 정리해놓겠습니다.

     

    1. 기본사용법

    result = my_array.reduce((acc, cur, i) => {
        return (acc~연산~cur);
    }, acc초기값);

    - acc: accumulate(누적값)

    - cur: current(현재값)

    - acc초기값: 누적하기 전에 시작값을 지정

    const my_array = [1,2,3,4,5]
    const result = my_array.reduce((acc, cur, i) => {
      console.log(acc, i);
      return acc + cur;
    }, 0);
    
    console.log(result);

    reduce함수는 주로 누적합 또는 누적곱을 구할때 많이 씁니다. 위 예제도 가장 기본적인 누적합을 나타내고 있습니다. acc초기값에 0을 주면 누구나 예상하는 배열의 누적값을 구하게 되고, 거기에 다른 값을 주게 되면 0이아닌 다른 시작값을 갖고 더해나간다고 보시면 되겠습니다.

     

    2. 홀짝 구분하기

    const my_array2=[1,2,3,4,5,6,7]
    
    const result2 = my_array2.reduce((acc, cur, i) => {
      acc.push(cur % 2 ?'홀수' : '짝수');
      return acc;
    },[])
    
    console.log(result2);
    
    // ['홀수', '짝수', '홀수', '짝수', '홀수', '짝수', '홀수']

    짝수만 Filter 

    const my_array3=[1,2,3,4,5,6,7]
    
    const result3 = my_array3.reduce((acc, cur, i) => { 
         if(i%2){
           acc.push(cur);
         }
         return acc; 
     },[]);
    console.log(result3);
    
    // [ 2, 4, 6 ]

     

    3. 객체 다루기

    - 나이에 3을 곱한 새로운 배열을 생성하는 예

    const obj_array=[
      {
        name: "one",
        age: 1,
      },
      {
        name: "two",
        age: 2,
      },
      {
        name: "three",
        age: 3,
      }
    ]
    
    const result = obj_array.reduce((acc, cur,i)=>{
      acc.push(cur.age*3)
      return acc;
    },[])
    console.log(result);
    
    //[ 3, 6, 9 ]

    위의 예제는 map함수와 비슷하게 사용이 가능합니다. 이처럼 reduce를 사용하면 map이나 filter, sort, find 등 다양한 함수들을 reduce로 직접 구현해서 사용할 수 있습니다.

     

    Reduce함수에 대해 간단한 사용법 몇가지를 알아보았습니다.

     

    반응형
    반응형

    Javascript에서 객체배열(Object Array) 내부의 요소를 변경해야할 경우가 자주 발생합니다. 예를 들면 아래와 같은 객체 배열이 주어질 경우 특정 요소 또는 전체 요소의 age값을 변경할 필요가 있습니다.

    const obj_array=[
      {
        name: "one",
        age: 1,
      },
      {
        name: "two",
        age: 2,
      },
      {
        name: "three",
        age: 3,
      }
    ]

     

    이때 유용하게 사용할 수 있는 함수로 Map 메소드가 있습니다. 

    Map은 내부에서 callback 함수를 실행한 결과를 가지고 새로운 배열을 만들 때 사용합니다.

     

    1. 모든 요소의 값 변경하기

    // age를 모두 4로
    const result = obj_array.map(obj => {
      return {...obj, age: 4}
    });
    console.log(result); 
    //[{ name: 'one', age: 4 },{ name: 'two', age: 4 },{ name: 'three', age: 4 }]
    
    // age에 4배하기
    const result = obj_array.map(obj => {
      return {...obj, age:obj.age*4}
    });
    console.log(result); 
    //[{ name: 'one', age: 4 },{ name: 'two', age: 8 },{ name: 'three', age: 12 }]

     

    2. 특정 요소들만 추출하기

    const result = obj_array.map(obj => obj.name);
    console.log(result); 
    //[ 'one', 'two', 'three' ]

     

    3. 특정 요소의 값 변경하기

    age가 3인경우 값을 4로 바꾸기

    const result = obj_array.map(obj => 
      {
        return obj.age===3 ? {...obj, age: 4} : obj
      });
    console.log(result);
    //[{ name: 'one', age: 1 },{ name: 'two', age: 2 },{ name: 'three', age: 4 }]

     

     

    반응형
    반응형

    서버리스 앱 만들기의 마지막 단원으로 Vue.js 프론트 앱을 배포해보도록 하겠습니다. 

     

    1. 앱 만들기

    Vue 앱을 만들어줍니다.

    vue create node_post_vue .    // .을 찍으면 현재 폴더에 프로젝트를 생성합니다.
    
    vue add router  // 곧바로 router 라이브러리를 함께 설치해줍니다.

     

    필요한 라이브러리를 아래와 같이 설치해줍니다.

    npm i vuex axios

    간단히 백엔드에서 보내오는 데이터를 읽어다 표현해주는 것만 할건데도 Store를 구성하고 각 컴포넌트에서 Store state를 이용해야하는게 좀 불편해 보이네요. 그래도 한번만 세팅해놓으면 다음부터는 비교적? 편하게 작업을 할 수 있다고 생각하고 진행하셔요^^;;

     

     (1) ./src/main.js

    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    import {store} from './store/store.js'
    
    createApp(App)
    .use(router)
    .use(store)
    .mount('#app')

     

    (2) ./src/App.vue

    <template>
      <router-view/>
    </template>
    
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
    }
    </style>

     

     (3) ./src/router/index.js

    import { createRouter, createWebHistory } from 'vue-router'
    import HomeView from '../views/HomeView.vue'
    
    const routes = [
      {
        path: '/',
        name: 'home',
        component: HomeView
      }
    ]
    
    const router = createRouter({
      history: createWebHistory(process.env.BASE_URL),
      routes
    })
    
    export default router

     

      (4) ./src/components/HelloWorld.vue

    <template>
      <div class="hello">    
        <ul>
          <li class="post" v-for="post in postlist" :key=post>
            <div class="title">
              {{ post.title }} 
            </div>
            <div class="content">
              {{ post.content }} 
            </div>
            <div class="lower">
              <div>...by {{ post.creator }} </div>
              <div>on {{ post.publish_date.split('T')[0] }}</div>
            </div>
          </li>
        </ul>
      </div>
    </template>
    
    <script scoped>
    export default {
      name: 'HelloWorld',
      props: {
        msg: String
      },
      computed:{
        postlist(){            
          return this.$store.state.posts;
        },    
      },
      created(){
          this.$store.dispatch('onLoad');
        }
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    ul {
      text-align: center;
      list-style-type: none;
      margin: 0 auto;
      padding: 0;
      width: 800px;
    }
    .post {
      /* display: inline-block; */
      margin: 10px 10px;  
      border: 1px solid #42b983;
      border-radius: 15px;
      padding: 8px;
    }
    
    .post .title{
      text-align: left;
      font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
      font-size:larger;
      font-weight: 900;
      color:#222;
    }
    .post .content{
      text-align: left;
      font-size:small;
      padding: 5px;
      height: 80px;
      color:#999;
    }
    .post .lower{
      text-align: right;
      color:grey;
      font-size:small
    }
    a {
      color: #42b983;
    }
    </style>

     

      (5) ./src/store/store.js

    import { createStore } from 'vuex';
    import axios from 'axios';
    
    axios.defaults.baseURL = 'https://vmsahpyntz.eu10.qoddiapp.com';
    axios.defaults.headers.post['Content-Type']='application/json;charset=utf-8';
    axios.defaults.headers.post['Access-Control-Allow-Origin']='*';
    
    export const store = createStore({
      state:{
        posts:[]
      },
      mutations:{
        updateState(state, payload){
          Object.keys(payload).forEach((key) => {
            state[key] = payload[key];
          });
        }
      },
      actions:{
        async onLoad(context){
          const res= await axios.get('/');
          const post = res.data;
          // console.log(res);
          
          context.commit('updateState',{
            posts:[...context.state.posts, ...post],
          })
        },
      }
    });

     

    2. gitlab에 배포하기

    저는 회사 특성상 github 접근이 불가능해서 gitlab을 주로 사용합니다. 사용 방법은 github과 동일합니다.

    git remote add origin [gitlab주소: 대활호 빼고]
    git pull origin main
    git add .
    git commit -m "initial commit"
    git push origin main // main인지 master인지 본인의 branch를 잘 확인하고 진행합니다.

     

    3. Netlify에서 연동하기

    Netlify에 접속해줍니다. 계정이 없다면 적당한 방법으로 계정을 생성해주셔요.

    "Sites  >  Add new site  >  Import an existing project"를 클릭해줍니다.

    아래 그림에서 본인의 저장소가 있는 곳을 선택합니다. 저는 Gitlab

     

    본인의 프로젝트를 선택합니다.

     

    배포 세팅을 하게 되됩니다. 배포할 브랜치, 빌드 명령어(npm run build), 배포 디렉토리(일반적으로 /dist) 를 확인하고, 아래에 Deploy Site를 눌러주면 배포가 시작됩니다.

     

    배포가 완료되면 아래와 같이 화면이 변경되며, 배포된 url이 표시가 됩니다. 

     

    해당 링크를 클릭하면 우리가 만든 사이트가 나타납니다.

     

    이제 수정사항이 생길때마다 Gitlab으로 배포만 하면 자동으로 Netlify도 업데이트됩니다. 

    지금까지 DB, Backend 서버, Frontend 서버를 모두 서버리스로 구현해보았습니다.

     

    ~~~끝~~~~

    반응형
    반응형

    제목이 참 힘드네요...

     

    데이터는 적당히 입력이 되었다고 하면, Node(Express)를 통해서 데이터를 넘겨주는 서버를 만들어보겠습니다.

    1 .env 파일

    CockroachDB연결정보는 사이트에서 제공하는 connection string을 그대로 붙이는게 편리합니다. 비밀번호도 찾아서 잘 넣어주시구요.

    PORT=3000
    NODE_ENV='development'
    SECRET=mysecretkeytest
    COCKROACHDB_CONNECT_URL='postgresql://<유저아이디>:<비밀번호>@wind-raccoon-4725.8nk.cockroachlabs.cloud:26257/defaultdb?sslmode=verify-full'

     

    2. postRoute.js

    Connection String에 정의된대로 연결하니 오히려 더 깔끔한 것 같네요.

    import express from 'express';
    import pg from 'pg';
    import dotenv from 'dotenv';
    import bodyParser from 'body-parser'
    
    dotenv.config();
    const { COCKROACHDB_CONNECT_URL } = process.env;
    
    const router = express.Router();
    router.use(express.json());
    
    const client = new pg.Client(COCKROACHDB_CONNECT_URL);
    
    client.connect(err => {
      if (err) {
        console.error('connection error', err.stack)
      } else {
      	console.log('success!')
      }
    });
    
    
    // 전체 리스트 읽기
    router.get('/', (req, res) => {
      // res.send('hello');
      const query = new pg.Query("SELECT * FROM MEMO_POST");
      client.query(query);
    
      var rows = [];
      /** 
       *  row에서 데이터 가져오고 end에서 검색할 때 발생한 각종 정보, error는 오류 발생시
       */
      query.on("row",row=>{
        rows.push(row);
      });
      query.on('end', () => {
        console.log(rows);
        console.log('query done')    
        res.send(rows);
        res.status(200).end();
      });
      query.on('error', err => {
        console.error(err.stack)
      });
    });

     

    3. index.js

    구동을 위해 index.js의 소스코드도 올려둡니다.

    import express from 'express';
    import session from 'express-session';
    import cookieParser from 'cookie-parser';
    import dotenv from 'dotenv';
    import cors from 'cors';
    
    // import mongoose from 'mongoose';
    // import auth from './routes/auth.js';
    import postRoute from './routes/postRoute.js';
    
    dotenv.config();
    
    const app = express();
    
    const { PORT, SECRET } = process.env;
    app.set('port', PORT || 3000);
    
    app.use(express.json());
    app.use(express.static('public'));
    app.use(express.urlencoded({ extended: true }));
    app.use(cookieParser(SECRET));
    app.use(session({
        resave: false,
        saveUninitialized: false,
        secret: SECRET,
        cookie: {
            httpOnly: true,
            secure: false
        }
    }));
    
    app.use(cors());  // 이걸로는 잘 안됨
    app.all('/*', function(req, res, next){
      res.header("Access-Control-Allow-Origin", "*");
      res.header("Access-Control-Allow-Headers", "X-Requested-With");
      next();
    })
    
    app.use('/', postRoute);
    
    app.listen(app.get('port'), ()=> {
      console.log(`http://localhost:${app.get('port')} 번 포트에서 서버 실행 중..`);
    });

     

    결과가 잘 나오네요^^

     

    반응형
    반응형

    모든 서비스 클라우드에서 구동하기를 해보려고, 이번엔 Database를 찾고 있습니다. 이번에도 역시 무료가 어느정도 가능한 서비스를 찾다보니 CockroachDB라는 것을 찾게 되었습니다.

     

     

    Cockroach Labs, the company building CockroachDB

     

    Cockroach Labs, the company building CockroachDB

    CockroachDB is a distributed database with standard SQL for cloud applications. CockroachDB powers companies like Comcast, Lush, and Bose.

    www.cockroachlabs.com

     

    Cockroach라면 우리말로 바퀴벌레인데요, 단어를 알게되는 순간 이미지가 급 안좋아지는데 이 또한 의미가 있다고 하네요. 뭐냐하면 CockroachDB는 시스템에 크고 작은 문제가 생겼을 때 생존하고 스스로 회복하는 것 (Resiliency) 에 가장 큰 강점을 두고 있다고 합니다. 분산 시스템을 설계할 때에 가장 어려운 문제 중 하나가 바로 장애 상황에서 일관성이나 가용성을 최대한 유지하면서 복구해내는 것인데요. 특히 분산 데이터베이스 시스템의 경우 복구에 많은 시간이 걸리거나 많은 데이터가 소실되면 어플리케이션에 큰 영향을 끼칠 수 있습니다.

     

    CockroachDB의 경우 디스크, 물리적 머신, 심지어 데이터 센터 단위의 장애가 생기더라도 생존할 수 있는 다양한 옵션을 제공하고 있습니다. 또한 문제 상황이 생기면 스스로 감지하고 사람의 개입 없이도 자동으로 서비스를 최대한 복구해냅니다. 정말 계속해서 나타나는 바퀴벌레의 생명력이 생각나네요. 계속해서 잘 살아남이 DB를 유지해주길 바래봅니다.

     

    가격정책을 보니까 제가 좋아하는 무료정책이 있습니다. 기간이 나와있지는 않는데, 10GiB의 스토리지와 월 50M 건의 요청 안에서 사용할 시 무료인 것으로 보입니다. 

     

    가입과정을 거쳐 진입하면 자체 콘솔화면이 나타납니다. 여기서 우측 상단에 보이는 Create Cluster를 눌러 생성을 시작합니다.

     

    다음으로는 Serverless 플랜을 선택합니다. 그리고 아래쪽에 "Start for free"를 눌러 다음을 진행해줍니다. 지금 저는 하나의 무료 cluster를 이미 생성했기 때문에 해당 메뉴가 활성화가 안되네요.

     

    제 화면은 아니지만 아래와 같이 Cluster name이 적당히 생성되고, 다음 오른쪽 보라색 생성버튼을 눌러줍니다. 

     

    생성되면 접속과 관련된 정보들이 나타납니다. 이 정보는 터미널에서 직접 DB를 관리할 때 필요한 것 같습니다. DBeaver같은 데이터베이스 관리도구를 사용하면 3번의 접속정보 정도만 알아도 사용 가능합니다. 중간에 Database이름, 사용자 이름과 비밀번호를 생성하는 부분이 있는데, 1번만 알려준다고 하니 잊어버리지 않도록 주의하시기 바랍니다. 잊어버리면 새로 생성할 수는 있습니다.

     

    아래와 같이 host, port, database, username, password 등 접속정보를 넣고 입력하면 접속이 됩니다.

     

    이제 웹상에 데이터 저장이 가능한 내 Postgresql DB가 생성되었습니다. 

     

    아래와 같이 입력하여 신규 Table을 생성하고, 데이터를 집어넣어봅시다.

    CREATE TABLE MEMO_POST (
    	POST_ID integer generated by default as identity,
    	TITLE VARCHAR(50),
    	CONTENT VARCHAR(50),
    	CREATOR VARCHAR(10) ,
    	PUBLISH_DATE TIMESTAMP 
    );
    
    insert into memo_post values (default,'첫번째포스팅','안녕하세요, 포스팅 테스트1 입니다.', 'wilkyway', CURRENT_TIMESTAMP);
    insert into memo_post values (default,'두번째포스팅','안녕하세요, 포스팅 테스트2 입니다.', 'wilkyway', CURRENT_TIMESTAMP);
    insert into memo_post values (default,'세번째포스팅','안녕하세요, 포스팅 테스트3 입니다.', 'wilkyway', CURRENT_TIMESTAMP);
    
    select * from memo_post

     

    조금 실수가 있어서 첫번째 라인이 지워졌지만.... 데이터 잘 입력되고 확인이 되네요^^

    반응형
    반응형

    머신러닝 알고리즘은 크게 지도학습, 비지도학습, 강화학습으로 분류됩니다. 각 카테고리에 속하는 주요한 알고리즘들을 간단히 살펴보겠습니다.

    1. 지도학습 (Supervised Learning)

    지도학습은 입력 데이터와 정답(label) 쌍을 통해 학습하는 방법입니다. 주어진 입력에 대해 정확한 출력을 예측하는 모델을 학습합니다. 주요한 지도학습 알고리즘으로는 다음과 같은 것들이 있습니다:
       1. 선형 회귀 (Linear Regression)
       2. 로지스틱 회귀 (Logistic Regression)
       3. 의사결정 트리 (Decision Trees)
       4. 랜덤 포레스트 (Random Forests)
       5. K-최근접 이웃 (K-Nearest Neighbors)
       6. 서포트 벡터 머신 (Support Vector Machines)
       7. 신경망 (Neural Networks)

    2. 비지도학습 (Unsupervised Learning)

    비지도학습은 정답(label) 없이 입력 데이터의 내부 구조를 발견하거나 데이터를 그룹화하는 방법입니다. 입력 데이터의 특징을 스스로 학습하여 새로운 관점이나 패턴을 발견합니다. 주요한 비지도학습 알고리즘으로는 다음과 같은 것들이 있습니다:
       1. 군집화 (Clustering)
       2. 주성분 분석 (Principal Component Analysis, PCA)
       3. 자기조직화 맵 (Self-Organizing Maps, SOM)
       4. 혼합 모델 (Mixture Models)
       5. 이상치 탐지 (Anomaly Detection)
       6. 차원 축소 (Dimensionality Reduction)

    3. 강화학습 (Reinforcement Learning)

    강화학습은 에이전트가 환경과 상호작용하며 보상을 최대화하는 의사결정을 학습하는 방법입니다. 시행착오를 통해 최적의 행동 정책을 학습하고 개선합니다. 주요한 강화학습 알고리즘으로는 다음과 같은 것들이 있습니다:
       1. Q-학습 (Q-Learning)
       2. SARSA
       3. 딥 강화학습 (Deep Reinforcement Learning)
       4. 강화학습 기반 신경망 (Reinforcement Learning-based Neural Networks)

     

    각각의 학습 방법은 다른 목적과 응용 분야에 적용될 수 있으며, 종종 혼합하여 사용되기도 합니다. 예를 들어, 지도학습을 통해 레이블된 데이터를 사용하여 모델을 학습한 후, 비지도학습을 통해 데이터의 구조를 이해하거나 강화학습을 통해 최적의 의사결정 전략을 개발하는 등의 방식으로 조합될 수 있습니다.

     

     

     

    반응형

    + Recent posts