1. 상태관리와 SPA

상태 ( state ) 란?

값이 변하는 데이터 

state라고 불리는 상태는 웹 페이지 내에서 눈에 보이는 눈에 보이지 않는 모든 변화하는 데이터

※ 상태 관리란
데이터의 흐름을 편리하게 관리
상태를 효율적으로 변경
불필요한 리렌더링 발생 X 
사용자에게 좋은 경험 제공 (페이지 로딩시간)

 

"리렌더링"이란 상태가 변경될 때 컴포넌트가 다시 그려지는 과정

 

파일구조

  • 상태관리는 웹페이지의 데이터 흐름을 효율적으로 관리하고 사용자 경험을 개선하는 데 필수적인 기술임
  • 상태 관리를 사용하면 하나의 컴포넌트에서 변경사항이 발생한다면 해당 부분의 상태만 변경시킬 수 있기 때문에
  • 기존 방식에 비해 성능을 향상하고 데이터를 관리하기 쉽게 만들어줌
  • 상태관리를 통해 불필요한 리렌더링을 방지하고 웹 애플리케이션의  성능을 최적화할 수 있음

상태 관리 적용

기본적인 틀

  • 자바스크립트 기반의 라이브러리인 React.js 와 비슷한 구조로 state와 setState를 사용해 컴포넌트의 상태를 관리함
  • 상태 변화에 따라 웹 페이지를 업데이트하기 위해 rander라는 함수를 사용함
  • React 에는 state와 setState와 같은 메서드들이 내장되어 있지만 바닐라 자바스크립에서는 내장되어 있지 않기 때문에  비슷한 기능을 구현하기 위해서는 직접 코드를 작성해야 함

2-2 동물 앨범 만들기

App.js 파일에서 TabBar  와 Content 컴포넌트의 상태를 관리하는 이유는 웹 애플리케이션의 복잡성을 줄이기 위함임

  1. 제일먼저 this.state 객체를 사용해서 컴포넌트의 필요한 상태를 정의하고 초기화해야함
  2.  웹페이지에서는 어떠한 버튼을 눌렀는지에 대한 데이터와 API 호출의 결과값 두 개의 데이터를 상태로 나타낼수 있음. this.state 내부의 두개의 데이터를 넣어야함

  1. 현재 눌린 버튼의 값을 나타내는 currentTab 이라는 프로퍼트를 작성하고 전체를 나타내는 all 이라는 문자열로 초기화함
  2. 다음 컨텐트 컴포넌트에 표시될 사진들의 데이터를  담기 위해 photos 라는 프로퍼티를 배열의 상태로 초기화함

  1. 상태들을 업데이트 역할을 하는 this.setState 함수를 생성함
  2. setState 함수의 매개변수로는 업데이트할 새로운값을 newState 라는 값으로 받고 함수의 내부에서는 매개변수로
    전달받은 값을 this.state 에 할당해 state 의 새로운 값으로 업데이트해 줌

  3.  앱 컴포넌트에서는 이 상태가 업데이트 될 때마다 텝바와 컨텐츠 컴포넌트의 상태도 알맞게 업데이트 해주어야  함

  4. 텝바 컴포넌트는 4개의 버튼들이 있는 컴포넌트이기 때문에 탭바 컴포넌트에 필요한 상태는 this.state 객체에 내부에 있는 currentTab 에 대한 값이고 컨텐츠 컴포넌트는 사진을 나타내는 기능의 컴포넌트이므로 컨텐츠 컴포넌트에 필요한 상태는 this.state 객체의 photos의 저장된 값이다. 

  5. 각각의 인스턴스들이 갖고 있는 setState 메서드의 인수로 전달해줘야함 
  6. 탭바 컴포넌트와 컨텐츠 컴포넌트도 setState  라는 함수를 가지고 있음
    이 값들을 currentTab 와 photos 라는 값을 각각의 인스턴스들이 갖고 있는 setState  메서드의 인수로 전달해주어야함.

  1. 텝바의 setState 메서드의 인수로는 this.state 객체가 갖고 있는 currentTab 데이터를 전달해주고
    컨텐츠 컴포넌트의 setState 메서드의 this.state 의 photos라는 값을 전달해줌
  2. 탭바 콤포넌트에 필요한 상태 및 기능들을 전달해야함
  3.  탭바 컴포넌트는 4개의 버튼을 누르는 기능과 어떠한 버튼이 눌렸는지에 대한 상태가 필요함
    탭바 함수에는 초기 상태를 나타내는 initialState 라는 값과 버튼을 누르는 기능을 하는 onClick이라는 함수를 전달함

  1. 탭바 함수에는 초기 상태를 나타내는 initialState 값과 버튼을 누르는 기능을 하는 onClick 함수를 전달함
  2. 온클릭 함수는 버튼이 클릭될 때 실행되는 함수로 버튼을 누르면 CurrentTab이라는 상태를 눌린 버튼의 값으로 변경 시켜야함
  3. 눌린 버튼의 상태에 맞는 API 를 호출해 알맞은 데이터를 가져와야함 

  1. 눌린 버튼에 대한 값은 name 이라는 매개변수로 전달 받고 setState 를 통해 상태가 변경되었을 때 
    state에 정의 되어 있는 값들을 변경 시켜줘야함
  2. spread 연산자를 사용해서 기존의 상태를 유지하고 this.state 객체에 있는 currentTab 에 대한 값으로는
    전달 받은 name을 넣어줌
  3. 그 다음 photos 의 값으로는 api 를 통해 받아온 사진을 넣어주어야함

  1. api 를 호출하기 위해 api 모듈을 import 해야함
  2. api.js 파일로 이동하면 export 라는 키워드를 통해 해당 함수를  공개 처리해주었고 
    해당 함수를 request 로 해줌

  1. 해당 모듈을 사용하기 위해 import 라는 키워드를 작성한 다음  {request}라는 함수를 중괄호 안에 
    작성해주면 사용가능함
  2. onClick 함수가 실행 될때 photos 배열의 값을 request 함수의 결과 값으로 변경 시켜줌
  3. API 는 비동기로 처리해야 하므로 request 함수의 앞에 await 키워드 작성 , onclick앞에 async 작성

  1.  웹 페이지의 초기 상태 값을 설정해주는 init이라는 함수 추가함
  2.  init 이라는 함수는 현재 this.stae 에서 currentTab 의 초기값은 임의로 설정해주었지만
    photos 라는 값에는 빈 배열이 담겨져 있음
  3. 웹 애플리케이션을 시작할 때 필요한 작업을 실행하고 초기 상태를 설정하는 역할을 하는 함수인 init 함수 추가해야함
  4. 웹 페이지의 초기 상태에서 필요한 데이터는 여기에서는 모든 동물의 사진임
  5.  init 함수의 내부에서는 모든 사진들을 가져와야함 

  1. API 를 호출해야 되기 때문에 try,catch 로 에러 처리를 해주고 try 문의 내부에서는 사진데이터의 초기값을 나타내는
    initialPhotos 라는 변수에 API 결과 값을 넣어주도록 해야함 
  2. await 이라는 키워드를 사용해야하기 때문에 init 함수의 앞에는 async라는 키워드를 작성해줌
  3. setState 의 내부에서 spread 연산자를 사용해 기존의 상태를 유지하면서 state  객체의 photos 라는 배열을 
    initialphotos 변수에 할당된 값으로 변경시켜주어야함 
  4. init 함수는 웹 애플리케이션이 실행될 때 실행되어야 하기때문에 코드의 밑에 함수를 호출해줘야함
    탬바 컴포넌트의 기능을 개발해야함

