3D Web Developer/C.S

[ C.S 지식 정리 ] 프론트 엔드 면접 대비 MarkUp&JS 정리 - [1]

안다미로 : 담은 것이 그릇에 넘치도록 많게. 2024. 10. 24. 15:51

 

[ C.S 지식 정리 ] 프론트 엔드 면접 대비 MarkUp&JS 정리 - [1]

 

 

 


 

∇ 프론트엔드 면접 대비 - [1]

목   차

1. HTML & CSS
2. JavaScript

 

 


1. HTML & CSS


 

 

1. px, em, rem의 차이

        - px : 절대 단위로, 화면 크기나 부모 요소의 변경에 상관없이 고정된 크기를 유지합니다.

                    주로 border 값에 사용됩니다.

        - em : 상대 단위로,  부모 요소의 'font-size' 등을 기준으로 크기가 결정됩니다.

                    예를 들어 font-size가 48px일때, 자식의 font-size가 1em이면 48px이 됩니다.

        - rem : 상대 단위로, 루트 요소(html)의 font-size를 기준으로 크기가 결정됩니다.

                        기본적으로 브라우저 상에서 html에 할당된 font-size는 16px이므로 1rem은 16px입니다.

                     반응형 디자인에서 많이 사용됩니다.

 

 

2. 반응형 웹에서 주로 사용하는 단위

              - 반응형 웹에서는 'rem'을 주로 사용합니다.

              - htrml의 'font-zise'를 조정함으로써 rem을 사용한 요소들의 크기를 한번에 조정할 수 있기 때문입니다.

 

 

 

3. vw, vh에 대한 설명

             - vw (vieport width ) : 뷰포트 너비의 1/100입니다.

                                               브라우저 너비가 변경될 때마다 자동으로 값이 조정됩니다.

 

             - vh ( viewport height ) : 뷰포트 높이의 1/100입니다.

                                                 브라우저 높이가 변경될 때마다 자동으로 값이 조정됩니다.

 

 

4. 반응형 브레이크 포인트 설정

           - 반응형 브레이크 포인트는 일반적으로 디바이스의 표준 해상도에 맞춰서 설정합니다.

 

5. CSS 선택자의 우선순위

           1. 인라인 스타일 

           2. ID 선택자

           3. 클래스, 속성 및 가상 클래스 선택자

           4. 태그 선택자

           5. 전체 선택자( *)

6. 페이지 크기가 변해도 항상 같은 비율을 유지하는 요소 만들기

           - CSS에서 'aspect-ratio' 속성을 사용하여,

               요소가 페이지 크기에 따라 비율을 유지하도록 설정할 수 있습니다.

.element {
    aspect-ratio: 16 / 9; /* 예시: 16:9 비율 */
}

7. Flexbox에 대한 설명

         - Flexbox는 CSS 레이아웃 모델로,

            컨테이너 안의 아이템들을 효율적으로 배치하고 정렬할 수 있도록 도와줍니다.

 

         - 주축(mainaxis)과 교차축(cross axis)를 기준으로 아이템을 정렬하며

            수평 및 수직 정렬을 쉽게 할 수 있습니다.

8. float의 동작

          - 'float' 속성은 요소를 왼쪽 또는 오른쪽으로 위치하게 하여, 텍스트나 인라인 요소가 그 주위를 감싸도록 합니다.

 

          - 그러나, 이 속성을 사용하면 레이아웃 상에 예기치 않은 결과를 만들 수 있어서

                FlexBOx나 Grid 레이아웃이 선호됩니다.

 

9. CSS에서 Cascading

           - Cascading은 CSS 규칙들이 적용되는 순서를 결정하는 메커니즘입니다.

               이는 스타일 시트가 여러 소스에서 올 경우 어떤 스타일이 적용될지를 결정합니다.

 

 

출처(Origin): CSS 스타일은 세 가지 주요 출처에서 올 수 있습니다:

  • 브라우저 기본 스타일: 브라우저가 기본적으로 제공하는 스타일입니다.
  • 사용자 스타일 시트: 사용자가 직접 정의한 스타일입니다.
  • 저자(개발자) 스타일 시트: 웹 페이지를 작성하는 개발자가 정의한 스타일입니다.

 

 

중요도(Importance): !important 규칙을 사용하면 해당 스타일 규칙의 우선순위가 높아집니다. !important가 붙은 규칙은 다른 모든 규칙보다 우선시됩니다.

 

 

 

