[면접을 위한 CS 전공 지식 노트] 1장 디자인 패턴: 디자인 패턴[1]
https://www.yes24.com/Product/Goods/108887922
면접을 위한 CS 전공지식 노트 - 예스24
디자인 패턴, 네트워크, 운영체제, 데이터베이스, 자료 구조, 개발자 면접과 포트폴리오까지!CS 전공지식 습득과 면접 대비, 이 책 한 권이면 충분하다!개발자 면접에서 큰 비중을 차지하는 CS(Comp
www.yes24.com
해당 책을 읽고, 공부한 후 정리한 블로그 글입니다.
https://github.com/gilbutITbook/080326
GitHub - gilbutITbook/080326: csnote
csnote. Contribute to gilbutITbook/080326 development by creating an account on GitHub.
github.com
예제 코드 출처입니다.
에디터를 키기 귀찮을 때 쓰는 웹 컴파일러 (회원가입 필요 없음)
<자바 스크립트>
JavaScript Playground
Try this online JavaScript Playground playground with instant live preview and console. Easy & Fast. Experiment yourself.
playcode.io
<자바>
https://www.tutorialspoint.com/online_java_compiler.php
Online Java Compiler
The best Online Java Compiler and Editor to provide an easy to use and simple IDE (Integrated Development Environment) for the students and working professionals to Edit, Save, Compile, Execute and Share Java Code with in your browser itself. Enjoy the bes
www.tutorialspoint.com
라이브러리 vs 프레임 워크
라이브러리: 공통으로 사용될 수 있는 특정 기능을 모듈화 한 것. 폴더명, 파일명 등에 대한 규칙이 없고, 프레임 워크에 비해 자유롭다. 도구로써 사용되고, 나한테 컨트롤이 되는 입장(나,가위 관계)
프레임 워크:공통으로 사용될 수 있는 특정 기능들을 모듈화 한것. 폴더명, 파일명 등에 대한 규칙이 있으며 라이브러리에 비해 엄격하다. 도구로써 사용되고, 나한테 컨트롤을 하는 입장(나,비행기 관계)
1. 공통점 : 공통으로 사용될 수 있는 특정한 기능들을 모듈화한 것을 의미한다.
2. 차이점:
- 라이브러리 : 폴더명, 파일명 등에 대한 규칙이 없고 프레임워크에 비해 자유롭다.
- 프레임워크 : 폴더명, 파일명 등에 대한 규칙이 있으며 라이브러리에 비해 좀 더 엄격하다.
0. 디자인 패턴
: 프로그램을 설계 할때 발생했던 문제점들을 객체 간의 상호 관계 등을 이용하여 해결할 수 있도록 하나의 "규약" 형태로 만들어 놓은 것을 의미.
1. 싱글톤 패턴
정의: 하나의 클래스에 오직 하나의 인스턴스만 가지며, 해당 인스턴스는 전역 접근이 가능한 패턴
특징:
1. 생성자를 통해서 여러번 호출 되더라도 인스턴스를 새로 생성하지 않고, 최초 호출시에 만들어두었던 인스턴스를 재활용하는 패턴이다.
class Singleton {
//1. private을 통해 외부에서 새로운 인스턴스는 못만들게함.
private static class SingleInstanceHolder {
//2. static 영역(전역)에 객체를 1개만(final) 생성해둠.
private static final Singleton INSTANCE = new Singleton();
}
//3. 인스턴스의 getter는 public으로 열어 인스턴스를 사용함.
public static Singleton getInstance() {
return SingleInstanceHolder.INSTANCE;
}
}
위의 코드를 보면 싱글톤 패턴은 인스턴스 생성은 "private static final"로 선언하여, 외부에서 여러번 호출하여도 같은 인스턴스가 호출되게한다.
<테스트 코드>
public class HelloWorld{
public static void main(String []args){
Singleton a = Singleton.getInstance();
Singleton b = Singleton.getInstance();
if(a==b)
{
System.out.println(true);
}
else{
System.out.println(false);
}
}
}
결과
+a) final: 초기값이 저장되면 최종적인 값이 되어 수정할 수 없는 것.
final String hello = "Hello world";
hello = "안녕하세요" // 에러 발생
장점:
1. 최초로 한번 생성한 하나의 인스턴스를 다른 모듈들이 공유하고, 재활용하여 사용하기에 인스턴스를 생성할때 드는 비용이 줄어든다.
(즉, 메모리 낭비를 방지할 수 있다.)
단점:
1. TDD(Test Driven Development)를 할때 단위 테스트를 주로 하는데, 단위 테스트는 테스트가 서로 독립적이어야 하며 테스트를 어떤 순서로든 실행할 수 있어야 한다.
하지만 싱글톤 패턴은 초기에 미리 생성된 인스턴스를 기반으로 구현하는 패턴이므로 각 테스트마다 "독립적인" 인스턴스를 만들기가 어렵다.
2. 사용하기가 쉽지만 모듈간의 결합을 강하게 만들 수 있다는 단점이 있다. 이러한 결합은 테스트에도 지장이 가며, 어떠한 로직을 수정하는데 어려움을 더욱 키운다.
(하지만, 의존성 주입을 통해 모듈간의 결합을 조금 더 느슨하게 만들어 해결할 수 있다. )
+a) 의존성 주입(DI, Dependency Injection)
의존성이란 종속성이라고도 하며, A가 B에 의존성이 있다는 것은 A가 B에 종속적이라는 의미이며, B(갑)의 변경에 의해 A(을)또한 변한다는 것을 의미한다.
이때, 의존성 주입은 메인 모듈이 "직접" 다른 하위 모듈에 대한 의존성을 주기보다는 중간에 의존성주입자에게 의존관계를 맡기는 형식이다. 이를 통해 메인 모듈은 하위 모듈에 대한 의존성이 떨어지게 되고, 이러한 현상을 디커플링이라고 한다.
장점:
1. 코드의 재사용성, 유연성이 높아진다.
2. 클래스간의 결합도를 낮출 수 있다.
3. 모듈들을 쉽게 교체할 수 잇는 구조가 되어 테스팅하기 쉽고, 마이그레이션하기도 수월하다.
4. 의존성 방향이 일관되고, 명확한 모듈관계로 애플리케이션의 코드 추론이 쉬워진다.
단점:
1. 모듈이 더 생기므로 복잡도가 증가하고, 이로인해 런타임 패널티가 생긴다.
[DIP(Dependency Inversion Principle),의존성 주입 원칙]
1. 상위 모듈은 하위모듈에 의존해서는 안된다.
2. 둘 다 추상클래스나 인터페이스에 의존해야 하며, 추상화는 세부 사항에 의존하지 말아야 한다.
+a) 마이그레이션(이주): 한 운영환경(시스템)으로부터 다른 운영환경(시스템)으로 이동하는것
2. 팩토리 패턴
정의: 객체를 사용하는 코드에서 객체 생성 부분을 떼어내는 추상화한 패턴이자 상속관계에 있는 두 클래스에서 상위 클래스가 중요한 뼈대를 결정하고, 하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정하는 패턴
특징:
상위와 하위는 분리 되어있기 때문에 느슨한 결합을 가지며 상위 클래스는 인스턴스 생성에 대해서 전혀 알 필요가 없기에 더 많은 유연성을 갖게 된다. 또한 객체 생성 로직이 따로 떼어져 있기 때문에 코드 리팩토링 시 하위 클래스만 수정해도 되어서 유지 보수성이 증가 된다.
abstract class Coffee {
public abstract int getPrice();
@Override
public String toString() {
return "this Coffee " + this.getPrice();
}
}
class CoffeeFactory {
public static Coffee getCoffee(String type, int price) {
if ("Latte".equalsIgnoreCase(type)) {
return new Latte(price);
} else if ("Americano".equalsIgnoreCase(type)) {
return new Americano(price);
} else {
return new DefaultCoffee();
}
}
}
class DefaultCoffee extends Coffee {
private int price;
public DefaultCoffee() {
this.price = -1;
}
@Override
public int getPrice() {
return this.price;
}
}
class LatteFactory extends Coffee {
private int price;
public LatteFactory(int price) {
this.price = price;
}
@Override
public int getPrice() {
return this.price;
}
}
class AmericanoFactory extends Coffee {
private int price;
public AmericanoFactory(int price) {
this.price = price;
}
@Override
public int getPrice() {
return this.price;
}
}
public class HelloCoffee {
public static void main(String[] args) {
Coffee latte = CoffeeFactory.getCoffee("Latte", 4000);
Coffee americano = CoffeeFactory.getCoffee("Americano", 3000);
System.out.println(latte);
System.out.println(americano);
}
}
결과
CoffeeFactory: 최 상위 클래스 (중요한 뼈대 결정)
Latte,Americano: 하위 클래스 (구체적인 내용 결정)
3. 전략 패턴
정의: 정책 패턴이라고도 하며, 객체의 행위를 바꾸고 싶은 경우 "직접" 수정하지 않고, 전략이라고 부르는 "캡슐화한 알고리즘"을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능하게 만드는 패턴
어떤 것을 살 때 네이버페이, 카카오페이 등 다양한 방법으로 결제하듯이 어떤 아이템을 살 때 LUNACard로 사는 것과 KAKAOCard로 사는 것을 구현한 예제 (결제 방식의 ‘전략’만 바꿔서 두 가지 방식으로 결제하는 것을 구현)
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
interface PaymentStrategy {
public void pay(int amount);
}
class KAKAOCardStrategy implements PaymentStrategy {
private String name;
private String cardNumber;
private String cvv;
private String dateOfExpiry;
public KAKAOCardStrategy(String nm, String ccNum, String cvv, String expiryDate){
this.name=nm;
this.cardNumber=ccNum;
this.cvv=cvv;
this.dateOfExpiry=expiryDate;
}
@Override
public void pay(int amount) {
System.out.println(amount +" paid using KAKAOCard.");
}
}
class LUNACardStrategy implements PaymentStrategy {
private String emailId;
private String password;
public LUNACardStrategy(String email, String pwd){
this.emailId=email;
this.password=pwd;
}
@Override
public void pay(int amount) {
System.out.println(amount + " paid using LUNACard.");
}
}
class Item {
private String name;
private int price;
public Item(String name, int cost){
this.name=name;
this.price=cost;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
}
class ShoppingCart {
List<Item> items;
public ShoppingCart(){
this.items=new ArrayList<Item>();
}
public void addItem(Item item){
this.items.add(item);
}
public void removeItem(Item item){
this.items.remove(item);
}
public int calculateTotal(){
int sum = 0;
for(Item item : items){
sum += item.getPrice();
}
return sum;
}
public void pay(PaymentStrategy paymentMethod){
int amount = calculateTotal();
paymentMethod.pay(amount);
}
}
public class HelloWorld{
public static void main(String []args){
ShoppingCart cart = new ShoppingCart();
Item A = new Item("kundolA",100);
Item B = new Item("kundolB",300);
cart.addItem(A);
cart.addItem(B);
// pay by LUNACard
cart.pay(new LUNACardStrategy("kundol@example.com", "pukubababo"));
// pay by KAKAOBank
cart.pay(new KAKAOCardStrategy("Ju hongchul", "123456789", "123", "12/01"));
}
}
/*
400 paid using LUNACard.
400 paid using KAKAOCard.
*/
쇼핑 카트에 아이템을 담아 LUNACard 또는 KAKAOCard라는 두 개의 전략으로 결제하는 코드.
4. 옵저버 패턴
정의: 옵저버 패턴(observer pattern)은 주체가 어떤 객체(subject)의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴
주체: 객체의 상태 변화를 보고 있는 관찰자.
옵저버: 이 객체의 상태 변화에 따라 전달되는 메서드 등을 기반으로 ‘추가 변화 사항’이 생기는 객체들을 의미.
+a)2번째 그림과 같이 주체와 객체를 분리하지않고, 변경되는 객체를 기반으로 구축하기도 한다.
왼쪽 그림은 주체와 객체가 같은 경우이고, 객체가 팔로우에게 글을 올리는 행위(객체의 변화)는 옵저버들에게 알려주는것과 같다고 생각하면 된다. 옵저버 패턴은 주로 이벤트 기반 시스템에 사용하며 MVC 패턴에도 사용된다.
주로 모델(주체)의 변화를 VIEW(옵저버)들에게 알린다. 이러한 사이클의 기반으로 Controller가 작동한다.
프록시(proxy) 객체
: 어떠한 대상의 기본적인 동작(속성 접근, 할당, 순회, 열거, 함수 호출 등)의 작업을 가로챌 수 있는 객체를 뜻하며, 한마디로 대신 작업하는 객체이다.
자바스크립트에서 프록시 객체는 두 개의 매개변수를 가진다.
1. target: 프록시할 대상
2. handler: 프록시 객체의 target 동작을 가로채서 정의할 동작들이 정해져 있는 함수
프록시 객체를 이용한 옵저버 패턴
function createReactiveObject(target, callback) {
const proxy = new Proxy(target, {
set(obj, prop, value) {
if (value !== obj[prop]) {
const prev = obj[prop]
obj[prop] = value
callback(`${prop}가 [${prev}] >> [${value}] 로 변경되었습니다. `)
}
return true
}
})
return proxy
}
const a = {
"형규" : "솔로"
}
const b = createReactiveObject(a, console.log)
b.형규 = "솔로"
b.형규 = "커플"
// 형규가 [솔로] >> [커플] 로 변경되었습니다.
프록시 객체(proxy)의 get() 함수는 속성과 함수에 대한 접근을 가로채며, has() 함수는 in 연산자의 사용을 가로챈다. set() 함수는 속성에 대한 접근을 가로채고, set() 함수를 통해 속성에 대한 접근을 “가로채”서 형규라는 속성이 솔로에서 커플로 되는 것을 감시할 수 있었습니다.
5. 프록시 패턴과 프록시 서버 패턴
5.2 프록시 패턴
정의: 대상 객체(subject)에 접근하기 전 그 접근에 대한 흐름을 가로채 대상 객체 앞단의 인터페이스 역할을 하는 디자인 패턴
이를 통해 객체의 속성, 변환 등을 보완하며 보안, 데이터 검증, 캐싱, 로깅에 사용합니다. 이는 앞서 설명한 프록시 객체로 쓰이기도 하지만 프록시 서버에서도 활용된다.
프록시 서버에서의 캐싱
캐시 안에 정보를 담아두고, 캐시 안에 있는 정보를 요구하는 요청에 대해 다시 저 멀리 있는 원격 서버에 요청하지 않고 캐시 안에 있는 데이터를 활용하는 것을 말한다. 이를 통해 불필요하게 외부와 연결하지 않기 때문에 트래픽을 줄일 수 있다는 장점이 있다.
5.1 프록시 서버 패턴
프록시 서버 (proxy server)
정의: 서버와 클라이언트 사이에서 클라이언트가 자신을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터 시스템이나 응용 프로그램을 가리킨다.
프록시 서버로 쓰는 nginx
nginx는 비동기 이벤트 기반의 구조와 다수의 연결을 효과적으로 처리 가능한 웹 서버이며, 주로 Node.js 서버 앞단의 프록시 서버로 활용.
nginx를 프록시 서버로 둬서 실제 포트를 숨길 수 있고 정적 자원을 gzip 압축하거나, 메인 서버 앞단에서의 로깅을 할 수도 있다. 뿐만 아니라 서버의 버퍼 오버플로우 취약점을 예방하기에도 좋다.
+a)용어 정리
버퍼 오버플로우
버퍼는 보통 데이터가 저장되는 메모리 공간으로, 메모리 공간을 벗어나는 경우를 말한다. 이때 사용되지 않아야 할 영역에 데이터가 덮어씌워져 주소, 값을 바꾸는 공격이 발생하기도 한다.
gzip 압축
LZ77과 Huffman 코딩의 조합인 DEFLATE 알고리즘을 기반으로 한 압축 기술이다. gzip 압축을 하면 데이터 전송량을 줄일 수 있지만, 압축을 해제했을 때 서버에서의 CPU 오버헤드도 생각해서 gzip 압축 사용 유무를 결정해야 한다.
프록시 서버로 쓰는 CloudFlare
CloudFlare는 전 세계적으로 분산된 서버가 있고 이를 통해 어떠한 시스템의 콘텐츠 전달을 빠르게 할 수 있는 CDN 서비스입니다.
+a) 용어 정리
1. DDOS 공격 방어
DDOS는 짧은 기간 동안 네트워크에 많은 요청을 보내 네트워크를 마비시켜 웹 사이트의 가용성을 방해하는 사이버 공격 유형
CloudFlare는 의심스러운 트래픽, 특히 사용자가 접속하는 것이 아닌 시스템을 통해 오는 트래픽을 자동으로 차단해서 DDOS 공격으로부터 보호한다. CloudFlare의 거대한 네트워크 용량과 캐싱 전략으로 소규모 DDOS 공격은 쉽게 막아낼 수 있으며 이러한 공격에 대한 방화벽 대시보드도 제공한다.
2. HTTPS 구축
서버에서 HTTPS를 구축할 때 인증서를 기반으로 구축할 수도 있다. 하지만 CloudFlare를 사용하면 별도의 인증서 설치 없이 좀 더 손쉽게 HTTPS를 구축할 수 있다.(SSL 인증서는 따로 구매해야 한다.)
3. CDN(Content Delivery Network)
각 사용자가 인터넷에 접속하는 곳과 가까운 곳에서 콘텐츠를 캐싱 또는 배포하는 서버 네트워크를 말한다. 이를 통해 사용자가 웹 서버로부터 콘텐츠를 다운로드하는 시간을 줄일 수 있다.(가까우니까)
CORS와 프런트엔드의 프록시 서버
CORS(Cross-Origin Resource Sharing): 서버가 웹 브라우저에서 리소스를 로드할 때 다른 오리진을 통해 로드하지 못하게 하는 HTTP 헤더 기반 메커니즘.
오리진
프로토콜과 호스트 이름, 포트의 조합을 말한다.
(EX: https://kundol.com:12010/test라는 주소에서 오리진은 https://kundol.com:12010을 뜻한다.)
예를 들어, 프론트에서 127.0.0.1:3000으로 테스팅을 하는데 백엔드 서버는 127.0.0.1:12010이라면 포트 번호가 다르기 때문에 CORS 에러가 나타나다. 이때 프록시 서버를 둬서 프론트엔드 서버에서 요청되는 오리진을 127.0.0.1:12010으로 바꿈으로서 cors 에러 처리를 할 수 있다.
참고로 127.0.0.1이란 루프백 IP로, 본인 PC의 IP를 뜻한다. localhost나 127.0.0.1을 입력하면 DNS를 타지 않고 바로 본인 PC로 연결된다.
두번째 그림처럼 프론트엔드 서버 앞단에 프록시 서버를 놓아 /api 요청은 users API, /api2 요청은 users API2에 요청할 수 있습니다. 자연스레 CORS 에러 해결은 물론이며 다양한 API 서버와의 통신도 매끄럽게 할 수 있다.
6. 이터레이터 패턴
정의: 이터레이터 패턴(iterator pattern)은 이터레이터(iterator)를 사용하여 컬렉션(collection)의 요소들에 접근하는 디자인 패턴
<자바스크립트 코드>
const mp = new Map()
mp.set('a', 1)
mp.set('b', 2)
mp.set('c', 3)
const st = new Set()
st.add(1)
st.add(2)
st.add(3)
for (let a of mp) console.log(a)
for (let a of st) console.log(a)
/*
[ 'a', 1 ]
[ 'b', 2 ]
[ 'c', 3 ]
1
2
3
*/
분명히 다른 자료 구조인 set과 map임에도 똑같은 for a of b라는 이터레이터 프로토콜을 통해 순회하는 것을 볼 수 있다.
이터레이터라는 똑같은 배로, 동그라미로 이루어진 컬렉션이든, 마름모로 이루어진 컬렉션이든 순회가 가능하다.
+a) 용어 정리
이터레이터 프로토콜
이터러블한 객체들을 순회할 때 쓰이는 규칙
이터러블한 객체
반복 가능한 객체로 배열을 일반화한 객체
7. 노출모듈 패턴 (revealing module pattern)
정의: 즉시 실행 함수를 통해 private, public 같은 접근 제어자를 만드는 패턴
public
클래스에 정의된 함수에서 접근 가능하며 자식 클래스와 외부 클래스에서 접근 가능한 범위
protected
클래스에 정의된 함수에서 접근 가능, 자식 클래스에서 접근 가능하지만 외부 클래스에서 접근 불가능한 범위
private
클래스에 정의된 함수에서 접근 가능하지만 자식 클래스와 외부 클래스에서 접근 불가능한 범위
즉시 실행 함수
함수를 정의하자마자 바로 호출하는 함수. 초기화 코드, 라이브러리 내 전역 변수의 충돌 방지 등에 사용한다.
8. MVC 패턴
정의: MVC 패턴은 모델(Model), 뷰(View), 컨트롤러(Controller)로 이루어진 디자인 패턴
애플리케이션의 구성 요소를 세 가지 역할로 구분하여 개발 프로세스에서 각각의 구성 요소에만 집중해서 개발
장점: 재사용성과 용이성이 좋다
단점: 애플리케이션이 복잡해질수록 모델과 뷰의 관계가 복잡해진다.
모델
모델(model)은 애플리케이션의 데이터인 데이터베이스, 상수, 변수 등을 뜻한다.
예를 들어. 사각형 모양의 박스 안에 글자가 들어 있다면 그 사각형 모양의 박스 위치 정보, 글자 내용, 글자 위치, 글자 포맷(utf-8 등)에 관한 정보를 모두 가지고 있어야 한다. 뷰에서 데이터를 생성하거나 수정하면 컨트롤러를 통해 모델을 생성하거나 갱신한다. => 옵저버 패턴
뷰
뷰(view)는 inputbox, checkbox, textarea 등 사용자 인터페이스 요소를 나타냅니다. 즉, 모델을 기반으로 사용자가 볼 수 있는 화면을 의미.
모델이 가지고 있는 정보를 따로 저장하지 않아야 하며 단순히 사각형 모양 등 화면에 표시하는 정보만 가지고 있어야 한다. 또한, 변경이 일어나면 컨트롤러에 이를 이벤트를 통해 전달.
컨트롤러
컨트롤러(controller)는 하나 이상의 모델과 하나 이상의 뷰를 잇는 다리 역할을 하며 이벤트 등 메인 로직을 담당한다. 또한, 모델과 뷰의 생명주기도 관리하며, 모델이나 뷰의 변경 통지를 받으면 이를 해석하여 각각의 구성 요소에 해당 내용에 대해 알려준다.
ex: 스프링 의 WEB MVC 라이브러리
Controller 및 Model
public class HelloController {
//2.MVC와 템플릿엔진
//내장 tomcat 서버가 콘트롤러에 hello-mvc로 넣어줌. ★템플릿엔진이 viewResolver에게 던짐★
@GetMapping("hello-mvc")
//@RequestParam는"name"이란 키값으로 parameter 받아서 name이란 이름으로 모델에 넘기기
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-template"; //view resolver가 이 값을 받아서 찾아서 html로 변환(tymeleaf엔진이 처리)
}
}
View
resources/templates/hello-template.html
<html xmlns:th="http://www.thymeleaf.org">
<body>
<!--우측의 "hello! empty"은 그냥 미리 보기 느낌. 실제 서버를 타서 오면'hello ' + ${name}이게 나옴 -->
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
실행 결과
9. MVP 패턴
정의: MVC 패턴으로부터 파생되었으며 MVC에서 C에 해당하는 컨트롤러가 프레젠터(presenter)로 교체된 패턴
뷰와 프레전터는 일대일 관계이기 때문에 MVC 패턴보다 더 강한 결합을 지닌 디자인 패턴이다.
10. MVVM 패턴
정의: MVC의 C에 해당하는 컨트롤러가 뷰모델(view model)로 바뀐 패턴
뷰모델: 뷰를 더 추상화한 계층
MVVM 패턴: MVC 패턴과는 다르게 커맨드와 데이터 바인딩을 가지는 것이 특징
뷰와 뷰모델 사이의 양방향 데이터 바인딩을 지원하며 UI를 별도의 코드 수정 없이 재사용할 수 있고 단위 테스팅하기 쉽다는 장점을 가진다.
MVVM 패턴의 프레임워크 예: vue.js
vue.js는 반응형(reactivity)이 특징인 프런트엔드 프레임워크이다.
함수를 사용하지 않고 값 대입만으로도 변수가 변경되며 양방향 바인딩, html을 토대로 컴포넌트를 구축할 수 있다. 재사용 가능한 컴포넌트 기반으로 UI를 구축할 수 있다.
+a) 용어 정리
커맨드
여러 가지 요소에 대한 처리를 하나의 액션으로 처리할 수 있게 하는 기법이다.
데이터 바인딩
화면에 보이는 데이터와 웹 브라우저의 메모리 데이터를 일치시키는 기법으로, 뷰모델을 변경하면 뷰가 변경된다.