jstl, jsp, freemarker, thymelaef 

이러한 서버사이드에서 렌더링을 해주는 라이브러리들이 있지!

템플릿을 표현함에 있어서 얘네들도 반복과 분기 처리를 하게 해주는 구문이 있었어...

 

Vue도 그런게 당연히 있지.

클라이언트 사이드에서 되는게 그저 신기할뿐...

 

v-for, 그리고 v-if(번외로 v-show)가 있다.

 

디렉티브 이름봐~ 뭐하는 놈인지 딱 알거 같음.

 

사용하는 방법도 매우 간편~

그럼 v-for와 v-if, v-show를 적용해 보겠음.

기존 코드에 적용하기 위해서 v-for는 select의 option에,

그리고 v-if와 v-show는 table element를 만들어서 해볼게.

 

코드
결과

자 일단 배열 데이터 만큼 v-for가 반복해준다는건 알겠지?

그리고 테이블 데이터를 보면 v-if와 v-show에 의해서 데이터가 가려지는것도!(v-else랑 v-else-if는 자매품)

하지만 크롬 콘솔모드에서 elements를 확인해 보면 큰 차이가 있어!

 

바로 v-if는 조건에 충족하지 않으면 렌더링 자체를 안하는 것!

v-show는 display 속성만 none으로 된다는 것!

 

아 그리고 추가적으로 v-for는 2.x때는 :key 라는 디렉티브가 필수가 되었어.

v-for를 쓰려면 꼭 있어야해!

 

그리고~~ 기존 코드와 조금 다른 점이 하나 더 있는데,

바로 v-bind: 디렉티브!

v-bind:value는 :value과 같아. 타이핑 수를 줄일 수 있지.

 

엇 저녁에 딸래미랑 안아주고 화해했음

 

지난글에선 v-model을 사용해서 input과 같은 유형의 elements와 value값을 동기화 시키는 작업을 했더랬지...

 

오늘은 그외 elements들의 속성!! 어트리뷰트(attribute)! 를 제어하는...

vue의 data와 연결하고 값만 띡띡 바꿔주면 동적으로 착착 변하니까 제법 편안한?

(코드 자체가 상당히 깔끔해짐)

 

img의 src와 class랑 style에 data를 바인딩 해보자.

 

v-bind: 를 사용해서 바인딩이 가능하지.

img src는 문자열의 데이터, 그리고 class나 style에 바인딩 되는 데이터는 json object의 형태를 갖고 있어.

 

결과 화면 보자고..

나는야 DIV가 우측정렬에 bold와 font크기의 변화가 있지?

그리고 첨부한 이미지 크기 또한 줄어들어 있어.

 

근데 위 코드를 보며 의문이 드는 부분 없었어?

object항목의 key값을 보면 text-align은 케밥 표기법으로, maxWidth는 카멜 표기법으로 되어 있지?

css의 속성은 모두 케밥 표기법으로 처리가 되는데 말이야...

여기서 css에 해당하는 데이터의 key값은 카멜로 표기해주면 알아서 케밥으로 변경 해준다는 점을 참고하라고.

근데 class는 안되, 그래서 보통 css를 작성할때 케밥 표기법으로 쓰잖아? 그러다보니 홀따옴표로 감싸서 사용해야하지.

 

그리고~

disabled나 readonly 속성 또한 v-bind로 처리가 가능하다는 점을 기억하며

여기서 마무리!

Vue의 장점 중 하나, 앵귤러 처럼 양방향 데이터 바인딩이 가능하다는점!~

제이쿼리나 기본 셀럭터 사용해서  $("#~"), document.getElementById 이런거 안해도 됨!

 

이게 얼마나 큰 차이인지 인지를 못 하는 분들이 간혹 계시던데,

멀리 안보고 성능과 코드 컨디션만 생각해도 엄청난 차이가 있음!

궁금하면 구글링 ㄱㄱ

 

자 그럼 다양한 Elements에 데이터를 바인딩 해보겠음.