상태를 기반으로 페이지를 렌더링할 때 사용되는 가장 일반적인 구조임

 

  1. 탭바.js 파일에서는 탭바라는 컴포넌트를 모듈로서 사용 할 거기때문에 export default 키워드를 작성해주고 이 탬바 함수를 모듈로 내보내 줌
  2. 함수의 내부에 기본적인 구조로 코드를 작성함
  3. this.state 와 this render 함수를 작성해주고 state 값을 업데이트 하는 this.setState 함수를 작성해줘야함
  4. setState  함수의 매개변수에는 업데이트 할 newState 라는 값을 전달받고 setState  내부에서는 this.state 값을 전달받을 값으로 업데이트 해주고 화면을 업데이트해주는 코드를 작성함 

  1. App.js 파일에서 탭바 함수의 initialState와 onClick 을 전달했었는데 탭바 함수의 매개 변수로 initialState, onClick 전달해줌
  2. 탭바 함수 내부에서의 state 값은 전달받은 이니셜 스테이트로 설정해주고 온클릭또한 전달받은 onclick함수로 설정함
  3. 탬바 컴포넌트에는 4개의 버튼들을 나타내야 하고 버튼을 눌렀을 때 onclick 함수를 실행해 알맞은 aip 를 호출해야함

  1. 4개의 버튼이라는 것을 만들어야 하는데 , 템플릿이라는 함수를 만들고 함수의 내부에 템프라는 변수를
    선언한 다음 4개의 버튼 요소들을 작성함
  2. 템플릿이라는 함수가 이 temp 라는 변수에 있는 값을 반환할 수 있도록 리턴문 작성함
  3. render 라는 함수는 템플릿함수를 통해 반환받은 템프 요소가 id 가 app 인 div  요소 내부에 추가하는 역할을 수행해야함
  4. render 함수 내부에서는 innerHTML 을 사용해서 새로운 요소를 추가해야 
  5. 먼저 id가 app 인 div 요소를 가져와야함

 

  1. 작성한 템플릿을 화면에 나타내주어야함
  2. render 함수의 내부에서 작성했던 템플릿이라는 함수를 호출해줌 
  3.  id가 app인 div요소를 가져와야함
  4. app.js에서 app이라는 함수가 전달받은 앱 요소를 탭바함수에 전달하고 탭바함수의 매개변수로 앱요소를 받아옴
  5. 템프에 작성된 요소를 감싸는 외부 div 를 생성해줌 
  6. target 이름 변수에 createElement를 사용해서 새로운 div 를 하나 만들어줌
  7. div 요소의 클래스 이름을 탭바로 설정해줌
  8. 매개변수로 받아온 app요소에 appendChild 메서드를 사용해서 생성해 주었던 target 이라는 요소를 추가함
  9. 랜더 함수의 내부에서 새로 생성한 target 이라는 요소에 innerHTML 을 사용해 this.template 함수의 
    반환값을 할당해줌
  10.  마지막으로 this.render함수를 호출

버튼을 흰색 배경으로 바꾸는 코드

클릭했을때 코드

1 컴포넌트

컴포넌트는 웹 애플리케이션의 구성요소로 웹 애플리케이션을 기능별로 나눈 독립적인 부분

  • 중복코드 작성하지 않고 재사용 가능 
  • 기능과 구조를 명확하게 분리 가능
  • 독립적인 요소  -> 유지보수 편리

컴포넌트와 모듈

  • 4 개의 버튼들이 있는 TabBar와 사진들을 Content로 나누고 각각 TabBar.js와 Content.js로 분리함
  • API를 호출하는 기능은 별도의 컴포넌트로 나누지 않았음
    -> 컴포넌트는 주로 사용자 인터페이스와 사용자와 상호작용을 하는 부분, UI를 나타내기 때문에
  • UI 재사용 부분이 아닌 재사용이 가능한 어떠한 기능인 API 를 호출하는 코드는 컴포넌트로 나눌 수 없음
    -> 컴포넌트로 분류할 수는 없지만 중복되는 기능은 컴포넌트가 아닌 하나의 모듈로 나눌수 있다

모듈

  • 재사용 가능한 코드의 집합으로 , 특정 기능을 수행하는 코드를 하나의 단위로 묶어 관리함
  • 모듈은 코드를 쉽게 관리 할 수 있도록 중복되는 기능을 작은 단위로 나눠 쉽게 재사용할 수 있도록 하는 방법 
  • 여러 부분으로 나눠진 코드를 각각의 모듈로 만들어 관리하면 필요할 때마다 조합해서 사용함
  • 재사용하기 쉽고 코드의 가독성이 좋아지고 코드의 유지보수기 편리함

