JPA 개념

[강의] 자바 ORM 표준 JPA 프로그래밍 - 기본편

JPA 개념

ORM(Object-Relational Mapping)

  • 우리가 일반 적으로 알고 있는 애플리케이션 Class와 RDB(Relational DataBase)의 테이블을 매핑(연결)한다는 뜻이며, 기술적으로는 어플리케이션의 객체를 RDB 테이블에 자동으로 영속화 해주는 것이라고 보면된다.

Untitled

JPA(Java Persistence API)

  • Java 진영에서 ORM(Object-Relational Mapping) 기술 표준으로 사용하는 인터페이스 모음

  • 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스

  • 인터페이스 이기 때문에 Hibernate, OpenJPA 등이 JPA를 구현함

  • data 가져다 DB에 넣는 것처럼, 객체를 DB에 넣을 수 있지 않을까? ⇒ JPA

Untitled

Untitled

Untitled

Untitled


생산성 - JPA와 CRUD

  • 저장 : JPA.persist (member)
  • 조회 : Member member = jpa.find (member Id)
  • 수정 : member.setName (”변경할 이름”)
  • 삭제 : jpa.remove (member)

Untitled

Untitled

Untitled

  • 어떤 것을 설명하는지 잘??

Untitled

Untitled


JPA 성능 최적화 기능

  • 1차 캐시와 동일성 (identify) 보장
  • 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
  • 지연 로딩(Lazy Loading)

Untitled

Untitled

Untitled

Untitled

Vue Cli 실습

[인프런 강의] Vue.js 시작하기 - Age of Vue.js

  • 기존의 서버가 실행되고 있다면 종료 : Ctrl + c

  • 터미널을 새로 연다 → command prompt 터미널

  • 프로젝트 생성 : vue create vue-form

  • 옵션 : vue2 선택

  • 경로 이동 : cd vue-form

  • 서버 실행 : npm run serve

  • 출력된 주소로 이동한다

  • 생성된 프로젝트 확인

  • HelloWorld.vue 제거

  • App.vue에서 코드 작성

    • 첫 생성 상태의 코드 삭제
    • 기본 코드 생성 : vueinit Tab
  • 기본 틀 생성

  • 코드 - App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template lang="">
<form action="">
<div>
<label for="username">id: </label>
<input id="username" type="text">
</div>

<div>
<label for="password">pw: </label>
<input id="password" type="password">
</div>

<button>login</button>

</form>
</template>
<script>
export default {

}
</script>
<style lang="">

</style>
  • 화면

Untitled

  • 입력 창과 컴포넌트에 같은 값이 담기도록 연결한다
    • 태그 출력 부에 v-model 사용
    • JS 부에 함수 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<label for="username">id: </label>
<input id="username" type="text" v-model="username">

...
...

<script>
export default {
data: function(){
return {
username: ''
, password: ''
}
}

}
</script>
  • 입력한 값과 같은 값이 컴포넌트에 담긴다

Untitled

  • login 버튼 클릭 → 두 입력 창의 값을 들고 오게 해야 한다
  • 버튼에 type=”submit” 추가
  • 함수 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
<button type="submit">login</button>

...
...
...

, methods:{
submitForm: function(event){
// 버튼 클릭시 새로 고침 되는 것을 막는다
event.preventDefault();
console.log(this.username, this.password);
}
}
  • 잠시 서버 종료 : Ctrl + c
  • axios 다운로드 : npm i axios

Untitled

  • axios import : import axios from ‘axios’;
  • 전체 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<template>
<form v-on:submit.prevent="submitForm">
<div>
<label for="username">id: </label>
<input id="username" type="text" v-model="username">
</div>
<div>
<label for="password">pw: </label>
<input id="password" type="password" v-model="password">
</div>
<button type="submit">login</button>
</form>
</template>

<script>
import axios from 'axios';