Elemtents.vue를 하나 만들자고, new file 하면 안되고, 꼭 New > Vue Component를 해야함.

그래야 기본적인 템플릿이 생성됨.

 

간단하게 몰빵해서 위 처럼 작성해 봤징.

 

그리고 textarea 부분은 양방향 통신인걸 확인 하기 위해서 저렇게 해줬어.

element에서 수정하면 {{textarea}}에서 노출 되는 값도 변하겠지?

 

자 그럼 실행을 확인하기 위해서, index.js에서 방금 만든파일을 추가 하자고,

import Elements from '../views/Elements.vue'

...
const routes = [
...
    {
      path: '/elements',
      name: 'Elements',
      component: Elements
    }
  ]
...

 

그리고 App.vue에서도

<template>
  <div id="nav">
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link> |
    <router-link to="/Elements">Elements</router-link>
  </div>
  <router-view/>
</template>

/Elements 로 접근하기 위해 한줄 추가.

 

아 물론 이건 없어도 되긴해, 그냥 주소 창에 localhost:8081/Elements 해도 들어가지니까.

위 처럼 되는거야~~

이게 얼마나 편한건지...모르는 분들도 계시겠지만, 

내 생각엔 지금까지 한 이정도만 하더라도 간단한 웹프로젝트는 가능할거라고 생각해.

아마도?ㅋㅋ

 

 

오늘 아침에  딸래미랑 싸우고 딸래미가 안아주지 않고 등원해서 속상함.

 

자 이제 라우터를 사용해보장~~

- 라우팅이란?

 나는 서버용 장비가 생각났어. 삼국지에 나오는 장비 말고, 분전함 같은 그 데이터 네비게이션 같은 역할하는 장비.

여기서는 그냥 웹브라우저에 어떤 주소 입력했는데, 해당 주소에 맞는 페이지를 보여주는거라고 보면 될듯.

미리 지정된 url에 맞는 페이지를 보여주는~~ 스프링에서 url 매핑 생각하면 될듯~~

 

앞선 글에서 나는 플러그인으로 라우터를 이미 설치했지.

 

근데 별도로 설치 할 수도 있쒀.

$ vue add router

위 처럼 cli로 할 수도 있고,

그 vue ui를 실행해서 프로젝트 매니저로 간담에 플러그인에서 추가 할 수도 있지.

설치된 플러그인 확인도 하고, 추가 설치도 가능해.

 

디폴트로 했을때랑 뭐가 다를거 같아?

위에 Home, About 보여?

폴더 구조를 보면 views에 Home.vue랑 About.vue가 있는데,

원래 default로 생성하면 Home.vue의 내용은 App.vue에 있어.

App.vue는 두 화면으로 분기가 가능하게끔 해주지

 

그리고 /src/router/index.js를 살펴보면

routes라는 배열에 두개의 정보가 있어.

각각 Home 과 About에 대한 정보인데,

component 부분을 보면 내용이 살짝 다르네?

아래에 있는 컴포넌트 위에는 주석으로 뭐라고 막 써있엉...

chunk file 에 대해 찾아보면 알테지만, 대략적으로 묶음 단위라고 생각하면 될것 같아.

빌드 이후의 파일 생성할때 하나의 파일로 묶여있으면 엄청난 양의 파일을 로딩해야겠지?

근데 나눠져 있으면 필요한 파일만 로딩하면 되는거고,

그래서 lazy load 기능도 있는건가봐, jpa에서 레이지 로딩 써봤지?

 

글구 여기서 중요한건 위 처럼 하는건 실상 prefetch(리소스를 캐시에 저장) 라는 기능을 쓰는건데,

이건 구글링하면 내용 나올 거고,

 

중요한건 해당 기능을 끄는 방법이지,

 

프로젝트 root에

(root가 어딘지 모르는 사람들도 있으니...프로젝트내 폴더 최상위 말하는거양~~

나도 예전엔 몰랐음. c:\ 에서 삽질했었지)

