* 두서없는 메모.

 

간만에 svn 사용하는 프로젝트에서 삽질할 일이 생겼다.

 

배포를 하는데, class 파일을 하나하나 ftp로 옮기며 운영배포를 하고,

trunc 브런치만 사용하는 숨막히는 상황을 마주하게됐다.

 

prd, stg, dev 브런치 전략을 구성하기 위해 

git에서만 사용해본 작업 흐름을 테스트해보려고 한다.

 

그래서. 간만에 svn 서버를 설치를 했는데... 

 

이거 유료였어?

 

 

45일 전체기능을 체험해보고 이후에는 제한이 된다는 건가?

 

일단 설치를 했다.

 

 

 

프로젝트를 만들어서 테스트를 해보자

그냥 눈에띄는 아무거자 주워담아 만든 테스트 프로젝트

 

 

연결이 잘 안되는건 잘못했다는것

 

프로젝트 폴더 임시로 하나 만들고 접속링크를 참조하자

 - https://127.0.0.1/svn/testRepo/trunk/testPrj

 

eclipse에 레파지토리가 잘 등록되었음

 - springboot 의존관계와 프로젝트 소스 commit 실패로 몇차례 시도.

 

 

일단 ignore 대상 무시하고 올려보자

잘못올린 소스 : ㅡ.ㅡ 바보냐. trunk 밑에 올렸어야지.

 - 번거롭지만, svn server에서 삭제하고(생략)

 - 테스트프로젝트 team 링크 끊고(생략)

 - 다시 올려보자

 

 

실행되는 프로젝트로 다시 해보자.

 

 

docker 선택시 도커없다고 혼나서 제외

mongodb 선택시 없다고 혼나서 제외

 

https://start.spring.io/starter.zip

https://start.spring.io/starter.zip?name=testPrg-1&groupId=com.jkoogi&artifactId=testPrg-1&version=0.0.1-SNAPSHOT&description=Demo+project+for+Spring+Boot&packageName=com.hmjo.jk&type=maven-project&packaging=war&javaVersion=21&language=java&bootVersion=3.3.0-M1&dependencies=lombok&dependencies=batch&dependencies=mysql&dependencies=h2&dependencies=data-jpa&dependencies=thymeleaf&dependencies=restdocs

 

 서비스 실행 성공버전.

 

 

프로젝트소스를 svn 레파지토리에 등록

 - 이렇게 넣으면 trunk에 프로젝트가 들어가지 않고, 소스가 들어간다. ㅠ.

 > 지우고 다시 넣자.

 

 

https://127.0.0.1/svn/testRepo/trunk/testPrg-1

 

 

 

 

 

 

 

'etc' 카테고리의 다른 글

git sourcetree - 작업중인 파일 목록 참조  (0) 2022.09.07

공휴일 달력표시정보 구성이 필요해서 음력 날짜를 양력 날짜로 변환하는 작업이 필요했다. 

 

인터넷을 찾아보니 몇가지 안을 도출하게 되었다. 

1. ibm에서 제공한 중국음력 유틸리티 라이브러리 참조

 - com.ibm.icu.util.ChineseCalendar 

 > 장점 : 범용적으로 많이 사용한 듯(표준프레임워크에서도 해당라이브러리를 사용하여 기능 구현) 하여 관려 자료가 많음

 > 단점 : 중국 음력과 한국 음력의 차이로 간혹 음력일자의 오차 발생 - 치명적 결함으로 비추

2. 공공API 조회

 - 한국천문연구원에서 제공하는 양력, 음력 매핑정보 조회 API를 이용하여 날짜조회

 > 장점 : 가장 정확하고 다른 기능에 부담없이 사용 가능

 > 단점 : 외부연계 필요, API 변경사항 현행화 관리 필요

3. 변환로직 직접 구현

 - 한국천문연구원에서 제공하는 음력일자를 기준으로 메타데이터를 구성하여 매핑로직 구현

 > 장점 : 이슈에 적극적으로 대응할 수 있다. (현실적 대안 : 관련 소스를 참조하여 디버깅 후 사용)

 > 단점 : 로직구현 및 천문연구원 메타정보 변경시 현행화 필요

4. 매핑정보 수동관리

 - 천문연구원에서 제공하는 날짜 대비 매핑일자를 메타정보로 관리 (테이블, 공통코드 등)

 > 장점 : 구현 및 관리에 가장 부담이 적음

 > 단점 : 매핑정보 관리 및 범용성이 떨어짐 (등록한 날짜만 사용가능)

 

서비스에서는 4번을 적극적으로 제안했지만, 3번이 현실적인 대안으로 보인다. 

* [참고1] 3번 검토자료

https://github.com/corestone/jsphelper3/blob/master/src/chk/jsphelper/util/LunarCalendarUtil.java

 - 음력 20330815 날짜 조회시 0908일이 조회되어야 하는데, 1007 로 응답된는 버그 확인
 > 80093aa

/* 2031 ~ 2040 까지 */
{ 2, 1, 5, 2, 1, 2, 2, 1, 2, 1, 2, 1, 384 }, // 2000년
{ 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 355 }, // 2000년
{ 1, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 2, 384 }, // 2000년 <-해당 메타정보
{ 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 384 }, // 2000년 <-수정 메타정보

* [참고2] 아래 블로그의 소스도 테스트한 결과 동일한 날짜에서 동일한 버그 확인

 - 아마 천문연구원에서 제공하던 메타정보가 변경된게 아닐까?

https://billcorea.tistory.com/113

 

안드로이드 앱 만들기 : 음력을 양력으로 변환 하기

예전에 어떤 앱을 만들기 할 때 사용했던 음력 변환 하는 소스를 어딘가에서 찾았던 거 같은데... 다시 한번 기억해 보기 위해서 적어 보기로 했다. https://billcorea.tistory.com/4 구글로간 음력 설명서

billcorea.tistory.com

 

* [참고3] 한국의 양력과 중국의 양력이 다를 수 있어서 ibm 라이브러리 사용을 제외하게된 참고자료

https://blog.naver.com/birdparang/221445233118

 

[자바] 양력에서 음력 변환 - ChineseCalendar 클래스가 맞지 않는 이유, 한국과 중국의 음력 차이