export default {
data: function () {
return {
username: ''
, password: ''
}
},
methods: {
submitForm: function () {
// 새로고침을 막는 명령어
// event.preventDefault();
console.log(this.username, this.password);
var url = 'https://jsonplaceholder.typicode.com/users';
var data = {
username: this.username,
password: this.password
}
axios.post(url, data)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
}
}
</script>

<style></style>
  • 결과
  • 입력한 값이 버튼 클릭과 동시에 넘어감을 확인

Untitled

Vue Cli

[인프런 강의] Vue.js 시작하기 - Age of Vue.js

Vue CLI 공식 사이트 링크

CLI란?

  • CLI = Command Line Interface

설치 방법

  • 구글링 : vue cli
  • Vue CLI 공식페이지 → Installation → 설치 코드 복사

Untitled

  • VSCode → 터미널 → 새 터미널
  • 버전 확인
1
2
3
4
// 10 이상인 버전이어야 한다
node -v
// 6 이상인 버전이어야 한다
npm -v
  • 설치 코드 복사 붙여넣기
1
2
3
4
npm install -g @vue/cli

// 권한이 없다면 다음 코드 실행
sudo npm install -g @vue/cli
  • 설치에 시간이 걸릴 수 있다. 대기한다.

Untitled

CLI 버전별 차이

  • VUE CLI 2.X

    • vue init ‘프로젝트 템플릿 유형’ ‘프로젝트 폴더 위치’
    • vue init webpack-simple ‘프로젝트 폴더 위치’
  • VUE CLI 3.X

    • vue create ‘프로젝트 폴더 위치’
    • 더 간단하다

CLI 사용법

  • VSCode → 터미널 → 새 터미널 → Command Prompt 터미널
  • 생성 : vew create [프로젝트 폴더 위치]

Untitled

  • Vue CLI 버전 4.5 이상이라면 Vue 2 선택한다

Untitled

  • 생성 성공 시 출력되는 메세지

Untitled

  • vue-cli 라는 프로젝트가 성공적으로 생성되었다.
  • 다음 명령으로 실행시킬 수 있다.
1
2
$  cd vue-cli
$ npm run serve
  • 명령 실행 후에 출력되는 주소로 이동

Untitled

  • 다음과 같이 출력되면 성공

Untitled

CLI로 생성한 프로젝트 폴더 구조 확인 및 main.js 파일 설명


  • 위 과정을 거치면서 다음과 같이 vue-cli 프로젝트가 생성되었다

Untitled

Vue 파일 구조

  • 한 파일에 HTML , JS, CSS 가 모두 들어있다
1
2
3
4
5
6
7
8
9
10
11
<template>
<!-- HTML -->
</template>

<script>
// Java Script
</script>

<style>
/* CSS */
</style>

개발할 때 고려해야 할 점

  • VSCord 플러그인 설치

    • Vue 3 Snippets
    • Vue 파일에서 ! Tab 과 같은 역할을 한다.
    • vueinit 입력하고 Tab
  • 서버 실행 명령에 의해 출력되는 주소에 App.vue 의 코드가 반영된다

  • 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template lang="">
<div>
app
</div>
</template>

<script>
export default {

}
</script>

<style lang="">
</style>
  • 결과

Untitled

script의 문자 데이터를 화면에 출력

  • 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template lang="">
<div>
{{ str }}
</div>
</template>

<script>
export default {
data: function(){
return{
str: 'hi'
}
}
}
</script>

<style lang="">
</style>
  • 결과

Untitled

싱글 컴포넌트 체계에서 컴포넌트 등록하기


  • components 폴더 하위에 생성해야 한다

  • 파일 생성 : AppHeader.vue

  • 코드 - AppHeader.vue

  • ‘renew’ 라는 이름으로 $emit 한다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<header>
<h1>{{ propsdata }}</h1>
<button v-on:click="sendEvent">send</button>
</header>
</template>

<script>
export default {
props: ['propsdata']
,methods: {
sendEvent: function () {
this.$emit('renew');
}
}
}
</script>

<style></style>
  • 코드 - App.vue
  • AppHeader.vue의 $emit을 받아서 renewStr 함수를 실행
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
<div>
<!-- <app-header v-bind:프롭스 속성 이름="상위 컴포넌트의 데이터 이름"></app-header> -->
<app-header v-bind:propsdata="str" v-on:renew="renewStr"></app-header>
</div>
</template>

<script>
// 사용할 컴포넌트를 import 한다
import AppHeader from './components/AppHeader.vue';

export default {
data: function () {
return {
str: 'Header'
}
},
components: {
'app-header': AppHeader
},
methods: {
renewStr: function () {
this.str = 'hi';
}
}
}
</script>

<style></style>
  • 결과
  • 버튼 클릭 → 문자 Header가 hi로 변경된다

Untitled

템플릿

Vue 라우터

[인프런 강의] Vue.js 시작하기 - Age of Vue.js

뷰 라우터

  • 뷰 라이브러를 이용하여 싱글 페이지 에플리케이션을 구현할 때 사용하는 라이브러리

싱글 페이지 에플리케이션

  • 싱글 페이지 애플리케이션은 서버로부터 완전한 새로운 페이지를 불러오지 않는다
  • 현재의 페이지를 동적으로 다시 작성함으로써 사용자와 소통하는 웹 애플리케이션이나 웹사이트를 말한다

뷰 라우터 사용법

Untitled

  • 파일 작성 : router.html
    • Vue.js 가 위
    • Vue router가 아래
    • 순서가 중요하다!
1
2
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router@3.5.3/dist/vue-router.js"></script>
  • 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="app"></div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router@3.5.3/dist/vue-router.js"></script>
<script>
var routerOne = new **VueRouter**({

});

new Vue({
el: '#app'
, **router**: routerOne
});

</script>
  • 결과
  • router 확인 가능

Untitled

Router 속성


  • routes : 페이지의 라우팅 정보. 배열 형태로 담긴다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var routerOne = new VueRouter({
// 페이지의 라우팅 정보
routes : [
// 로그인 페이지 정보
{
// 페이지의 url
path: '/login'
// 해당 url에서 표시될 컴포넌트
, component: LoginComponent
}
// 메인 페이지 정보
, {
path: '/main'
, component: MainComponent
}
]

});
  • 코드
  • router-view 라는 설정되어 있는 태그를 사용하는 듯하다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<div id="app">
<router-view></router-view>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router@3.5.3/dist/vue-router.js"></script>
<script>
var LoginComponent ={
template : '<div>login</div>'
}

var MainComponent ={
template : '<div>main</div>'
}

var routerOne = new VueRouter({
// 페이지의 라우팅 정보
routes : [
// 로그인 페이지 정보
{
// 페이지의 url
path: '/login'
// 해당 url에서 표시될 컴포넌트
, component: LoginComponent
}
// 메인 페이지 정보
, {
path: '/main'
, component: MainComponent
}
]

});

new Vue({
el: '#app'
, router: routerOne
});

</script>
  • 결과
  • 주소 창에 입력해줘야 한다
    • login
    • main

Untitled

라우터 링크


  • 링크로 사용하는 라우터
  • 코드
    • 위 코드에서
      태그 부분만 변경한다
    • router-view 와 같이 설정되어 있는 고유의 태그router-link 사용한다
1
2
3
4
5
6
7
8
<div id="app">
<div>
<!-- <a href="" ...> 로 쓰는 앵커 태그와 같은 역할 -->
<router-link to="/login">Login</router-link>
<router-link to="/main">Main</router-link>
</div>
<router-view></router-view>
</div>

참고자료

1
2
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router@3.5.3/dist/vue-router.js"></script>

Vue 컴포넌트

[인프런 강의] Vue.js 시작하기 - Age of Vue.js

Vue 컴포넌트

  • 화면의 영역을 구분하여 개발하는 기능
  • 코드의 재사용성이 올라가고 빠르게 화면을 제작 가능

Untitled

  • 컴포넌트 등록 코드
1
Vue.component('컴포넌트 이름', '컴포넌트 내용');

전역 Component

  • 파일 생성 : component.html
  • 직접 태그를 생성할 수 있다
  • 태그 내에 생성한 태그 적용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div id="app">
<app-header></app-header>
<app-content></app-content>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 전역 컴포넌트
Vue.component('app-header', {
template: '<h1>Header</h1>'
});

Vue.component('app-content', {
template: '<div>content</div>'
})

new Vue({
el: '#app'
});

</script>
  • 결과
  • Root 아래로 하위 Component 가 생성되었다.

Untitled

지역 Component

  • 실제로 가장 많이 사용되는 방식
  • 문법
1
2
3
4
5
6
7
8
9
10
// 전역 컴포넌트
Vue.component('컴포넌트 이름', 컴포넌트 내용);

// **지역 컴포넌트**
new Vue({
el: '#app',
components: {
'컴포넌트 이름' : 컴포넌트 내용
}
});
  • 실제 지역 컴포넌트 등록, 출력
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="app">
<app-footer></app-footer>
</div>

<script>
new Vue({
el: '#app',
// 지역 컴포넌트 등록 방식
components: {
// '컴포넌트 이름' : 컴포넌트 내용
'app-footer': {
template: '<footer>footer</footer>'
}
}
});
</script>
  • 결과

Untitled

Component 통신

  • 프롭스 속성 : 상위에서 하위로는 데이터를 내려줌
  • 이벤트 발생 : 하위에서 상위로는 이벤트를 올려줌

Untitled

  • 데이터의 흐름을 추적할 수 있다.
    • 이벤트는 올라간다
    • 데이터는 내려간다

Untitled

실습

  • 데이터를 내려본다
  • 파일 생성 : props.html
  • 코드 작성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
var appHeader = {
template: '<h1>header</h1>'
}

new Vue({
el: '#app',
components: {
'app-header': appHeader
},
data: {
message: 'hi'
}
})

</script>
  • root에서 관리하는 데이터 (메세지 : ‘hi’ ) 가 보인다
  • 해당 데이터를 app-header 컴포넌트에 내려볼 예정이다

Untitled

  • 문법
  • v-bind: 프롭스 속성 이름=“상위 컴포넌트의 데이터 이름”
1
2
3
<div id="app">
<app-header v-bind:프롭스 속성 이름="상위 컴포넌트의 데이터 이름"></app-header>
</div>
  • 코드
  • 데이터를 받을 변수 이름을 설정해주는 듯하다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div id="app">
<!-- <app-header v-bind:프롭스 속성 이름="상위 컴포넌트의 데이터 이름"></app-header> -->
<app-header v-bind:propsdata="message"></app-header>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var appHeader = {
template: '<h1>header</h1>'
, **props: ['propsdata']**
}

new Vue({
el: '#app',
components: {
'app-header': appHeader
},
data: {
message: 'hi'
}
})

</script>
  • 결과
  • Root의 데이터가 AppHeader로 잘 내려갔다

Untitled

Props 데이터


데이터 바인딩

1
2
3
4
var appHeader = {
template: '<h1>{{ propsdata }}</h1>'
, props: ['propsdata']
}
  • 결과
  • Root에서 수정 시, 화면, 하위 컴포넌트에 모두 반영된다

Untitled

여러 데이터를 서로 다른 하위 컴포넌트에 내려보내기


  • new Vue의 데이터 안에 변수 생성
  • 태그 등록 부에 설정 추가
  • 태그 출력 부에 props 설정 추가
  • 데이터 바인딩
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<div id="app">
<!-- <app-header v-bind:프롭스 속성 이름="상위 컴포넌트의 데이터 이름"></app-header> -->
<app-header v-bind:propsdata="message"></app-header>
<app-content v-bind:propsdata="num"></app-content>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
var appHeader = {
template: '<h1>{{ propsdata }}</h1>'
, props: ['propsdata']
}
var appContent = {
template : '<div>{{ propsdata }}</div>'
, props: ['propsdata']
}

new Vue({
el: '#app',
components: {
'app-header': appHeader
, 'app-content': appContent
},
data: {
message: 'hi'
, num: 10
}

})

</script>
  • 결과

Untitled

이벤트 올리기


  • 데이터는 내려 보낸다.
  • 이벤트는 올려 보낸다.
  • 파일 생성 : event-emit.html
  • 문법 : **v-on:하위 컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메서드 이름"**
  • 코드 작성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div id="app">
<app-header></app-header>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>

var appHeader = {
template: '<button v-on:click="passEvent">click me</button>'
, methods: {
passEvent: function(){
this.$emit('pass');
}
}
}

new Vue({
el: '#app'
, components: {
'app-header': appHeader
}
});

</script>
  • 결과

  • Vue → event 에서 확인가능

Untitled

Untitled

이벤트 올리기2


  • 버튼 클릭시 log 출력 : hihi
  • pass 라는 이벤트 발생을 조건으로 태그에 설정 추가
  • logText라는 mothods의 실행을 태그에 설정 추가
  • 문법 : **v-on:하위 컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메서드 이름"**
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<div id="app">
<!-- <app-header v-on:하위 컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메서드 이름"></app-header> -->
<app-header v-on:pass="logText"></app-header>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>

var appHeader = {
template: '<button v-on:click="passEvent">click me</button>'
, methods: {
passEvent: function(){
this.$emit('pass');
}
}
}

new Vue({
el: '#app'
, components: {
'app-header': appHeader
}
, methods: {
logText: function(){
console.log('hihi');
}
}
});

</script>
  • 결과

Untitled

이벤트 : 숫자 증가


  • 버튼 클릭마다 숫자를 1만큼 늘려 본다
  • 할 일
    • 해당 기능을 가질 버튼을 만든다
    • new Vue의 data에 숫자 데이터를 만든다
    • new Vue의 methods에 숫자 증가 함수를 만든다
    • 태그 출력 부에 조건과 실행 함수를 설정해준다
  • 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<div id="app">
<!-- <app-header v-on:하위 컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메서드 이름"></app-header> -->
<app-header v-on:pass="logText"></app-header>
<app-content v-on:increase="increaseNumber"></app-content>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>

var appHeader = {
template: '<button v-on:click="passEvent">click me</button>'
, methods: {
passEvent: function(){
this.$emit('pass');
}
}
}

var appContent = {
template: '<button v-on:click="addNumber">add</button>'
, methods: {
addNumber : function(){
this.$emit('increase');
}
}
}

new Vue({
el: '#app'
, components: {
'app-header': appHeader
, 'app-content' : appContent
}
, methods: {
logText: function(){
console.log('hihi');
}
, increaseNumber: function () {
this.num = this.num + 1;
}
}
, data: {
num: 10
}
});

</script>
  • 결과
  • 버튼 클릭할 때마다 num값이 증가한다
  • 단 event 메뉴를 갔다 와야 변경된 점이 반영된다

Untitled

같은 레벨에서의 컴포넌트 통신 방법


  • 같은 레벨끼리 바로 통신은 불가능
  • Root를 거쳐서 통신해야 한다

Untitled

  • 파일 작성 : component-same-level.html
  • 1단계 : 코드 작성- Root로 숫자 10 보내기
    • this.num을 이용해 컴포넌트의 mothods에 담긴 값 10을 넘겨준다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<div id="app">
<app-header v-bind:프롭스 속성 이름="상위 컴포넌트의 데이터 이름"></app-header>
<app-content v-on:pass="deliverNum"></app-content>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var appHeader = {
template: '<div>header</div>'
}

var appContent = {
template: '<div>content<button v-on:click="passNum">pass</button></div>'
, methods: {
passNum: function(){
this.$emit('pass', 10);
}
}
}

new Vue({
el: '#app'
, components: {
'app-header': appHeader
, 'app-content': appContent
}
, data: {
num: 0
}
, methods: {
deliverNum: function(value){
this.num = value;
}
}
})

</script>
  • 코드 작성
  • 2단계 : 코드 작성- Root에서 해당 컴포넌트로 숫자 10 보내기
    • props속성을 정의해주고 Root에서 10을 넘겨준다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<div id="app">
<!-- <app-header v-bind:프롭스 속성 이름="상위 컴포넌트의 데이터 이름"></app-header> -->
<app-header v-bind:propsdata="num"></app-header>
<app-content v-on:pass="deliverNum"></app-content>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var appHeader = {
template: '<div>header</div>'
, props: ['propsdata']

}

var appContent = {
template: '<div>content<button v-on:click="passNum">pass</button></div>'
, methods: {
passNum: function(){
this.$emit('pass', 10);
}
}
}

new Vue({
el: '#app'
, components: {
'app-header': appHeader
, 'app-content': appContent
}
, data: {
num: 0
}
, methods: {
deliverNum: function(value){
this.num = value;
}
}
})

</script>
  • 결과
  • appHeader 컴포넌트에 10이 전달되었다

Untitled

Vue 인스턴스

[인프런 강의] Vue.js 시작하기 - Age of Vue.js

인스턴스

  • 인스턴스는 Vue로 개발할 때 필수로 생성해야 하는 코드
1
new Vue();
  • 생성 후에 콘솔 창에서 확인 가능
1
2
var vm = new Vue();
console.log(vm);
  • 파일 생성 : instance.html
  • 코드 작성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app">
<!-- -->
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'hi'
}
});