vue.config.js 라는 파일을 생성하고 prefetch를 안쓴다고 작성해야함.

module.exports = {
  chainWebpack: (config) => {
    config.plugins.delete('prefetch')
  }
}

 

근데 막상 꼭 혹은 자주 이용할것 같은 애들은 그래도 캐시에 올라가 있으면 좋지 않겠어?

    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
    component: () => import(
      /* webpackChunkName: "about" */
      /* webpackPrefetch: true */
      '../views/About.vue')

위 코드를 아래 처럼 바꾸면 되징.

 

그리고 /**/ 이건 꼭 오라클에서 HINT 쓰는거랑 비슷해 보이는데 ㅋㅋ

이건 매직코멘트래 

링크 남길게 이건 

https://webpack.js.org/api/module-methods/#magic-comments

 

Module Methods | webpack

webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

webpack.js.org

 

목표는 Vue Native로 앱을 만드는 것이 목표.(한 10년뒤에 가능할까... vue 10.x가 나오려나...)

 

Vue는 그동안 cdn방식으로 선언적? 여튼 SFC(싱글 파일 컴포넌트)가 아닌 방식으로 야금야금 만들어 보았다.

그래서 데이터 바인딩이나 기타 템플릿 관련 문법은 원래도 진입 장벽이 낮았으니 문제는 안될거라 생각함.

 

왜 vue.js인가?!

앵귤러나 리액트보다 쉽다. 그냥 내가 보기엔 그랬다.

리액트도 앵귤러도 책 있는데, 앞 부분 조금 보니 짜증나더라.

뷰는 사이트가서 가이드 문서만봐도 편안하드라.

 

근데 3.x 들을 문법이 살짝 다르다네?

 

일단 npm을 설치한다!!

https://nodejs.org/ko/download/

 

다운로드 | Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

 

나는 윈도우니까 64bit msi 버전을 다운받고 설치했다!!

npm 명령어가 시스템 명령어로 자동으로 등록되는데...

인텔리제이 터미널에서 사용하려면 이거 설치 후 인텔리제이 껏다 켜야함.

 

그리고 여기저기 찾아보니 인텔리제이...(길어...) 에서 cli환경으로 작업하려면 

기본 터미널을 Git bash를 사용하란다.

 

그러니 Shell path 부분을 위 처럼 변경 해야함.

 

항상 느끼는 거지만 개발보단 개발을 위한 준비 과정이 더 힘든 느낌이랄까...

개발을 개발새발 해서 그런건가...

그래서 내 코드가 똥망일지두...ㅠㅠ

 

그리고 위 처럼 플러그인 설치를 하자!

 

이제 Vue CLI를 설치하자

CLI가 뭔지 모르는 흑우들 읍제? '커맨드 라인 인터페이스'다

요새 코인판에서 유행하는 화법인듯.

나는 안 물렸다. 수익율 그래도 300%넘겼다.

 

인텔리제이 터미널에서 아래와 같이 입력하자.

$ npm install -g @vue/cli

 

그리고~~~

vue create vue-project 라던가 vue create vue-project-manually 라던가를 이용하면,

프로젝트 생성을 할 수 있는데...

시대가 어느 땐데 cli를 이용하냐구...(응 멍소리 일발장전)

 

$ vue ui

위 처럼 입력하면 뭔가 8000 포트로 서버가 올라가고 브라우저가 실행된다 아래처럼.

크 역시 21세기는 GUI지...

GUI 모르는 흑우들 읍제? 응...

 

위와 같은 화면이 촥! 떠준다고.

 

여기서 프로젝트 편하게 생성 하시라 이 말씀. 여윽시 GUI의 시대.

 

대강 스크린샷 첨부하게따!!!

 

이건 척 보면 알겠지?

 

 

수동으로 가즈아~

 

