Skip to content

[Project๐Ÿ—‚] AI์™€ ํ•˜๋Š” ๋๋ง์ž‡๊ธฐ! ์ธ๊ฐ„์€ AI๋ฅผ ์ด๊ธธ ์ˆ˜ ์žˆ์„๊นŒ?!

Notifications You must be signed in to change notification settings

parkjisu6239/2021_ToyPjt_End-To-End

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

1 Commit
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๋๋ง์ž‡๊ธฐ

2021.03 ์ดˆ๊ธฐ Django๋กœ ๊ฐœ๋ฐœ

2021.06 Django REST frame work + Vue.js ๋กœ ์—…๋ฐ์ดํŠธ

๋ชฉ์ 

  • ์›น๊ฐœ๋ฐœ ์—ฐ์Šต
  • ๊ฐ„๋‹จํ•œ toy project ๊ตฌํ˜„, ์• ๋‹ˆ๋ฉ”์ด์…˜ ์—ฐ์Šต
  • ํ•™์Šต ๋‚ด์šฉ ๋ณต๊ธฐ

๊ฐœ์š”

ํด๋ผ์ด์–ธํŠธ

  • Vue.js
  • axios๋กœ ์„œ๋ฒ„ API์— ์š”์ฒญ
  • props, emit์œผ๋กœ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
  • CSS ์• ๋‹ˆ๋ฉ”์ด์…˜

์„œ๋ฒ„

  • Django REST frame work
  • ๋๋ง์ž‡๊ธฐ ๊ทœ์น™(์ด์ „ ๋‹จ์–ด์˜ ๋งˆ์ง€๋ง‰ ๊ธ€์ž ํ™•์ธ, ๋‘์Œ๋ฒ•์น™, ์ค‘๋ณต๋‹จ์–ด, ์˜ต์…˜,,)
  • ๊ตญ๋ฆฝ๊ตญ์–ด์› API ํ™œ์šฉ

Preview

front-Chrome-2021-06-20-20-04-15

์ƒ์„ธ๋‚ด์šฉ _ front

install

"axios": "^0.21.1",
"bootstrap": "^5.0.1",
"bootstrap-vue": "^2.21.2",
"core-js": "^3.6.5",
"vue": "^2.6.11"

Design

  • ๋ ˆ์ด์•„์›ƒ & ์ปจ์…‰ : 90's ๋‹Œํ…๋„ ๊ฒŒ์ž„๊ธฐ(ํ•€ํ„ฐ๋ ˆ์ŠคํŠธ ์ฐธ๊ณ )
  • font : ๋‘ฅ๊ทผ๋ชจ๊ผด

์ปดํฌ๋„ŒํŠธ

  • App.vue : ์ตœ์ƒ๋‹จ ์ปดํฌ๋„ŒํŠธ
  • components
    • Option
      • OnOffToggle.vue : ์™ธ๋ž˜์–ด ์˜ต์…˜ ํ† ๊ธ€ ๋ฒ„ํŠผ
      • SelectTextLen.vue : ์ตœ์†Œ ๊ธ€์ž์ˆ˜ ์˜ต์…˜ ๋ผ๋””์˜ค ๋ฒ„ํŠผ
    • Introduce.vue : ๋งจ ์ฒ˜์Œ ๋ฃฐ ์„ค๋ช…ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ (1)
    • SelectOption.vue : Next ํด๋ฆญ์‹œ ๋‚˜์˜ค๋Š” ์˜ต์…˜ ์„ ํƒ ์ปดํฌ๋„ŒํŠธ (2)
    • GameStage.vue : ๋๋ง์ž‡๊ธฐ ์ง„ํ–‰์ค‘ ๋ณด์—ฌ์ง€๋Š” ์ปดํฌ๋„ŒํŠธ (3)
    • Lose.vue : ํŒจ๋ฐฐ ํ™”๋ฉด (4)
    • Win.vue : ์Šน๋ฆฌ ํ™”๋ฉด (5)

๊ตฌํ˜„ ์„ค๋ช…

โœ… App.vue

  • ํ™”๋ฉด์˜ ๋‹จ๊ณ„๊ฐ€ ์ง„ํ–‰๋  ๋•Œ๋งˆ๋‹ค emit์œผ๋กœ ํ˜„์žฌ ์ง„ํ–‰ ์ƒํƒœ๋ฅผ ์ตœ์ƒ๋‹จ์ธ app์— ์ „๋‹ฌํ•œ๋‹ค.
  • status ๋ฅผ ํ†ตํ•ด ํ˜„์žฌ ํ™”๋ฉด์— ๋ณด์—ฌ์งˆ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฒฐ์ •๋œ๋‹ค.