명시도(Specificity): 선택자의 명시도는 선택자가 얼마나 구체적인지를 나타내며, 이는 다음과 같이 계산됩니다:

  • 인라인 스타일: 가장 높은 명시도 (예: <div style="color: red;">)
  • ID 선택자: 높은 명시도 (예: #myId)
  • 클래스, 속성, 가상 클래스 선택자: 중간 명시도 (예: .myClass, [type="text"], :hover)
  • 태그 선택자: 낮은 명시도 (예: div, p)
  • 전체 선택자 (*): 가장 낮은 명시도

 

 

소스 순서(Order of Appearance): 동일한 명시도를 가진 규칙이 여러 개 있을 경우, 나중에 정의된 규칙이 우선합니다.

 

 

 

10. SCSS에 대한 설명

            - SCSS는 Sass의 문법 중 하나로, CSS 보다 더 강력한 기능을 제공합니다.

 

            - 중첩 규칙, 변수 , 믹스인 등을 지원하여 코드 재사용성과 유지보수성을 높입니다.

 

 

11. position 속성에 대한 설명

             - position 속성은 요소의 위치를 지정하는 방법을 정의합니다.

 

                    - static : 기본값으로 문서의 흐름에 따라 배치됩니다.

                    - relative : 원래 위치를 기준으로 상대적으로 배치됩니다.

                    - absolute : 가장 가까운 위치 지정, 조상 요소를 기준으로 배치됩니다.

                    - fixed : 뷰포트를 기준으로 고정되어, 스크롤 시에도 위치가 변하지 않습니다.

                    - sticky : 스크롤 위치에 따라 relative와 fixed 사이를 전환합니다.

 

 

12. margin과 padding에 대한 설명

            - margin과 padding은 CSS에서 요소의 여백을 관리하는 두 가지 주요 속성입니다.

            - 이 둘은 요소와 그 주변 환경 간의 간격을 조절하지만, 서로 다른 방식으로 작동합니다.

 

 

              ○ margin 

                     - 외부 여백으로, 요소의 경계(border) 바깥쪽에 위치합니다.

                     - 요소와 다른 요소 사이의 간격을 조정하는 데 사용됩니다.

                     - 상하좌우에 개별적으로 설정할 수 있으며, 

                            단축 속성으로 한 번에 설정할 수 도 있습니다.

.example {
    margin-top: 10px;
    margin-right: 20px;
    margin-bottom: 10px;
    margin-left: 20px;
    /* 또는 단축 속성 사용 */
    margin: 10px 20px;
}

 

              ○ padding

                     - 내부 여백으로, 요소의 내용(content)과 경계(border) 사이에 위치합니다.

                     - 요소 내 콘텐츠와 테두리 사이의 간격을 조정하는 데 사용됩니다.

                     - 상하좌우에 개별적으로 설정할 수 있으며, 

                            단축 속성으로 한 번에 설정할 수 도 있습니다.

.example {
    padding-top: 10px;
    padding-right: 20px;
    padding-bottom: 10px;
    padding-left: 20px;
    /* 또는 단축 속성 사용 */
    padding: 10px 20px;
}

 

    ※패딩은 요소의 크기에 영향을 미칩니다.

      예를 들어, 박스 모델(box model)에서 width height를 지정할 때 패딩 값이 포함되지 않도록 주의해야 합니다.

       이를 해결하기 위해 box-sizing 속성을 border-box로 설정하여 패딩과 보더가 포함된 크기를 지정할 수 있습니다.

.example {
    box-sizing: border-box; /* 패딩과 보더를 포함하여 크기를 계산 */
}

 

 

 

 

13.HTML 렌더링 도중 JavaScript가 실행되면 렌더링이 멈추는 이유가 뭔가요?

 

        A. 렌더링 엔진과 JavaScript 엔진의 직렬적 실행.

              - 렌더링 엔진과 JavaScript 엔진은 병렬적으로 작동해야 합니다.

   

       B. DOM 생성 중단

              - 렌더링 엔진이 HTML을 파싱하여 DOM을 생성하는 도중 JavaScript를 만나면,

               DOM 생성을 임시로 중단합니다.

 

       C. 제어권 이전

            - JavaScript를 만나면 렌더링 엔진은 JavaScript엔진에 제어권을 이전합니다.

                JavaScript 코드의 파싱과 실행이 완전히 완료될 때까지 HTML 파싱이 중단됩니다.

 

       D. JavaScript의 DOM 조작 가능성

              - JavaScript는 DOM을 조작할 수 있기 때문에, JavaScript 실행 전에 완전한 DOM 구조를 보장 X

             - JavaScript 코드 실핼 중에는 HTML 파싱을 중단해야 합니다.

 

       E. 리소스 로딩 순서 

              - JavaScript 파일이 먼저 로드되고 실행되면, CSS 파싱이 지연될 수 있기에

                 화면 레이아웃이 제대로 구성되지 않은 상태로 사용자에게 보여질 수 있습니다.

 

   

         이러한 문제점들을 해결하기 위해서, 다음과 같은 방법을 취할 수 있습니다.

                      - script 태그를 body 끝에 배치하기.

                      - async 또는 defer 속성 사용하기.

                      - JavaScript 코드를 DOM 로드 완료 후 실행되도록 설정.

 

 

 


2. JavaScript.


 

 

 

 

 

1. 자바스크립트는 무슨 언어인가요?

           - JavaScript는 가벼운, 인터프리터 혹은 JIT(Just-In-Time) 컴파일 프로그래밍 언어.

 

                ※ 주요 특징.

                           - 인터프리터 언어 : 실행 시점에 코드를 해석하고 실행.

                           - 동적 타입 : 변수의 타입을 실행 시점에 결정

                           - 멀티 패러다임 : 객체지향, 함수형, 명령형 프로그래밍을 모두 지원

                           - 프로토타입 기반 : 클래스 대신 프로토타입을 사용해 상속을 구현.

                           - 싱글(단일) 스레드 : 한 번에 하나의 작업만 처리 가능

                           - 이벤트 기반 : 비동기 프로그래밍을 위해 이벤트 루프를 사용.

                         -   일급함수( 함수를 일급 객체로 취급하는 것)가 존재.

 

                ※ 주요 용도.

                        - 웹 브라우저에서의 클라이언트 사이드 스크립팅

                        - Node.js를 이용한 서버 사이드 개발

                       - 데스크탑 및 모바일 애플리케이션 개발 ( Electron, React Native 등)

 


 

 

2. 변수 선언, 초기화, 할당의 차이점

              - 변수 선언(Declaration) : 변수를 생성하는 과정입니다. 

                                    - 메모리 공간을 확보하고 변수명과 연결합니다.

                                    - ex ) 'let myVar;"

 

             - 변수 초기화 (initialization)

                           - 선언된 변수에 최초로 값을 할당합니다.

                               - ex ) 'let myVar = 0;'

 

             - 변수 할당(Assignment)

                          -이미 선언된 변수에 새로운 값을 저장합니다.

                               - ex ) 'myVar = 5;'

 

 

                주로  'var'로 선언된 변수는 자동으로 'undefined'로 초기화되지만,

                    'let'과 'const'는 TDZ(Temporal Dead Zone)에 있어 초기화, 전 접근 시 에러가 발생.

 

 

 


 

   