2. 컴포넌트와 모듈시스템

모듈시스템

컴포넌트 단위로 나눈 자바스크립트 파일은 하나의 모듈이며 다른 파일에서 필요할 때 가져와 사용가능함

 

모듈 사용법 알아보기

  • 자바스크립트는 ES6 버전부터 기본적으로 ECMAScript 모듈 시스템이라는 모듈 시스템 제공함
  • 모듈 시스템에서 모듈은 보통 하나의 파일을 의미하고 이 모듈들은 각각 자신만의 스코프를 갖고 있음
    -> 일반적으로 모듈 내부에 작성되어 있는 기능들은 서로 외부에 공유할 수 없고 모듈 내부에서만 사용 가능함
    -> 즉 모듈 내부에 작성된 식별자들은 전부 비공개 처리가 되어 있음 
  • ECMAScript 모듈 시스템은 비공개 처리된 식별자들을 공개 상태로 변경해 주는 Export라는 키워드를 제공함

  • 식별자의 선언문 앞에 Export 키워드를 작성하면 해당 식별자는 공개 상태변경되어 다른 파일에서 사용 가능한 상태가 됨
  • export 키워드를 통해 공개된 식별자를 다른 파일에서 사용하기 위해서는 ECMAScript 모듈 시스템이 제공하는 import라는 키워드를 사용함
자바스크립트의 ESMAScript 모듈 시스템에서는 이 Export 키워드를 사용해 외부에 공개할 기능을 명시해주고
import라는 키워드를 통해 다음과 같이 공개된 모듈들을 가져올 수 있음 

 

자바스크립트 파일을 모듈로서 사용하는 방법

  • index.html 파일에 스크립트 태그의 타입을 모듈로 설정함
  • 모듈로 사용되는 자바스크립트 파일은 자바스크립트의 파일이 아니라 모듈임을 명시해 주기 위해 JS에서 mjs로 변경해 줌 

한 번에 import 하고 export 하는 방

 

  • 만약 모듈에서 내보내고자 하는 값이 다음과 같이 단 한 개만 존재한다면 코드의 가장 아래쪽에  default라는 키워드를 작성해서 식별자를 좀 더 간단하게 export 할 수 있음 

하지만 const let var 랑 default는 같이 사용할 수 없음

 

test.mjs 파일이 적혀있는 스크립트 태그를 삭제했지만 오류 생기지 않고 알맞은 값이 나옴

자바스크립트 파일을 모듈로서 사용하면 여러 모듈의 중심이 되는 파일인 index.mjs 파일만 이렇게 스크립트 태그로 로드해주면 됨  


2-1 동물 앨범 만들기

  • 각각 파일들이 가져와야 할 모듈이 서로 중복되는 경우에는 새로운 자바스크립트 파일을 생성해서 관리해야 함
  • 여러 개의 모듈들을 관리하는 새로운 자바스크립트 파일의 이름은 보통 App.js로 설정함
  • App.js 파일에서는 필요한 기능들을 불러와서 조합하거나 다른 모듈로부터 정보를 전달받아 처리함
App.js
웹 애플리케이션의 시작점
주요 기능들 작성
여러 모듈들 조합 및 연결 
가독성 증가

 

i

1 - index.html과 index.js 파일을 제외한 모든 파일 삭제

2 - src 폴더의 내부에 components 폴더를 생성함 

3 - components 폴더 내부에 TabBar.js 와 Content.js 와 api.js 생성해 줌

4 - index.js 파일에 있는 코드를 복사해서 api.js로 옮겨 줌

5 - api.js는 api를 호출하고 결과 값을 반환하는 역할만 해야 함 

6 - src 폴더의 내부에 이 모듈을 관리하는 자바스크립트 파일인 App.js 파일을 생성해 줌

7 - index.html 수정함 

8 - index.html 에서 클래스 이름인 TABBAR와 CONTENT 인 div 요소는 모듈로 나눠지는 파일이기 때문에 삭제해 주고

     주석으로 표시하고  스크립트 타입을 module로 작성함

9 - index.js를 수정함

10 - index.js 파일에서는 여러 모듈들을 관리하는 역할의 app.js 파일을 import 해줌

11 - index.js 파일에 웹페이지들의 핵심이 작성되어 있는 app.js 모듈을 가져와서 웹페이지에 나타내 주는 코드를 작성해야 함

12 -  4개의 버튼과 사진들이 표시되어야 하는 부분은 index.html 파일에서 id 가 app인 div 요소의 내부에 존재해야 하므로

13 -  우선 html 문서에 id 가 app인 요소를 찾아 app 엘리먼트라는 변수에 할당함

14  - 그다음 생성자 함수를 사용해 app컴포넌트를 불러와야 함

15 -  new 키워드를 사용해서 컴포넌트의 새로운 인스턴스를 생성하고 AppElement 변수에 담은 id가 app인 요소를

        생성자 함수에 전달해서 AppComponent의 인스턴스가 AppElement 요소를 화면에 표시할 수 있도록 AppElement

       요소를 조작할 수 있도록 해줌

16 - TabBar.js로 넘어가서 코드작성함

17 - TabBar.js 에서는 tabBar 컴포넌트를 나타내는 tabBar라는 함수 하나를 모듈로서 내보내주어야 하기 때문에

       식별자가 단 하나만 존재할 때 사용할 수 있는 export default를 사용해서 내보내줌 ( content.js 도 마찬가지 )

 

18 - 모든 모듈들을 관리하는 app.js 파일에 코드를 작성해야 함 

19 - App.js 파일에서는 tabBar 모듈과 content 모듈을 가져와서 관리해야 하기 때문에 두 개의 모듈들을 import 해야 함

20 - index.js 파일에서 생성한 앱 컴포넌트의 인스턴스에 인수로 앱 엘리먼트 요소를 전달해 주었기 때문에 export default라는 키워드가 붙어있는 앱 함수 옆에 있는 소괄호 안에 전달받은 app 앨리먼트 요소를 작성함