기능 선택하는건데, 필요한거 알아서 선택하자.
여기도 필요한거 알아서 체킹
프리셋 지정하는건데 할거면 하고..이미지 뜨는거라고 생각하믄대
겁나 오래걸려, 내컴 안 느린데 오래걸려 멈춘줄. CLI가 좀 더 빠르긴 한거같네.

 

자 이렇게 프로젝트 생성을 했어.

그럼 인텔리제이에서 오픈해보자고.

 

File -> Open 

 

이렇게 여러 파일들이 생겼지.

 

그리고 이 어플리케이션을 실행하려면

 

위 처럼 만들어 주라고~

 

그리고 실행하면 짜잔~!

위 주소로 들어가 보면~
짜잔!

 

8080포트는 싫어? 그럼 다른 포트를 해

serve.js 라는 파일 열어서 port만 바꾸면 됨.

 

그리고 크롬에 vue devtools 플러그인 설치하면 좀 좋아~~

 

오늘은 여기까지~!!

linux 에서 톰캣 환경 설정시 별 다른 생각 없이 하다보면 헤매는 부분 중 하나.

 

3월즘에도 엄청 헤맸는데, 이번에도 하루는 날려버린 부분...ㅠ

 

톰캣실행이 실행은 아주 잘 되는데 스프링 부트는 deploy가 제대로 되지 않는다.

 

이유는 os에 있는 기본 openjdk로 실행되기 때문,

 

설정문제인가해서 설정파일을 엄청 찾아보지만~~ 찾을 수 없고

 

실행로그를 확인하다보니 jdk 1.8.xx 라고 써있는걸 발견

 

잉?난 zulu-11 설치했는뎅?

 

> sudo update-alternatives --config java

 

위 명령어로 디폴트로 사용할 자바 버전을 선택해 줄 수 있다.

 

다음에 또 헤맬까봐 글 남기는중...ㅠ

 

구글링해도 안나와서 엄청 헤매다가 해결하려니 스트레스 ㅠ

오라클 자바 삭제 후 openjdk 를 설치해야하는데,

openjdk에는 cert파일도 내용이 없죠.ㅠㅠ

https request하면 인증서 관련 오류를 마구 뱉어내요.


그래서 윈도우 사용하는 로컬머신에 일단 테스트 후 azul사의 zulu를 사용하기로 결정.


okky에서도 반응이 좋은듯 해서 이걸로...ㅎㅎ


참고로 msi를 제공하기에 윈도우에서는 기존 자바 폴더와 똑같이 설정해주면, 환경변수나 기타 설정을 할 필요가 없어요.


https://www.azul.com/files/zulu_8.9_install.pdf


해당 메뉴얼 보시면 아주 잘 나와 있습니다만, 영어 싫어 하시는분들을 위해서 4줄 요약


> sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0x219BD9C9

> sudo apt-add-repository 'deb http://repos.azulsystems.com/ubuntu stable main'

> apt-get update

> apt-get install zulu-8



그리고 자바홈 설정


> vi /etc/profile

...

export JAVA_HOME=/usr/lib/jvm/zulu-8-amd64

...


오라클자바 삭제는


> apt-get remove oracle*

> apt-get autoremove --purge

> apt-get autoclean


오라클 자바 삭제는 아래 글 참고했어용.

http://rudas5594.tistory.com/271


아래 처럼 나온다면 아주 성공적!


> java -version

openjdk version "1.8.0_181"

OpenJDK Runtime Environment (Zulu 8.31.0.1-linux64) (build 1.8.0_181-b02)

OpenJDK 64-Bit Server VM (Zulu 8.31.0.1-linux64) (build 25.181-b02, mixed mode)

인터넷 찾아가며 이것저것 짜집기도 하고 영 별거 아닌걸로 고생아닌고생하니까 짜증이 나네요...


그래서 제가 짠거 공개할게요.

springdml restTemplate 이용해서 했고요..

인터넷 찾아보니, 이게 뭐 convert가 좀 문제라서...

한글이 마구 깨지는데..

이거 구글링 열심히해서 어떤분 소스 베껴다가 넣었어요.

