컴퓨터의 기본이해 및 Javascript 문법

Taewoong Moon·2023년 1월 29일
0

컴퓨터의 구성요소(메모리)

컴퓨터의 기본동작은 3가지 구성요소로 크게 진행된다.
CPU(Central Processing Unit), RAM(Random Access Memory), HDD(하드디스크)

CPU: 주 기억장치라고 불리는 RAM에서 코드들을 불러와 연산, 논리, 흐름제어 등을 한다.

RAM: 하드 디스크에서 임시적인 내용들을 그대로 불러와서 CPU와 네트워킹을 한다. 개발자가 가장 많이 신경써야하는 부분은 RAM

HDD: 보조기억장치라고도 불리며 응용 프로그램들을 저장해 놓았다가 실행이 되면 RAM에서 복사를 해준다.

CPU, RAM, HDD 비교

가격: CPU - RAM- HDD 순으로 비싸다.
크기: HDD - RAM- CPU 순으로 크다.
처리속도: CPU - RAM - HDD 순으로 비싸다.

위에서 처리속도를 비교해보면 HDD와 CPU간에 속도차이가 심해서, 네트워킹을 할 때 문제가 생겨서 RAM이 만들어진것도 있다.

RAM(메모리)의 구조

  • RAM은 위에서 말했다시피 운영체제와 운영시스템으로 구성되어 있기때문에 프론트엔드 개발자 입장에서 가장 많이 신경써야하는 부분이다.
  • 하드디스크에서 RAM으로 코드가 복사되면 기계어로 컴파일링 되서 해당 기계어들이 데이터 - 힙 - 스택 세가지 중에 하나에 쌓인다.
  • RAM이 코드-데이터-힙-스택 이렇게 나누는 건 메모리에서 나누는게 아니라 OS별로 임시적으로 나눈다.

정확히 RAM의 구조에 대해서 말하면, 컴퓨터를 실행시키는 순간 RAM의 운영체제에 기본적인 정보들이 다들어간다.

운영체제 구성요소: CPU, 메모리, 앱, 화면, 사운드카드, 마우스

그리고 HDD에서 프로그램이 실행되는 순간, 운영체제의 앱 별로 메모리가 코드- 데이터 - 힙 - 스택 형식으로 쌓이게 되는 것이다.

CPU의 구조

  • 연산, 논리 , 흐름 제어등이 실행되는 공간
  • 정확히 말하면 제어장치(Control Unit) 와 연산 장치(Arithmetic Unit)으로 나뉘어 각자 역할을 한다.
  • 코드들은 각 동작단위 (Statement)로 주솟값에 저장되어서 해당 주솟값들의 코드들은 기계어로 바뀐 뒤 Control Unit에서 평가를 받는다.
    CU에서 평가를 받았을 때 연산이 필요하면 ALU로 넘어가고 필요하지 않다면 바로 데이터-힙-스택 중 한곳으로 저장이 된다.



그렇다면 이런 컴퓨터의 동작원리를 알아야 하는 이유는?

최소한 메모리에는 어떤 방식으로 코드가 저장되고 실행되는 지 알아야지, Javascript내에서 주솟값에 저장된 데이터들이 왜 이런식으로 변형되고 동작하는지 알 수 있다.

Javascript 변수

메모리 내에서 입력 -> 처리 -> 출력 과정에서 처리할 때 저장할 수 있는 공간이 필요하다.

변수: 이름을 정해서 데이터를 저장할 수 있는 공간

여기서 중요포인트는 이름을 정한다는 것이다. 그렇다면 변수의 이름은 개발자 입장에서 최대한 의미있는 이름으로 정해져야 한다.

변수이름 짓는 방법론

  • 자바스크립트 언어에 원래 있는 예약어 (default, const, continue ...)는 사용할 수 없다. 예약어와 변수 관련한 것은 다른 프로그래밍 언어에서도 마찬가지다.
  • 변수 이름에 두가지 이상이 사용되면 camelCase를 사용한다.
  • 특수문자를 사용할 수 없다.
  • 숫자를 변수의 시작으로 사용할 수 없다.

Javascript 데이터 타입