21 - import 키워드를 통해 가져온 tabBar  컴포넌트와 conetent 컴포넌트를 앱 컴포넌트에서 사용할 수 있도록 코드를 작성해야 함

22 - tabBar라는 변수에 new 키워드를 사용해서 tabBar 컴포넌트의 인스턴스를 할당해 주고 content라는 변수에는

       new 키워드를 사용해 content 컴포넌트의 인스턴스를  할당해 줌

23 -  컴포넌트를 생성자 함수를 사용해 활용하면 동일한 구조와 기능을 가진 컴포넌트의 인스턴스를 여러 번 편리하게 재 사용할 수 있음  또한, 새로운 기능이 추가되거나 수정이 되더라도 기능을 쉽게 추가, 수정할 수 있

 

 

1-1 동물 앨범 만들기

동물 사진들은 API 호출을 통해 불러올 수 있음

 

API 사용법

API 주소만 호출하게 될 경우 값을 반환하고 API 주소의 뒤쪽에 동물 이름을 넣어 호출하게 되면

이 name에 해당하는 동물들의 사진들만 반환하는 api 

 

  1. API 주소를 const 키워드를 통해 작성해 줌 
  2. API를 호출하는 기능을 하는 getData라는 함수를 작성해 줌 / const getData =()=>{}
  3. getData 함수의 내부에서는 res라는 변수의 fetch 메서드를 사용해서 API를 호출해 주고 API를 비동기적으로 처리해 주기 위해 함수의 앞에는 async를 작성하고 feach메서드 앞에는 await를 작성해야 함 
    const getData = async() =>{  let res = await feach(API_URL);
  4.  API는 tryCatch 문을 사용해 에러 처리를 해야 함  /  try 내부에서는 만약 res라는 결괏값이 존재할 경우 data라는 변수에 API호출의 결괏값을 JSON으로 파싱 해야 함 /   if(res){ let data = await res.json()}
  5. 그다음 API 호출결과를 console.log탭에서 확인 -> console.log(data);
  6. 에러를 처리하는 catch 문의 내부에는 에러를 출력하는 코드를 console.log(err)
  7. 코드 가장 하단에 getData();를 호출해서 출력값을 확인, 개발자 도구 열어 콘솔탭에 데이터확인함
  8. 그 다음 API 호출 결과 값을 이 클래스 이름이 콘텐츠 인 div 요소의 내부에 나타내줘야 함
  9. data 변수에  photos라는 배열을 forEach 배열 메서드를 사용해서 배열에 담긴 요소들을 하나씩 꺼내주어야 함
    data.photos.forEach((elm)=>{})
  10. forEach 함수의 내부에는 엘리먼트 요소들을 하나씩 출력해보아야 함 console.log(elm)
  11. API 호출 결과인 데이터에 photos라는 배열을 forEach 메서드를 통해 요소들을 하나씩 출력하면 photos 배열에 담긴 요소들이 하나씩 출력됨
  12. element요소의 url이라는 값을 image 태그에 src로 넣어 이미지를 index.html의 content div에 나타내야 함
  13. class이름이 content인 div 요소에 html 코드를 넣기 위해서 DOM API를 사용해야 함
    코드를 추가해 줄 대상 요소인 컨텐트 요소를 가져와야 함 const $content = document.querySelector('div.content'); 가져올 수 있음
  14. forEach 메서드의 내부에 `<img src=${elm.url}></img>` 작성해 줌
  15. 여러 개의 이미지 태그들을 한 번에 묶어서 이 콘텐츠 엘리먼트에 넣어주어야 하기 때문에 let templat =[]; 빈 배열을 전역변수로 만들어주고 생성한 템플릿 변수의 복합 대입 연산자를 사용해서 여러 개의 이미지 태그들을 템플릿이라는 변수에 모두 담아줌 template +=  `<img src=${elm.url}></img>` 
  16. 템플릿 변수에 담긴 배열을 콘텐츠 엘리먼트의 innerHTML을 사용해서 추가해 줌 $content.innerHTML = tamplate;작성 후 실행

 


1-2 동물 앨범 만들기

각 버튼에 맞는 이미지로 세팅해 보기

 

  1. 코드에서 API를 호출해 이름값이 penguin 인 데이터만 전달받기 위해서는 API 주소 뒤에 원하는 동물의 이름을 전달해주어야 함
  2. getData 함수에 penguin이라는 값을 전달하고 
  3. getData 함수에서는 매개변수로 name이라는 값을 전달받아 API URL 뒤쪽에 추가로 작성해주어야 함`${API_URL}$(name)`
  4. 버튼을 눌렀을 때 각각 다른 화면이 나올 수 있도록 해주기
  5. index.html로 가서 a태그를 이용해 페이지 이동시켜 줌
  6. clicked라는 클래스 이름은 버튼의 배경색을 흰색으로 표시해 주기 위한 클래스임 버튼을 눌렀을 때 각각 화면의 이미지가 맞게 실행될 수 있도록 해주기 

1.this 와 화살표 함수

화살표 함수와 일반함수의 차이점은 함수 내부의 this 가 가리키는 값이 다르다는 것임

 

this는 함수가 어떻게 호출 되었는가에 따라 바인딩(binding) 하는 값이 달라지는 키워드임

웹개발에서 바인딩 (Binding)이란, 데이터를 특정 위치에 동적으로 연결하는 것을 의미한다.

 

화살표 함수 내부의 this 가 어떠한 값을 갖는지 알아보기

콜백함수를 사용하는 예제

  • 생성한 count 변수를 0 으로 초기화
  • 내장함수인 setInterval 메서드를 사용함
  • setInterval 메서드는 매개 변수 변수로 콜백함수와 딜레이 타임을 전달받는 메서드임 
  • 콜백 함수로는 function 키워드를 사용해서 count변수의 값을 1씩 증가시켜주고 증가된 카운트의 값을 출력해주는 코드를 콜백함수의 내부에 작성해줌
  • setInterval 함수에 전달된 콜백함수인 this 는 생성자 함수를 통해 새로운 카운터 객체를 가리키지 않고 전역객체인 window 객체를 가리키기 때문에 숫자가 1씩 증가되어 출력이 아니라 NaN이라는 값이 2초마다 출력됨

콜백함수를 화살표 함수로 변경해 코드를 작성하는 방법

  • 콜백함수를 화살표 함수로 변경했을 뿐인데 코드가 알맞게 동작함 ex) 1 2 3 4 5 / 2초마다 1씩증가
  • this 는 함수가 호출된 방법에 따라 가리키는 값이 달라짐
  • 화살표 함수의 this 는 함수의 호출 방식이 아닌 함수가 정의 된 시점에서 상위 스코프의 this 를 참조 한다는 특징이 있음
  • 자바스키립트가 식별자의 스코프를 결정하는 방법인 Lexical Scope (렉시컬 스코프) 와 유사

 