<div class="realScreenArea">
    <Introduce v-if="status === 1" @status-change="StatusChange"/>
    <SelectOptions v-else-if="status === 2" @status-change="StatusChange" @set-game-options="setGameOption"/>
    <GameStage v-else-if="status === 3"
               :foreign="foreign"
               :textLen="textLen"
               @status-change="StatusChange"
               />
    <Lose v-else-if="status === 4"/>
    <Win v-else-if="status === 5"/>
</div>

โœ… Introduce.vue

front-Chrome-2021-06-20-20-38-27

  • ์ฒซ ํ™”๋ฉด์—์„œ ๊ฒŒ์ž„ ๊ทœ์น™์„ ์„ค๋ช…ํ•˜๊ณ , Next ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
  • ๋ฒ„ํŠผ์— ๋งˆ์šฐ์Šค ์˜ค๋ฒ„์‹œ ์ƒ‰ ๋ณ€ํ™”, ๊ทธ๋ฆผ์ž ํšจ๊ณผ๋ฅผ ์ค€๋‹ค.
<template>
  <div>
    <div>
      <h3 class="subHeadline">์ฟต์ฟต๋”ฐ</h3>
      <div>
        <div>1. ์ž…๋ ฅํ•˜๋Š” ๋‹จ์–ด๊ฐ€ ๊ตญ๋ฆฝ๊ตญ์–ด์› ์‚ฌ์ „์— ๋“ฑ์žฌ๋œ ๋‹จ์–ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.</div>
        <div>2. ํ•œ๋ฐฉ ๋‹จ์–ด ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค</div>
        <div>3. ๋‘์Œ ๋ฒ•์น™์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. (ex. ๋ฆผ -> ์ž„) </div>
        <div>4. ์ค‘๋ณต ๋‹จ์–ด ์‚ฌ์šฉ ๋ถˆ๊ฐ€ </div>
      </div>
      <br>
      <br>
      <div class="Button" @click="Next">Next</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Introduce',
  methods: {
    Next() {
      this.$emit('status-change', 2)
    }
  }

}
</script>

<style scoped>
.Button {
  color: white;
  font-size: 30px;
  background-color: rgb(81, 112, 24);
  border-radius: 10px;
  text-align: center;
  width: 300px;
  height: 60px;
  padding-top: 5px;
  margin: 0px auto;
  transform: translate(0px, 20px);
  transition-duration: 0.1s;
  cursor: pointer;
}

.Button:hover {
  background-color: rgb(101, 139, 30);
  box-shadow: 1px 5px 0px rgba(0, 0, 0, 0.119);
}
</style>

โœ… SelectOption.vue > OnOffToggle.vue

front-Chrome-2021-06-20-20-44-17

  • OnOff toggle ๊ธฐ๋Šฅ
  • ๋’ท ๋ฐฐ๊ฒฝ, ๊ธ€์ž, ์› ์„ธ๊ฐ€์ง€์˜ ์œ„์น˜ ์„ค์ •์„ ์œ„ํ•ด z-index๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. z-index๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฐ˜๋“œ์‹œ position ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค.
  • ์›์˜ ๋ถ€๋“œ๋Ÿฌ์šด ์ด๋™์„ ์œ„ํ•ด transition ์†์„ฑ์„ ์„ค์ •ํ•œ๋‹ค. ๊ธฐ๋ณธ์ด ๋˜๋Š” ์Šคํƒ€์ผ ์„ค์ •์— transition ์†์„ฑ์„ ์ž‘์„ฑํ•ด๋‘๋ฉด, ์Šคํƒ€์ผ์ด ๋ณ€๊ฒฝ๋ ๋•Œ ์• ๋‹ˆ๋ฉ”์ด์…˜์ฒ˜๋Ÿผ ๋ณด์—ฌ์ง„๋‹ค.
<template>
  <div style="height: 2rem; position: relative;">
    <div :class="{ optionBody: true, optionBodyTrue: option, optionBodyFalse: !option}" @click="toggleOption">
      <div class="optionText">
        <p v-if="option">On</p>
        <p v-else>Off</p>
      </div>
      <div :class="{ optionCircle: true, optionCircleTrue: option, optionCircleFalse: !option}"></div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'OnOffToggle',
  data() {
    return {
      option: 1,
    }
  },
  methods: {
    toggleOption() {
      this.option = (this.option + 1) % 2 // 1 -> 0, 0 -> 1
      this.$emit('foreign-option', this.option)
    }
  }
}
</script>