데이터 타입은 메모리 저장에 있어서 가장 중요한 부분이다. 코드의 데이터가 메모리에 저장될 때 크게 데이터 타입은 두가지로 나뉜다.

원시 데이터(Primitive): Number, String, Null, Undefined, Boolean, Symbol

객체 데이터 (Reference): Object, array, function

이렇게 데이터를 나누는 이유는 뭔가?
흔히들 인강 또는 책에서 원시 데이터는 copy by value, 객체 데이터는 copy by reference라고들 한다. 이게 무슨말이냐?

메모리셀에 데이터를 저장할 때 각 동작별로 고유의 주솟값에 저장을 한다.

원시 데이터: 값 자체를 주소에 저장한다.
객체 데이터: 값 자체가 너무커서 Heap이라는 객체 저장하는 곳에 데이터를 저장하고 해당 데이터를 주소는 참조를 한다.

사실 조금 더 자세하게 들어가면, 원시 및 객체 타입 둘다 Core Javascript 책을 참조하면 둘다 참조를 하지만, 값이 한 단계 더 들어가냐 마냐의 차이긴하다.

이렇게 둘의 차이를 두면 무슨 변화가 생기냐? 다음 코드를 보자.

let a = 1;
b = a; 
console.log(a,b) // 1 1
b = 2
console.log(a,b) // 1 2

let a = {name: 'Taewoong Moon', age: 16};
b = a
console.log(a,b) // 둘다 {name: 'Taewoong Moon', age: 16};
b.name = '문태웅'
console.log(a,b) // 둘다 {name: '문태웅', age: 16};

값을 복사한 원시 데이터 같은 경우는 b에 새로운 값을 재할당 했을 때, 새로운 주소를 생성해서 b에 데이터를 복사하는 반면
객체 데이터 같은 경우는 힙의 내부 데이터가 변한것이기 때문에 Heap의 값만 바뀌고, a와 b는 둘다 같은 주소를 참조하고 있다. 그렇기 때문에 b가 a를 그대로 복사하면 둘 다 내부의 데이터가 바뀌는 문제가 발생한다.

그래서 객체형 데이터 같은 경우는 Javascript 를 깊은 복사를 하거나 얕은 복사를 해야한다.

참조형 데이터 복사 방법

1. 얕은 복사 진행

let a = {name: 'TaewoongMoon' , age: 16};
function copyShallowObject(object){
  	return {
    	name: object.name;
      	age: object.age;
    }
};

위의 함수와 아애 새로운 객체를 리턴하는 함수를 만들어서 진행해도 된다. 다만 이런식으로 하드코딩했을 경우에는 내부의 프로퍼티 key값이 무엇인지 항상 알아야하는 단점이 있다.

let a = {name : 'TaewoongMoon', age: 16};

function copyShallowObject(object){
	let result = {};
  	for(prop in object){
    	result[prop] = object[prop];
    }
  	return result;
}

위의 함수는 굳이 하드코딩을 할 필요가 없다. 다만 a의 내부프로퍼티에서 nested object, 즉, 객체가 중첩될 경우에는 shallow copy를 한 함수기 때문에 nested object는 또 힙의 데이터를 참조만 해서 문제가 된다. 그렇기 때문에 깊은 복사를 재귀함수를 통해서 하는 것이다.

2. 깊은 복사 진행

let a = {name : 'Taewoong Moon', age: {young: '16', old: '27'}}

function copyObjectDeep(object){
	let result = {};
  	if(typeof object === 'object' && object !== null){
    	for(prop in object){
        	result[prop] = copyObjectDeep(object[prop])
        }
    }else{
    result = object;
    }
	return result;
}

위의 재귀함수를 구현해서 깊은 복사를 한 후 메모리에 저장을 하면 문제가 발생하지 않는다. 위의 코드를 처음보면 이해가 잘 되지 않지만, 계속해서 눈으로 익숙해지며 재귀함수 프로그래밍을 많이 짜봐야 이해가 되긴한다. (사실 아직도, 잘 눈에 안익음)

profile
모든 코드에 의미를 담겠습니다.

0개의 댓글