</script>
  • 결과

Untitled

생성자 함수

  • 함수 이름의 첫 이니셜이 대문자이다
  • 콘솔 창에서 코딩
1
2
3
4
5
6
function Person(name, job){
this.name = name;
this.job = job;
}

var p = new Person('josh', 'developer');

Untitled

  • 미리 함수를 정의한다
  • 정의된 함수를 언제든 가져다 사용 가능하다
  • 이것이 new Vue()사용하는 이유

Untitled

인스턴스 속성

  • 인스턴스에서 사용할 수 있는 속성과 API는 다음과 같다
1
2
3
4
5
6
7
8
9
new Vue({
el: ,
template: ,
data: ,
methods: ,
created: ,
watch: ,

});
  • el : 인스턴스가 그려지는 화면의 시작점 (특정 HTML 태그)
  • template : 화면에 표시할 요소(HTML, CSS 등)
  • data : 뷰의 반응성(Reactivity)가 반영된 데이터 속성
  • methods : 화면의 동작과 이벤트 로직을 제어하는 메서드
  • created : 뷰의 라이프 사이클과 관련된 속성
  • watch : data에서 정의한 속성이 변화했을 때 추가 동작을 수행할 수 있게 정의하는 속성

Vue.js 기초 개념

[인프런 강의] Vue.js 시작하기 - Age of Vue.js