3. 데이터 타입

          - 자바스크립트의 데이터 타입은 크게 2가지로 나눌 수 있습니다.

 

 

                  1. 원시 타입 ( Primitive Types)

 

                         -  Number : 숫자 

                              ex) 42,  3.14 등

 

                         - BigInt : 큰 정수 

                              ex) 9007199254740991n 등

 

                         - String : 문자열 

                               ex) Hello

 

                         - Boolean : 논리값

                                 - > true 또는 false

 

                         - Undefined : 값이 할당되지 않은 상태.

 

                         - Null : 의도적으로 값이 없음을 나타냄.

 

                         - Symbol : 고유한 식별자 

 

                  2. 참조 타입 ( Reference Type)

 

                         - Object : 키-값 쌍의 집합 

                               ex)     {name : "John" , age:30}

 

                        - Array : 객체의 특별한 형태, 순서가 있는 컬렉션.

                        - Function : 호출 가능한 객체.

 

 

                ※ 특징 정리.

 

                        - 원시 타입은 값이 직접 저장되고, 참조 타입은 메모리 주소가 저장됩니다.

 

                        - JavaScript는 동적 타입  언어로, 변수의 타입이 런타임시에 결정됩니다.

 

 

4. 생성자

                - 생성자는 객체를 생성하고 초기화하는 특별한 함수입니다.

 

                       - 'new' 키워드와 함께 사용됩니다. ( new 연산자를 통해 호출)

                               - > new 연산자를 사용하지 않으면 생성자를 반활할 수 없기 때문에 undefined가 출력.

 

                           ○ new 연산자의 원리.

                                       - 빈 객체를 생성.

                                       - 새로 생성된 빈 객체는 생성자의 프로토타입을 상속받는다.

                                       - this를 새로 생성된 객체에 바인드.

                                       - 생성자에 명시적으로 다른 객체를 리턴하지 않는 경우,

                                          this로 바인드된 객체가 반환됩니다. ( 일반적으로 생성자는 값을 리턴 X )

 

                       - 대문자로 시작합니다.

                       - 새로운 객체를 생성하고, 'this'를 통해 속성과 메서드를 추가합니다.

                       - 프로토타입을 통해 메서드를 공유할 수 있습니다.

 