원본 주소 : https://gist.github.com/ucpwang/949145408a12bb40a671


주석같은거 안달려 있으니 알아서 보시면 될거 같고요.

contents에서 img태그 찾아서 #n 으로 치환해서 멀티파트로 파일 넘기는것까지 구현했습니다.

error코드 인증실패 리턴시에는 토큰값 갱신 하시는 로직 따로 작성하시면 되어요.



public String blogPost(String token, String title, String contents) { contents = contents.replaceAll("<br>", ""); contents = contents.replaceAll("<BR>", ""); List<String> imageSrcs = new ArrayList<>(); List<Resource> resources = new ArrayList<>(); int startIdx = 0; int imgIdx = contents.indexOf("<img", startIdx); while(imgIdx > -1){ int srcIdx = contents.indexOf("//image", imgIdx); int endIdx = contents.indexOf("\"", srcIdx); String imgSrc = contents.substring(srcIdx, endIdx); imageSrcs.add(imgSrc); startIdx = endIdx; imgIdx = contents.indexOf("<img", startIdx); } int idx = 0; for(String imageSrc : imageSrcs){ contents = contents.replace(imageSrc, "#"+idx); idx++; int qIdx = imageSrc.indexOf("?"); if(qIdx < 0){ qIdx = imageSrc.length(); } imageSrc = imageSrc.substring(0, qIdx); String fileSrc = imageSrc.replace(imageServerHost, saveDirectory); Resource file = new FileSystemResource(fileSrc); resources.add(file); } String header = "Bearer " + token; // Bearer 다음에 공백 추가 RestTemplate restTemplate = new RestTemplate(); String apiURL = "https://openapi.naver.com/blog/writePost.json"; try { for (HttpMessageConverter<?> hmc : restTemplate.getMessageConverters()) { if (hmc instanceof AllEncompassingFormHttpMessageConverter) { /** AllEncompassingFormHttpMessageConverter 생성자 내용 일부 가져와서 수정 **/ List<HttpMessageConverter<?>> partConverterList = new ArrayList<HttpMessageConverter<?>>(); partConverterList.add(new ByteArrayHttpMessageConverter()); StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8")); stringHttpMessageConverter.setWriteAcceptCharset(false); partConverterList.add(stringHttpMessageConverter); partConverterList.add(new ResourceHttpMessageConverter()); partConverterList.add(new SourceHttpMessageConverter()); if (ClassUtils.isPresent("javax.xml.bind.Binder", AllEncompassingFormHttpMessageConverter.class.getClassLoader())) { partConverterList.add(new Jaxb2RootElementHttpMessageConverter()); } if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", AllEncompassingFormHttpMessageConverter.class.getClassLoader()) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", AllEncompassingFormHttpMessageConverter.class.getClassLoader())) { partConverterList.add(new MappingJackson2HttpMessageConverter()); } else if (ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper", AllEncompassingFormHttpMessageConverter.class.getClassLoader()) && ClassUtils.isPresent("org.codehaus.jackson.JsonGenerator", AllEncompassingFormHttpMessageConverter.class.getClassLoader())) { partConverterList.add(new MappingJackson2HttpMessageConverter()); } ((AllEncompassingFormHttpMessageConverter) hmc).setPartConverters(partConverterList); } } HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", header); MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>(); parameters.add("title", title); parameters.add("contents", contents); for(Resource resource : resources){ parameters.add("image", resource); } HttpEntity<?> httpEntity = new HttpEntity<>(parameters,headers); ResponseEntity<HashMap> re = restTemplate.exchange(apiURL, HttpMethod.POST, httpEntity, HashMap.class); System.out.println(re); return (String) re.getBody().get("error_code"); } catch (Exception e) { System.out.println(e); } return null; }


오래전 개인적으로 프로젝트를 수주받아 일을 하던차.

이미지 업로드를 해야하는데, drag & drop 기능을 넣어 달란다.


"아니 그게 active-x 없이 되는 거야?"


"몰라. 너가 알아서해"


이러던 와중 찾아보니 html5에서 drag&drop이 되더라.

그래서 이걸 input file element를 이용해 동기화해서 이용하려고 해보니.


input file은 보안 문제상 javascript에서 set value가 불가능하다고. ㅠ


하긴 생각해보면 아무파일이나 local에서 읽어다가 막 올릴 수 있겠지.

인증서도 막 올릴수 있겠지. ㅠ


근데 이런 문제는 css로 해결할 수 있다니.

얼마전부터 css를 하다보니 참 새삼 위대함을 느낀다.



일단 JQGRID를 이용해서 해당 그리드에 드랍을 하면,  

파일 정보를 읽어서 그리드에 표시하고 저장버튼을 눌러 저장을 할 수 있는 형식으로 만들었다.

물론 여기까지 오는데 꾀 많은 템플릿? 데모? 를 만들었다.




그리드 부분을 아래처럼 div로 감싸고 droparea란 id로 지정을 했다.

 

 <div style="float: left;" id="droparea">

    <table id="theGrid01"></table>
    <table id="thePager01"></table>
</div>

그리고 드래그 엔터시와 아웃시 살짜쿵 스타일 변화를 주었다.

  $('#droparea').on('dragenter', function (e) 

{

    e.stopPropagation();

    e.preventDefault();

    $(this).css('border', '2px dotted #0B85A1');

});

$('#droparea').on('dragleave', function (e) 

{

     e.stopPropagation();

     e.preventDefault();

     $(this).css('border', '');

});

 


그리고 실제 파일 드랍시 발생하는 부분이다.

     $('#droparea').on('drop', function (e){

         $(this).css('border', '');

         e.preventDefault();

         var files = e.originalEvent.dataTransfer.files;

     

         handleFileUpload(files);

    });

위에서 보다시피 이벤트에서 파일을 얻어와 그걸 handleFileUpload에 넘긴다.


자 그럼 그 내용이 뭔지 보자.

// 소스 내용 자체는 참 쉽다.

var fd = new FormData();

// 일단 FormData를 local변수로 하나 생성하고

function handleFileUpload(files,obj)

{

    fd = new FormData(); // FormData를 초기화 하는 이유는 드랍시마다 초기화 하려고..

    // 그리드도 초기화

    $("#theGrid01").jqGrid("clearGridData", true).trigger("reloadGrid");


    // 드랍된 파일이 몇개일까..

    for (var i = 0; i < files.length; i++) 

    {        

        // fd에 파일을 추가한다.

        fd.append('file_'+i, files[i]); 

 

        var grid = $("#theGrid01");

        var rowId = grid.jqGrid('getGridParam', 'reccount');

        rowId++;

        rowId = rowId + "";

        // 파일 사이즈를 구해서

        var sizeStr="";

        var sizeKB = files[i].size/1024;

        if(parseInt(sizeKB) > 1024)

        {

            var sizeMB = sizeKB/1024;

            sizeStr = sizeMB.toFixed(2)+" MB";

        }

        else

        {

            sizeStr = sizeKB.toFixed(2)+" KB";

        }

        

        var parameters = {

            rowID : rowId,

        // 초기 데이터를 넣고

            initdata : {"FILE_NAME":files[i].name,"FILE_SIZE":sizeStr},

            position : "last",

            useDefValues : false,

            useFormatter : false,

            addRowParams : {

                extraparam : {},

                keys : true

            }

        }

        // 그리드에 row를 추가

        grid.jqGrid('addRow', parameters);

        grid.jqGrid('setCell', rowId, "ST", gv_insert, "");

        grid.jqGrid('setCell', rowId, "AT", "I");

 

    }

}


위 처럼 하면 전송할 폼데이터 및 그리드에 해당 파일 정보가 쓰인다.


마지막으로 저장 버튼 누를시 이벤트는

function txcall(txid) {

    

    

    var url = "";

    var mydata = "";

    switch (txid) {

    case "SAVE":

        url = "호출경로";

        mydata = fd; // 아까 위에서 생성한 폼데이터

        break;

    }

    transactionFile(txid, url, mydata, "txcallback");

}

transactionFIle은 jquery의 ajax를 이용해서 만든 함수다.

결국 그냥 ajax로 post방식으로 서버로 전송하는거다.

 

위 내용은 php로 했고, 서버사이드프로그램은 뭘 해도 상관없을듯 하다?...


추가적으로 끄적이자면. 큰 용량의 파일을 업로드시. 서버에 저장공간이 남아돈다면 모를까.

적당한 이미지로 보여주는것이 좋다.

PHP에서는...


thumb.php라는 오픈소스가 있는데, 이것을 이용해서 이미지를 사이즈를 작게 만들어서 저장하는 것도 방법이라면 방법이다.



드래그앤 드랍 참조 1 : http://hayageek.com/drag-and-drop-file-upload-jquery/


 

자바스크립트 배열에 대해 알아보자.
1. 배열은 어떻게 선언할까..


  var arr_temp = new Array(); // 저는 이걸 가장 많이 씁니다.
  var arr_temp = []
  
  또는 선언과 동시에 값을 넣을 수 있다.
  var arr_temp = [11,22,33,44];
  그리고 배열안에 배열도 가능하다
  var arr_temp = [[1,2,3],[4,5,6],[7,8,9]];
  또 위는 아래와 같다.
  var arr_temp = [];
  arr_temp[0] = [1,2,3];
  arr_temp[1] = [4,5,6];
  arr_temp[2] = [7,8,9];
  뭐 이렇게 다양한 방법으로 배열 선언이 가능하다.

2. OBJECT는 어떻게 선언할까..


  var obj_temp = {}; // 저는 이걸 가장 많이 씁니다.
  var obj_temp = new Object();

  이것도 마찬가지로 선언과 동시에 값을 넣을 수 있다.
  var obj_temp = {key1:"aa", key2:"bb"};

  그리고 오브젝트 안에 오브젝트도 가능하다.
  var obj_temp = {key1:{num1:"aa", num2:"bb"}};

  

3. 자 그럼 지원되는 함수는 뭐가 있을까요?..  

(참고 : http://www.w3schools.com/jsref/jsref_obj_array.asp)


  뭔가 영어로 엄청 써있다. 근데 자주 쓰일만한것을 알아보자
  
  push() : 배열의 마지막에 원소를 추가.
  ex) arr_temp.push(temp);

  unshift() : 배열의 첫번째에 원소를 추가.
  ex) arr_temp.unshift(temp);

  shift() : 배열의 첫번째 원소를 삭제. 스텍을 연상하면 될 것이다.
  ex) arr_temp.shift();
  

  pop() : 배열의 마지막 원소를 삭제.

  ex) arr_temp.pop();
 
  slice() : 배열을 index로 substring처럼 쪼갠다고 보면 된다.

  ex) arr_temp.slice(2, 3);
  
  concat() : 배열 두개를 합친다.
  ex) arr_temp1.concat(arr_temp2);

  보통 이것 외에 다른것 써본적이 없다. 딱히 쓸일이 없다랄까..

  이제 OBJECT에는 어떤 함수가 있나 보자.

  여기도 마찬가지로 영어로 뭔가 많다.
  
  keys() : 말 그대로 key를 배열로 반환해준다. key로 ordering을 한다.
  ex) Object.keys(obj_temp);
  
  values() : 이건 value를 배열로 반환해준다. key로 ordering을 한다.
  ex) Object.values(obj_temp);

  keys()와 values()는 함꼐 쓰면 용이 할 수 있겠다.
  
  entries() : key와 value를 2차원 배열로 만들어 준다. 마찬가지로  key로 ordering을 한다.
  ex) Object.entries(obj_temp);

자, 이 외에것은 위의 링크에 들어가면 매우 잘 나와 있다.
참고해보시길.



+ Recent posts