Vue는 무엇인가?

  • View = HTML. 브라우저에서 사용자에게 보여지는 요소들 (버튼, 입력 창 등)
  • DOM = HTML 은 DOM을 이용해 JAVA Script로 조작할 수 있게 구성된다.
  • Vue
    • DOM Listneners = View 의 이벤트를 청취하여 JavaScript의 데이터를 바꿔주거나 특정 로직을 실행한다
    • Data Biindings = JavaScript에서 관련 로직을 실행하고 View에 반영한다

Untitled

실습1

  • 폴더 생성

  • 파일 생성 : web-dev.html

  • 기본 코드 생성 : ! + TAB

  • 패널 토글 : *Ctrl + *

  • 쉽게 작성 예시 : div#app 입력한 후에 Enter

  • console.log 가 div 태그의 정보를 받아와서 출력한다

1
2
3
4
5
6
7
8
9
10
11
<div id="app"></div>

<script>

var div = document.querySelector('#app');
console.log(div);
div.innerHTML = 'hello world';

str = 'hello world!!!'; // 여기까지만 작성하면 !!!는 반영되지 않는다
div.innerHTML = str;
</script>
  • 서버 실행
  • F12
  • Console 칸에서 결과 확인

Untitled

실습2

1
2
3
4
Object.defineProperty(대상 객체, 객체의 속성, {


})
  • 사용 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="app"></div>

<script>
var div = document.querySelector('#app');
var viewModel = {};

Object.defineProperty(viewModel, 'str', {
// 속성에 접글했을 때의 동작을 정의
get: function(){
console.log('접근');

},
// 속성에 값을 할당했을 때의 동작을 정의
set: function(newValue){
console.log('할당', newValue);

}

})
</script>
  • 결과

Untitled

  • set:function 수정
1
2
3
4
5
// 속성에 값을 할당했을 때의 동작을 정의
set: function(newValue){
console.log('할당', newValue);
**div.innerHTML = newValue;**
}
  • 결과
  • 실행 결과 곧바로 화면에 반영!
  • data binding
    • = Re Activity 특성

Untitled

  • 위에서 작성한 코드를 함수에 담는다
  • 그 함수를 즉시 실행 함수 문법에 담는다 : (function() { … } )();
  • div.innerHTML = newValue; 부분을 render(newValue)로 대체한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
(function() {
function init() {

Object.defineProperty(viewModel, 'str', {
// 속성에 접글했을 때의 동작을 정의
get: function () {
console.log('접근');

},
// 속성에 값을 할당했을 때의 동작을 정의
set: function (newValue) {
console.log('할당', newValue);
// div.innerHTML = newValue;
**render(newValue);**
}
});
}

function **render**(value) {
div.innerHTML = value;
}

init();

})();
  • 결과

Untitled

Vue 개발자 도구 사용법

  • getting-started → index.html
  • vue.js 스크립트를 들고 와서 실행하는 간단한 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Getting Started</title>
</head>
<body>
<div id="app">
{{ message }}
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js'
}
})
</script>
</body>
</html>
  • 라이브 서버 실행

  • Vue 개발자 도구 확인

    • Vue → Components

    Untitled

  • data 변경 가능

    • 화면에 반영된다

Untitled


Slot

랜더링(Rendering)

  • 읽어들인 코드를 웹 표준에 맞게, 화면에 적절히 그려내는 중요 구성요소
  • 즉, HTML, CSS, JS 등을 통해 만든 페이지가 브라우저에서 보여지게 되는 것
  • https://velog.io/@plum3526/랜더링Rendering

Vue.js 기초 환경설정

[인프런 강의] Vue.js 시작하기 - Age of Vue.js

사전 설치 목록


  • chrome 브라우저 설치
  • Visual Studio 설치
  • Node.js 설치
    • LTS 선택해서 다운로드
  • Vue.js devtools
    • 크롬 확장 프로그램

vue.js 강의 수강 기록


git repository

VSCode 확장 프로그램(플러그인) 설치

  • 좌측 메뉴에서 extention 클릭
  • 설치할 프로그램 검색 후 설치
  • Vetur
    • Vue tooling for VS Code
  • Material Icon Theme
    • 아이콘 테마
  • night owl
    • 코드 강조
  • Live server
    • Launch a development local Server with live reload feature for static & dynamic pages
    • 정적 및 동적 페이지에 대한 실시간 로드 기능이 있는 개발 로컬 서버 시작
  • Vue 3 Snippets
    • Vue 파일에서 ! Tab 과 같은 역할을 한다.

Untitled