Lexical Scope 

함수의 호출 방법이 아니라 함수가 선언된 위치에 따라 스코프가 결정되는 방법 

 

일반함수로 호출이 되었으므로 웹 브라우저의 전역 객체인 윈도우 객체가 this 에 바인딩 된것임

 

  • 콜백함수를 화살표 함수로 작성한다면 이 화살표 함수 내부의 this 는 함수가 어디에 선언되었는가에따라 바인딩 되는 값이 달라지기 때문에 콜백 함수가 선언된 위치인 setInterval 메서드 내부를 기준으로 창의 스코프를 참조함

※ 함수가 어디에 선언되었는가 ?

함수 선언 위치에 의해 스코프 결정 -> Lexical Scope (렉시컬 스코프)

  • 화살표 함수는 함수의 선언 위치에 따라 스코프를 결정하는 방법인 Lexical Scope (렉시컬 스코프)를 따라 상위 스코프의 this 를 참조하기 때문에 함수의 호출위치와 상관없이 항상 고정된 this 의 값을 가짐
  • 콜백함수의 내부에서 this 키워드가 자신이 포함된 객체가 아니라 전역객체를 가리킨다는 문제점을 해결하기 위한 대안으로 사용

 

 

this의 값에 윈도우 객체가 바인딩되어 출력됨

화살표 함수의 this는 자신을  포함하고 있는 함수가 선언된 위치의 상위 스코프를 참조하기 때문에

프린트 메서드가 선언된 위치인 cafe객체의 상위 스코프인 전역객체가 출력

-> 자바스크립트에서 객체의 메서드를 작성할 때에는 화살표 함수를 사용하지 않고 일반함수를 사용함

 

1.자바스크립트의 this

자신이 속한 객체를 가리킴 

this 는 자신이 속한 객체를 가리키는 키워드로 자바스크립트의 함수와 관련이 있음

자바스크립트의 this 키워드는 함수가 어떻게 호출되었는가에 따라 바인딩되는 값이 달라진다는 ,

즉 값이 동적으로 결정

"바인딩되다"라는 표현은 주로 프로그래밍에서 특정 변수나 객체가 특정 값이나 함수에 연결되는 것을 의미합니다.

 

전역공간

window 객체는 웹 브라우저의 전역객체로 전역공간에 항상 존재하는 객체를 의미함

 

함수

  • this 키워드는 자신을 포함하고 있는 함수가 어떻게 호출 되었는가에 따라 값이 달라짐
  • this 키워드를 포함하고 있는 fuc함수를 호출한 객체인 윈도우 객체가 this에 바인딩이 됨

메서드

메서드 = 객체의 프로퍼티에 저장된 함수

함수를 메서드로써 호출하면 메서드를 포함하고 있는 객체 자체가 출력이 됨

메서드를 호출 했을 때 메서드의 호출문에 있는 점 바로 앞에 객체가 출력이 된다고 봐도됨

 

  • this가 포함 된 함수인 print 메서드를 갖고 있는 newCafe 라는 객체의 프로퍼티들이 출력됨
  • print 메서드를 호출 했을 때 점 바로 앞에 있는 객체가 출력이 됨

  • 코드를 실행하면 전역 객체인 윈도우 객체가 출력됨
  • 함수가 메서드로써 호출이 되면 무조건 이 메서드의 점 앞에 있는 객체 그 자체가 출력이 되는건 아닌가? 라고 생각한다면

※ this 키워드에 대한 설명을 다시 한번 생각해야함

this 는 자신이 속한 객체를 가리키는 키워드로 자신을 포함하고 있는 함수가 어떻게 호출 되었는가에 따라 가리키는 값이 달라지는 키워드이다

 

  • 코드에서 this 를 포함하고 있는 print 함수는 메서드로서 호출된 것이 아니라 전역 공간에서 일반함수로 호출이 되었음myCafe 함수를 호출한 객체인 전역 객체, 윈도우 객체가 출력이 됨

this 는 함수가 선언된 위치나 방법에 영향을 받지 않고 무조건 함수가 호출된 방법에 따라 가리키는 값이 달라진다는 것을 기억해야함 

 

this-2

자바스크립트의 this 는 함수가 어떻게 호출되었는가에 따라 가리키는 값이 달라짐

 

생성자함수

  • this 값으로는 생성자 함수를 통해 생성한 Cafe{} 라는 객체가 출력이 됨
  • 생성자 함수의 this 는 생성자 함수가 새로 생성할 새로운 객체 즉, 인스턴스를 가리킴
  • 인스턴스 (instance)는 객체 지향 프로그래밍 (OOP)의 핵심 개념 중 하나로, 클래스로부터 생성된 객체를 의미합니다

 

함수가 콜백함수로서 호출될 때 this는 어떠한 값을 가리키는지 알아보기

  • 자바스크립트의 this 는 자신을 포함하고 있는 함수가 어떻게 호출되었는가에 따라 값이 달라짐
  • setMenu 의 메서드의 this 는 getMenu라는 함수 내부에서 메서드로서 호출이 아닌 일반함수로서 호출이 됨
  • 함수가 일반함수로서 호출되면 this는 전역 객체인 윈도우 객체를 출력함
  • '핫초코는'는 웹 브라우저의 전역 객체인 윈도우 객체의 메뉴에 프로퍼티에 할당됨.