<style>
.optionBody{
  width: 5.5rem;
  height: 2rem;
  border-radius: 15px;
  z-index: 0;
  position: absolute;
  cursor: pointer;
  transition-duration: 0.5s;
}

.optionBodyTrue{
  background-color: #FFC107;
}

.optionBodyFalse{
  background-color: #bebebe;
}

.optionText{
  padding-top: 4px;
  padding-left: 34px;
  z-index: 1;
  position: absolute;
}

.optionCircle {
  margin-top: 3px;
  margin-right: 3px;
  margin-left: 3px;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background-color: white;
  z-index: 2;
  position: relative;
  transition-duration: 0.5s;
}

.optionCircleTrue {
  transform: translate(57px, 0px)
}

.optionCircleFalse {
  transform: translate(1px, 0px)
}
</style>

โœ… SelectOption.vue > SelectTextLen.vue

  • ์ฒดํฌ ๋ฐ•์Šค์˜ ์š”์†Œ๋ฅผ ํ•œ๊ฐœ๋งŒ ์„ ํƒํ•˜๊ฒŒ ํ• ๋•Œ๋Š” radio๋กœ ํ•˜๋ฉด ๋œ๋‹ค. ์ค‘๋ณต ์„ ํƒ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด checkbox๋กœ ์„ค์ •ํ•˜๋ฉด ๋œ๋‹ค.
  • type์„ radio๋กœ, name์„ ๋ชจ๋‘ ๋™์ผํ•˜๊ฒŒ ํ•˜๊ณ  v-model์„ ์„ค์ •ํ•˜๋ฉด, ์„ ํƒ๋œ ์š”์†Œ๋ฅผ ๋ณ€์ˆ˜ ํ•œ๊ฐœ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
  • str์„ num์œผ๋กœ ๋ฐ”๊พธ๋Š” ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ str*1์„ ํ•ด์„œ ์ž๋™ํ˜•๋ณ€ํ™˜ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
  • watch๋กœ ์„ ํƒ๋œ radio ์š”์†Œ๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค emit ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.
<template>
  <div>
    <div class="checkBox">
      <div>
        <label for="2">2๊ธ€์ž</label>
        <input id="2" name="textLen" v-model="selectedValue" value="2" type="radio">
      </div>
      <div>
        <label for="3">3๊ธ€์ž</label>
        <input id="3" name="textLen" v-model="selectedValue" value="3" type="radio">
      </div>
      <div>
        <label for="4">4๊ธ€์ž</label>
        <input id="4" name="textLen" v-model="selectedValue" value="4" type="radio">
      </div>
      <div>
        <label for="5">5๊ธ€์ž</label>
        <input id="5" name="textLen" v-model="selectedValue" value="5" type="radio">
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'SelectTextLen',
  data(){
    return {
      selectedValue: 2
    }
  },
  watch: {
    selectedValue() {
      this.$emit('textlen-option', this.selectedValue*1) // ์ž๋™ํ˜•๋ณ€ํ™˜!
    }
  }
}
</script>

โœ… GameStage.vue

  • ๋งํ’์„ ์€ ์ด ์‚ฌ์ดํŠธ๋ฅผ ์ฐธ๊ณ ํ–ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž ์ž…๋ ฅ์€ v-model๋กœ ์—ฐ๊ฒฐํ–ˆ๋‹ค.
  • ์—”ํ„ฐ๋ฅผ ๋ˆ„๋ฅด๋ฉด ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค. ์„œ๋ฒ„์—์„œ ๋Œ์•„์˜ค๋Š” ์‘๋‹ต์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ํ‘œ์‹œํ•œ๋‹ค.
  • props๋กœ ๋ฐ›์€ ์™ธ๋ž˜์–ด ํ—ˆ์šฉ ์˜ต์…˜๊ณผ ์ตœ์†Œ ๊ธ€์ž์ˆ˜ ์˜ต์…˜์„ axios ์š”์ฒญ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