필수는 아니지만 있으면 좋은 플러그인

  • ESLint
    • Integrates ESLint JavaScript into VS Code.
  • Prettier
    • Code formatter using prettier
  • Auto Close Tag
    • Visual Studio IDE 또는 Sublime Text와 동일한 HTML/XML 닫기 태그 자동 추가
  • Atom Keymap
    • Popular Atom keybindings for Visual Studio Code

테마 관련 플러그인 적용

  • 설치 후 VSCode 다시 시작
  • extension
  • 설치한 테마 플러그인 → 테마 설정

Untitled

Live Server 사용

  • 확인할 html 파일을 우 클릭 → Open with Live Server

Untitled

  • 결과

Untitled

Vue 개발자 도구 ( Vetur )

  • html 페이지 출력 한 곳에서 우클릭 → 검사 or F12
  • Vue 클릭

Untitled

  • 확인 가능

Untitled

JAVA lamda

재귀함수

  • 자신을 정의할 때 자신을 리턴하는 함수

  • 다시(재) 귀한(귀) 하는 함수

  • 실습1

  • 인자로 받은 숫자까지 1식 증가하는 모든 수를 더한 수를 리턴하는 함수를 만든다

    예) 함수(3) = 1 + 2 + 3 = 6

    // 단, 반복문 사용 금지.재귀함수로 풀이한다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Main {

public static void main(String[] args) {

System.out.println(reFunc(100));

}

static public int reFunc(int num) {

if(num>1) {
num = num + reFunc(num-1);
return num;
}else {
return num;
}
}
}

컬렉션(Collection)

자료 : https://st-lab.tistory.com/240

  • 자바에서 미리 만들어놓은 데이터를 수집하고 관리(추가 ,생성 ,삭제 ,초기화 ,크기 ,리스트)해주는 목적의 클래스와 인터페이스

  • 왜 사용하는가?

    • 일관된 API
    • 프로그래밍의 노력 감소
    • 프로그램 속도 및 품질 향상
  • 선언법
    (중요) 컬렉션종류<데이터타입> 이름 = new 컬렉션종류<데이터타입>();
    예) HashSet<String> set = new HashSet<String>();

[객체 리스트]

  • Set

  • 구현클래스 : HashSet, TreeSet, LinkedHashSet

  • 중학교때 배웠던 “집합”. 순서가 없다. 데이터의 중복을 허용하지 않는다.

  • Hash : 임의의 길이를 갖는 데이터를 고정된 길이의 데이터로 변환(매핑)하는 것

  • 해쉬는 유니크함을 보장하기 때문에 순회할 필요가 없다.

  • 동일한 입력값에 대해서는 동일한 결과값(다이제스트)를 갖는다.

  • 이 다이제스트의 값을 index로 활용한다.

    • 함수 : equals(), hashCode(), removeAll(), contains(값), remove(값) add(), size()
    • 정의예 : HashSet<String> alphabetSet = new HashSet<>();
      for(String spell: alphabet){
      alphabetSet.add(spell);
      }
  • HashSet의 add() = 중복된 값은 추가하지 않는다

  • Set.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    import java.util.HashSet;
    // 함수 : equals(), hashCode(), removeAll(), contains(값),
    // remove(값) add(), size()

    public class Set {

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    String[] alphabet = {"a", "b", "c", "d", "e", "f", "g", "g", "a"};

    HashSet<String> alphabetSet = new HashSet<>();
    HashSet<String> alphabetSet2 = new HashSet<>();

    for(String spell: alphabet) {
    alphabetSet.add(spell);
    alphabetSet2.add(spell);
    }

    alphabetSet.add("z"); // 중복없이 추가
    alphabetSet.remove("z");

    System.out.println(alphabetSet); // 중복없이 출력
    System.out.println(alphabetSet.contains("h"));
    System.out.println(alphabetSet.size());
    System.out.println(alphabetSet.equals(alphabetSet2));

    }

    }

  • List

  • 구현클래스 : ArrayList, LinkedList, Vector

  • 순서가 있는 데이터의 집합으로 데이터의 중복을 허용

    • 함수 : add(값), addAll(리스트), remove(인덱스), clear(), size()
      get(인덱스), indexOf(값), lastIndexOf(값)
  • 반복문과 결합 : 향상된for문 for(자료형 이름 : 리스트)
    while(iterator.hasNext())

  • 예제)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

// ArrayList 선언
ArrayList<Integer> al = new ArrayList<Integer>();

// ArrayList에 데이터 입력
for (int i = 1; i <= 5; i++)
al.add(i);

// 결과 출력
System.out.println(al); //[1, 2, 3, 4, 5]

// **인덱스 제거**하기
al.remove(3);

// **값으로 제거**하기
al.remove(al.indexOf(5));
al.remove(Integer.valueOf(3)); // 값 지우기 : 오버로딩 사용
System.out.println(al);

// 결과 출력
System.out.println(al); //[1, 2, 3, 5]

// 하나씩 가져와서 결과 출력
for (int i = 0; i < al.size(); i++)
System.out.print(al.get(i) + " "); //1 2 3 5

  • Queue
  • 구현클래스 : LinkedList, PriorityQueue
  • Map
  • 구현클래스 : Hashtable, HashMap, TreeMap
  • 키(Key), 값(Value)의 쌍으로 이루어진 데이터의 집합
  • 함수 리스트
    add(), remove(), clear(), size()
    • // 직접 위의 함수들 구현해보는 것도 좋은 공부다
    • private int[] nums, private int current;

String 문자열 클래스

  • 이제야 눈에 보이는 스트링. 원시타입이 아니다 (헷갈리지 않게 조심)
  • 자바에서 컬렉션으로 만들어 놓은 자료구조다
  • charAt(), compareTo(), concat(), indexOf(), trim(), toLowerCase(), toUpperCase(), substring, length(), isEmpty(), contains() 문자의 위치반환 없으면-1, matches(정규식) 등의 함수가 있다
  • 스트링은 값이 달라질 때 새로운 객체를 만들어서 할당받는다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