함수가 callback 함수로서 호출되면 callback 함수에 있는 this는 예상한 것처럼 동작하지 않고 this 값에 전역 객체인 window 객체가 바인딩 된다는 문제가 있음

 

 

자바스크립트의 this 는 함수의 호출 방식에 의해 값이 동적으로 바인딩이 되고
함수가 일반함수로서 그리고 콜백함수로서 호출 될 때의 this 는 전역 객체를 가리킴
함수가 함수가 메서드로서 호출되었을 때의 this 는 메서드를 포함하고 있는 객체를 가리키고
마지막으로 생성자 함수로서 호출되면 this는 생성자 함수가 새로 생성할 새로운 객체를 가리킴

 

1.DOM API-2

createElement

새로운 노드를 생성할 수 있음

타입 요소에 텍스트 값이 추가됨

별도의 텍스트 노드가 새로 생성됨

 

DOM API를 사용해 div 요소와 text 노드를 생성했지만 화면에는 '몰티즈'라는 텍스트는 안보임

-> 화면에 보이지 않는 이유는 생성만 되었을 뿐 , 아직 DOM 트리에 추가된게 아니기 때문임

  1. appendChild라는 메서드를 사용해서 전달받은 노니를 원하는 요소의 마지막 자식으로 추가할 수 있음
  2. DOM 트리는 노드 간의 상하 관계를 한눈에 볼 수 있는 트리구조임 
  3. 상하관계는 부모 관계라고 함 
  4. appendChild 는 부모 노드를 작성한 다음 부모 노드에 appendChild를 작성하고 appendChild의 괄호 안에는 부모 노드에 새로 추가할 자식 노드를 작성해야 함

버튼 태그로 이루어져 있는 노드를 추가하는 코드

  1. 새로운 버튼 요소를 생성해야 하므로 버튼이라는 변수에  document.createElement를 사용해 태그의 이름인 버튼을 작성해 버튼요소를 생성
  2. 버튼 요소의 id는 new 버튼으로 설정, 또한 버튼 요소의 클래스 이름도 new button 
  3. 버튼 요소의 텍스트에는 textContent 사용해서 한글로 '버튼'이라고 작성 
  4. 버튼요소를 클래스 이름이 animalInfo 인 자식 노드로 추가함
  5. animalInfo 요소를 변수 생성 후 document.querySelector를 사용해서 클래스 이름이 animalInfo 인 div 요소를 할당
  6. 부모 노드인 animalInfo의 부모 노드를 작성한 다음 appendChild 메서드를 사용해서 추가할 요소인 button 요소를 괄호 안에 작성해  animalInfo 요소의 자식 노드로 button 요소를 추가함 

DOM 은 특정 요소에 여러 가지 이벤트를 추가할 수  있는

AddEventListener라는 DOM API를 제공함

 

AddEventListener( 이벤트, 리스너)를 매개변수로 전달받음

  • 이벤트는 어떠한 이벤트를 발생시킬 것인지 나타내고 
  • 리스너는 앞에 이벤트가 발생했을 때 실행될 어떠한 함수를 전달받음
  • window라는 객체에 alert라는 메서드를 사용
  • window 라는 객체는 현재 사용하고 있는 웹 브라우저의 창을 나타내는 객체
  • alert() 메서드

특정 요소의 내부에 HTML 요소를 추가할 수 있는 DOM API 인

InnerHTML 

InnerHTML 은

DOM API 속성 중 하나로 특정 요소의 HTML을 문자열 형태로 읽거나 설정할 수 있음

요소의 내부 HTML 을 나타내는 문자열을 반환하거나 설정된 문자열을 요소의 자식으로 해석함

요소 내부에 있는 모든 HTML 요소들이 출력됨

 

요소의 내부의 HTML 을 새로운 문자열로 생성해 보기

innerHTML을 사용해서 특정요소를 추가하면 

기존의 모든 자식 요소들은 제거가 됨 , 새로운 요소로 대책 된다는 특징이 있음

-> 성능이나 보안에 문제가 있기 때문에 주의해야 함. 가능하다면 createElement나 textContent 같은 다른 DOM API를 사용해서 개발하는 게 좋음

 


2. 여러 가지 폼 조작 

폼(Form)이란

웹 페이지에서 사용자로부터 데이터를 수집하거나 사용자와의 상호작용을 가능하게 하는 HTML 요소

자주 사용하는 태그는  <input> <select> <textarea>

 

label 태그

일반적으로 특정 폼 요소의 라벨을 정의할 때 사용하는 태그

select태그

여러 개의 옵션 중 하나를 선택할 수 있는 드롭다운 목록을 제공

  • label의 for 속성을 select id 값으로 설정해 주면 label 태그는 select 태그의 라벨로써 동작함
  • select 태그의 내부에 있는 option 태그들에는 value라는 속성은 실제 서버에 전달되는 option 태그의 값으로 폼 데이터를 조작할 때 해당값을 이용함 / 사용자들은 한글로 작성된 과일 이름이지만 자바스크립트 파일에서는 option 태그 내부의 value 속성값으로 폼 요소를 조작할 수 있음 
  • option에 slected를 작성하면 기본값을 설정할 수 있음

  1. document에 getElementById를 사용해서 select 요소를 가져온 다음 $fruitselect에 할당함
  2. 가져온 요소에 이벤트를 처리함
  3. 이벤트 리스너를 사용하면 사용자가 select 요소의 옵션을 변경할 때마다 이벤트를 감지해 옵션을 변경할 때마다 이벤트를 감지해서 작업을 처리할 수 있음
  4. 이벤트는 값이 변경될 때마다 실행되어야 하기 때문에 'change' 이벤트를 작성
  5. 해당 이벤트를 발생할 때마다 실행될 콜백함수에는 매개변수로 event를 전달받아서 전달받은 이벤트라는 값을 사용해서 이벤트. 타깃. 벨류 출력하면 select태그 내부의 값을 변경할 때마다 변경된 값에 해당되는 벨류 값을 출력함 

- select 요소를 가져온 다음 옵션 태그에 있는 특정  값을 삭제해보기

 

- input 태그 사용해 보기