function Student(grade, name) {
	this.grade = grade
  	this.name = name
  	this.introduce = function() {
    	console.log('학년: ' + this.grade + ' 이름: ' + this.name)
	}
}
var gildong = new Student(3, '홍길동')
var cheolsoo = Student(1, '김철수')

console.log(gildong)
console.log(cheolsoo)
Student { grade: 3, name: '홍길동', introduce: [Function (anonymous)] }
Undefined
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.greet = function() {
    console.log(`Hello, I'm ${this.name}`);
  };
}

const john = new Person('John', 30);
john.greet(); // 출력: Hello, I'm John

                    

 

 

5. this

       - this는 현재 실행 컨텍스트를 참조하는 키워드입니다.

 

      - 값은 함수 호출 방식에 따라 달라집니다.

 

 

 

             √ 단독으로 쓴 this. (전역 컨테스트 ) - stric mode에서도 마찬가지.

 

                   전역객체는 모든 객체의 유일한 최상위 객체를 의미합니다.

                   일반적으로 브라우저에서의 전역객체는 window 이며, 서버(node.js)에서의 전역객체는 global 입니다.

// 브라우저
console.log(this); // window

// node.js
console.log(this); // global

 

                  전역 객체는 전역 스코프를 가지는 전역변수를 프로퍼티로 소유합니다.

const globalFn = () => {
	console.log('call globalFn');
}

window.globalFn(); // call globalFn
this.globalFn(); // call globalFn

 

 

             √ 일반함수

                  일반함수를 호출하면 this는 전역객체에 바인딩 된다.

// 함수 선언식
function funcDeclaration () {
	console.dir(this);
}
funcDeclaration(); // window

// 함수 표현식
const funcExpressions = () => {
	console.dir(this);
}
funcExpressions(); // window

              

             √ 함수 안에서  쓴 this.(내부함수)

 

                       - 함수 안에서 사용된 this 는 함수의 주인에게 바인딩됩니다.

                             ( 함수의 주인 = window 객체 ) / 일반 함수의 주 = 전역 객체.

                      - 다만, strict mode에서는 함수 내의 디폴트 바인딩이 없기 때문에 undefined가 됩니다.

                      - 내부함수는 내부함수가 일반함수, 메소드, 콜백함수 내부 어디에서 선언되었든 상관없이

                       this가 전역객체에 바인딩 된다.

const obj = {
	foo: function() {
		function fooInner() {
			console.log('fooInner this:', this);
		}

		fooInner();
	},

	// that 변수에 bar 메서드의 this를 할당하여 사용함으로써
	// 내부함수의 this가 전역객체를 바인딩하지 않도록 한다.
	bar: function() {
		const that = this;
		function barInner() {
			console.log('barInner this:', that);
		}
	
		barInner();
	},

	// 화살표함수의 this는 상위 컨텍스트의 this를 계승받기 때문에,
  // baz 메서드의 this를 바인딩 한다.
	baz: function() {
		const bazInner = () => {
			console.log('bazInner this:', this);
		}
		
		bazInner();
	}
}

obj.foo(); // window
obj.bar(); // obj
obj.baz(); // obj

 

 

             √ 메서드 안에서  쓴 this.

 

                       - 메서드의 주인은 메서드를 소유(호출)한 객체.

                               -> 따라서 메서드 안에서 쓴 this는  해당 메서드를 호추한 객체로 바인딩됩니다.

 

                      - 단, 메서드가 화살표 함수로 작성되었을 경우,

                         화살표 함수의 this는 상위 컨텍스트의 this를 계승받기 때문에 this가 전역객체에 바인딩 됩니다.

                                

var person = {
  firstName: 'John',
  lastName: 'Doe',
  fullName: function () {
    return this.firstName + ' ' + this.lastName;
  },
};
 
person.fullName(); //"John Doe"
var num = 0;
 
function showNum() {
  console.log(this.num);
}
 
showNum(); //0
 
var obj = {
  num: 200,
  func: showNum,
};
 
obj.func(); //200

 

 

             √ 이벤트 핸들 안에서  쓴 this.

 

                      - DOM 요소 자체를 참조.

                      - 이벤트 핸들러에서 this는 이벤트를 받는 HTML 요소를 가리킵니다.

var btn = document.querySelector('#btn')
btn.addEventListener('click', function () {
  console.log(this); //#btn
});

 

 

             √ 생성자 안에서  쓴 this.

 

                     - 생성자 함수의 코드가 실행되기 전에 빈 객체가 생성되는데,

                       이 후 생성자 함수 내에서 사용되는 this는 이 빈 객체를 바인딩한다.

function Person(name) {
  this.name = name;
}
 
var kim = new Person('kim');
var lee = new Person('lee');
 