//자바에서 문자열1에서 문자열2를 포함한 갯수 찾기
```java
public int getCountInclude(String str1, String str2){
boolean include = true;
int count = 0;
include = str1.contains(str2); //포함되었는지 참,거짓 판단
while(include) { //포함되었다면
count++;
int where = str1.indexOf(str2); //시작하는 위치 파악
str1 = str1.substring(where+str2.length());
System.out.println("str1 : "+str1);
//방금 찾은 거를 빼고 남은 문자열을 부모로 업데이트
//substring 함수는 인자가 하나면 해당 위치부터 이후로 끝까지 자르는 함수
include = str1.contains(str2);
}
return count;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

### 제네릭(Generic)

- 뜻 : 포괄적인, 일반적인
- Object 를 만들면 사용(저장, 로드)하기전에 형변환 작업을 해줘야 하는 불편함이 존재한다.
- 범용 컬렉션의 장점과 특화된 클래스의 장점을 모두 겸비한 템플릿.
- Java5에서 추가
- 컬렉션, 람다식, 스트림, NIO(New IO)등에서 널리 사용되므로 제네릭을 이해하지 못하면 API 문서를 정확히 이해할 수 없다.

- 목적
- 자료형을 일반화. 정의시가 아니라 인스턴스 생성시 자료형을 결정하도록 한다.
- 우리가 어떤 자료구조를 만들어서 배포하려고 할때 '여러 데이터타입을 지원하고 싶다.' 그러면 String에 대한 클래스, Integer에 대한 클래스 등등을 하나하나 타입별로 만들어줘야하나? 너무 비효율적이다.

- 제네릭은 이런 문제를 해결해준다.
- 그렇게 강조했던 메소드의 정의와 호출 다시한번 보자. 어떤 이름으로 넘어오든지 정의한 영역내에서는 이 이름으로 쓰겠다는 뜻이었던가?
- 마찬가지로 제너릭이라는 것은 어떤 데이터타입으로 넘어오든지 이 정의한 영역내에는 넘어온 그 데이터타입으로 쓰겠다 라고 하는것이다.
- 즉 데이터형을 정의시 명시하지 않고 호출할때 정할 수 있도록 일반화 한것이다.
- 클래스 내부에서 지정하지 않고 외부에서 지정도록 한 것이다.
- 엄밀히 말하자면 컴파일때 해당 타입으로 캐스팅하는 것이다.

- 사용 예시

```java
import java.util.List;
import java.util.ArrayList;

public class 제네릭 {
// 함수의 정의와 호출이 다르다. 파라미터와 아큐먼트는 다르다


public static void main(String[] args) {

//일반
List list = new ArrayList();
list.add("hello");
String str = (String)list.get(0);
System.out.println(str);

//제네릭사용한 코드 < 데이터 타입>
List<String> list2 = new ArrayList<String>();
list2.add("hello");
String str2 = list2.get(0);
System.out.println(str2);

}


}
1
2
3
4
5
6
7
public class Box<T>{
// 클래스 뒤에 <T> 타입 파라미터를 명시했기 때문에 변수의 타입으로 사용 가능합니다.
private T t;
public T get() { return t; }
public void set(T t){ this.t = t; }
}

  • 특징

  • 보편적(암묵적)으로 매개변수의 타입으로는 아래의 이름을 쓴다.
    : Element
    : Key
    : Number
    : Type
    : Value

  • 특정범위 내로 좁혀서 제한하고 싶다면 extends, super, ? 를 활용한다.

  • 예를 들어서, 이면 T타입의 조상만 가능하고 K로 쓰겠다는 말이다.

  • 문법

  • 정의 : 클래스 또는 인터페이스 이름 뒤에 <타입파라미터>

  • 생략하면 컴파일러가 제네릭 관련 문장에서 자료형의 이름을 추론한다. 이걸 다이아몬드 표시라고 한다.

  • 타입 파라미터로 명시할수 있는 것은 참조타입만 가능하다.

  • 여러 개의 타입변수는 쉼표로 구분하여 명시한다.

  • 사용 : 본문에서 그 이름을 데이터타입처럼 사용하면 된다.

  • 장점

  1. 런타임에 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지함
  2. 반환값에 대한 타입 변환(캐스팅) 및 타입검사에 들어가는 노력 줄어듬
  3. 코드의 재사용성이 높아

람다식(Lamda Expression)

  • 자바8에 함수적 프로그래밍 기법으로 도입됨. 람다가 포함되면서 자바가 완전해졌다고 말하는 이가 있을 정도
  • 익명함수를 생성하기 위한 식
  • y = f(x) 형태를 (타입 매개변수) -> { 실행문 } 으로 정의
    좋든 싫든 자바의 람다식은 선택이 아닌 필수가 되었다
  • 장점 : 1. 코드가 매우 간결해진다
    2. 인스턴스 생성안하고 기능하나만 필요할 때
    3. 컬렉션요소를 매핑해서 쉽게 집계할 수 있다
  • 단점 : 1. 가독성이 안좋아진다

2.함수이름이 없기 때문에 stacktrace보고 디버깅하기 어렵다
3. 이 함수가 있음을 인식하기가 어렵다

  • 결론 : 저런 단점들 때문에 고급개발자는 람다식 쓰지 말라 하는 사람 많다
  • 코드가 3줄안에 끝나고 단 한번만 쓰임을 보장할 수 있고 행동이 명확할 때만 제한적으로 사용
  • 문법 : 인풋데이터 -> 함수본문
    • 예 :1. 줄임이 없는 예
      (String s) -> { System.out.println(s); }

      1. 매개변수가 하나일 때 괄호생략. 본문이 하나일 때 중괄호와 세미콜론 생략
        s -> System.out.println(s)
        (a,b) -> a+b

      2. 제네릭으로 사용한 예
        Calculate<Integer> ci = (a,b) -> a+b;
        System.out.println(ci.cal(4,3));

JAVA thread

상수와 enum

  • final 키워드

  • final에 초기값을 줄 수 있는 경우는 2가지 뿐이다

  • 필드선언 시, 생성자

  • 초기화되지 않은 final 필드가 남아있으면 컴파일 에러

  • 진짜 상수는 static final로 선언. 객체마다 저장할 필요가 없으며 다른값으로 바꿀 수도 없기 때문

  • 명명규칙 : 대문자에 언더바 조합

  • enum은 열거형(Enumeration). 상수의 그룹을 나타낸다.

  • 주목적 : 우리만의 데이터 타입을 가지기 위해서

  • 모든 enum들은 내부적으로 java.lang.Enum 클래스에 의해 상속된다.

  • 만드는 문법 : enum 열거체이름 { 상수1이름, 상수2이름, ... }

    • 예) enum Rainbow { RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET }
  • 사용문법 : 열거체이름.상수이름

    • Rainbow.RED
  • 메소드

  • values() 모든 상수 배열로 반환

    • 예) Rainbow[] arr = Rainbow.**values**();
  • ordinal() 상수 인덱스 반환.

    • 예) int idx = Rainbow.YELLOW.**ordinal**();
  • valueOf() 상수 문자 값 반환

    • 예) Rainbow rb = Rainbow.**valueOf**("GREEN");