((year % 4) == 0 && (year % 100) != 0) || (year % 400) == 0; 위 코드는 양력의 윤년(2월 29일...

blog.naver.com

 

결론.

[참고1] 자료의 버그를 수정하여 유틸로 사용

 - 테스트 데이터 구성 : 천문연구원의 2023~2050 음력 공휴일(설날, 부처님오신날, 추석) 매핑자료 검색

 > https://astro.kasi.re.kr/life/pageView/8

(행활천문관 > 음양력변환계산 > 특정음력일찾기 : 2023~2050 음력일자 조회 결과)

 

음양력변환계산 | 생활천문관 | 천문우주지식정보

양력 날짜를 입력하여 대응하는 음력 날짜 확인 ※ 입력범위 : -59년 02월 13일 ~ 2050년 12월 31일 --> ※ 1582년 로마 교황 그레고리우스 13세는 율리우스력을 그레고리력으로 개정함에 따라 (율리우스

astro.kasi.re.kr

 

 

test 메타정보.txt
0.01MB

offline 환경에서 이클립스가 너무 느리게 동작했다.

에디터에 클릭만 해도 stop.

 

환장하것네.. 

 

그래서 이것저것 시도하다보니 효과를 본게 있어서 끄적여논다.

 

Preferences > General > Startup and Shutdown [Plug-ins activated on startup] 항목 체크해제

Preferences > Validation [The selected validators will run when validation is performed] 항목 체크해제

 

[추가]

https://winterandsnow.tistory.com/27

 

[Eclipse] JPA Project Change Event Handler (waiting) 안나오게 하는 방법

개발 도중 JPA Project Change Event Handler (waiting) 이런 메시지가 계속 나오면서 이클립스가 느려지거나 멈추는 현상이 계속 발생했습니다. 그래서 여러 방법을 시도해보고 이 방법으로 해결하였습니

winterandsnow.tistory.com

빌드만 하면 완료 상태여도 버벅이는 현상

https://tnsgud.tistory.com/332

 

이클립스(Eclipse) 실행 시 Build workspace (빌드) 느릴때(멈춤) 해결 방법 - vailidation

이클립스(Eclipse) 실행 시 Build workspace (빌드) 느릴때(멈춤) 해결 방법 - vailidation 이클립스나(Eclipse), 스프링(STS), 전자정부프레임웍(eGovFrame)를 사용하다 보면 수시로 "Building workspace" 절차가 진행 됩

tnsgud.tistory.com

 

- [Preferences] -> [Web] -> [Jsp Files] -> [Validation] -> Validate JSP fragments 해제

https://ssd0908.tistory.com/entry/%EC%9D%B4%ED%81%B4%EB%A6%BD%EC%8A%A4eclipse-%EC%84%B1%EB%8A%A5%EA%B0%9C%EC%84%A0-%EB%B0%8F-Validation-%EC%B5%9C%EC%A0%81%ED%99%94-%EC%84%A4%EC%A0%95

 

[Eclipse] 이클립스 성능개선 및 Validation 최적화 설정

이번 포스트에서는 이클립스/STS Tool 최적화에 대해서 알아보겠습니다. 개발에 앞서 이클립스 툴을 최적화 및 성능을 개선하면 개발 시간 단축 및 더 향상된 퍼포먼스를 발휘할 수 있습니다. 이

ssd0908.tistory.com

 

 

아후.. 이것저것 해보는데.. 애쓴다.

'tools' 카테고리의 다른 글

vsCode git pull request  (0) 2023.04.16
오류  (0) 2022.10.24
git. push가 갑자기 안되네.. github가 잘못했네.  (0) 2021.10.15
VSCode Workspace Trust?  (0) 2021.08.27
Visual Studio Code  (0) 2021.06.20

간만에 windows 11에 레드마인을 설치했다. 

 

bitnami redmine을 설치하는데, OS별 설치파일 다운로드 하는곳을 못찾아서 

https://bitnami.com/stack/redmine/virtual-machine

 

Redmine Virtual Machines

Bitnami VMs optimized for VMware Cloud on AWS and VMware Cloud Director are available through the VMware Marketplace. VMware Marketplace

bitnami.com

레드마인 커뮤니티에서 낮은버전을 찾아 설치했다.

http://www.redmine.or.kr/projects/community/wiki/%EB%A0%88%EB%93%9C%EB%A7%88%EC%9D%B8_%EC%84%A4%EC%B9%98(bitnami) 

 

레드마인 설치(Bitnami) - REDMINE 커뮤니티 - Redmine 커뮤니티

 

www.redmine.or.kr

 

bitnami-redmine-4.2.4-0-windows-x64-installer.exe

 

설치야 특별할게 없어서 잘 진행했는데, 

서버 포트와 db 포트를 변경하고 싶었다. 

 

간단하게 인터넷을 찾아보고 변경을 했는데, db 포트를 변경해도 안바뀌고 

dbeaver에서 변경한 포트로 접속이 안됐다.

변경을 시도하다가 이상한 에러로그때문에 잠깐 삽질을 했었지만..

더보기

[Thu Aug 31 21:58:33.018393 2023] [ssl:warn] [pid 19064:tid 444] AH01909: localhost:443:0 server certificate does NOT include an ID which matches the server name
[Thu Aug 31 21:58:33.068371 2023] [ssl:warn] [pid 19064:tid 444] AH01909: localhost:443:0 server certificate does NOT include an ID which matches the server name
[Thu Aug 31 21:58:33.086154 2023] [mpm_winnt:notice] [pid 19064:tid 444] AH00455: Apache/2.4.52 (Win64) OpenSSL/1.1.1m PHP/7.4.28 configured -- resuming normal operations
[Thu Aug 31 21:58:33.086154 2023] [mpm_winnt:notice] [pid 19064:tid 444] AH00456: Apache Lounge VC15 Server built: Dec 23 2021 11:00:40
[Thu Aug 31 21:58:33.086154 2023] [core:notice] [pid 19064:tid 444] AH00094: Command line: 'D:\\jkSpace\\redmine\\redmine-4.2.4-0\\apache2\\bin\\httpd.exe -d D:/jkSpace/redmine/redmine-4.2.4-0/apache2 -f D:\\jkSpace\\redmine\\redmine-4.2.4-0\\apache2\\conf\\httpd.conf'
[Thu Aug 31 21:58:33.091358 2023] [mpm_winnt:notice] [pid 19064:tid 444] AH00418: Parent: Created child process 17280

 

결국 설정파일 중 관련 내용을 들춰보다 변경에 성공하여 남겨둔다.

 

 

(...)\redmine-4.2.4-0\apache2\conf\httpd.conf
Listen 8000 … ServerName localhost:8000
(...)\redmine-4.2.4-0\apache2\conf\bitnami\bitnami.conf
<IfVersion < 2.3 > NameVirtualHost *:8000 NameVirtualHost *:443 </IfVersion> <VirtualHost default:8000>
(...)\redmine-4.2.4-0\apps\redmine\htdocs\config\database.yml
port: 3366
(...)\redmine-4.2.4-0\mariadb\my.ini
[mysqladmin] user=root port=3366 … datadir="D:/jkSpace/redmine/redmine-4.2.4-0/mariadb/data" port=3366
(...)\redmine-4.2.4-0\apps\redmine\conf\httpd-vhosts.conf
<VirtualHost *:8000>
(...)\redmine-4.2.4-0\apps\redmine\htdocs\config\configuration.yml
git 관련 명령 수정

 

'install > redmine' 카테고리의 다른 글

bitnami redmine 설치  (2) 2017.03.05

HTML에 기반을 둔 커스텀 엘리먼트인 컴포넌트를 제작하고 활용

컴포넌트의 상탯값 관리와 뷰 간의 이동을 도와주는 Vuex와 라우터제공

 

05-1 복잡한 로직과 computed 속성  

computed 속성 : 머스태시를 이용해 HTML 엘리먼트값 변경에 따른 연산 작업지원

 - 원본 data를 수정으로 필요성 확인

 

* 010501 [DoIt!실습] 대문자로 변환하는 프로그램 만들기

- 0105/ex05_01 > computed.html 파일 생성

<!DOCTYPE html>
<html lang="KO">
<head>
    <meta charset="UTF-8">
    <title>computed</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
    <div id="main">
        <p>원본 문장 : "{{ sOriginalMessage }}"</p>
        <p>대분자로 변환된 문장 : "{{ fnUpperCaseMsg }}"</p>
    </div>
    <script>
        new Vue({
            el:'#main',
            // data는 머스태시 안에 넣을 값이 간달할 때 사용
            data:{
                sOriginalMessage: 'How are you?'
            },
            computed:{
                // sOriginalMessage의 데이터를 모두 대문자로 변환
                // 이때 데이터에 접근하기 위해 this 사용
                fnUpperCaseMsg: function(){
                    return this.sOriginalMessage.toUpperCase();
                }
            }
        })
    </script>
    
</body>
</html>

 

* 머스태시 사용 : 문자열을 {{}} 로 감싸고 엘리먼트(P) 값 표시 
 - {{ sOriginalMessage }} : 문자열 변수 대체

 - {{ fnUpperCaseMsg }} : 함수실행결과 대체

* data 속성

 - 문자열 변수(sOriginalMessage - 속성 : JSON 형식내 값 > 뷰에서는 변수처럼 처리됨) 값 초기화

* computed 속성 : computed 속성은 캐시 메모리에 저장 - 속도개선 효과 기대

 - 머스태시 내용이 복잡한 경우 함수로 전환하여 사용

 - fnUpperCaseMsg() 함수에서 this를 사용하여 data에 정의된 변수(sOriginalMessage)를 사용하여 처리함


05-2 이벤트 핸들러 로직과 methods 속성  

* 메서드 :  뷰 인스턴스에 포함해 사용하는함수

 - methods 속성 : 이벤트 핸들러를 사용해 이벤트 실행로직 작성(마우스 클릭 등)
 - 예제 : 버튼을 누를 때마다 10부터 거꾸로 세는 예제

 > computed 속성 : 머스태시 확장할 때 사용

 > methods 속성 : 이벤트 핸들러에 사용

 

* 010502 [DoIt!실습] 카운트다운 프로그램 만들기

- 0105/ex05_02 > computed.html 파일 생성

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>mothods</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
    <div id="main">
        <p>클릭 숫자 : {{nClicks}}</p>
        <p>카운트다운 : {{fnCounter}}</p>
        <!-- 버튼을 누르면 fnIncrement 메서드 실행 -->
        <button v-on:click="fnIncrement">눌러주세요!</button>
    </div>
</body>
<script>
    new Vue({
        el:'#main',
        data:{
            nClicks:0
        },
        // computed는 머스태시 안의 로직이 복잡할 때 사용
        computed: {
            fnCounter(){
                // nClicks 값이 10을 기준으로 카운트다운 되도록 1만큼 감소시킴
                return 10 - this.nClicks;
            }
        },
        // 메서드는 이벤트 핸들러 로직을 실행할 때 사용
        methods:{
            // nClicks 값을 1만큼 증가시킴
            fnIncrement(){
                this.nClicks++;
            }
        }
    });
</script>
</html>

* 머스태시적용

 - nClicks : 클릭개수 정보 변수를 바인딩 - 엘리먼트(p)

 - fnCounter() : 카운트로 변경되는 값 반환 - 10부터 시작하는 카운트다운 처리

* v-on 디렉티브 적용

 - 버튼을 누르면 fnlncrement() 함수를 이벤트 핸들러로 연결하여 실행

 > fnlncrement() 함수의 구체적인 기능을 methods 속성에서 정의한다

* data, computed 속성

 - data : nClicks 변수 초기값 설정 - 0

 - computed : 머스태시 선언 함수 기술 - fnCounter()
 > fnCounter() 함수는 10을 기준으로 지금까지 클릭한 횟수를 저장

 > nClicks 변수값과 뺄셈을 수행

 * 머스태시에 선언된 내용의 로직이 복갑해지면 함수로 바꿔서 computed 속성에 정의

* methods 속성

 - fnlncrement() 함수 : nClicks 변수(클릭한 횟수 저장) 값을 ++ 연산자로 증가시킨 후 반환

 > data 속성에 정의된 nClicks 변수에 접근하기 위 해 this를 사용

 

* [하나만 더 배워요!] computed 속성과 methods 속성의 차이점

 - 함수 정의 시 두 속성의 역할 : 함수 실행

 • computed 속성 : 복잡한 로직으로 머스태시 작업을 함수로 정의 - 계산량이 많아 캐시가 필요할 때
 • methods 속성 : 뷰의 이벤트 핸들러 로직을 함수로 정의


05-3 컴포넌트로 HTML 엘리먼트 만들기  

* 컴포넌트(component) : HTML의 기본 엘리먼트 외에 자신만의 엘리먼트 제작 지원

 

* 컴포넌트의 동작 원리 이해하기

 - 컴포넌트 사용법 : HTML 엘리 먼트와 동일.  여는 태그 <>, 닫는 태그 </>에 적용해 사용
  > <my-element></my-element>

 - 템플릿(template) : 컴포넌트를 등록하여 엘리먼트처럼 사용
 - 컴포넌트를 신규 엘리먼트로 구성 시 화면에 표시할 부분을 대응하는 속성 : 템플릿 속성

  > 기존 HTML, CSS, 자바스크립트를 사용해서 화면에 표시할 내용 구현

  > 사용 방법 : [template:] 속성 선언 > 문자열로 HTML 문서의 내용을 작성

 ** 문자열 줄바꿈을 고려한 이스케이프 문자 사용 : 역따음표(',backtic-백틱) - 예제 참고 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>component</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
    <div id="main">
        <my-element></my-element>
    </div>
</body>

<script>
    // my-element 엘리멘트용 컴포넌트 등록
    Vue.component('my-element',{
        // 컴포넌트의 data 속성은 반드시 함수로 정의!
        data: function(){
            return {
                strHello: '안녕하세요',
            }
        },
        // 템플릿은 화면에 표시할 엘리멘트 구조를 정의
        template: `<h1>{{strHello}}</h1>`
    });
    new Vue({
        el:'#main',
    });
</script>
</html>

* 010503 [DoIt!실습] 좋아하는 과일 나열하기

- 0105/ex05_03 > component_basic.html 파일 생성

- 화면에 표시할 내용 : template 속성으로 HTML, CSS, 자바스크립트를 함께 사용하면서 작성
- 백틱을 사용한 가독성 확보
 > 예제 활용 : template, data 속성만 사용하지 만 computed, methods 속성도 활용

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>component_basic</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
    <style>
        .fruit_style {/* 테두리 스타일과 안쪽 여백을 넣어줌*/
            border: 1px solid #ccc;
            background-color: #fff;
            padding-left: 1em;
        }
    </style>
</head>
<body>
    <div id="main">
        <h1>{{ sTitle }}</h1>
        <!-- 신규 컴포넌트 엘리먼트 2개 사용 -->
        <favorite-fruits></favorite-fruits>
        <favorite-fruits></favorite-fruits>
    </div>
</body>
<script>
    // 좋아하는 과일 3개를 표시하는 컴포넌트 정의
    Vue.component('favorite-fruits',{
        // 컴포넌트의 data 속성은 반드시 함수로 정의
        data: function(){
            return {
                aFruits:[{sFruit_name:'사과'}, {sFruit_name:'오렌지'},{sFruit_name:'수박'}]
            }
        },
        // 컴포넌트 템플릿 화면에 표시할 엘리먼트 구조 정의
        template:`
        <div>
            <div v-for="item in aFruits" class="fruit_style">
                <p>좋아하는 과일:{{item.sFruit_name}}</p>
            </div><br>
        </div>`
    });
    new Vue({
        el:'#main',
        data:{
            sTitle:'안녕하세요!'
        }
    });
</script>
</html>

* 박스 스타일

 - 화면에 표시할 영역을 눈으로 쉽게 확인하기 위해 CSS 스타일 적용

 - [.fruit_ style]이라는 클래스 선택자로 경계선 구성

 > 선 : 직선, 두께 : 1px, 색상 : #ccc(회색) 설정

 > 배경색 : 흰색

* 컴포넌트 사용

 - sTitle(제목 문자열) 변수 : h1 엘리먼트의 값으로 표시.

 - h1 엘리먼트 : HTML5 예약어는 커스텀 불가

 - favorite-fruits 커스텀 엘리먼트 : HTML 엘리먼트와 같은 방식으로 사용

 > 좋아하는과일 세 가지 목록을 표시

 > 두 번 연속 사용 : 두 번 표시됨

* 컴포넌트 등록 - 뷰 객체의 component() 함수를 사용해 엘리먼트 등록

 - 매개변수1 : [favorite-fruits] 전달

 - 매개변수2 : [data, template] 속성 정의

 > data 속성 : aFruits 배열을 JSON 형식으로 정의 - 변수나 함수로 선언

 > aFruits 배열 :  sFruit_name, 과일 이름(사과, 오렌지, 수박) 항목 3개 구성

 - function() 함수에서 return 문으로 반환

** 컴포넌트에서 data 속성을 사용할 때는 반드시 함수로 사용

 - 컴포넌트 안에 data 속성을 변 수로 선언하면 실행 시 인스턴스가 생성되지 않음
 > ‘ReferenceError: aFruits is not defined’라는 오류 발생

 - 같은 컴포넌트를 여러 개 사용 시, data 속성의 변숫값들이 별도의 메모리 공간에서 개별적으로 관리되도록 하려는 의도 

 - 따라서 컴포 넌트 내부는 반드시 함수로 작성해야 합니 다.

* 컴포넌트 템플릿 작성

 - div 엘리먼트로 그룹

 - v-for 디렉티브를 사용해서 aFruits 배열 변수에 있는 항목을 하나씩 꺼내서 표시

 - p 엘리먼트에 머스태시로 바인딩하기 위해 {{ item.sFriiit_name }} 입력

 > 항목이 3개 표시, fruit_ style 클래스 선택자로 스타일 적용

 

* [하나만 더 배워요!] 목록의 구조를 잡을 때 사용하는 ul, ol, li 엘리먼트
 - ul(unordered list)과 ol(ordered list) : 목록 영역 결정
 > ul : 순서 없는 목록 - 글머리 기호 항목 앞에 표시

 - li(list) : 목록의 각 항목 표시

 > ol : 순서 있는 목록 - 항목 앞에 번호가 하나씩 커지면서 표시

<!-- ul, ol, li 엘리먼트사용 예 -->

<ul>
  <li>사과 </li> <li> 바나나 </li> <li> 수박 </li>
</ul> 

<ol>
  <li> 커피 </li> <li> 홍차 </li> <li> 녹차 </li>
</ol>




05-4 컴포넌트 속성 props  

* 컴포넌트 속성(props) : 컴포넌트에서 전달되는 어트리뷰트의 값
 - 문자열, 객체 배열 형식

 > 좋아하는과일 나열 예제 변경 : 컴포넌트 엘리먼트로 props 속성 사용

 

* 010504 [DoIt!실습] 컴포넌트 속성을 활용해 좋아하는 과일 나열하기

- 0105/ex05_04 > component_prop.html 파일 생성

 

* 뷰 컴포넌트의 어트리뷰트를 선언하는 방법, 값을 전달받아 사용하는 방법 확인

 - 뷰의 컴포넌트 기능은 HTML의 일반엘리먼트처럼 사용할 수 있으므로 기능을 무한대로 확장가능

 > 다양한 주제별로 그에 맞는 엘리먼트 설계해서 사용
 > 의미있는 컴포넌트 엘리먼트 이름으로 심플코드 개발 가능(어트리뷰트 설계 유의) : 유지보수 용이

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>component_prop</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
    <script>
        // Vue 인스턴스에 신규 엘리먼트 컴포넌트 등록
        // props에 엘리먼트에 사용될 속서 이름 선언
        // template에 전달받은 속성 객체의 text 제목을 렌더링에 활용
        Vue.component('favorite-fruits', {
            props: ['fruit'],
            template:`<li>{{ fruit.text }}</li>`
        })
    </script>
</head>
<body>
    <div id="app">
        <h1>좋아하는 과일!</h1>
        <ol>
            <!-- 
                favorite-fruits 신규 엘리먼트 사용
                aFruits 배열의 값을 반복문으로 가져와 fruit 속성에 바인딩하여 컴포넌트에 전달
                key 속성은 반드시 고유한 값으로 전달되어야 하므로 item의 id값 대입
             -->
             <favorite-fruits
              v-for="item in aFruits"
              v-bind:fruit="item"
              v-bind:key="item.id">
             </favorite-fruits>
        </ol>
    </div>
    <script>
        var app = new Vue({
            el:'#app',
            data:{
                aFruits:[
                      {id:0, text: '사과'}
                    , {id:1, text: '오렌지'}
                    , {id:2, text: '수박'}
                ]
            }
        });
    </script>
</body>
</html>

* 컴포넌트등록 

 - 컴포넌트 : HTML 엘리먼트와 동일하게 사용 - 어트리뷰트 사용가능

 > props 속성 선언

 - 선언된 이름을 다른 속성에서 전달받아 매개변수처럼 사용

* 컴포넌트 등록 (이름 : favorite-fruits)

 - props 속성에 대괄호([])를 사용해서 어트리뷰트 이름을 문자열로 선언
 > HTML에서 favorite-fruits 엘리먼트를 사용할 때 다음과 같이 fruit 어트리뷰트에 값 전달

 <favorite-fruits fruit="사과"></favorite-fruits>

* template 속성에 li 엘리먼트로 속성값 표시

 - 머스태시로 <li>{{ fruit.text }}</li> 작성 :  li 엘리먼 트값으로 바인딩
 > 속성값으로 전달받은 fruit 변수는 text 속성으로 전달

 > 유의 : props 속성에 선언하여 어트리뷰트로 전달받은 fruit 변수 : 일반 변수처럼 사용가능

* 컴포넌트사용 

 - favorite-fruits 컴포넌트를 등록 > 일반적인 HTML 엘리먼트처럼 사용

 > 소스에서는 먼저 ol로 순서 있는 목록의 영역 지정

 - 목록의 개별 항목은 li 엘리먼트 대신에 favorite-fruits 엘리먼트 사용

 > favorite-fruits 엘리먼트 : 내부적으로 li 엘리 먼트를 가지 면서 전달받은 속성값을 표시하도록 설계

 - 신규로 등록한 컴포넌트의 엘리 먼트에 어트리뷰트를 어 떻게 사용하는지 잘 표현

 - v-for 디렉티브도 사용가능 : aFruits 배열 변수에서 값을 꺼내 item에 하나씩 저장

 - v-bind 디렉티브를 사용해서 fruit 어트리뷰트에 바인딩하여 항목값을 전달

 > v-bind:key 바인딩은 v-for 디렉티브를 사용할 때는 key 어트리뷰트에 고유한 값 전달해 사용하도록 강제
 > item.id의 값을 전달하면 간단히 해결

* data 속성 

 - aFruits 배열 변수 : data 속성에 정의

 > JSON 형태로 id와 text에 번호와 과일 이름을 저장

 


05-5 상탯값 관리와 Vuex  

 

 


05-5 상탯값 관리와 Vuex  

 

 


05-6 내비게이션과 라우터  

 

 


05-7 새로 고침이 필요 없는 SPA 만들기  

 

 

드디어 뷰다뷰

04-1 뷰, 자바스크립트프레임워크의절대 강자

* 뷰 (Vue.js)

 - 2013년 출시 : 에반 유(Evan You) 개발 - 자바스크립트 프레임 워크

 - 앵귤러, 리액트에서 발견할 수 없는 콤팩트한 프레임워크 제작

 - 훌륭한 문서, 제이퀴리를 넘어선 좋은 아이디어 결합

 > 뷰 2.0부터 크게 주목

 

https://ko.vuejs.org/

 

Vue.js - The Progressive JavaScript Framework | Vue.js

접근성 HTML,CSS, 자바스크립트 표준을 기반으로, 쓰기 편한 API와 최고 수준의 문서를 제공합니다.

ko.vuejs.org

 

* 목적 : 인터랙티브 웹 인터페이스를 개발 - 프로그레시브 자바스크립트 프레임워크

 - 프로그레시브(progressive) : 프로그램 실행에 필요한 최소한의 모듈로부 터 점점 확장

 > 웹에서 UI, 비즈니스로직, 데이터 관리를 돕는 최고 성능의 콤팩트한 자바스크립트 라이브러리 

 

[뷰가 주목받는 4가지 이유]

 - 뷰의 기능 대부분이 앵귤러, 리액트와 유사하며 가상 돔(virtual DOM)을 제어하는 기능도 제공

① 디자이너와 개발자를 위해 쉽게 설계

 - HTML과 CSS 토대에서 동작 : 기존 웹 표준 작업과 유사

 - 접근성이 좋은 공식 문서

  (리액트 : JSX라는 새로운 문법 공부, 모두 자바스 크립트로만 관리 - 진입 장벽이 높음)

② MVC(model view controller) 모델을 지원

 - 리액티브 양방향 데이터 바인딩(reactive two-way data binding) 지원 (like 앵귤러)

 > 리액티브 : 데이터의 변화를 자동으로 체크해서 화면을 바꾸는 동기화

 - DOM 작업에 집중할 수 있도록 직관적으로 쓰기 편한 디렉티브를 제공

③ HTML5와 자바스크립트만 알면 되므로 쉽게 시작

 - 뷰는 HTML5와 자바 스크립트만 필요

 - 앵귤러 비

 > 정적 타입의 자바스크립트를 위해 만든 타입스크립트(TypeScripr)문법 필요

 > 파일 구조 복잡, 큰 덩치

④ 설치하기 쉽고 용량이 작아서 속도가 빠르다

 - 설치하기 쉽고 필요한 파일 용량이 작다.

 - HTML, CSS, 자바스 크립트환경에서 연결해 사용하기 편리

 

[뷰, 자바스크립트 프레임워크의 절대 강자!]

 - 뷰 : 출발은 늦었지만 두 프레 임 워크의 단점 보완 - 성능 우수

 > 앵귤러, 리액트에 비해 전망이 좋다.

 - 자바스크립트 관련 기술 트렌드 통계 :  bestofjs.org

 

 


04-2 ‘안녕하세요!’ 예제 만들기

* 핵심내용

 - 처음 시작을 CDN으로 설정 하는 방법

 - 머스태시 {{ }}  활용법

 - data 속성 바인딩 관계

 

* 010402 [DoIt!실습] 뷰로 ‘안녕하세요!’ 출력하기

- 0104/ex04_01 > hello_vuejs.html 파일 생성

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>hello_vuejs</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>

<body>
    <div id="main">
        <!-- sTitle값을 받아서 HTML의 엘리멘트값으로 변환하여 표시 -->
        <p>{{ sTitle }}</p>
    </div>    
    <script>
        // VUE 객체를 생성해 앱을 초기화하고 시작
        new Vue({
            // id 선택자인 'main'의 div 엘리먼트와 앱을 연결해서 구동
            el : '#main',
            data : {
                // {{ sTitle }}로 데이터값 전달
                sTitle : '안녕하세요!'
            }
        });
    </script>
</body>
</html>

* 보완 : cdn 참조링크
 - 교제 : https://cdn.jsdelivr.net/npm/vue 

 > 수정 : https://cdn.jsdelivr.net/npm/vue@2

 

 * 뷰 적용시 가장 쉬운 방법 : cdn 연결
  -  방법 : 뷰 모듈 주소를 head 테그 사이에 설정

 * 머스태시 사용 : 변수, 함수 결과를 html의 엘리먼트 값으로 변환하여 브라우저에 출력 - 랜더링(rendering)

  -  중괄호 2개를 겹쳐서 표현 : 콧수염 모양과 미슷하여 '머스태시'라고 함

  > {{ sTitle }} : sTitle 문자열 값을 p 엘리먼트의 값으로 변환하여 표시

 * 뷰 앱 구동 

  - 뷰 객체 생성 : HTML의 body 엘리먼트 중, 뷰 화면이 표시될 영역을 el(element) 속성에 선택자로 지정

  > [el : '#main'] - el속성에 #main 으로 div 엘리먼트 부분을 연결 : #main 부분에 뷰 실행내용이 렌더링 됨

 * data 속성

  - 뷰안에서 사용할 데이터를 변수명으로 선언하여 관리

  > 객체, 함수 선언 - 데이터를 읽고 저장하는 일 지원 : 리엑티브(reactive) 하다고 표현?

  - [sTitle : '안녕하세요!'] 문자열의 제목을 저장하는 sTitle 변수의 초기값 정의

  > 뷰에서 HTML 엘리먼트와 함께 머스태시 안에 바인되어 자동으로 표시할 때 sTitle 값 활용

  (sTitle 값을 HTML 구조 안에서 직관적으로 활용 가능)


04-3 단방향 바인딩과 v-bind 디렉티브

 

데이터 바인딩 : HTML의 어트리뷰트값을 수정할 때 V-bind라는 디렉티브를 이용해서 데이터를 브라우저 화면에 지동으로 반영하는 것

 - 변수값을 HTML 어트리뷰트값에 연결 : 변수가 새로운 값으로 바뀔 때마다 HTML 엘리먼트에 실시간으로 렌더링

 > v-bind 디렉터브는 데이터가 한쪽으로만 바인딩되는 단방향 바인딩 (양방향 : v-model - 04-4절)

    (HTML 엘리먼트의 어트리뷰트값 변경시, 연결된 변수값은 변경안됨)

 

* 010402 [DoIt!실습] 올해 연도를 자동으로 표기하는 프로그램 만들기

# 0104/ex04-02/v-bind.html

<!DOCTYPE html>
<html lang="kr">
<head>
    <meta charset="UTF-8">
    <title>v-bind</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
    <style>
        /* 화면에 렌더링할 때 사용할 제목의 색상을 파란색으로 정의 */
        .blue_style {color: blue;}
    </style>
</head>
<body>
    <div id="main">
        <!-- v-bind 안에서도 자바스크립트를 사용할 수 있으므로 변수와 문장을 연결 -->
        <h1 v-bind:class="sColorName + '_style'">안녕하세요!</h1>
        <!-- 콜론(:) 앞은 생략 가능 -->
        <!-- <input:value="sDate"/> 화면깨짐 -->
        <input v-bind:value="sDate"/>
    </div>
    <script>
        let app = new Vue({
            el: '#main',
            data:{
                // Data 객체의 getFullYear() 메서드로 올해 연도 문장 준비
                sDate: '올해 연도: ' + new Date().getFullYear(),
                sColorName: 'blue'
            }
        })
    </script>
</body>
</html>

* 제목에 CSS 스타일 적용 : 뷰는 CSS 스타일을 그대로 활용 - 웹 표준 활용 가능
 - 제목의 글자 색상 스타일 파란색으로 변경

 > .blue_style 클래스 선택자 이용 : color: blue 정의

* v-bind 디렉티브 적용
 - <h1> 태그 안에서 class 어트리뷰트와 뷰의 속성 바인딩 : v-bind 디렉티브 활용

 > v-bind 입력 > 콜론(:)  > 바인딩할 뷰의 속성 연결
 - sColorName 색상 문자열 제목 + _style 연결 : 클래스 선택자 이름

 > class 어트리뷰트에 대입 : sColorName 값이 blue > blue_style 완성된 선택자 이름

 > v-bind 디렉티브를 통해 바인딩 : class="blue_style" 대입

 > h1 엘리먼트 : 파란색 제목으로 표시

* v-bind 생략 : 되나? 된다. 책 코드 자세히 보면 input 뒤에 스페이스가 있...
 - v-bind는 콜론(:)만 남기고 생략 가능

 > input 엘리먼트에서 :value만 사용 : value 어트리뷰트에 sDate의 날짜를 문장으로 받아서 대입

 > input 엘리먼트를 통해서 만들어진 텍스트 박스 안에 오늘 날짜 표시

 > (:) 만 있고 엘리먼트의 어트리뷰트 이어서 표시 : 'v-bind' 디렉티브 생략

* sDate와 sColorNamedata 속성
 - 올해 연도 저장 : sDate 문자열 변수

 - CSS 스타일에 사용 : sColorNam 문자열 변수

 > 올해 연도 : 자바스크립트의 Date객체 생성 - getFullYear() 메서드 : 올해 연도를 숫자로 반환 - sDate에 저장

 > ‘blue’라는 문장을 sColorName 변수에 초기값으로 대입

 > sDatesColorName 두 변수에 담긴 문자열은 v-bind 디렉티브를 사용해서 바인딩할 때 적용

 

* 화면깨짐 : <input:value="sDate"/>
 - Vue 버전 영향인 둣  > input 다음에 공백(스페이스) 있었...

* 개선소스 결과

 

* 하나만 더 배워요! - 머스태시와 v-bind의 차이점

 - 머스태시({{ }}) : HTML의 값을 만들 때 사용

 - v-bind : HTML 어트리뷰트에 바인당할 때 사용

머스태시와 v-vind 차이점
<p>{{ sTitle }}</p> // HTML 엘리먼트값을 만듬
<input v-bind:value=”sDate"> // HTML 어트리뷰트값을 만듬

04-4 양방향 바인딩과 v-model 디렉티브

* 양방향 데이터 바인딩 : v-model 디렉티브를 사용
 - HTML 어트리뷰트에 양방향 데이터 바인딩을 수행

 > 작성 : v-model:[HTML 엘리먼트의 어트리뷰트]

 - 바인딩된 값이 해당 엘리먼트의 어트리뷰트에 대입

 > 엘리먼트의 어 트리 뷰트값이 변수와도 연동

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>v-model</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
    <div id="main">
        <p>{{ sMsg }}</p>
        <!-- v-model은 데이터를 가져오는 동시에 입력이 동기화 됨 -->
        <!-- 엘리먼트의 어트리뷰트는 'v-model:' 다음에 명시 -->
        <input v-model:value="sMsg">
    </div>
    <script>
        var main = new Vue({
            el:'#main',
            data: {
                sMsg:'안녕하세요!'
            }
        })
    </script>
    
</body>
</html>

 - v-model 디 렉티브 : v-bind와 비슷하지만 양방향으로 바인딩됨

 - 변수에 있는 값을 바인딩하여 HTML 어트리뷰트에 렌더링

 > sMsg라는 문자열 변숫값은 p 엘리먼트에 머스태시로 바인딩되어 HTML값을 표시

 > input 엘리먼트의 value 어트리뷰트는sMsg라는문자열 변수와 바인딩되어 input 엘리먼트 안에 값을 표시

 -  HTML 어트리뷰트의 값이 바뀌면 바인딩된 변수의 내용도 함께 동기화

 > input 엘리먼트의 입력값 변경 시 value 어트리뷰트에 저장

 > 저장된 값은 실시간으로 sMsg 변수와 연동되어 자동으로 저장

 >> input 엘리먼트에 입력된 값은sMsg 변수와 일치됨(동기화)

 - sMsg 문자열 변수는 상탯값을 저장하고 있으므로 data 속성에 정의 : 초기값 설정

 

* [ 하나만 더 배워요! ] v-bind v-model의 차이점

<input v-bind:value=’’sDate"> // sDate 값을 HTML 어트리뷰트에 보내기만 함
<input v-model:value="sMsg"> // sMsg 값과 입력값이 서로 연동됨

04-5 조건 판단과 v-if, v-else 디렉티브

* v-if 디렉티브 : 조건이 충족될 때만 렌더링을 수행하도록 돕는 어트리뷰트

 - HTML 엘리먼트중에서 어떤 것을사용할지 특정 조건을 기준으로 판단 시 사용

 > v-if 디렉티브에 조건을 바인딩해서 대입하면 true 또는 faIse에 따라 사용할 HTML 엘리먼트를 결정

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>v-if</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
    <div id="app">
        <h1>{{ bFlag }}</h1>
        <!-- v-if, v-else 로 직접 bFlag 데이터에 접근해 조건 판단 -->
        <p v-if="bFlag == true">앞면!</p>
        <p v-else>뒷면!</p>
    </div>
    <script>
        var app = new Vue({
            el:'#app',
            data:{
                // 난수(0~1) 생성 후 0.5보다 크면 true, 아니면 false 지정
                bFlag:Math.random() > 0.5
            }
        })
    </script>
</body>
</html>

 - h1 엘리먼트를 사용해서 true 또는 false라는 값을 가진 bFlag 변숫값을 제목으로 표시

 > v-if 디렉티브를 이용해서 true이면 p 엘리먼트값으로 ‘앞면!'

 > false이면 v-else 디렉티브에 지정한 엘리먼트를 실행하므로 ‘뒷면!'

 - 상황을 연출하기 위해서 random() 함수를 사용

 > random() 함수는 01 사이의 부동소수점 난수(임의의 수)를 생성
 >> 0.5보다 큰지 확인하는 조건을 설정 > 동전 던지기처럼 truefalse값을 bFlag에 저장


04-6 반복문과 v-for 디렉티브

* v-for 디렉티브 : 반복문으로 배열값을 읽어서 목록의 항목과 인덱스 변수에 저장하도록 돕는 어트리뷰트
- 반복문으로 데이터를 하나씩 차례로 꺼내서 사용할 때 유용

 > 값을 하나 꺼내 저장해 두는 항목변수(item)를활용해 원하는 데이터 속성에 접근

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-for</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
    <div id="main">
        <h1>좋아하는 과일은?</h1>
        <ol>
            <!-- v-for를 통해서 반복문으로 aFruits 과일 배열 데이터를 가져옴 -->
            <li v-for="item in aFruits">
                <!-- aFruits 안의 항목을 하나씩 꺼내서 HTML로 렌더링 -->
                {{ item.sFruitName}}
            </li>
        </ol>
    </div>
    <script>
        var main = new Vue({
            el:'#main',
            data:{
                // 과일 이름으로 이루어진 aFruits 배열을 데이터로 정의
                aFruits:[
                    {sFruitName : '사과'},
                    {sFruitName : '오렌지'},
                    {sFruitName : '포도'}
                ]
            }
        })
    </script>
</body>
</html>

 - 데이터를 하나씩 차례로 읽어 원하는 항목만 선택해서 표시 : 배열 데이터를 주로 활용

> 처음부터 끝까지 값을 하나씩 읽고 원하는 로직으로 바인딩한 후 HTML로 렌더링 하는 방식

 - aFruits라는 배열에 저장된 데이터 : v-for디렉터브를 이용해서 값을 하나씩 차례로 꺼낸 후 item이라는 변수에 대입

 - 머스태시를 이용해서 순서 있는 목록을 만드는 ol 엘리먼트의 리스트 항목인 li로 하나씩 연결

 > 과일 이름은 item 변수의 sFruitName 문자열 변수에 저장되었으므로 점(.)을 이용해서 접근

 - 과일 이름을 배열로 정의하기 위해 대괄호를 이용 : JSON 형식으로 저장

 > JSON : 중괄호를 사용하고 키(sFruitName)와 값(과일 이름)을 콜론(:) 으로 구분



04-7 이벤트 핸들러 실행과 v-on 디렉티브

* v-on 디렉티브 : 뷰에서 발생하는 이벤트를 지켜보면서 DOM 엘리먼트를 제어

 - 이벤트가 발생했을 때 이에 해당하는 함수를 실행하는 방식으로 사용자와 상호 작용시 사용

  > 작성 : v-on:[이벤트 이름]

 - 이벤트 핸들러 :  이벤트가 발생했을 때 실행되는 함수

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>v-on</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
    <div id="app">
        <h1>{{ sTitle }}</h1>
        <!-- 버튼을 누르면 fnChangeTitle 메서드로 이벤트 핸들러 수정 -->
        <button v-on:click="fnChangeTitle">눌러주세요.</button>
    </div>
</body>
<script>
    new Vue({
        el:'#app',
        data:{
            // sTitle의 초기값 설정
            sTitle:'안녕하세요!'
        },
        methods:{
            // 버튼을 눌렀을 때 sTitle의 제목값 변경
            fnChangeTitle(){
                // this는 Vue 객체의 인스턴스를 가리킴
                this.sTitle = 'Hello!'
            }
        }
    });
</script>
</html>

 - v-on 디렉티브를 이용해 button 엘리먼트를 click 이벤트에 바인딩해서 fnChangeTitleQ 함수를 실행

 - 화면에 표시되는 값이 실시간으로 바뀌도록 sTitle이라는 문자열 변수를 정의 : 초기값 설

 - methods 속성 : 이벤트를 발생시키거나 뷰 안에서 어떤 기능을 수행하는 모듈 형식의 함수를 만들 때 사용

 > methods 속성 안에 fnChangeTitleQ 함수정의 : 사용자가 버튼을 클릭했을 때 이벤트 핸들러로 실행

 - this 키워드는 methods 속성의 소유자를 지목 : this는 생성된 뷰 객체 자신

 > this를 사용하는 이유 : methods 속성의 소유자만이 바깥에 있는 data 속성에 접근 - sTitle값 사용

 

 

Uncaught TypeError: Cannot read properties of undefined (reading 'browserObject')
at webcontent.js:1:266
at webcontent.js:2:463
at webcontent.js:2:467

methods 를 method 로 오타 상태에서 라이브서버를 실행하니 화면이 안떴다. 그래서 오타를 수정하고 새로고침 상태에서 실행하니 위와 같은 오류메시지가 표시되며 이벤트가 동작하지 않았다. 
수정없이 라이브서버를 재실행 했더니 이벤트가 잘 동작했다.

그랬다9.


미션 코딩! v-for 디렉티브로 고객 정보 출력하기

 

1차 html 코딩

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>v-for-mission</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
    <div id="main">
        <h1>고객정보</h1>
        <!-- 
        * 번호 : 0
          이름 : 홍길동
          나이 : 27
        * 번호 : 1
          이름 : 이순신
          나이 : 30
        * 번호 : 2
          이름 : 김유신
          나이 : 40
        -->
        <ul >
            <li>
                번호 : 0
            </li>
            <p>이름 : 홍길동</p>
            <p>나이 : 27</p>
            <li>
            번호 : 1
            </li>
            <p>이름 : 이순신</p>
            <p>나이 : 30</p>
            <li>
            번호 : 2
            </li>
            <p>이름 : 김유신</p>
            <p>나이 : 40</p>
        </ul>
    </div>
    <script>
        var main = new Vue({
            el:'#main',
            data:{
            }
        })
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>v-for-mission</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
    <div id="main">
        <h1>고객정보</h1>
        <!-- 
        * 번호 : 0
          이름 : 홍길동
          나이 : 27
        * 번호 : 1
          이름 : 이순신
          나이 : 30
        * 번호 : 2
          이름 : 김유신
          나이 : 40
        -->
        <ul v-for="item in customers">
            <li>
                번호 : {{item.no}}
            </li>
            <p>이름 : {{item.name}}</p>
            <p>나이 : {{item.age}}</p>
        </ul>
    </div>
    <script>
        var main = new Vue({
            el:'#main',
            data:{
                customers : [
                    {no:0, name:"홍길동", age:27}, 
                    {no:1, name:"이순신", age:30}, 
                    {no:2, name:"김유신", age:40}, 
                ]
            }
        })
    </script>
</body>
</html>

 


 

* 뷰(Vue.js) : 실글페이지 애플리케이션 (SPA), 리액티브프로그래밍, 데이터바인딩 지원

* 뷰티파이(Vuetify.js) : 구글 머티리얼 디자인 스펙에 맞는 컴포넌트 단


03-1 ‘안녕하세요! PWA by JS’ 구경하기  

 - 3장에서 작성할 실습 프로젝트 실행

 

* 010301 [DoIt!실습] ‘안녕하세요! PWA byJS’ 예제 실행하기

- 0103/ex03_01-sample : index.html > <GO Live> 실행

 


* 매니페스트 등록 확인
 - 크롬 개발자도구 > Application > Manifest
 > Identity
 > Presentation

 > Icons


* 서비스워크 동작
 - 크롬 개발자도구 > Application > Service Worker

 > Status : 녹색 상태 아이콘 - 동작


* PWA 이벤트 처리 :  console 확인


* Offline 상태 동작확인
 - 크롬 개발자도구 > Network > No throttling > Offline : 인터넷 차단

 > 새로고침하여 동작여부 확인

 - Network에서 Offline 설정 시 
 > 정상 처리된 거래는 캐시에서 조회된 파일

 > 연결 실패한 거래는 빨간 항목으로 표시


* 서비스워커 삭제 : 캐시에 남아있는 결과화면 방지를 위해 실습 후의 기존 서비스워커 삭제 필요
 - 크롬 개발자도구 > Application > Storage > Clear site data (Usage 그래프 아래) 

* 프로그램 종료

 - vsCode <Go Live> 서버 종료 : IDE 하단 상태바에 표시된 [Port:5500] 클릭으로 서비스 정지

 


 

03-2 매니페스트 작성하기  

* 010302 [DoIt!실습] 프로젝트 준비하기

- 0103/ex03_practice > 프로젝트 폴더 설정 : 파일 > 폴더 열기

* 다양한 아이콘 준비 : 멀티플랫폼 지원 대응 - 셈플프로젝트 이미지 리소스 복사

 - 홈화면 아이콘

 - 웨브라우저 파비콘(favicon)

 - 스플래시스크린(splash screen)


* 010303 [DoIt!실습] 웹앱 매니페스트 작성하기
- 0103/ex03_practice/manifest.json 파일을 생성

 

* 파일작성

 - 유효성 검사 : https://manifest-validator.appspot.com/ 막힘

{
    "name":"안녕하세요! PWA by JS",
    "short_name":"PWA by JS",
    "description":"PWA start program",
    "scope":".",
    "start_url":"./",
    "display":"fullscreen",
    "orientation":"protrait",
    "theme_color":"#ffffff",
    "background_color":"#ffffff",
    "icons":[
        {
            "src":"images/icons/android-chrome-512x512.png",
            "sizes":"512x512",
            "type":"image/png"
        }
    ]
}

 - name : 바로가기아이콘설치 퀀장 팝업 배너 및 스크린에 표시되는 제목

 - short_name : 바탕화면 바로가기 아이콘 아래 표시되는 제목

 - description : 애플리케이션의 간단한 소개 (PWA 수집 웹크롤러에 수집되는 정보)

 - scope :  매니페스트에 정의된 내용이 적용될 파일들의 범위 지정

 - start_url : 프로그램 실행으로 시작될 URL을 루트경로로 지정

   ('.' : 현재위치 / './' : 현재위치를 중심으로 시작하는 하위폴더)

 - display : PWA를 실행하면 나타나는 화면의 형태

  > fullscreen : 최대화면 - 지원하지않는 OS인 경우 standalone 적용

  > standalone : 화면만 표시(주소, 상태표시줄등 제거)

  > minimal-ui : standalone에 주소만 추가 - 지원하지 않는 OS인 경우 standalone 적용

  > browser : 브라우저와 같은 구성

  (모바일기기가 PWA를 앱으로 인식하는 옵션 : fullscreen, standalone, minimal-ui / 웹으로 인식하는 옵션 : browser)

 - orientation : 화면의 방향

  > portrait : 세로(초상화)

  > landscape : 가로(풍경화)

 - theme_color : 상태표시줄의 색상 설정

 - background_color : 스플래시스크린 배경색 설정

 - icons : 스플래시스크린에 표시할 아이콘 이미지 - 128dpi에 가까운 이미지를 화면에 표시
  > src : 이미지 경로(절대/상대)

  > sizes : 이미지 픽셀 크기

  > type : 이미지 파일 유형


 

03-3 메인 화면 작성하기 

* 010303 [DoIt!실습] index.html 파일 작성하기

- 0103/ex03_practice > index.html 파일 작성하기

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">

    <!-- PWA 매니페스트 파일 연결, 상태 표시줄 색상을 흰색으로 변경 -->
    <link rel="manifest" href="manifest.json">
    <meta name="theme-color" content="#ffffff">

    <!-- 모바일 기기 뷰포트, 브라우저 주소 표시줄의 파비콘 설정 -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- <meta name="viewport" content="width=device-width, user-scalabe=no"> -->
    <link rel="shortcut icon" href="images/icons/favicon.ico">
    <link rel="icon" type="image/png" sizes="16x16" href="images/icons/favicon-16x16.png">
    <link rel="icon" type="image/png" sizes="32x32" href="images/icons/favicon-32x32.png">

    <title>안녕하세요! PWA by JS</title>
        <style>
            html, body{
                /* html, body 모두 높이를 100%로 고정시켜야 플렉스 박스 동작 */
                heigth: 100%;
                background-color: #F3A530;
                color: #ffffff;
            }
		/* 화면에 출력될 div엘리먼트를 화면 가운데 배치하도록 설정 */
            .container{
                height: 100%;            /* 높이를 100%로 고정 ㅇ*/
                display: flex;           /* 플렉스 박스로 배치 */
                align-items: center;     /* 상하 가운데 정렬 */
                justify-content: center; /* 좌우 가운데 정렬 */
            }
        </style>
</head>
<body>
    <div class="container">
        <h1>안녕하세요!</h1>
        <img src="/images/hello-pwa.png" alt=""/>
        <p>by JK</p>
    </div>
    <!-- 서비스워커 등록 -->
    <script>
        if('serviceWorker' in navigator){
            navigator.serviceWorker
            .register('/service_worker.js')
            .then(function () {
                console.log("서비스워크가 등록됨!");
            })
        }
    </script>
</body>
</html>

 

* 언어설정 : 설정하지 않으면 실행할 때마다 ‘디른 언어로 번역하시 겠습니 까?’라고 질문

 - <html lang="ko">

* 뷰포트설정 - 모바일 브라우저로  PC 사이트 접속시 작게 보이는 현상 방지

 - content의 어트리뷰트 값 설정

  > width-=device-width : 몹바일 기기의 해상도로 너비값 자동 설정

  > initial-scale=1 : 모바일 기기에서 확대하거나 축소 기능 허용

  > user-scalable=no : 모바일 기기에서 확대하거나 축소 기능 제한

* 플렉스 박스 설정 : 화면에 표시할 글자와 이미지를 배치할 레이아웃 - 플렉스 박스(flex box)
  - 모바일 기기의 크기를 자동으로 고려한 최적의 레이아웃 표현
  > html, body 높이를 100%로 고정 필요

* 화면 요소 배치

  - 화면에 실제 출력되는 내용 :  container 클래스를 선택자로 지정한 div 엘리먼

 > div 엘리먼트를 화면 가운데 배치하도록 지정

* 서비스워커 등록 : if('serviceWorker' in navigator)...

 - navigator.serviceworker에는 ServiceWorkerContainer라는 읽기 전용의 객체가 반환
 > 이 객체 안에 있는 register() 메서드를 이용해

 모바일 브라우저가 서비스 워커를 지원하는지 확인한 후

 > 서비스 워커를 등록

 - then() 메서드는 register() 메서드의 실행이 성공하면 실행

 > register() 메서드가 실행되면 콘솔에 성공 메시지를 줄력

 


 

03-4 서비스 워커 만들고 실행하기  

* 010304 [DoIt!실습] 캐시를 관리하는 서비스 워커 만들기

- 0103/ex03_practice > 캐시를 관리하는 서비스 워커 만들기

 

* 서비스워커

 - 브라우저와분리되어 독립해서 실행 가능

 - 캐시, 푸시 알림 , 웹 API와 연동 등 다양한 기능을 별도로 수행

 > 실습대상 : 필요한 파일을 캐시하여 메모리에 저장

 

* service_worker.Js 파일 생성

// 캐시 제목과 캐시할 파일 선언
const sCacheName = 'hello-pwa'; // 캐시 제목 선언
const aFilesToCache = [         // 캐시할 파일 선언
    './', './index.html', './manifest.json', './images/hello-pwa.png'
];

// 서비스 워커 설치하고 캐시파일 저장
self.addEventListener('install', pEvent => {
    console.log("서비스 워커 설치함!");
    pEvent.waitUntil(
        caches.open(sCacheName)
        .then(pCache => {
            console.log("파일을 캐시에 저장함!");
            return pCache.addAll(aFilesToCache);
        })
    );
});

//고유 번호를 할당받은 서비스 워커 작동
self.addEventListener('activate', pEvent => {
    console.log("서비스워커 동작 시작됨!");
});

// 데이터 요청을 받으면 네트워크 또는 캐시에서 찾아 반환
self.addEventListener('fetch', pEvent => {
    pEvent.respondWith(
        caches.match(pEvent.request)
        .then(response => {
            if(!response){
                console.log("네트워크에서 데이터 요청!", pEvent.request);
                return fetch(pEvent.request);
            }
            console.log("캐시에서 데이터 요청!", pEvent.request);
            return response;
        }).catch(err => console.log(err))
    );
});

 - 오프라인 동작을 위해 서비스워커가 캐시에 저장하

 > 캐시 제목과 캐시할 파일 선언 : 캐시 제목은 서비스워커와 구분되도록 고유이름 사용

* 서비스 워커 설치 및 캐시 파일 저장 - install 이벤트

 - 서비스 워커의 생애 주기

 > [install - activate - fetch] 순서로 이벤트 발생

 * install : PWA를 설치 - 서비스워커의 첫번째 생애주기

 

 > 설치전 : installing

 > 설치 후 대기 :installed

* 서비스 워커가 제대로 설치되면 pEvent에 포함된 waitUntil() 함수를이용해 비로소 캐시에 필요한 파일 저장
* 서비스 워커가준비될 때 캐시를 저장하는 것 :  ‘프리 캐시(pre-cache)’
 - waitUntil() 함수는 installing 상태에서 프리 캐시가 완료될 때까지 대기

 - activate : 설치후 상태

 

* activate 이벤트 : 서비스 워커의 두 번째 생애 주기


- 서비스 워커 업데이트  : 서비스 워커가 고유한ID를 발급받아 브라우저에 성공적으로 등록되면 동작
 > 웹 브라우저 의 개발자 도구에서 확인

 

* 서비스 워커 설치 후 - 업데이트 등의 이유로 캐시 제목 변경 : install 이벤트 처음부터 다시 발생

 - 테스트할 때는 'Update on reload’ 체크 박스를 선텍 : 매번 캐시제목 변경 서비스워커등록 생략

 > 새로 고침 : 기존 서비스 워커 ID 제거 -> 새로운 ID를 부여 : install 이벤트부터 새로 시작

 

* 앱 업데이트 시 서비스 워커 새로운 내용으로 교체 : activate 이벤트

 - 활성중 : activating

 - 활성후 : activated

* 서비스 워커의 내용 업데이트 : 
 - 먼저 캐시 제목과 프리 캐시 파일 변경 : 새로운 서비스 워커 ID로 새로운 캐시 내용이 설치 목적

 - activating 상태에서 waitUntil() 함수를 사용해서 기존 캐시 제거 : 코드작성

 

* 오프라인 전환할 때 동작 - fetch 이벤트

 - 서비스 워커의 마지막 생애 주기는 fetch 이벤트로부터 시작
 > 이벤트가 발생 사례 : 브라우지 〈새로 고침〉
* 동작

 - 온라인 상태 : 서버에서 조회

 - 오프라인 상태 : 캐시에서 조

* 서비스 워커의 유무에 따른 fetch 이벤트 처리

 - 1 : 온라인 - 서비스워커 없음

 - 2 : 오프라인 - 서비스워커 있

* PWA 오프라인 동작 구조 :  fetch 이 벤트 발생 후 (pEvent에 있는) respondWidth() 함수 활용

 - respondWidth() 함수 : 결과값 준비 까지 네트워크 요청 일시 정지

 > 캐시, 모바일 기기에 임시로 저장한 데이터로 처리

 

* service_worker.js

 - 오프라인 처리 : PWA가 실행되면 캐시에서 가져올 데이터를 caches.match() 함수로 캐시 저장소에서 검색

 > 발견된 캐시(response)를 반환하도록 코드를 작성

 - 캐시를 발견하지 못하면 fetch(pEvent.request)를 통해 네트워크에 요청

 

* 실행 실습 후 서비스워커 삭제 : 다음실습 준

 


* 서비스 워커의 주요 이벤트 복습하기

 - install : 서비스워커가 설치될 때 실행(앱설치) - 캐시파일 저장

 - activate : 서비스워커 설치 후, 업데이트 역할 - 기존캐시 제거

 - fetch : 서비스워커 설치 후 다음 실행 때 실제 작업할 내용 작성 - 브라우저 서버요청시 오프라인 상태면 캐시파일 조회

 

* 사용하는 브라우저 서비스워커 지원 확인

 - https://mobilehtml5.org/tests/sw 접속 후 새로고

서비스워커 지원하지 않을때 표시되는 메시지라고? 
Service Worker NOT serving files on first loads
Couldn't ask for Service Worker ID.

두번째 하니 아래와 같이 표시된다. 뭐지?


 

미션 코딩! 캐시 변경하고 서비스 워커 다시 등록하기  

 

 

* 03장 실습 결과물을 복사한 후 캐시 제목을 바꾸고 캐시 이미지를 추가해 서비스 워커를 다시 등록

 - 크롬 개발자 도구의 캐시 저장소(Cache Storage)에서 캐시 제목과 추가한 이미지 확인

 > 실습할 때마다 기존의 서비스 워커는 반드시 미리 제거

 - 캐시 제목 뒤에 -v1, -v2..처럼 버전의 번호를 올리면서 테스트

// 캐시 제목과 캐시할 파일 선언
// const sCacheName = 'hello-pwa'; // 캐시 제목 선언
// const aFilesToCache = [         // 캐시할 파일 선언
//     './', './index.html', './manifest.json', './images/hello-pwa.png'
// ];
// // 미션코딩 - 캐시변경하고 서비스워커 다시 등록하기
const sCacheName = 'hello-pwa-v1'; // 캐시 제목 변경 *
const aFilesToCache = [         // 캐시할 파일 선언
    './', './index.html', './manifest.json', './images/hello-pwa.png',
    './images/icons/favicon.ico',               //파비콘 이미지 캐시 추가 *
    './images/icons/android-chrome-192x192.png' //아이콘 이미지 캐시 추가 *
];

* 이전 서비스 워커를 제거한 후 테스트

 - 라이브 서버로 웹 브라우저에서 실행

 - Update on reload' 체크 박스 선택 해제

 > 웹 브라우저 새로 고침에도 서비스 워커 : 신규 ID로 등록되지 않고 그대로 있음

* Status 항목에서 skipWaiting을 선택

 - 캐시 저장소에서 변경된 캐시 제목과 캐시에 추가로 등록된 이미지 확인

 - 앱 재실행 후에도 Status 항목에 skipWaiting 표시가 안되네.. 뭘 놓쳤지..

 

 

vsCode 설치시 기본 git commit이 가능하여 사용하던 중 pull request 이용을 해볼까 싶어 찾아봤는데, 

맙소사. pull request는 별도 플러그인을 설치해줘야 하나보다. 

 

https://technote.kr/354

 

[VSCODE] Github Pull Requests 생성하기

[Github 에 반영하기 (git commit/push)] 에서 보았듯이 write 권한이 없는 repository 에는 직접 반영을 할 수 없다. 이에 write 권한을 가지고 있는 계정의 review를 받고 해당 계정을 통해 반영이 이루어 져야

technote.kr

 

굳이...? ㅎㅎ

 

이참에 터미널을 사용해봐야겠다. 

'tools' 카테고리의 다른 글

ecilpse 속도 개선  (1) 2023.09.12
오류  (0) 2022.10.24
git. push가 갑자기 안되네.. github가 잘못했네.  (0) 2021.10.15
VSCode Workspace Trust?  (0) 2021.08.27
Visual Studio Code  (0) 2021.06.20

기본앱 위치를 확인하여 시작프로그램에 등록

 - 기본앱 경로의 탐색기 접근시 권한이슈 대응

 > https://www.tabmode.com/goods/windows10/win10_owner_admin.html

 

현재 이 폴더에 대한 액세스 권한이 없습니다. - 폴더에 소유권과 액세스 권한을 취득하기《1/2》

파일이나 폴더를 열려고 하면 이 폴더에 액세스 할 권한이 거부되었습니다. 라는 메시지가 표시되면서 파일 또는 폴더에 액세스 할 수없는 경우가 있습니다. 이 문제는, 파일 또는 폴더에 대한

www.tabmode.com

- 프로그램 위치 확인 : 관리자권한실행시 메시지 창에 경로 표시됨

> C:\Program Files\WindowsApps\Microsoft.YourPhone_1.22022.147.0_x64__8wekyb3d8bbwe\

 - 내 경우
 > C:\Program Files\WindowsApps\Microsoft.YourPhone_1.23022.140.0_x64__8wekyb3d8bbwe\PhoneExperienceHost.exe

 

* 시작프로그램에 PhoneExperienceHost.exe 바로가기 파일을 넣어본다.

 

* 인터넷에서는 삭제하는 방법만 널려있는데, 난 사용하려고 하네.. 

https://albaeconomy.tistory.com/entry/yourphoneexe-%EC%82%AC%EC%9A%A9%EC%9E%90-%ED%9C%B4%EB%8C%80%ED%8F%B0-%EC%A0%95%EC%B2%B4-%EB%B0%8F-%EC%82%AD%EC%A0%9C

 

yourphone.exe : 사용자 휴대폰 정체 및 삭제

yourphone.exe : 사용자 휴대폰 정체 및 삭제 작업관리자에 존재하는 프로세스 중에 사용자 휴대폰 yourphone.exe 는 윈도우에서 제공하는 PC 와 스마트폰 간의 파일 동기화 프로그램이라고 합니다. 파일

albaeconomy.tistory.com

 

mobilehostapot_on.bat
0.00MB
mobilehotspot_on.ps1
0.00MB

참고

https://jjam89.tistory.com/147

 

[Windows] 노트북 모바일 핫스팟 자동 실행(호스트된 네트워크 지원이 ''아니요'' 일 시 해결방법)

Batch File 생성 전 명령어 실행 해보기 관리자 권한으로 cmd 실행 아래의 명령어를 실행시킵니다. (앞의 $는 빼고 복사해주세요.) $ netsh wlan start hostednetwork //start hotspot 이미지의 cmd창과 실제 cmd창에

jjam89.tistory.com

 

윈도우 시작프로그램 폴더에 아래 두 파일을 넣는다.

 - 경로 : C:\Users\{user}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

 - 스크립트파일 : mobilehotspot_on.ps1

$connectionProfile = [Windows.Networking.Connectivity.NetworkInformation,Windows.Networking.Connectivity,ContentType=WindowsRuntime]::GetInternetConnectionProfile()
$tetheringManager = [Windows.Networking.NetworkOperators.NetworkOperatorTetheringManager,Windows.Networking.NetworkOperators,ContentType=WindowsRuntime]::CreateFromConnectionProfile($connectionProfile)
 
# Start Mobile Hotspot
$tetheringManager.StartTetheringAsync()

 - 실행파일 : mobilehostapot_on.bat

@echo off
Powershell.exe -noprofile -executionpolicy bypass -file "C:\Users\jkoogi\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\mobilehotspot_on.ps1"

+ Recent posts