console.log(kim.name); //kim
console.log(lee.name); //lee
function Foo(name) {
  // 생성자 함수 코드 실행 전
	this.name = name;
}

const foo = new Foo('Cho');
console.log(foo); // Foo { name: 'Cho' }

        주의! new 키워드를 빼먹는 순간, 일반 함수 호출과 같아지기 때문에

                   new를 빼는 순간 this가 window에 바인딩 됩니다.

var name = 'window';
function Person(name) {
  this.name = name;
}
 
var kim = Person('kim');
 
console.log(window.name); //kim

 

             √ 명시적 바인딩을 한 this.

                       

                    call은 함수를 호출하며 첫 번째 인자로 전달하는 값에 this를 바인딩 한다.

 

                    apply는 함수를 호출하며 첫 번째 인자로 전달하는 값에 this를 바인딩 한다.

      

                   인자는 배열 형태로 전달하며, 실제 배열이 전달되는 것이 아니고 배열의 요소들이 전달된다

 

                    bind는 첫 번째 인자로 전달하는 값에 this를 바인딩 하며, 새로운 함수를 반환한다.

function foo(num1, num2) {
	console.log(this.name, num1 + num2);
}

const person = {
	name: 'cho',
};

foo.call(person, 1, 2); // cho, 3
foo.apply(person, [1, 2]); // cho, 3

const newFoo = foo.bind(person);
newFoo(1, 2); // cho, 3

 

             √ 화살표 함수로 쓴 this.

            화살표 함수 내의 this는 Lexical this를 바인딩 합니다.

            다시 말해, 화살표 함수가 정의된 스코프에 존재하는 this를 바인딩 합니다.

// 전역 스코프에 정의되있으므로, this가 전역 객체를 가리킨다.
const foo = () => {
	console.log(this);
}

foo(); // window

// foo 메서드의 스코프에 정의되있으므로, this가 foo 메서드의 this를 가리킨다.
const obj = {
	foo: function() {
		const fooInner = () => {
			console.log(this);
		}

		fooInner();
	}
};

obj.foo(); // obj

 

6. call, apply, bind

         - 함수의 'this'를 명시적으로 설정(바인딩)하는데 사용됩니다.

          

         - "Call,  apply, bind"는 "함수 호출 방법"을 지정해서   'this'를 그때그때 알맞은 객체로 명시적으로 바꿔주는 메소드

 

                  ※ call, apply와 bind의 차이점.

                           - call, apply는 함수를 호출해서 인수를 전달.

                           - bind는 함수를 호출하지 않고,

                                    함수와 this값을 유지하는 새로운 함수를 생성

 

                  ※ call 과 apply의 차이점.

                           - call의 경우, 호출한 함수의 인수를   ,로 구분한 리스트 형식으로 전달.

                           -apply는 인수(인자)를 배열 []로 전달.

 

 

            - 자바스크립트에서 함수를 호출하는 방법에는 일반적으로 함수 뒤에  ()를 붙여서 호출하는 방법과

                 call, apply를 붙여 호출하는 방법이 있습니다.

 

                        ● call() 

                                -"call" 메서드는 메서드의 호출 주체인 함수를 '즉시 실행'하는 메서드.

             

function.call(thisArg[ , arg1, arg2[, ...]])

                              -  thisArg : 함수 호출에 제공하는 this의 값

                              -  arg1, arg2 ,... : 함수가 호출되어야 하는 인수.

let person1 = {
  name: 'Olivia'
};


let person2 = {
name: 'Seulgi',
greeting: function() {
console.log(this.name + '야, 안녕~?');
}
};
person2.greeting(); // Seulgi야, 안녕~?
person2.greeting.call(person1); // Olivia야, 안녕~?
- `person2` 함수를 호출하고 있지만, `call`메소드를 통해 
**첫 번째** 매개변수(thisArg)에 `person1`을 넣어줘서 
  `this`의 값은 `person1`이 되어 **Olivia가 출력**된다.
  