실습-enum

  • Main.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Main {

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    String 요일 = "TUESDAY";
    Test t1 = new Test(Day.valueOf(요일));
    t1.요일평가();
    }
    }
  • Test.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public class Test {

    Day day;

    public Test(Day day) {
    this.day = day;
    }

    public void 요일평가() {
    switch(day) {
    case MONDAY:
    System.out.println("월요일은 좋지 않음");
    break;
    case FRIDAY:
    System.out.println("금요일은 좋음");
    break;
    case SATURDAY:
    case SUNDAY:
    System.out.println("주말은 최고지");
    break;
    default:
    System.out.println("평법합니다.");
    break;
    }
    }
    }
  • Day.java

    1
    2
    3
    4
    5
    6
    	// 문법 : enum 이름{값 값 값}
    public enum Day {

    SUNDAY, MONDAY, TUESDAY, WHEDNESDAY, THURSDAY, FRIDAY, SATURDAY

    }

사전지식

  • 프로그램 : 어떤 작업을 위해 실행할 수 있는 파일
  • 프로세스 : 실행되고 있는 프로그램. 실행되기 위해서는 메모리에 올라와야 한다. 프로세스는 운영체제로부터 자원을 할당받는다. 1개의 프로세스는 최소 1개의 스레드를 가지고있다.
    • 예) 크롬을 켜서 유튜브를 보고있는동시에 마우스를 움직이는 동시에 파일은 다운 받아지고 있다.
    • 예) 햄버거를 시키면 그릴에서 고기를 굽고, 음료수는 기계에서, 감자튀김은 튀김기에서.

Thread

  • 쓰레드 : 하나의 프로세스내에서 돌아가는 병행적인 메소드

  • 쓰레드는 프로세스내에서 Stack영역만 따로 할당받고 Code, Data, Heap영역은 공유한다. 즉, 프로세스내의 여러자원들을 공유하면서 실행된다.

  • 모든 자바어플리케이션은 Main Thread가 main()메소드를 실행하면서 시작한다.

    • 멀티 쓰레드의 장점 : 시스템자원의 효율성 증대, 처리량 증가, 응답시간 단축, 통신의 부담 감소
    • 멀티 쓰레드의 단점 : 주의깊은 설계, 까다로운 디버깅, 동기화문제, 하나의 쓰레드가 잘못되어도 프로그램이 멈춤
  • 멀티 프로세스 대신 멀티쓰레드를 사용하는 이유

  • 위에서 말한 쓰레드의 장점.

  • 생성방법 2가지

    1. Thread상속 (java.lang.Thread)
    2. Runnable 인터페이스를 구현
  • 대표적인 메소드

  • sleep, start, join, run 이 있다.

  • 호출시 실행하는 메소드는 start해주지만 쓰레드가 실제 돌아갈때는 오버라이드하는 run이 돌아간다.

  • run을 통해 실행시키면 stack으로 쌓여서 병행처리가 안된다. 해당메소드가 종료되어야 다른 스레드가 실행된다.

  • start를 통해 실행해야 정상적인 병행처리가 된다.

  • 쓰레드를 start하면 바로 실행하는것이 아니라 실행대기상태에 있따가 OS의 스케쥴러가 작성한 스케줄에 의해 순서대로 자기 차례에 실행되는 구조다.

  • 쓰레드의 상태 6가지. getState()를 하면 알 수 있다.

    • NEW
    • RUNNABLE
    • BLOCKED
    • WAITING
    • TIMED_WAITING
    • TERMINATED
  • 쓰레드의 종료

  • 쓰레드는 자신의 run메소드가 모두 실행되면 자동적으로 종료된다.

  • 그런데 run메소드의 끝까지 가기전에 ‘즉시 종료’ 해야한다면 boolean으로 된 플래그를 사용하거나 interrupt()메소드를 이용하는 방법이 있다

  • interrupt() 메소드는 InterruptedException 예외를 발생시키는데, 주의해야할점은 interrupt메소드를 이용하기위해서는 종료시키고 싶은 메소드가 일시정지상태일때 정지된다는것이다.

  • 돌아가고있는 중에서는 정지가 안된다.

