목적있는 시나리오
단위로 개발을 해야한다. 요구 사항은 시맨틱에 목적이 더해진 목적있는 시나리오
라고 할 수 있다. 그리고 이러한 사전 설계 및 요구 분석을 바탕으로 코드는 왼손은 거둘뿐
과 같은 의미로 단지 해당 요구 사항에서 쓸 수 있는 object(oop인 js에서의)를 알고 이를 바탕으로 작성할 뿐이다. 즉, 중요한건 요구 분석과 이에 대한 명확화이다. const element = document.getElementById('inputElement');
const inputValue = element.value;
console.log(inputValue); // 1차적 목표
element.value = "수정된 value 값" // 2차적 목표
그럼 여기에서의 시나리오는 심플하게
inputValue
에 할당한다.이런식으로 될거다. 그럼 이러한 프로세스를 함수 단위로 나누려면? 아니 이 시나리오 자체를 하나의 object로 관리한다고 생각해보자
const InputElement = {
createInputElement (id = "inputElement") {
this.element = document.getElementById(id);
},
get getAttributeValue() {
return this?.element?.value;
}
set setAttributeValue(value) {
if(this?.element?.value) {
this.element.value = value;
}
}
}
이렇게 하나의 시나리오라고 해도 그 중간에 연결되는 로직들을 단순화 시켜놓는게 좋다.
host environment
, 즉, 호스트 환경에서 실행되는 언어인데, 이 때의 host = js가 돌아가는 플랫폼이다. 이 때, 이 host마다 특정한 기능들을 제공하는데 document도 그중에 하나다. 따로 사전처리를 안해도 built-in object인 document 등을 쓸 수 있는데, 이게 앞서 말한 host environment 덕분이다. 호스트에서 제공을 해주기 때문!. 예를 들어, JS의 host로는 NodeJS, Browser 등이 있는데, 여기 둘다 document object를 쓸 수 있도록 제공한다. JS는 oop 이면서 host 환경에서 실행되는 언어임을 기억하고, 이에 따라 이러한 host가 제공하는 각종 특정한 기능들을 마치 JS의 디폴트 기능처럼 쓸 수 있다(built-in object). 하지만 앞서 말했듯이 JS 내의 빌트인 오브젝트가 아닌 이상 document 등은 JS에서만 쓸 수 있는건 아니고 JS에서는 host가 기본으로 제공할뿐 python, java 등의 다른 언어에서도 쓸 수 있다(import 해서).{writable : true, enumerable: true}
등을 말한다. Array.isArray()
로 치면 built-in object는 Array이고, isArray는 Array object 내의 함수이다. 이 때, 함수도 하나의 키와 값으로(속성을 포함한) 이뤄진 프로퍼티로 object 내에 존재한다. 예를 들어, built-in object 중에 Function도 있는데 이를 활용해서 JS Engine이 function 키워드를 만나게 되면function Hello() {};
즉, 위의 상황을 마주하게 되면 Hello 라는 키에 대한 값으로 function object를 생성해서 이렇게 하나의 키-값으로 된 프로퍼티를 생성한다. 이에 따라 js에서 함수는 callable-object
가 된다. 추가로 Promise, Proxy, Reflect 등의 built-in object 들이 있다.
이에 더하여 class에서 작성한 함수들은 method 이다. instance를 통해 호출하는건 모두 메서드라고 할 수 있다. 실제로 클래스에 생성한 함수는 위에서 메서드를 표기했던 것과 마찬가지로 예를 들어,
class Sports {
viewSports() {
}
}
위와 같은 클래스가 있을 때 Sports.prototype.viewSports = function () {}
이렇게 할당해준 것과 같다. 그리고 이렇게 만든 메서드는 인스턴스를 통해 호출 할 수 있다. 이 때, 해당 메서드를 각각의 인스턴스의 _proto_
키에 참조하고 있기 때문에 인스턴스를 생성할 때마다 참조가 많아져 메모리를 쓰게 된다. 다시 말해, 오브젝트의 프로토타입에 연결된 메서드를 인스턴스에서 참조하게 된다. 그리고 이를 프로토타입 쉐어링 메커니즘이라 한다. 그럼 왜 우리는 인스턴스르 통해 메서드를 호출할 때 SomeInstance._proto_.method
이런식으로 호출하는게 아닐까? 이건 _proto_
를 생략할 수 있도록 만들어놨기 때문이다.
그러나 이와 달리 함수는 하나 밖에 없다. 예를 들어,
class Sports {
static viewSports() {
}
}
이렇게 했을 때 viewSports가 함수이다. 이에 따라 Sports.viewSports() 이렇게 호출하며, 인스턴스에서는 이를 호출할 수 없고, 이에 따라 메모리가 인스턴스 생성에 따라 늘어나지 않는다. 하지만, 이건 장단점이 있는 부분으로 이를 고려한 설계를 하면 되는 것이지 그렇다고 메서드를 아예 만들면 안된다 이건 아니다. 직관적으로 생각하면 맨처음에 봤던 것처럼 object 단위로 호출하면 함수이고, instance 단위로 호출하면 메서드이다.
global object? : 앞서 말했듯이 js object-based 언어라 built-in object가 있다. 이 때, global도 하나의 object이다. global object는 앞서 말한 host 개념으로 봤을 때, nodeJS라는 js의 host 환경이 제공하는 object이다.
window object? : 앞서 global object와 프로퍼티와 함수가 유사하다. 이 떄, window도 하나의 object이며 브라우저에서(host) 제공하는 object이다.
엘리먼트 !== tag : 엘리먼트는 start tag와 end tag까지를 포함하는 개념으로 tag보다 상위 개념이다. 태그는 엘리먼트의 시작과 끝을 규정한다
그리고 반대로 말하면, 엘리먼트는 태그의 시작과 끝을 말한다
라고 할 수 있다. 이 때, element !== tag
지만 element name === tag name
이다. 즉, div tag에서 tag name은 div인데, div tag로 이뤄진 엘리멘트의 element name도 div이다. 그래서 div element도 맞고, div tag도 맞다.
dom 의 처리 기준은 element로 시작 태그 ~ 끝 태그까지의 전체이다.
Symbol.toStringTag로 element object의 이름을 출력할 수 있다.
HTML 내의 모든 element는 하나의 인터페이스를 가진다. 예를 들어, input element는 HTMLInputElement
인터페이스이며, 이를 object화 한 것이다. 인터페이스는 하나의 object로 생성해야 사용할 수 있기에 input element를 사용하려면 HTMLInputElement 인터페이스를 바탕으로하는 하나의 object 단위를 생성해야한다. 그리고 이 하나의 element object에는 수많은 프로퍼티가 있다.
시나리오가 확정되기전까진 절대로 코딩에 들어가지 않는다. 시나리오는 일종의 수도코드와 같다(코드로 치는게 아닌). 시나리오를 작성할 때는 주어/동사 구조나 주어/동사/목적어 구조로 쓴다. 요구분석은 이러한 시나리오들을 연결하는 것이다. 이벤트+프로세스(이벤트에 대한 대응)
단위로 시나리오를 만들고, 이를 연결하며 요구 사항을 분석한다.
이 때, 사용자 중심 모델 시나리오가 시스템 처리 중심 모델보다 중요하다.
사실 실제 코드를 치는 코딩보다 중요한건 시나리오를 만드는 분석력
이다.
프로그램 개발은 결국 요구사항 분석 및 구현
이다. 이를 위해선 최적의 object, method, property를 사용해야하므로, 어떤 것들이 있는지 알아야한다(기술적으로 안되는건 사용할 수 있는 것들로는 구현이 불가능한 것들이다). 따라서 내가 사용할 수 있는게 뭐가 있는지 아는 것이 요구 분석의 기본이다.