특정 값을 입력하기 위해 사용되는 태그 

  • input 태그에 type 속성을 알맞게 작성하면  유효성 거사를 자동으로 수행해 준다는 장점이 있음
  • 사용자가 어떠한 데이터를 입력할 것인지에 대한 데이터 타입을 명확하게 알 수 있음
  • 초기값을 주고 싶다면 value를 작성 

 

- 버튼을 사용하지 않고 input 태그의 값을 가져오고 조작해 보기 

  • userName의 값을 수정하고 싶다면 value 속성을 사용하고 
  • 버튼이 아니라 입력폼에 값이 입력될 때마다 입력된 값을 가져오고 싶다면 input요소의 eventListener를 사용해서 input 이라는 이벤트가 발생할때마다 callback 함수의 매개변수로는 이벤트의 타겟에는 value 값을 출력해준다면 비밀번호를 입력하는 input에 값이 입력될때마다 작성되어 있는 값을 출력할 수 있음 

 

1 웹과 DOM

자바스크립트는

웹 페이지를 동적으로 만들어주기 위해 개발된 프로그래밍 언어이다.

DOM을 통해 웹 페이지의 요소에 접근할 수 있다

 

DOM 이란

Document Object Model의 약자로 직역하면 문서 객체 모델 이라고 할 수 있음

 

DOM 은 HTML로 작성된 여러 요소들에 자바스크립트가 접근하고 조작할 수 있도록 브라우저가 변환시킨 어떠한 객체이다

즉,  HTML 로 작성된 요소들을 자바스크립트가 이해할 수 있도록 객체로 변환한 것 

웹의 구성요소

  • 인터넷에서 사용자들이 정보를 공유할 수 있는 공간 
  • HTML로 작성된 페이지를 웹 페이지라고 부름
  • 웹 페이지가 여러 개 모여있는 웹 페이지들의 집합을 웹 사이트라고 부름
  • 웹 사이트는 URL에 접속해서 볼 수 있는 웹 페이지들을 통트렁 부르는 말로 홈페이지라고 함

 

HTML 
Hyper Text Markup Language 
웹 페이지의 요소들이 어떻게 구성되어 있는지 알려주는 역할

CSS
Cascding Style Sheets
웹 페이지의 요소들을 꾸며주는 역할( 색상,크기 등)

Javascript 
웹 페이지를 동적으로 만들어 사용자와 상호작용을 가능하게 만드는 역할

 

DOM 트리DOM은 웹 브라우저가 HTML로 작성된 요소들을 Javascript 가 이용할 수 있도록 객체 형태로 변환한 모델임

태그 요소들은 각각 노드라고 부르며 하나의 객체 형태로 이루어져 있음

document는 문서노드이며 파란색으로 표시된 노드들은 요소노드, 분홍색으로 표시된 노드는 텍스트 노드임

 

2) DOM API -1

DOM은 JavaScript가 자신에게 접근해서 조작할 수 있는 방법을 제공함

JavaScript 를 사용해 DOM 요소에 접근하려면 DOM 이 제공하는 방법인 DOM API 를 사용해야 함

 

DOM API 

getElementByid = 특정 요소를 id 값으로 가져온다는 의미로 특정 요소의 객체 값을 반환함

DOM에서 어떠한 요소를 찾을 때에는 가장 먼저 문서노드 -> 다큐먼트에 접근해야 함

DOM  API를 사용해서 특정 요소를 변수에 할당할 때에는 일반적으로 요소를 할당할 변수의 이름 앞에 

$라는 기호를 붙여서 작성하거나 변수명의 뒤에 element를 작성함 

 

querySelector

css선택자로 요소 노드를 반환하는 API 

 

JavaScript의 DOM API 에는 조건을 만족하는 요소가 여러 개일 경우 사용하는  DOM API 

  • querySelectorAll
  • getElementByClassName
  • getElementsByTageName

 

querySelectorAll 

전달받은 클래스 이름을 갖고 있는 여러 요소들을 전부 찾은 다음 반환하는 DOM API 

 

getElementsByClassName 

css 선택자가 아닌 클래스의 이름만으로 여러 요소들을 찾는 DOM API

 

getElementsByTagName

요소들의 태그 네임을 통해 요소들을 찾을 수 있음. 태그는 div, img, 버튼과 같은 HTML 요소들의 태그 이름임

특정 태그로 이루어진 여러 개의 요소들을 출력할 수 있음 

 

요소들의 속성값과 텍스트 등을 변경할 수 있는 즉, 조작할 수 있는 DOM API 

 

  • 요소의 클래스 이름을 변경하는 방법

 

  • ID값을 변경하는 방법 

classList는 className처럼 특정 요소의 클래스 속성에 접근 가능한 프로퍼티이지만 add, contains, item과 같은

여러 가지 메서드들을 제공함 

 

classList  add() , remove() 사용해 보기

 

텍스트 노드의 값을 조작해 보기

textContent ()

 

요소 노드의 스타일을 조작해 보기 

 

02 비동기와 API

1.async와 await

async 와 await 은 프로미스 객체를 더욱 쉽게 작성할 수 있게 도와주고 코드를 직관적으로 해석할 수 있게 도와줌

 

  • delay 함수가 호출하면 생성한 프로미스 객체를 반환할 수 있도록  리터문으로 작성
  • delay 함수를 호출하는 start라는 함수를 작성해 줌
  • delay 함수는 프로미스 객체를 반환하기 때문에 함수 호출문 뒤에 then 메세드를 사용해서 resolve함수를 통해 전달받은 결과 값을 출력하는 코드를 작성함 

async라는 키워드를 작성해 볼 경우 

  • async는 비동기를 수행할 함수의 오른쪽에 작성함 
  • 어떠한 함수에 async라는 키워드를 작성하면 해당 함수는 항상 자동으로 프로미스 객체를 반환함
  • await 키워드 async 키워드가 작성된 함수의 내부에서 사용하는 키워드임 
  • await 키워드가 작성된 코드가 실행되면 해당 작업이 종료될 때까지 프로그램의 실행이 중단됨

  • await이라는 키워드는 프로미스 객체가 처리 완료될 때까지 함수의 실행을 기다리게 만듦
  • 비동기 작업들을 소요되는 시간을 예측할 수 있게 

 