실습 - Thread

  • Runnable 인터페이스 사용

  • checkThread.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class checkThread implements Runnable {
    String name;

    public checkThread(String name) {
    this.name = name;
    }

    @Override
    public void run() {
    for(int i=0; i<5; i++) {
    try {
    System.out.println(name);
    Thread.sleep(1000); // 1000 밀리세컨드 == 1초
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    System.out.println(name + "쓰레드 종료");
    }

    }
  • Main.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class Main {

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    Runnable d1 = new checkThread("피카츄"); // 다형성
    Runnable d2 = new checkThread("꼬부기");
    Runnable d3 = new checkThread("파이리");
    Runnable d4 = new checkThread("롱스톤");

    Thread thread1 = new Thread(d1);
    Thread thread2 = new Thread(d2);
    Thread thread3 = new Thread(d3);
    Thread thread4 = new Thread(d4);

    thread1.start();
    thread2.start();
    thread3.start();
    thread4.start();

    }
    }
  • 코드 실행시 4개의 쓰레드 순서가 바뀌기도 한다

Untitled

실습 - Thread 타이머

  • 시간을 이용한 프로그래밍

  • < 5판 3선승제 - 컴퓨터와 가위바위보 게임>

  • 이겼다 / 졌다 판단해서 출력

  • 위의 개발에다가 방금 배운 쓰레드로 타이머 만들기 원래는 사용자의 입력을 받을때까지 아무작업 안하고 기다렸는데 멀티쓰레드로 타이머가 돌아가면서 3초 안에 입력 안하면 지게 만들기

  • Thread 클래스 상속하여 사용

  • 정답지

  • GameControl.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    import java.util.Scanner;

    public class GameControl {

    public static boolean inputCheck = false; //유저가 입력 했는지

    static int life = 999; //남은목숨. 컴퓨터가 이기면 1감소
    static int totalGameCount = 1; //총 게임진행횟수
    static int win=0; //유저의 승리횟수
    static int draw=0; //비김
    static int lose=0; //유저의 패배횟수

    public static void main(String[] args) {
    GameTimer timer = null;
    GameControl gc = new GameControl();
    String computersChoice = null; //컴퓨터의 선택
    String usersChoice = null; // 유저의 선택

    // 난수를 이용하여 컴퓨터의 가위 바위 보를 정한다.
    String[] data = {"가위", "바위", "보"};

    while(win<3 && lose<3) { //누구 하나라도 해당횟수의 승리를 하게되면 중단
    timer = new GameTimer(totalGameCount); //게임진행횟수를 인자로줌. 매번 새로운 타이머 생성
    timer.start();
    usersChoice = gc.choiceRSP(); //유저입력 true로 바꾸는 작업도 안에서 한다.
    computersChoice = data[(int) (Math.random()*3)]; //0.000001~2.9999999니까 0,1,2
    System.out.println("\n"+gc.judge(usersChoice,computersChoice));
    gc.showScore();
    totalGameCount++;
    }
    gc.printGameOver();

    }

    //유저에게 가위바위보중 하나를 입력받도록 한다.
    public String choiceRSP() {
    System.out.println("\n****가위, 바위, 보 중 무엇을 내겠습니까?****");
    Scanner sc = new Scanner(System.in);
    String result = sc.nextLine();
    if(!result.equals("가위") && !result.equals("바위") && !result.equals("보")) {
    System.out.println("가위바위보 중에 하나를 입력해주세요.");
    }else {
    inputCheck = true; // 정상적인 가위바위보를 냈을때 입력이 완료로 변경
    }
    return result;
    }

    //결과 판단하기
    public String judge(String usersChoice, String computersChoice) {
    System.out.printf("당신은 %s를 내고 컴퓨터는 %s를 냈습니다.", usersChoice, computersChoice);
    inputCheck = false; //이것이 핵심이였음!!!!!!!!!!!!
    if( usersChoice.equals(computersChoice) ){
    draw++;
    return "비김";
    }else if( (usersChoice.equals("가위") && computersChoice.equals("보"))
    || (usersChoice.equals("바위") && computersChoice.equals("가위"))
    || (usersChoice.equals("보") && computersChoice.equals("바위")) ){
    win++;
    return "승리";
    }else{
    life--;
    lose++;
    return "패배";
    }
    }

    public void showScore() {
    System.out.printf("총%s판(%d승 %d무 %d패)\n", totalGameCount, win, draw, lose);
    }

    public void printGameOver() {
    System.out.println("게임이 끝났습니다.");
    if(win>lose) {
    System.out.println("당신이 이겼습니다.");
    }else {
    System.out.println("컴퓨터가 이겼습니다.");
    }
    }
    }
  • GameTimer.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    public class GameTimer extends Thread{
    int gameCount=0;
    public GameTimer(int now) { //몇번째 게임에 만들어진 타이머인가
    super();
    this.gameCount = now;
    }

    @Override
    public void run() {
    for(int i=5; i>=1; i--){
    /* 여러번 경기를 할때 어려움이 발생하는 지점
    * inputCheck를 true로 하면 다음 타이머 작동안하고,
    * false로 하면 이전것이 살아있어서 남아있는 초를 출력하게 된다.
    * 타이머는 5초를 셀 뿐이다. 타이머의 제어는 타이머의 외부에서 일어나도록 하자. 객체지향적으로
    */

    if(GameControl.inputCheck==true || gameCount!=GameControl.totalGameCount){
    //유저가 입력했거나 타이머가 자동한게임회차와 본게임의 회차가 다르면
    return; //run함수를 나가버리면 쓰레드는 자신이 가지고있는 자원을 정상적으로 반납하며 종료된다.
    }
    try {
    System.out.println(i); //타임 출력
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    //System.exit(0); //타이머가 끝났다고 시스템이 끝나면안되지.
    System.out.println(this.getName()+" 시간초과");
    }
    }
  • 나의 풀이

  • 단, GameTimer는 그대로 사용

  • Main.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    import java.util.Random;
    import java.util.Scanner;
    import java.util.Timer;
    import java.util.TimerTask;

    public class Main {
    public static boolean inputCheck = false;
    static int totalGameCount = 1;
    static int win=0;
    static int lose=0;
    static int draw=0;
    static int select=10;
    static int count=0;
    static int rand=0;

    public static void main(String[] args) {
    // TODO Auto-generated method stub
    GameTimer timer = null;
    Main gc = new Main();
    System.out.println("게임을 시작합니다.");
    Random random = new Random();

    while(win<3 && lose<3) {

    timer = new GameTimer(totalGameCount); //게임진행횟수를 인자로줌. 매번 새로운 타이머 생성
    timer.start();
    select = gc.choiceRSP(); //유저입력 true로 바꾸는 작업도 안에서 한다.
    rand =random.nextInt(3)+1;
    gc.judge(select, rand);

    totalGameCount++;
    }

    matchResult();
    }

    public int choiceRSP() {
    System.out.printf("1. 가위 \n2. 바위\n3. 보\n");
    System.out.printf("선택지 중에서 하나를 선택해주세요 : ");
    Scanner scanner = new Scanner(System.in);
    select = scanner.nextInt();
    return select;
    }

    public void judge(int select, int a) {

    inputCheck = false; //이것이 핵심이였음!!!!!!!!!!!!
    String pc="";
    String me="";
    String[] arr = {"scissor", "rock", "paper"};
    me = arr[select-1];
    pc = arr[a-1];
    System.out.println("==============");
    System.out.println("나 : " + me);
    System.out.println("컴퓨터 : " + pc);

    switch(select-1) {
    case 0:
    if(pc==arr[1]) {
    System.out.println("결과 : 패배");
    lose++;
    }else if(pc==arr[2]) {
    System.out.printf("결과 : 승리!!! > %d승\n", ++win);
    }else {
    System.out.println("결과 : 무승부");
    }
    break;
    case 1:
    if(pc==arr[0]) {
    System.out.printf("결과 : 승리!!! > %d승\n", ++win);
    }else if(pc==arr[2]) {
    System.out.println("결과 : 패배");
    lose++;
    }else {
    System.out.println("결과 : 무승부");
    }
    break;
    case 2:
    if(pc==arr[0]) {
    System.out.println("결과 : 패배");
    lose++;
    }else if(pc==arr[1]) {
    System.out.printf("결과 : 승리!!! > %d승\n", ++win);
    }else {
    System.out.println("결과 : 무승부");
    }
    break;
    default:
    break;
    }
    System.out.println("==============");
    }

    static public void matchResult() {
    System.out.println("==============");
    System.out.println("==============");
    System.out.printf("최종 전적 : %d승 / %d패\n", win, lose);
    }
    }
  • GameTimer.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    public class GameTimer extends Thread{
    int gameCount=0;


    public GameTimer(int now) { //몇번째 게임에 만들어진 타이머인가
    super();
    this.gameCount = now;
    }

    @Override
    public void run() {
    for(int i=5; i>=1; i--){
    /* 여러번 경기를 할때 어려움이 발생하는 지점
    * inputCheck를 true로 하면 다음 타이머 작동안하고,
    * false로 하면 이전것이 살아있어서 남아있는 초를 출력하게 된다.
    * 타이머는 5초를 셀 뿐이다. 타이머의 제어는 타이머의 외부에서 일어나도록 하자. 객체지향적으로
    */

    if(Main.inputCheck==true || gameCount!=Main.totalGameCount){
    //유저가 입력했거나 타이머가 자동한게임회차와 본게임의 회차가 다르면
    return; //run함수를 나가버리면 쓰레드는 자신이 가지고있는 자원을 정상적으로 반납하며 종료된다.
    }
    try {
    System.out.println(i); //타임 출력
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    //System.exit(0); //타이머가 끝났다고 시스템이 끝나면안되지.
    System.out.println(this.getName()+" 시간초과");
    }
    }