<template>
  <div>
    <h3 class="subHeadline">์ฟต์ฟต๋”ฐ</h3>
    <div class="d-flex justify-content-between">
      <div class="d-flex flex-column align-items-start">
        <span class="player-speech-bubble">{{ inputTxt }}</span>
        <div class="d-flex flex-column align-items-center">
          <img src="@/assets/player.png" alt="">
          <div>player</div>
        </div>
      </div>

      <div class="d-flex flex-column align-items-end justify-content-between">
        <span class="ai-speech-bubble"> {{ AItxt }} </span>
        <div class="d-flex flex-column align-items-center">
          <img src="@/assets/AI.png" alt="">
          <div>AI</div>
        </div>
      </div>
    </div>
    <br>
    <div class="input-group mb-3">
      <input @keyup.enter="UserInput" type="text" class="form-control" v-model="inputTxt" aria-describedby="button-addon" autofocus>
      <button @click="UserInput" class="btn btn-outline-success" type="button" id="button-addon">์ฟต์ฟต๋”ฐ!</button>
    </div>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  name: 'GameStage',
  data() {
    return {
      inputTxt: '',
      AItxt: '...'
    }
  },
  props: {
    foreign: {
      type: Number
    },
    textLen: {
      type: Number
    }
  },
  methods: {
    UserInput(){
      axios.post(`${process.env.VUE_APP_API_URL}word/user/${this.foreign}/${this.textLen}/`, {content: this.inputTxt})
        .then(res => {
          // ํ†ต๊ณผ
          if (res.data.result === 1) {
            this.AItxt = '...' // AI ์ƒ๊ฐ์ค‘
            this.AIInput()// AI์˜ ์ž…๋ ฅ ์š”์ฒญ ๋ณด๋‚ด๊ธฐ
          } else { // Lose ํ™”๋ฉด ๋„์šฐ๊ธฐ
            this.$emit('status-change', 4)
            console.log('๋‹น์‹ ์ด ์กŒ์Šต๋‹ˆ๋‹ค.', res.data.msg)
          }
        })
        .catch(err => {
          console.log(err)
        })

    },
    AIInput(){
      axios.post(`${process.env.VUE_APP_API_URL}word/ai/${this.foreign}/${this.textLen}/`)
        .then(res => {
          // ํ†ต๊ณผ
          if (res.data.result === 1) {
            this.AItxt = res.data.word // AI ์ž…๋ ฅ ๋งํ’์„ ์— ์—…๋ฐ์ดํŠธ
            this.inputTxt = '' // ์ธํ’‹ ๋น„์šฐ๊ธฐ
          } else { // Win ํ™”๋ฉด ๋„์šฐ๊ธฐ
            this.$emit('status-change', 5)
            console.log('๋‹น์‹ ์ด ์ด๊ฒผ์Šต๋‹ˆ๋‹ค.', res.data.msg)
          }
        })
        .catch(err => {
          console.log(err)
        })

    }
  }
}
</script>

์ƒ์„ธ๋‚ด์šฉ _ back

install

django-cors-headers==3.7.0
djangorestframework==3.12.4
bs4==0.0.1
requests==2.25.1
...

settings

  • corsheaders
    • ์„œ๋กœ ๋‹ค๋ฅธ origin (ip๋Š” ๊ฐ™์ง€๋งŒ, ํฌํŠธ๋ฒˆํ˜ธ๊ฐ€ ๋‹ค๋ฆ„. ํ”„๋ก ํŠธ 8080, ์„œ๋ฒ„ 8000) ์—์„œ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์ฃผ๊ณ  ๋ฐ›์„ ๋•Œ ํ•„์š”
    • ์„œ๋ฒ„๋Š” ์ƒ๊ด€ ์—†๋Š”๋ฐ ๋ธŒ๋ผ์šฐ์ €์—์„œ CORS ์˜ค๋ฅ˜๊ฐ€ ๋œจ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜๋“œ์‹œ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.
INSTALLED_APPS = [
    'word',
    'corsheaders',
    'rest_framework',
    ...
]

MIDDLEWARE = [
    ..
    'corsheaders.middleware.CorsMiddleware', # CORS ์ถ”๊ฐ€
    'django.middleware.common.CommonMiddleware',
    ..
]

CORS_ALLOW_ALL_ORIGINS = True

urls

urlpatterns = [
    path('user/<int:foreign>/<int:txtlen>/', views.user_input), # ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๊ฒ€์ฆ ๋ฐ ์ €์žฅ
    path('ai/<int:foreign>/<int:txtlen>/', views.ai_input), # AI ์ž…๋ ฅ ๊ฒ€์ฆ ๋ฐ ์ €์žฅ
    path('reset/', views.reset), # ๋ฆฌ์…‹
]