다만 await 키워드는 프로미스 객체를 반환하는 어떠한 함수의 내부에서만 사용이 가능하기 때문에

async 키워드가 붙어 있는 함수의 내부에서만 사용 가능함 

 

 

try 문 내부에는 우리가 실행할 코드를 작성해 주고 catch 문의 내부에는 에러 객체를 전달받고 

에러가 발생했을 때 실행 될 코드를 작성해 주면 에러처리를 쉽게 할 수 있음

  • start()라는 함수는 비동기 작업을 처리하는 함수이기 때문에 async 키워드를 작성해 주고 try와 catch 문을 사용함 
  • 비동기 처리했음에도 불구하고 await이라는 키워드를 사용해서 작업을 순차적으로 처리하고 있기 때문18초씩이나 오래 걸림 
  • await이라는 키워드는 해당 작업이 처리 완료 될 때까지 다음 작업들을 중단한다는 특징이 있기 때문에 전부 처리가 완료 될 때까지 해당 작업들이 실행되지 않아 이렇게 한 번에 순서대로 출력

이를 해결하기 위해 promise all 사용함

훨씬 빠르게 10초 만에 모든 작업이 완료됨

promise all

  • 자바스크립트에서 제공되는 메서드로 여러 개의 프로미스를 병렬로 실행하고
  • 모든 프로미스가 완료될 때까지 기다렸다가 결과를 한 번에 반환하는 역할을 함
  • 전달된 프로미스 배열이 모두 Fulfilled 성공될 때까지 대기하며 하나라도 실패 상태가 된다면 즉시 실패 상태가 되어 오류를 출력하게 됨
  • async와 await 키워드는 API 호출과 함께 자주 사용되는 키워드임

2.API 호출

비동기 처리는 대표적으로 웹 사이트에서 데이터를 주고받는 통신을 할 때 사용됨

  • 웹 브라우저는 API를 사용해서 웹 사이트에 필요한 데이터를 요청하고 전달받음
  • API를 호출하기 위해서는 가장 먼저 API 호출에 응답할 수 있는 어떠한 서버가 필요함
  • API는 API 주소를 통해 호출할 수 있고 API 주소를 사용해 API를 호출하면 서버는 화면에 표시된 데이터들을 웹 브라우저에게 전달함

https://jsonplaceholder.typicode.com/ 에 Resources에 user 10 API 

데이터는 다음과 같이 어떤 하나의 배열로 이루어져 있고 배열 안에는 각각의 데이터가 객체 형태로 저장되어 있음

이러한 자바스크립트의 데이터 구조를 제이슨 JSON (JavaScript Object Notation )이라고 부름

 

JOSN (JavaScript Object Notation )

  • 자바스크립트 객체 표기법이라는 뜻으로 자바스크립트에서 데이터를 문자열 형태로 나타내기 위해서 사용함
  • 보통 웹 애플리케이션에서 데이터를 전송할 때 사용되며 Key와 Vaule 쌍으로 이루어져 있음

API 호출

fetch라는 내장함수를 사용해서 API를 호출할 수 있음 

fetch 메서드의 괄호 안에는('사용하고자 하는 API 주소')를 작성

json 형식의 데이터가 아니라 Response 객체가 출력됨

주의

fetch함수와. then 메서드 연결 문제: fetch 함수 뒤에. then 메서드를 연결할 때는 줄 바꿈 없이 연결해야 함.

  • response 변수를 출력하면 Fulfilled 상태인 promise 객체가 출력됨
  • promise 객체를 반환하는 함수는 비동기 처리 함수이고 이러한 함수는 then 메서드를 사용해 결과 값을 출력할 수 있음

async와 await 키워드 사용한다면?

fetch 메서드가 반환하는 프로미스 객체가 처리될 때까지 함수의 실행을 중단할 수 있도록 fetch 메서드의 앞쪽에는 

await 키워드를 작성함 

JSON 형식의 데이터는 javaScript 에서 객체 형태의 데이터를 가독성 좋게 나타내기 위한 하나의 표기법이기 때문에

javaScript 에서 JSON 형식의 데이터를 javaScript  가 활용할 수 있는 어떠한 객체 형태로 변환하기 위해서는

JON();이라는 메서드를 사용해야 한다 response에 담긴 값을 (parsing 파싱) 한 결과를 data라는 변수에 할당함

fetch 메서드의 반환값인 response 에는 json 형식의 데이터가 담겨 있기 때문에 json 메서드를 사용해서 해당 변수에 담긴 값을 자바스크립트가 활용할 수 있는 어떠한 객체의 형태로 변환함

 

fetch 메서드는 비동기적으로 처리되는 함수이기 때문에 API 호출이 완전히 끝난 후에 response 객체를 객체로 변환할 수 있도록 다시 해당 코드에도 await 키워드를 작성해야 함

※ 데이터가 JSON(); 로 인해 배열에 담겨서 출력됨 

 

JavaScript에서 "파싱(parsing)"이란 특정 형식의 데이터를 다른 형식으로 변환하는 과정을 의미합니다. 주로 문자열을 더 쉽게 다룰 수 있는 객체나 배열 등으로 변환하는 작업을 말합니다

 

  • API 호출처럼 성공할 수도 실패할 수도 있는 비동기 작업은 항상 에러를 처리할 수 있도록 처리해야 함

  1. try 문의 내부에는 fetch 메서드를 사용해서 API를 호출하는 코드를 작성 
  2. JSON 형태의 데이터를 알맞게 파싱 해서 출력하는 코드를 작성
  3. catch 문 내부에는 매개변수로 err 객체를 전달받아 에러가 발생하면 에러를 출력하는 코드를 작성

※ API 호출을 async와 await를 사용해서 비동기로 처리하게 되면 가독성이 좋고 코드의 실행 순서와 코드의 역할을 직관적으로 알 수 있어 좋고 에러 처리 또한 편리하게 할 수 있음 

+ Recent posts