자바스크립트를 사용해 웹소켓을 사용하길 원한다면 가장 많이 사용되는 라이브러리입니다. 그러나 이 라이브러리는 순수한 웹소켓 기술만 이용한 라이브러리가 아닙니다.이 어려움을 해결하기 위해 socket.io는 웹소켓을 사용할 수 없는 브라우저인 경우 서버에서 데이터를 일정 간격마다 받아오는 polling 기능으로 실시간 기능 구현을 가능케 해줍니다.
위에서 말했듯 웹소켓 기술은 아직 모든 브라우저에서 동작하지는 못하기 때문에, 모든 사용자를 고려해야 하는 경우 실시간성 기능 구현에 어려움이 생기게 됩니다.
hoverEvent = (e) => {
// 콘솔로 이 이벤트가 누구에게서 일어났는 지 확인할 수 있습니다.
console.log(e.target);
if(e.target.className === 'app'){
// 이벤트의 장본인의 배경 색을 바꿔볼까요?
e.target.style.background = "#eee";
}
}
componentDidMount() {
// 리액트 요소가 잘 잡혔나 확인해봅시다!
console.log(this.div);
// 마우스를 올렸을 때, 이벤트가 일어나는 지 확인해봅시다.
this.div.current.addEventListener("mouseover", this.hoverEvent);
}
클래스란? 객체 지향 프로그래밍에서 클래스는 특정 객체를생성하기 위해 변수와 함수를 정의하는 일종의 틀을 말한다. 객체를 정의하기 위한 상태와 함수로 구성되어 있다. 객체 단위로 코드를 그룹화하고 쉽게 재사용하려고 사용한다.
class Cat {
// 생성자 함수
constructor(name) {
// 여기서 this는 이 클래스입니다.
this.name = name;
}
// 함수
showName(){
console.log(this.name);
}
}
let cat = new Cat('perl');
cat.showName();
console.log(cat);
클래스를 상속한다는 건, 이미 만들어 둔 어떤 클래스를 가지고 자식 클래스를 만든다는 것이다.
class Cat {
// 생성자 함수
constructor(name) {
// 여기서 this는 이 클래스입니다.
this.name = name;
}
// 함수
showName(){
return this.name;
}
}
// extends는 Cat 클래스를 상속 받아 온단 뜻입니다.
class MyCat extends Cat {
// 생성자 함수
constructor(name, age) {
// super를 메서드로 사용하기
super(name);
this.age = age;
}
// 부모 클래스가 가진 것과 같은 이름의 함수를 만들 수 있습니다.
// 오버라이딩한다고 해요.
showName(){
// super를 키워드로 사용하기
return '내 고양이 이름은 '+super.showName()+'입니다.';
}
showAge(){
console.log('내 고양이는 '+this.age+'살 입니다!');
}
}
let my_cat = new MyCat('perl', 4);
my_cat.showName();
my_cat.showAge();
super 키워드
메소드로 사용할 수 있다.(constructor 안에서)
부모의 constructor를 호출하면서 인수를 전달한다.
this를 쓸 수 있게 해준다.
키워드로 사용할 수 있다.
부모 클래스에 대한 필드나 함수를 참조할 수 있다.
let, const와 Scope
스코프(Scope)가 뭘까? 우리가 어떤 변수를 선언했을 때, 그 변수를 사용할 수 있는 유효범위를 스코프라고 부른다. 변수에 접근할 수 있는 범위다.
var: 함수 단위 let : block 단위 (변수 : let으로 선언한 변수는 값이 변할 수 있다.) const : block 단위(상수: 한번 선언한 값은 바꿀 수 없다.)
function scope(){
const a = 0;
let b = 0;
var c = 0;
// {} 증괄호 안에 든 내용을 블럭이라고 표현해요.
if(a === 0){
const a = 1;
let b = 1;
var c = 1;
console.log(a, b, c);
}
// 앗! c는 값이 변했죠?
// 그렇습니다. var는 함수 단위라서 if문 밖에서 선언한 값이 변했어요.
// let과 const로 선언한 겂은 어떤가요? if문 안쪽 내용이 바깥 내용에 영향을 끼치지 않죠?
console.log(a, b, c);
}
Spread 연산자 (Spread 문법) 어떤 객체 안에 있는 요소들을 객체 바깥으로 꺼내주는 연산자다.
let array = [1,2,3,4,5];
// ... <- 이 점 3개를 스프레드 문법이라고 불러요.
// 배열 안에 있는 항목들(요소들)을 전부 꺼내준다는 뜻입니다.
// 즉 [...array]은 array에 있는 항목을 전부 꺼내
// 새로운 배열([] => 이 껍데기가 새로운 배열을 뜻하죠!)에 넣어주겠단 말입니다!
let new_array = [...array];
console.log(new_array);
//[ 1, 2, 3, 4, 5 ]
삼항 연산자는 if문의 단축 형태입니다. 사용법: 조건 ? 참일 경우 : 거짓일 경우
let info = {name: "mean0", id: 0};
let is_me = info.name === "mean0"? true : false;
console.log(is_me);
//true
Array 내장 함수 map 배열에 속한 항목을 변환할 때 많이 사용한다. 어떤 배열에 속한 항목을 원하는 대로 변환하고, 변환한 값을 새로운 배열로 만들어 준다. 원본 배열은 값이 변하지 않는다. 간단히 설명하면 원 배열의 값을 하나하나 불러와서 array_item에 담아서 오른쪽 함수 안의 구문을 반복한다는 것이다. for of와 조금 비슷하다.
concat은 중복 항목을 제거해주지 않는다. 다른 내장함수와 함께 사용해서 제거해야 한다. 중복 제거를 원할 시에는 Set()을 사용하면 된다.
const array_num01 = [0, 1, 2, 3];
const array_num02 = [3, 4, 5];
// Set은 자바스크립트의 자료형 중 하나로,
// 중복되지 않는 값을 가지는 리스트입니다. :)!
// ... <- 이 점 3개는 스프레드 문법이라고 불러요.
// 배열 안에 있는 항목들(요소들)을 전부 꺼내준다는 뜻입니다.
// 즉 [...array_num01]은 array_num01에 있는 항목을 전부 꺼내
// 새로운 배열([] 이 껍데기가 새로운 배열을 뜻하죠!)에 넣어주겠단 말입니다!
const merge = [...new Set([...array_num01, ...array_num02])];
// 중복 항목(숫자 3)이 제거되었나요? 아니면 그대로 있나요? :)
console.log(merge);
from
쓰임새가 다양하다.
배열로 만들고자 하는 것이나 유사배열을 복사해서 새로운 배열로 만들 때 사용한다.
새로운 배열을 만들 때 사용한다. (초기화한다고도 표현한다.)
유사배열이란? [a,b,c,b] 이 모양으로 생겼지만 배열의 내장 함수를 사용하지 못하는 것들이다. DOM nodelist같은 게 유사배열이다.
// 배열화 하자!
const my_name = "mean0";
const my_name_array = Array.from(my_name);
console.log(my_name_array);
// 길이가 문자열과 같고, 0부터 4까지 숫자를 요소로 갖는 배열을 만들어볼거예요.
const text_array = Array.from('hello', (item, idx) => {return idx});
console.log(text_array);
// 새 배열을 만들어 보자!(=> 빈 배열을 초기화한다고도 해요.)
// 길이가 4고, 0부터 3까지 숫자를 요소로 갖는 배열을 만들어볼거예요.
const new_array = Array.from({length: 4}, (item, idx)=>{ return idx;});
console.log(new_array);
//[ 'm', 'e', 'a', 'n', '0' ]
//[ 0, 1, 2, 3, 4 ]
//[ 0, 1, 2, 3 ]
quiz. 고양이들만 새 배열에 넣기.
const animals = ["복슬 강아지", "검정 고양이", "노란 햄스터", "강아지", "노랑 고양이", "고양이", "흰 토끼"];
let cats = [];
for (let i = 0; i < animals.length; i++) {
let animal = animals[i];
// indexOf는 파라미터로 넘겨준 텍스트가 몇 번째 위치에 있는 지 알려주는 친구입니다.
// 파라미터로 넘겨준 텍스트가 없으면 -1을 반환해요!
// 즉 아래 구문은 고양이라는 단어를 포함하고 있니? 라고 묻는 구문이죠!
if (animal.indexOf("고양이") !== -1) {
cats.push(animal);
}
}
console.log(cats);
nvm ls # nvm으로 설치한 노드 버전 리스트 확인 명령어
node -v # 노드 버전 확인 명렁어
nvm use 사용할 노드 버전
npm으로 yarn을 설치했다. -g는 글로벌이라는 의미이다.
npm install -g yarn
# 옵션 global은 전역에 이 패키지를 깔겠다는 뜻입니다.
yarn add global create-react-app
CRA란 웹사이트를 만들 때 필요한 것을 몽땅 때려넣은 만든 패키지이다. 레고의 해리포터 성 만들기 같은 거라고 생각하면 편하다.
첫 리액트 프로젝트(week-1)를 만든다.
# yarn create react-app [우리의 첫 리액트 프로젝트 이름]
# 우리가 설치한 create-react-app 패키지를 써서 프로젝트를 만들어요.
# 주의! 꼭 sparta_react 폴더 경로에서 입력해주세요!
yarn create react-app week-1
이 코드를 조각조각 내보면 아래와 같이 나눌 수 있을 거예요. 나눈 조각 하나하나를 컴포넌트라고 부른다.
<header/>
<container/>
<imagebanner/>
<contents1/>
<footer/>
즉, 이 웹 사이트는, 크게 <header/>, <container/>, <footer/> 세 개의 컴포넌트가 있고, <container/> 컴포넌트는, <imagebanner/>, <contents1/> 컴포넌트로 이루어져 있는 거죠!
State
state는 Component가 가지고 있는 데이터입니다.
Props
props는 Component가 부모 Component로부터 받아온 데이터입니다.
Component
함수형 컴포넌트
// 리액트 패키지를 불러옵니다.
import React from 'react';
// 함수형 컴포넌트는 이렇게 쓸 수도 있고
// function Bucketlist(props){
// return (
// <div>버킷 리스트</div>
// );
// }
// 이렇게 쓸 수도 있어요. =>가 들어간 함수를 화살표 함수라고 불러요.
// 저희는 앞으로 화살표 함수를 사용할거예요.
// 앗 () 안에 props! 부모 컴포넌트에게 받아온 데이터입니다.
// js 함수가 값을 받아오는 것과 똑같이 받아오네요.
const BucketList = (props) => {
// 컴포넌트가 뿌려줄 ui 요소(리엑트 엘리먼트라고 불러요.)를 반환해줍니다.
return (
<div>
버킷 리스트
</div>
);
}
// 우리가 만든 함수형 컴포넌트를 export 해줍니다.
// export 해주면 다른 컴포넌트에서 BucketList 컴포넌트를 불러다 쓸 수 있어요.
export default BucketList;
클래스형 컴포넌트
import React from 'react';
import logo from './logo.svg';
import './App.css';
// BucketList 컴포넌트를 import 해옵니다.
// import [컴포넌트 명] from [컴포넌트가 있는 파일경로];
import BucketList from './BucketList';
// 클래스형 컴포넌트는 이렇게 생겼습니다!
class App extends React.Component {
constructor(props){
super(props);
// App 컴포넌트의 state를 정의해줍니다.
this.state = {
list: ['영화관 가기', '매일 책읽기', '수영 배우기'],
};
}
// 랜더 함수 안에 리액트 엘리먼트를 넣어줍니다!
render() {
return (
<div className="App">
<h1>내 버킷리스트</h1>
{/* 컴포넌트를 넣어줍니다. */}
<BucketList/>
</div>
);
}
}
export default App;
1주차 과제도 해보았다.
import logo from './logo.svg';
import './App.css';
import React from "react";
import Start from "./Start";
class App extends React.Component{
constructor(props){
super(props);
this.state = {
name: "고양이"
};
}
render () {
return (
<div className="App">
{ <Start name={this.state.name}/> /*name으로 state의name값을 보낸다. */}
</div>
)
}
}
export default App;
컴포넌트 스타일링 기법 중, 제가 가장 좋아하는 방식입니다! 😎 왜 좋아하냐구요? 많은 이유가 있지만, 두 개만 꼽아볼게요.
class 이름 짓기에서 해방됩니다!
컴포넌트에 스타일을 적기 때문에, 간단하고 직관적입니다!
CSS-in-JS 라이브러리 중 하나입니다! 컴포넌트에 스타일을 직접 입히는 방식이라고 편하게 생각하셔도 됩니다!
라이프 사이클이란?
컴포넌트의 라이프 사이클(= 컴포넌트 생명주기)은 정말 중요한 개념입니다! 컴포넌트가 렌더링을 준비하는 순간부터, 페이지에서 사라질 때까지가 라이프 사이클이에요.
아래 도표는 어떻게 라이프 사이클이 흘러가는 지 그린 도표입니다.
컴포넌트는 생성되고 → 수정(업데이트)되고 → 사라집니다.
생성은 처음으로 컴포넌트를 불러오는 단계입니다.
수정(업데이트)는 사용자의 행동(클릭, 데이터 입력 등)으로 데이터가 바뀌거나, 부모 컴포넌트가 렌더링할 때 업데이트 됩니다. 아래의 경우죠!
props가 바뀔 때
state가 바뀔 때
부모 컴포넌트가 업데이트 되었을 때(=리렌더링했을 때)
또는, 강제로 업데이트 했을 경우! (forceUpdate()를 통해 강제로 컴포넌트를 업데이트할 수 있습니다.)
제거는 페이지를 이동하거나, 사용자의 행동(삭제 버튼 클릭 등)으로 인해 컴포넌트가 화면에서 사라지는 단계입니다.
컴포넌트는 생성되고 → 수정(업데이트)되고 → 사라집니다.
생성은 처음으로 컴포넌트를 불러오는 단계입니다.
수정(업데이트)는 사용자의 행동(클릭, 데이터 입력 등)으로 데이터가 바뀌거나, 부모 컴포넌트가 렌더링할 때 업데이트 됩니다. 아래의 경우죠!
props가 바뀔 때
state가 바뀔 때
부모 컴포넌트가 업데이트 되었을 때(=리렌더링했을 때)
또는, 강제로 업데이트 했을 경우! (forceUpdate()를 통해 강제로 컴포넌트를 업데이트할 수 있습니다.)
제거는 페이지를 이동하거나, 사용자의 행동(삭제 버튼 클릭 등)으로 인해 컴포넌트가 화면에서 사라지는 단계입니다.
라이프 사이클 함수는 클래스형 컴포넌트에서만 사용할 수 있습니다. 라이프 사이클을 아는 건 중요한데 왜 우리는 클래스형 컴포넌트보다 함수형 컴포넌트를 많이 쓰냐구요? 리액트 공식 매뉴얼에서 함수형 컴포넌트를 더 권장하기 때문입니다! (리액트 16.8버전부터 등장한 React Hooks으로 라이프 사이클 함수를 대체할 수 있거든요.) 더 많은 라이프 사이클 함수는 공식 문서에서 확인할 수 있어요 😉
06. Ref! 리액트에서 돔요소를 가져오려면?
React.createRef()
이제 가상돔이 뭔지, 돔이 뭔진 알겠죠? 라이프 사이클도 알구요. 그런데 만약에, 내가 어떤 인풋박스에서 텍스트를 가져오고 싶으면 어떻게 접근해야할까요? (render()가 끝나고 가져오면 될까요? 아니면 mount가 끝나고? 아니, 그 전에 가상돔에서 가져오나? 아니면 DOM에서? 😖) → 답은, 리액트 요소에서 가져온다!
<div>
{/* 함수를 호출합니다. 이 클래스 안의 addNemo 함수를 불러오기 때문에 this.addNemo로 표기해요. */}
<button onClick={this.addNemo}>하나 추가</button>
<button onClick={this.removeNemo}>하나 빼기</button>
</div>
항해 2주차도 지나간다... 주특기 기본과정 노드강의를 들었는데 솔직히 웹개발기초반에서 하던 것들과 크게 다른게 없이 API CRUD 말고는 크게 배운 것이 없는 것 같았다. 기초반이 짧았어서 심화반이 두렵다... 헉헉 막연한 두려움에 node교과서 라는 책을 사서 일단 보고는 있는데 기본적인 단어들 부터 검색하면 읽어야 하는 지경이라 조금 속도가 더디다.(예를 들면 스택, 큐 이런 단어들 조차 너무 생소해서 검색해서 이해해야한다 ㅎㅎ;;)
이번 WIL의 키워드 - Node.js : Restful API, package.json - Spring : DI, IoC, Bean - React : DOM, 서버리스
여러 사이트들을 돌아다니면서 읽어보고 まとめて 정리해 보았다.
먼저 REST API
REST 란, 자원을 표현으로구분하여 해당 자원의 정보를 주고받는 모든 것을 의미한다. 즉, 자원의 표현에 의한 정보전달을 뜻한다. REST는 RepreSentational State Transfer 의 약자로 "상태를 유지하지 않는" 것을 뜻한다.
자원 : 해당 소프트웨어가 관리하는 모든 것 자원의 표현 : 자원을 표현하는 지정 방식, 또는 이름
정보전달 데이터가 요청되는 시점에 자원의 정보를 전달한다. JSON 또는 XML을 통해 데이터를 주고받는 것이 일반적이다. WWW( world wide web) 과 같은 분산 하이퍼미디어 시스템을 위한 SW개발 아키텍처의 한 형식이다. REST는 기본적으로 웹의 기존기술과 HTTP프로토콜을 그대로 활용하기 때문에 웹의 장점을 최대화 한 아키텍쳐 스타일이다. REST는 네트워크 상에서 클라이언트와 서버 간 통신 방식 중 하나이다.
| HTTP 란?
- HyperText Transfer Protocol의 준말로 링크 기반으로 데이터를 요청하고 받겠다는 것. - 클라이언트와 서버가 요청을 하고 응답을 하기 위해 따르는 프로토콜. - HTML 문서를 주고 받을 수 있음, 뿐만 아니라 이미지, 동영상, 오디오, 텍스트 문서 등을 주고 받을 수 있음.
RESTful API
API: Application Programming Interface
REST RESTful API는 REST 특징을 지키면서 API를 제공하는 것이다.
즉, HTTP 통신에서 어떤 자원에 대한 CRUD 요청을 Resource와 Method로 표현하여 특정한 형태로 전달하는 방식으로
Get, Post 등의 방식(Method)을 사용하여 요청을 보내며,
요청을 위한 자원은 특정한 형태(Representation of Resource)으로 표현한다.
풀어 설명하자면, 어떤 자원에 대해 CRUD(Create, Read, Update, Delete) 연산을 수행하기 위해 URI(Resource)로 요청을 보내는 것. 자원을 이름으로 구분해 해당 자원의 상태를 주고받는 모든 것을 의미한다고도 할 수 있겠다.
예를 들어, 우리는 게시글을 작성하기 위해 http://localhost:8080/board 라는 URI에 POST방식을 사용하여 JSON형태의 데이터를 전달할 수 있다. 위와 같이 CRUD 연산에 대한 요청을 할 때, 요청을 위한 Resource(자원, URI)와 이에 대한 Method(행위, POST) 그리고 Representation of Resource(자원의 형태, JSON)을 사용하면 표현이 명확해지므로 이를 REST라 하며, 이러한 규칙을 지켜서 설계된 API를 Rest API 또는 Restful한 API라고 한다. 그리고 위에서 살짝 언급하였듯이, 이러한 Rest API는 Resource(자원), Method(행위), Representation of Resource(자원의 형태)로 구성된다.
이러한 REST 기반의 API를 웹으로 구현한 것이 REST API, RESTful API다.
RESTful API를 사용하는 이유
큰 특징으로는 '애플리케이션 분리 및 통합', '다양한 클라이언트의 등장'이다.
애플리케이션의 복잡도가 증가하면서 애플리케이션을 어떻게 분리하고 통합하느냐가 주요 이슈가 되었고, 이에 자바 진영에서는 과거 EJB(Enterprise Java Beans), SOA(Service Oriented Architecture)에 이어 최근에는 MSA(Micro Service Architecture)와 함께 REST가 떠오르고 있는 것이다.
그리고 모바일과 같은 다양한 클라이언트의 등장하면서 최근의 서버 프로그램은 다양한 브라우저와 안드로이폰, 아이폰과 같은 모바일 디바이스에서도 통신을 할 수 있어야 한다.
이러한 멀티 플랫폼에 대한 지원을 위해 Backend 하나로 다양한 Device를 대응할 수 있는 REST의 필요성이 증대되었다.
GraphQL
GraphQL 은 Graph Query Language 의 줄임말이다. Query Language 란 무엇인가? Query Language 는 정보를 얻기 위해 보내는 질의문(Query)을 만들기 위해 사용되는 Computer 언어의 일종이다. GraphQL 은 이런 Query Language 중에서도 Server API 를 통해 정보를 주고받기 위해 사용하는 Query Language 이다.
* RESTful과의 차이점 · GraphQL API는 주로 하나의 Endpoint 에 사용함 · 요청할 때 사용한 Query 문에 따라 응답의 구조가 달라진다.
GraphQL vs RESTful 장단점
GraphQL 은 다음과 같은 장점을 가진다.
HTTP 요청의 횟수를 줄일 수 있다.
RESTful 은 각 Resource 종류 별로 요청을 해야하고, 따라서 요청 횟수가 필요한 Resource 의 종류에 비례한다. 반면 GraphQL 은 원하는 정보를 하나의 Query 에 모두 담아 요청하는 것이 가능하다.
HTTP 응답의 Size 를 줄일 수 있다.
RESTful 은 응답의 형태가 정해져있고, 따라서 필요한 정보만 부분적으로 요청하는 것이 힘들다. 반면 GraphQL 은 원하는 대로 정보를 요청하는 것이 가능하다.
GraphQL 은 다음과 같은 단점을 가진다.
File 전송 등 Text 만으로 하기 힘든 내용들을 처리하기 복잡하다.
고정된 요청과 응답만 필요할 경우에는 Query 로 인해 요청의 크기가 RESTful API 의 경우보다 더 커진다.
재귀적인 Query 가 불가능하다. (결과에 따라 응답의 깊이가 얼마든지 깊어질 수 있는 API 를 만들 수 없다.)
결론!!
File 전송과 같이 RESTful 이 더 유리한 API 가 있을 수 있고, 다양한 정보를 주고받는 것 같이 GraphQL 이 더 유리한 API 가 있을 수 있다.
GraphQL 은 여러 장점을 가지고 Server 의 구조를 단순화 시켜줄 수 있는 좋은 Query Language 이다. 다만, GraphQL 의 장점이 언제나 의미를 가지는 것은 아니며, 어떤 조건에서 사용하는지, 어떤 목표로 사용하는지에 따라서 장점으로 작용하기도, 단점으로 작용하기도 한다. 훌륭한 API 개발자가 되기 위해서는 이런 장단점을 잘 파악하여 GraphQL 만 쓸 것인지, RESTful structure 또한 사용할 것인지, 혹은 RESTful structure 만 사용할 것인지를 결정하는 것이 중요하다.
문서 객체 모델(The Document Object Model, 이하 DOM) 은 HTML, XML 문서의 프로그래밍 interface 이다. DOM은 문서의 구조화된 표현(structured representation)을 제공하며 프로그래밍 언어가 DOM 구조에 접근할 수 있는 방법을 제공하여 그들이 문서 구조, 스타일, 내용 등을 변경할 수 있게 돕는다. DOM 은 구조화된 nodes와 property 와 method 를 갖고 있는 objects로 문서를 표현한다. 이들은 웹 페이지를 스크립트 또는 프로그래밍 언어들에서 사용될 수 있게 연결시켜주는 역할을 담당한다.
웹 페이지는 일종의 문서(document)다. 이 문서는 웹 브라우저를 통해 그 내용이 해석되어 웹 브라우저 화면에 나타나거나 HTML 소스 자체로 나타나기도 한다. 동일한 문서를 사용하여 이처럼 다른 형태로 나타날 수 있다는 점에 주목할 필요가 있다. DOM 은 동일한 문서를 표현하고, 저장하고, 조작하는 방법을 제공한다. DOM 은 웹 페이지의 객체 지향 표현이며, 자바스크립트와 같은 스크립팅 언어를 이용해 DOM 을 수정할 수 있다.
W3C DOM, WHATWG DOM 표준은 대부분의 브라우저에서 DOM 을 구현하는 기준이다. 많은 브라우저들이 표준 규약에서 제공하는 기능 외에도 추가적인 기능들을 제공하기 때문에 사용자가 작성한 문서들이 각기 다른 DOM 이 적용된 다양한 브라우저 환경에서 동작할 수 있다는 사실을 항상 인지하고 있어야 한다.
이 문서의 대부분의 예제와 같이, 위에서 사용된 예제는JavaScript이다. 위의 예제는 자바스크립트로 작성되었지만 문서(document) 와 문서의 요소(element) 에 접근하기 위해 DOM 이 사용되었다. DOM 은 프로그래밍 언어는 아니지만 DOM 이 없다면 자바스크립트 언어는 웹 페이지 또는 XML 페이지 및 요소들과 관련된 모델이나 개념들에 대한 정보를 갖지 못하게 된다. 문서의 모든 element - 전체 문서, 헤드, 문서 안의 table, table header, table cell 안의 text - 는 문서를 위한 document object model 의 한 부분이다. 때문에, 이러한 요소들을 DOM 과 자바스크립트와 같은 스크립팅 언어를 통해 접근하고 조작할 수 있는 것이다.
초창기에는 자바스크립트와 DOM 가 밀접하게 연결되어 있었지만, 나중에는 각각 분리되어 발전해왔다. 페이지 콘텐츠(the page content)는 DOM 에 저장되고 자바스크립트를 통해 접근하거나 조작할 수 있다. 이것을 방정식으로 표현하면 아래와 같다:
API (web or XML page) = DOM + JS (scripting language)
DOM(Document Object Model)
DOM은 문서 객체 모델이라고 하는데 결국은 브라우저에서 다룰 HTML 문서를 파싱하여"문서의 구성요소들을 객체로 구조화하여 나타낸 것"이다.
Virtual DOM이란?
→"DOM을 추상화한 가상의 객체"
어떤 문제를 해결하기 위한 기술인가?
DOM 조작에 의한 렌더링이 비효율적인 문제
SPA(Single Page Application)특징으로DOM 복잡도 증가에 따른 최적화 및 유지 보수가 더 어려워지는 문제
결론적으로DOM을 반복적으로 직접 조작하면 그 만큼 브라우저가 렌더링을 자주하게 되고, 그 만큼 PC 자원을 많이 소모하게되는 문제를 해결하기 위한 기술이다.
간단히 짚고 넘어가는 브라우저의 렌더링 방법
앞서 DOM을 반복 조작하면 렌더링도 자주한다고 얘기했는데 그건 브라우저의 렌더링 방식이 그렇게 되어있기 때문이다.
간단하게 설명하면 과정은 아래와 같다
HTML을 파싱하여DOM 객체를 생성하고, CSS를 파싱하여스타일 규칙을 만든다.
이 두개를 합쳐서 실제로 웹 브라우저에 보여져야할 요소를 표현한"렌더 트리"라는 것을 만든다.
이 렌더 트리를 기준으로레이아웃을 배치하고색을 칠하는 등의 작업을 한다.
이 과정에서 문제가 되는 경우는 현대의 웹처럼 변경해야할 대상도 많고 변경도 많은 경우이다.
프로그래밍에 의해 DOM을 변경해야하고 변경할 구성 요소가 100개면 위의 과정을 100번을 하는 비효율적인 작업을 해왔다.
정확히는 DOM을 변경하는게 문제가 아니고렌더링을 여러번 하는게 문제이다.
어떻게 해결했는가? (동작 원리)
해결 방법은 바로Virtual DOM이라는DOM을 추상화한 가상의 객체를 메모리에 만들어 놓는 것이다.
Virtual DOM은 DOM과 유사한 역할을 담당할 객체이다.
즉, 변경 사항을 DOM에 직접 수정하는게 아니라 중간 단계로 Virtual DOM을 수정하고 Virtual DOM을 통해서 DOM을 수정하게 했다.
실질적인 방법은 Virtual DOM에 변경 내역을 한 번에 모으고(버퍼링) 실제 DOM과 변경된 Virtual DOM의 차이를 판단한 후, 구성요소의 변경이 부분만 찾아 변경하고 그에 따른 렌더링을 한 번만 하는 것으로 해결했다.
주의사항과 한계
0.1초마다 화면에 데이터가 변경된다면? Virtual DOM으로 0.5초씩 모아가지고 렌더링을 적게할 수 있을까? → 안된다. 동시에 변경되는 것에 한해서만 렌더링된다.
React나 Vue등을 이용해서 Virtual DOM을 쓰면 무조건 빠른가? → 아니다. 똑같이 최적화를 해야한다. (슬라이드를 옮기거나 무한 스크롤등의 움직임이 있을 때는 Virtual DOM을 이용해서 반복 렌더링을 하지 않도록 해줘야한다.)
Virtual DOM은 메모리에 존재한다. DOM에 준하는 무거운 객체(Virtual DOM)가 메모리에 상주(?)하고 있기 때문에 메모리의 사용이 많이 늘어날 수 밖에 없다.
Virtual DOM을 조작하는 것도 엄청나게 많은 컴포넌트를 조작하게 된다면 오버헤드가 생기기 마련이다. Virtual DOM 제어가 DOM 직접 제어에 비해 상대적으로 비용이 적게 들 뿐이다.
서버리스(Serverless)는 말 그대로 ‘서버(Server)가 없다(-less)’는 뜻으로 애플리케이션의 확장을 관리할 필요가 없는 클라우드 컴퓨팅 모델을 가리킵니다. 이름 때문에 물리적인 서버가 아예 없고 클라이언트에서 모든 것을 처리하는 구조로 착각할 수 있습니다. 하지만 실제로 서버가 없는 구조는 아닙니다. 서버에서 처리하는 작업을 클라우드 기반의 서비스로 처리해서 서버 구축 및 관리 비용을 줄이는 구조입니다. 따라서 개발 기간과 비용을 단축할 수 있을 뿐 아니라, 서버 운영과 유지 보수의 어려움을 크게 줄일 수 있습니다.
이점이 또 있습니다. 서버리스는 개발자가 인프라는 대부분 무시하고 코드에 집중할 수 있도록 합니다. 서버 사양이 개발자에게 영향을 주지 않으므로 ‘서버리스’인 것입니다. 물론 물리적 서버는 여전히 존재하지만 클라우드 제공업체가 서비스 중 서버가 하는 관리한다는 점이 다르며 이 점이 개발자 및 서비스 환경이 서버에 신경을 쓰지 않아도 된다는 이점을 이끌어냅니다.
작동 방식
서버를 사용해야 하는 경우, 그러니까 표준 IaaS(Infrastructure as a Service) 모델에서 사용자는 용량 단위를 미리 구매합니다. 이는 애플리케이션을 실행하기 위해 ‘상시 가용할 수 있는’ 서버 구성 요소에 대한 비용을 지불하는 것입니다. 서버리스의 모델들은 이와 다릅니다. 이벤트를 실행할 애플리케이션 코드를 트리거(특정한 작용에 대응하여 자동으로 반작용이 실행되게끔 만드는 논리적 장치)하면 클라우드 제공업체는 해당 코드에 리소스(서버 자원)를 동적으로 할당하고, 사용자는 코드 실행이 끝나면 비용을 지불하지 않습니다.
장점과 단점
장점도 있고 단점도 있습니다. 장단점을 살펴보고 어떤 환경에 어울릴지 그려보세요.
1. 장점
– 서버 관리가 필요 없습니다.
– 유연한 확장성: 애플리케이션을 활용하여 자유자재로 확장을 구현할 수 있습니다.
– 높은 가용성: 고정된 서버가 없음은 제한된 가용성이 아님을 의미합니다. 가용성을 위한 별도의 설계가 필요 없습니다.
– 유휴 용량에 대한 비용: 사용하지 않는 것에 대해선 비용을 지불할 필요가 없습니다. 실행하지 않을 때는 비용이 발생하지 않습니다.
– 개발자 생산성을 높이고 운영 비용을 줄일 수 있습니다.
2. 단점
– 콜드스타트(Cold-Start): 빠른 응답이 필요한 제품(서비스)의 경우 서버리스로의 전환은 부적합할 수 있습니다. 이는 실행할 함수를 호출하기 위해 컨테이너가 실행되는 대기 시간이 존재하기 때문인데, 서버를 항시 가동하지 않는 서버리스의 특징에 기인합니다.
– 무상태(Stateless)적인 기능의 구현 불가: 작은 기능으로 잘게 나눠진 함수들은 요청마다 새로 기동하도록 호출되기 때문에 기동 전후의 상태를 공유할 수 없습니다. 또한 변수와 데이터의 공유가 불가능하며, 데이터를 로컬 스토리지에서 읽고 쓸 수 없습니다.
– 벤더 종속의 문제: 함수가 사용할 수 있는 최대 메모리, 최대 처리 가능 시간 제약 등의 제약을 서버리스 서비스 벤더가 설정하며 서버리스 사용자 및 서버리스 기반의 서비스는 이에 종속됩니다. 이에 맞춰 벤더가 설정한 제약을 벗어나는 큰 기능은 잘게 나누어 구현해야 합니다.
파이어베이스란?
파이어베이스는 “앱을 개발하고, 개선하고, 키워갈 수 있는” 도구 모음(toolset)이며, 이러한 도구가 없다면 개발자들은 일반적으로 서비스의 상당 부분을 직접 만들어내야만 합니다. 그런데 개발자들은 앱의 사용자 경험(UX)에 집중을 해야 하기 때문에, 그런 세세한 부분들까지 전부 만드는 걸 좋아하지 않습니다. 그런 부분들로는 분석, 인증, 데이터베이스, 구성 설정, 파일 저장, 푸시(push) 메시지 등, 열거하자면 끝이 없습니다. 파이어베이스로 만든 이러한 서비스들이 클라우드에 호스팅 되면, 개발자의 입장에서는 거의 아무런 노력을 들이지 않고도 앱의 규모를 확장할 수 있습니다.
허허... 하다하다 서버를 클라우딩하다니... 신기하군;; 진짜 개발쪽을 알아보면 알아볼수록 이 쪽 세계는 변화무쌍해서 어디로 튈지 모르는게 너무 신기하다... 그 변화를 따라가려면 계속 공부해야하고 실력을 키워나가야 한다는 것... 그리고 변화를 주도하려면 끊임없이 창의적 생각을 해야하며 발전해나가야 한다는 것!
또 다시 다가온 알고리즘의 시간
중복문자제거 소문자로 된 한개의 문자열이 입력되면 중복된 문자를 제거하고 출력하는 프로그램을 작성하 세요. 제거된 문자열의 각 문자는 원래 문자열의 순서를 유지합니다. ▣ 입력설명 첫 줄에 문자열이 입력됩니다. ▣ 출력설명 첫 줄에 중복문자가 제거된 문자열을 출력합니다. ▣ 입력예제 1 ksekkset ▣ 출력예제 1 kset
풀이
처음엔 이중포문을 돌릴 생각을 했는데 결과값을 가져오는게 쉽지 않았다. 답안을 보고서야 알았다... indexOf
indexOf를 사용하면 편하다. indexOf('찾을문자', 찾기시작할index넘버)
function solution(s){
let answer = "";
for(let i = 0; i < s.length; i++){
// console.log(s[i],i, s.indexOf(s[i]))
if(s.indexOf(s[i])===i){ //indexOf가 배열에서 최초로 발견되는 index넘버값을
//알려주므로 현재 index넘버값과 최초발견 index넘버값이 같은 것들을 추리면 중복 문자를 제거할 수 있다.
answer +=s[i]
}
}
return answer
}
console.log(solution("ksekkset"))