views

  • ์‚ฌ์šฉ์ž ์ž…๋ ฅ

    1. ์ค‘๋ณต ๋‹จ์–ด๊ฐ€ ์žˆ๋Š”์ง€
    2. ๋๋ง์ž‡๊ธฐ ๊ทœ์น™์— ์žˆ๋Š”์ง€
    3. ๊ตญ๋ฆฝ๊ตญ์–ด์›์— ๋“ฑ์žฌ๋˜์–ด ์žˆ๊ณ , ์„ ํƒํ•œ ์˜ต์…˜์— ๋งž๋Š”์ง€
    • ์œ„ 3๊ฐ€์ง€๊ฐ€ ๋ชจ๋‘ ๋งŒ์กฑํ•˜๋Š” ๊ฒฝ์šฐ DB์— ์ €์žฅ, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์‚ฌ์šฉ์ž์˜ ํŒจ๋ฐฐ!
  • AI ์ž…๋ ฅ : ์‚ฌ์šฉ์ž ์ž…๋ ฅ์˜ ๋ ๊ธ€์ž๋กœ ํƒ์ƒ‰

    1. ๊ทธ ๋‹จ์–ด๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ธ€์ž๊ฐ€ ์žˆ๋Š”์ง€
      • ์žˆ๋‹ค๋ฉด ๊ทธ ์ค‘์— ๋žœ๋ค 1๊ฐœ ์ถœ๋ ฅ
      • ์—†๋‹ค๋ฉด, ๋‘์Œ ๋ฒ•์น™ ์ ์šฉ ํ•˜๊ธฐ ( ใ„น -> ใ…‡ , ใ„ด -> ใ…‡)
        • ๋‘์Œ๋ฒ•์น™ ์ ์šฉํ•œ ๊ธ€์ž๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋‹จ์–ด๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ทธ์ค‘์— ๋žœ๋ค 1๊ฐœ ์ถœ๋ ฅ
        • ๋‘์Œ๋ฒ•์น™ ๋ถˆ๊ฐ€ or ๋‘์Œ๋ฒ•์น™ํ•ด๋„ ์—†๋‹ค๋ฉด -> ์‚ฌ์šฉ์ž์˜ ์Šน๋ฆฌ!

๋งˆ๋ฌด๋ฆฌ

  • ํ”„๋ก ํŠธ ๊พธ๋ฏธ๋Š”๋ฐ ์‹œ๊ฐ„์ด ๊ต‰์žฅํžˆ ์˜ค๋ž˜ ๋“ค์—ˆ๋‹ค. ๋ ˆ์ด์•„์›ƒ์„ ์•ˆ์งœ๊ณ  ๊พธ๋ฏธ๋ฉด์„œ ๋™์‹œ์— ํ•˜๋‹ˆ๊นŒ ์ง„๋„๊ฐ€ ์•ˆ๋‚˜๊ฐ„๋‹ค.
  • ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๊ธฐํš ๋‹จ๊ณ„์—์„œ ๋””์ž์ธ์ด๋‚˜ ๋ ˆ์ด์•„์›ƒ์„ ๋ฌด์กฐ๊ฑด ๋จผ์ € ์งœ๊ณ  ๋ ˆํผ๋Ÿฐ์Šค๋กœ ๋งŒ๋“ค์–ด์„œ ๊ทธ๋Œ€๋กœ ๋”ฐ๋ผ ๊ฐ€๋Š” ๊ฒŒ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.
  • onoff ํ† ๊ธ€์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ์—ˆ์ง€๋งŒ, ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณด๊ธฐ๋กœ ํ–ˆ๊ณ  ์„ฑ๊ณตํ–ˆ๋‹ค. ํšจ์œจ์ ์ธ์ง€๋Š” ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์€ ๊ฒƒ ๊ฐ™๋‹ค.
  • ํ”„๋ก ํŠธ ํ•˜๋‹จ์— ๋ฒ„ํŠผ๋“ค๋„ ์ง์ ‘ js, css, html๋กœ ๋งŒ๋“ค์–ด์„œ ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ๋ฅผ ์ฃผ๊ณ  ์‹ถ์—ˆ์ง€๋งŒ, ์‹œ๊ฐ„๊ด€๊ณ„์ƒ ํฌํ† ์ƒต์œผ๋กœ ์ด๋ฏธ์ง€ ๋งŒ๋“ค์–ด์„œ ๋ถ™์—ฌ๋„ฃ์—ˆ๋‹ค.
  • vue, django ์•ˆ์“ด์ง€ ํ•œ๋‹ฌ ์•ˆ๋˜์—ˆ๋Š”๋ฐ ๋ฒŒ์จ ๋ช‡๋ช‡ ๊ฐ€๋ฌผ๊ฐ€๋ฌผํ–ˆ๋‹ค. ์ฃผ๋ง์—๋Š” ํ”„๋กœ์ ํŠธ ํ•˜๋‚˜์”ฉ ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

About

[Project๐Ÿ—‚] AI์™€ ํ•˜๋Š” ๋๋ง์ž‡๊ธฐ! ์ธ๊ฐ„์€ AI๋ฅผ ์ด๊ธธ ์ˆ˜ ์žˆ์„๊นŒ?!

Topics

Resources

Stars

Watchers

Forks