### apply()
> `apply`메서드는 `call`메서드와 같이 메서드의 호출 주체인 함수를 
**즉시 실행**하는 메서드
```jsx
function.apply(thisArg, [argsArr])

 

 

                        ● apply()

                             - 인자를 [] 형태로 전달.

 

                             - apply() 메소드를 사용하기 좋은 상황 : 배열 중 가장 큰 값이나 작은 값 구하기 같은 것

 

 

apply()메소드를 사용하지 않고 가장 큰 수를 구할 경우

let arr = [1, 3, 5, 7, 9, 11, 13, 15];
let maxNum = Math.max(...arr);
conosle.log(maxNum); // 15


apply()메소드를 하여 가장 큰 수를 구할 경우

let arr = [1 ,3, 5, 7, 9, 11, 13, 15];
let maxNum = Math.max.apply(null, arr);

console.log(maxNum); // 15

 

                        ● bind() 

                                - bind 메서드는 함수를 즉시 실행하지 않고, 넘겨 받은 인수를 바탕으로

                                    새로운 함수를 반환하는 메서드,

                                - 함수가 가르키는 this만 바꾸고 호출하지는 않습니다.

                                - 변수를 할당하여 호출하는 형태로 사용할 수 있고,

                                        커스텀 this를 가르키는 함수를 만들 수 있습니다.

function.bind(thisArg[ , arg1[, arg2[, ...]]])


thisArg : 바인딩 함수가 타겟 함수의 this에 전달하는 값.
전달하는게 없으면, null

arg1, arg2, ... : 함수가 호출되어야하는 인수
let person1 = {
  name: "Olivia",
  age: 25,
  location: "Dublin"
}

let person2 = {
  name: "Seulgi",
  age: 29,
  location: "Seoul",
  introduce: function(age, name) {
    console.log(`${this.name}은 ${this.age}살이고, ${this.location}에 살고 있습니다`);
  }
};
person2.introduce(); // Seulgi은 29살이고, Seoul에 살고 있습니다

let oldMe = person2.introduce.bind(person1);

oldMe(); // Olivia은 25살이고, Dublin에 살고 있습니다

 

7. 콜백 함수

          - 콜백 함수는 쉽게 말하면, 매개변수로 함수 객체를 전달( 다른 함수에 인자로 전달)해서

                   호출 함수 내에서 매개변수 함수를 실행하는 것을 말합니다.

function sayHello(name, callback) {
    const words = '안녕하세요 내 이름은 ' + name + ' 입니다.';
    
    callback(words); // 매개변수의 함수(콜백 함수) 호출
}

sayHello("인파", function printing(name) {
	console.log(name); // 안녕하세요 내 이름은 인파 입니다.
});

               - sayHello() 함수를 호출할 때, 입력 매개변수로 문자열(인파)과 printing 함수 자체를 전달.

               - sayHello() 함수가 실행되면, 실행문 안에서,

                    함수가 들어있는 두번째 매개변수인 callback을 괄호()를 붙여서 호출합니다.

 

 즉!  '콜백 함수'란 파라미터 값으로 일반적인 변수나 값을 전달하는 것이 아니라,

           "함수 자체"를 전달하는 것을 의미합니다.

      

   또한, 어차피 매개변수에 함수를 전달해 일회용으로 사용하기 때문에 굳이 함수 이름을 명시할 필요 없이

            보통 콜백 함수 형태로 함수를 넘겨줄 때 함수의 이름이 없는 '익명 함수' 형태로 넣어줍니다.

function sayHello(name, callback) {
    const words = '안녕하세요 내 이름은 ' + name + ' 입니다.';
    
    callback(words);
}

sayHello("인파", function (name) { // 함수의 이름이 없는 익명 함수
	console.log(name); 
});

 

            @ 콜백 함수 간결하게 만드는 방법들.

                           a. 익명의 함수 사용

                           b. 화살표 함수 모양의 콜백

                           c. 함수의 이름을 넘기기.

 

            @ 콜백 함수 활용 사례.

 

                       A. 이벤트 리스너로 사용.

let button = document.getElementById("button"); // 버튼 요소를 선택

// 버튼에 클릭 이벤트 리스너를 추가
button.addEventListener("click", function () { // 콜백 함수
  console.log("Button clicked!"); 
});

                                - addEventListener는 특정 이벤트 발생 시 콜백 함수를 실행하는 메서드.  

                                - 클릭과 같은 이벤트를 처리하기 위해 등록하는 이벤트 리스너로 콜백함수 활용.

                                - 버튼을 클릭하면 그에 연관되는 스크립트 실행을 콜백 함수로 등록하는 형태.

 

                       B. 고차 함수에 사용. 

// 예시 : 배열의 각 요소를 두 배로 곱해서 새로운 배열을 생성하는 콜백 함수 
let numbers = [1, 2, 3, 4, 5]; // 배열 선언 
let doubled = []; // 빈 배열 선언 

// numbers 배열의 각 요소에 대해 콜백 함수 실행 
numbers.forEach(function (num) { 
    doubled.push(num * 2); // 콜백 함수로 각 요소를 두 배로 곱해서 doubled 배열에 추가 
}); 

console.log(doubled); // [2, 4, 6, 8, 10]

                       C. Ajax 결과값을 받을 때 사용.

                                  - 서버와 데이터를 주고받을 때 사용하는 fetch 메서드의 서버 요청의 결과값을 처리하기 위해 사용

// fetch 메서드를 사용하여 서버로부터 JSON 데이터를 받아오고 콜백 함수로 화면에 출력
fetch("https://jsonplaceholder.typicode.com/users")
  .then(function (response) {
    // fetch 메서드가 성공하면 콜백 함수로 response 인자를 받음
    return response.json(); // response 객체의 json 메서드를 호출하여 JSON 데이터를 반환
  })
  .then(function (data) {
    // json 메서드가 성공하면 콜백 함수로 data 인자를 받음
	console.log(data);
  })

                       D. 타이머 실행 함수로 사용.

                               - setTimeout이나 setInterval 과 같은 타이머 함수에서 일정 시간마다 스크립트 실행하는 용도.

// 3000 밀리초(3초) 후에 콜백 함수 실행
setTimeout(function () {
  console.log("Time is up!"); // 콜백 함수로 콘솔에 메시지 출력
}, 3000);

                       E. 애니메이션 완료.

 

            @ 콜백 함수 장/단점

                     - 장점.

                           - 비동기 프로그래밍을 가능하게 함

                           - 코드의 유연성 증대

                    - 단점.

                           - 중첩된 콜백은 가독성을 저하시킬 수 있음 ( 콜백 지옥)

 

 

 

8. 콜백 지옥 해결 방법

             - "콜백 지옥(Callback Hell)"이란,

                      함수의 매개변수로 넘겨지는 콜백 함수가 반복되어서

                      코드의 들여스기 수준이 감당하기 힘들어질 정도로 깊어지는 현상을 말합니다.

function add(x, callback) {
    let sum = x + x;
    console.log(sum);
    callback(sum);
}

add(2, function(result) {
    add(result, function(result) {
        add(result, function(result) {
            console.log('finish!!');
        })
    })
})

/*
4
8
16
finish!!
*/

 

진짜 지옥....

 

          - 이런 더러운 콜백 지옥을 해결하는 방법.

 

                          1. Promise 사용

                                  - 비동기 작업을 체이닝 형태로 처리 가능합니다.

fetchData()
  .then(processData)
  .then(saveData)
  .catch(handleError);

 

 

                          2. Async/Await 사용.

                                - Promise를 더 동기적인 형태로 작성 가능하도록 해줍니다.

async function handleData() {
  try {
    const data = await fetchData();
    const processed = await processData(data);
    await saveData(processed);
  } catch (error) {
    handleError(error);
  }
}

 

                          3. 함수 분리.

                                  - 콜백 함수를 별도의 명명된 함수로 분리해줍니다.

function handleData(error, data) {
  if (error) return handleError(error);
  processData(data, handleProcessed);
}

function handleProcessed(error, processed) {
  if (error) return handleError(error);
  saveData(processed, handleSaved);
}

fetchData(handleData);

 

                          4. 모듈화 : 관련 기능을 모듈로 분리하여, 복잡성을 관리.

                          5. 라이브러리 사용 : async.js와 같은 라이브러리를 사용하여 비동기 흐름 관리.

 

9. Promise

              - Promise는 비동기 작업의 최종 완료 또는 실패를 나타내는 객체입니다.

 

                      √  3가지 상태를 가집니다.

                            - 대기 (pending)

                            - 이행 (fulfilled)

                            - 거부 (rejected)

 

                     -    . then() /   .catch() /  .finally() 메서드를 통해 결과를 처리합니다.

const myPromise = new Promise((resolve, reject) => {
  // 비동기 작업 수행
  if (/* 성공 조건 */) {
    resolve(result);
  } else {
    reject(error);
  }
});

myPromise
  .then(result => {
    // 성공 처리
  })
  .catch(error => {
    // 오류 처리
  })
  .finally(() => {
    // 항상 실행되는 코드
  });

 

 

                      √  promise의 장점.

                             - 비동기 코드를 체이닝 형태로 작성가능하여서, 가독성이 향상

                             - 에러 처리가 용이

                             - 여러 비동기 작업들을 병렬로 처리 가능,(promise.all)

 

 

 

10. Promise.all()

              √ promise.all()은 여러 Promise를 병렬로 실행하고, 모든 Promise가 이행되고 나면 

                        결과 배열을 반환하는 메서드입니다.

 

                         - 모든 Promise가 성공적으로 이행되면 결과 배열을 반환

                         - promise들 중 하나라도 거부되면 전체가 거부,

                              첫번째로 거부된 Promise의 이유를 반환.

const promise1 = fetch('/api/data1');
const promise2 = fetch('/api/data2');
const promise3 = fetch('/api/data3');

Promise.all([promise1, promise2, promise3])
  .then(([result1, result2, result3]) => {
    // 모든 요청이 성공적으로 완료됨
    console.log(result1, result2, result3);
  })
  .catch(error => {
    // 하나라도 실패하면 이 블록이 실행됨
    console.error('Error:', error);
  });

   

              √ promise.all()의 주요 특징.

                        - 병렬 처리로 전체 실행 시간을 단축

                        - 모든 Promise의 결과가 필요한 경우에 유용

                        - 에러 처리 시 주의가 필요. (하나의 실패 = 전체의 실패_

 

 

 

 

11. Promise와 Callback 비교

                - Promise와 Callback은 비동기 프로그래밍을 위한 패턴

 

                 √ 코드 구조

                        - Callback : 중첩된 구조로 인해 가독성이 저하됨.

                        - promise : 체이닝을 통해 선형적인 코드 흐름 제공

 

                 √ 에러 처리 방식

                        - Callback : 각 콜백마다 에러 처리 필요.

                        - promise :  .catch()를 통해 중앙집중식 에러 처리.

 

                 √ 흐름 제어

                        - Callback : 복잡한 비동기 로직에서 흐름 제어가 어려울 수 있음.

                        - promise :  .then()을 사용한 체이닝으로 순차적 실행 용이

 

                 √ 병렬 처리

                        - Callback : 복잡한 추가 구현 필요.

                        - promise :  promise.all(),  promise.race() 등으로 쉽게 구현

 

 

                 √ 표준화

                        - Callback : 표준화된 패턴이 없어서 라이브러리마다 다를 수 있음

                        - promise :  ES6에서 표준화되어서 일관된 사용 가능

 

 

 

 

 

14. var, let, const 차이

             √  JavaScript에서 변수 선언에 사용되는 키워드들의 주요 차이점

 

                     1. 스코프

                             - var : 함수 스코프

                             - let, const : 블록 스코프

 

                     2. 재선언

                             - var : 동일한 스코프 내에서 재선언 가능

                             - let, const : 동일한 스코프 내에서 재선언 불가

 

                    3. 재할당

                            - var, let : 재할당 가능

                            - const : 재할당 불가 ( 객체의 내용은 변경 가능

                  

                    4. 호이스팅

                            - var: 선언과 초기화가 호이스팅 됨

                            - let, const : 선언만 호이스팅되고, TDZ 영향을 받음.

 

                    5. 전역 객체 프로퍼티

                            - var: 전역 스코프에서 선언 시 전역 객체의 프로퍼티가 됨

                            - let, const : 전역 객체의 프로퍼티가 되지 않음.

15. TDZ (Temporal Dead Zone)

           TDZ는 변수가 선언되었지만 초기화되지 않은 상태의 시간적 사각지대를 의미합니다.

 

                      - let & const로 선언된 변수에 적용됩니다.

                      - 변수 선언부터 초기화되기 전까지의 구간을 의미합니다

                      - TDZ 내에서 변수에 접근하면 'ReferenceError'가 발생합니다.

 

            ★ TDZ의 목적

                      - 변수 사용의 일관성과 예측 가능성을 증대

                      - 초기화되지 않은 변수의 사용을 방지 !

 

 

 

 

16. 함수 선언형과 함수 표현식의 차이

 

             함수 선언형과 함수 표현식은 함수를 정의하는 두 가지 주요 방식입니다.

 

                ○ 함수 선언형 ( Function Decalaration )

                     

function greet(name) {
  console.log(`Hello, ${name}!`);
}

 

 

                ○ 함수 표현식 ( Function Expression )

       

const greet = function(name) {
  console.log(`Hello, ${name}!`);
};

 

 

             ※ 두 방식의 주요 차이점.

 

                        1. 호이스팅

                                 - 함수 선언형 : 전체가 호이스팅 ( 선언 전에 호출 가능 )

                                 - 함수 표현식 : 변수 선언만 호이스팅 ( 선언 전 호출 시 에러 발생 )

 

                        2. 사용 시점

                                 - 함수 선언형 : 코드의 어느 위치에서든 사용 가능.

                                 - 함수 표현식 : 선언 이후에만 사용 가능.

 

                        3. 유연성

                                 - 함수 표현식 : 조건에 따라 다른 함수를 할당하는 등 더 유연한 사용 가능.

 

                        4. 즉시 실행 함수 (IIFE)

                                 - 함수 표현식은 즉시 실행 함수로 활용 가능.

 

                        5. 네이밍

                                 - 함수 선언형 : 반드시 이름이 필요.

                                 - 함수 표현식 : 익명 함수로 사용 가능.

 

// 함수 선언형
hoisted(); // "This works!"
function hoisted() {
  console.log("This works!");
}

// 함수 표현식
notHoisted(); // TypeError: notHoisted is not a function
var notHoisted = function() {
  console.log("This doesn't work!");
};

 

 


갈 길이 먼...CS 공부..