ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [면접 스터디] 프론트엔드 CS 관련 기술 면접 질문
    Front-end 개발 2024. 7. 21. 23:10

     

    이번 주 면접 스터디 주제는 CS와 관련된 아래의 키워드로 구성된다.

     

    CS 기술 면접 키워드
    - 스레드와 프로세스의 차이, 싱글 스레드와 멀티스레드
    - 재귀함수
    - 자료구조 (트리, 힙, 스택, 큐)
    - 객체지향과 절차지향
    - 함수형 프로그래밍이란?
    - 프레임워크와 라이브러리
    - JavaScript는 싱글 스레드 언어인데, 병렬처리가 가능한 이유
    - CS 지식을 프로젝트에 적용해본 경험

     

    1. 기술 면접


    1-1. 스레드(threads)와 프로세스(process)의 차이

    독립적인 프로세스는 메모리 영역을 다른 프로세스와 공유하지 않습니다. 하지만 스레드는 프로세스 내에서 프로세스 자원을 공유합니다. 스레드는 프로세스 내에서 실행에 필요한 다른 ID, 레지스터 값, 스택으로 구성되며 각각 다른 정보를 가지고 있기 때문에 다른 코드를 실행할 수 있습니다.

    프로그램은 실행되기 전에는 보조 기억장치에 저장되어 있는 데이터이지만, 이를 메모리에 적재하고 CPU 자원을 받아 실행하게 되면 프로세스가 됩니다. 프로세스는 실행되는 프로그램이고, 쓰레드는 이를 구성하는 실행 흐름 단위입니다.

    프로세스는 타 프로세스와 자원을 공유하지 않지만 프로세스 간 통신(IPC, Inter-Process Communcation)을 통해서 자원 및 데이터의 공유가 가능합니다.

     

    1-2. 싱글 스레드와 멀티 스레드

    싱글 스레드는 하나의 스레드로 작업을 처리하는 방식으로 리소스 사용량이 적고 프로그래밍이 간단합니다. 순차적으로 작업이 진행되기 때문에 입출력이 빈번한 작업에서는 처리 속도가 떨어집니다. 멀티 스레드는 여러 스레드가 동시에 다양한 작업을 처리하는 방식으로 리소스 사용량이 많고 프로그래밍이 복잡합니다. 동시에 여러 작업을 처리하는 환경에서 유리하나, 적절한 동기화 없이 공유 리소스에 접근하게 되면 문제가 발생할 수 있습니다.

     

    싱글 스레드의 장점

    - 문맥 교환(context switch)*이 필요 없음

    - 자원 접근에 대한 동기화 문제가 발생하지 않음

    - 프로그래밍 난이도가 쉽고, CPU와 메모리를 적게 사용함

    현재 실행 중인 작업의 상태를 저장하고 다음 작업의 상태를 불러오는 과정

     

    싱글 스레드의 단점

    - 병렬 처리를 하지 못함

    - 연산량이 많은 작업에서 처리 시간이 오래 걸리며, 에러 처리를 못할 경우, 전체 앱이 멈춤

     

    멀티 스레드의 장점

    - 사용자에 대한 응답성*이 증가한다.

    - 프로세스 내 자원들과 메모리를 공유하기 때문에 메모리 공간과 시스템 자원을 효율적으로 사용할 수 있다.

    - 멀티 프로세서 구조에서 각각의 스레드가 병렬로 수행될 수 있으므로 병렬성이 증가한다.

    * 에러가 발생하여 스레드 중 하나가 중단되어나, 긴 작업을 수행하더라도, 새로운 스레드를 만들어 프로그램이 계속해서 실행되므로 사용자에 대한 응답이 가능함

     

    멀티 스레드의 단점

    - 싱글 코어에서는 문맥교환, 동기화 등으로 스레드 생성 시간이 오버헤드로 작용해 단일 스레드보다 느릴 수 있다.

    -  재현과 디버깅이 어려운 경우가 많은 Race conditoin, deadlock과 같은 병렬 처리에서만 발생하는 특별한 문제가 있다.

     

    1-3. 재귀함수

    재귀함수는 자기 자신을 호출하느 함수로, 문제를 해결하기 위해 동일한 계산을 반복적으로 수행합니다. 이를 통해 문제를 더 작은 문제로 나누고, 그 작은 문제를 해결하여 최종적으로 원래 문제의 해답을 찾아내는 방식입니다. 예를 들어, 팩토리얼 계산이나 피보나치 수열과 같은 문제를 재귀함수로 해결할 수 있습니다.

    재귀함수를 사용할 때는 종료 조건(기본 사례)을 명확히 설정하고, 스택 오버플로우를 방지하기 위해 주의해야 합니다.

     

    1-4. 자료구조 (p.170)

    [큐]

    큐는 먼저 들어온 것이 먼저 나가는 선입선출(FIFO, First In First Out) 방식으로 데이터를 다루는 구조이다. 큐의 예시로 비행기를 탈 때 우리가 줄을 서는 모습을 생각할 수 있다. 먼저 도착한 사람이 먼저 탑승하는 것처럼, 줄의 뒷부분에서는 서서 차례를 기다리는 모습이다. 큐에서도 두가지 작업만 허용된다. 인큐(Enqueue)와 디큐(Dequeue)로 인큐는 항목을 큐의 뒷부분에 삽입하는 것을 의미하며, 디큐는 앞쪽 항목을 제거하는 것을 의미한다.


    [스택]

    스택은 나중에 들어온 것이 먼저 나가는 후입선출(LIFO, Last In First Out) 방식으로 데이터를 다루는 구조이다. 스택은 오직 두 가지 작업만 수행할 수 있는 구조이다. 스택에 항목을 추가(push)와 스택에서 항목을 꺼내는 작업(pop)이다. 스택은 접근에 제한이 있는 데이터 구조로, 요소는 스택의 맨 위에서만 추가하거나 제거할 수 있다. 푸쉬는 항목을 스택의 맨 위에 쌓는 것과 같고 팝은 맨 위의 요소를 꺼내는 것과 같다.

     

    [트리]

    트리는 계층적인 구조를 가지며 노드들이 연결된 형태입니다. 이진 트리는 각 노드가 최대 두 개의 자식 노드를 가지는 트립니다. 완전 이진 트리는 마지막 레벨을 제외한 모든 레벨에 노드가 완전히 채워져 있는 트리입니다.

     

    [힙]

    힙은 완전 이진 트리의 일종으로, 부모 노드와 자식 노드 간에 특정한 조건을 만족하는 자료구조입니다. 최대 힙은 부모 노드의 값이 자식 노드보다 크거나 같고, 최소 힙은 부모 노드의 값이 자식 노드보다 작거나 같습니다. 주로 우선순위 큐, 정렬, 스케줄링 등에서 활용됩니다.

     

    1-5. 객체지향과 절차지향

    객체 지향 프로그래밍(OOP, Object-Oriented Programming)은 절차 지향 프로그래밍과 대비되는 개념으로 Java, C++, C# 등의 언어에서 지원합니다. 상속(Inheritance), 캡슐화(Encapsulation), 추상화(Abstaction), 다형성(Polymorphism) 의 4가지 특징을 가지고 있습니다.

    상속은 부모 클래스의 모든 속성과 메서드를 상속하여 자식 클래스에게 줄 수 있습니다.

    캡슐화는 프로퍼티와 메서드를 묶어 코드 관리 및 가독성을 높일 수 있습니다.

    추상화는 자세한 구현 정보는 숨기고 일반 인터페이스를 정의하는 것을 의미합니다. 구현 세부 정보만 바꾸면 되기 때문에 코드 관리 및 유지보수가 용이합니다.

    다형성은 상속에서 확장된 개념으로 상속된 객체의 다양한 형태를 의미합니다. 메서드 오버라이딩을 통해서 결과값의 형태는 같지만(?) 다른 구현 방식을 가진 메서드를 정의하여 사용할 수 있습니다.

     

    1-6. 함수형 프로그래밍

    함수형 프로그래밍(Functional Programming)은 프로그래밍 패러다임 중 하나로, 부작용을 최소화하고 상태 변경을 피하는데 초첨을 둡니다. 대신, 순수함수를 통해 입력과 출력 사이의 변환을 일정하게 보장합니다. 따라서 코드의 가독성, 재사용성, 테스트 용이성 등을 향상할 수 있습니다.

    또한 불변성(Immutability)을 강조하며, 원본 데이터의 변경이 아닌 새로운 데이터를 생성하는 방식으로 작업을 수행합니다. 이를 위해, 고차 함수(Higher-Order Function)와 람다식(Lambda Expression)을 활용하여 데이터 처리를 추상화하고 모듈화할 수 있는데, 병렬처리와 분산처리에도 용이하며, 오류를 줄이고 안정성을 높이는데 도움이 됩니다.

     

    1-7. 프레임워크와 라이브러리

    [라이브러리]

    라이브러리는 재사용 가능한 코드의 모음으로 특정 기능을 수행하기 위해 필요할 때 가져다 쓸 수 있습니다. 예를 들어, React에서 사용하는 React-router-dom, axios,styled-components 라이브러리가 있습니다.

    라이브러리의 장점은 개발자가 원하는 대로 애플리케이션을 설계하고 구현할 수 있다는 것입니다. 라이브러리를 사용하는 것은 애플리케이션에 대한 통제권을 가질 수 있으며, 필요한 부분만 추가 하면 되므로 유연성과 성능면에서 유리합니다. 반면에 라이브러리의 단점은 특정 아키텍처를 직접 제작하다 보면 애플리케이션이 복잡해지거나 오류가 발생할 수 있다는 것입니다. 일부 사람들은 자신만의 규칙을 구축하는데 시간과 비용을 들이고 싶지 않기 때문에 프레임워크를 선택합니다.

     

    [프레임워크]

    프레임워크는 애플리케이션의 전체적인 구조와 흐름을 정의하고, 개발자가 그 안에 필요한 코드를 작성하도록 하는 것 입니다. 예를 들어, 프론트엔드 영역에는 Vue.js, Angular.js, Next.js 프레임워크가 있습니다.

    프레임워크의 장점은 개발자가 무엇을 해야 할지 알려주고, 모범 사례와 도구를 제공한다는 것입니다. 프레임워크는 대규모 애플리케이션을 구축하는데 필요한 모든 것들을 제공하고, 개발자가 특정 방식에 따라야 하므로 코드의 품질과 일관성을 보장합니다. 반면에 프레임워크는 단점이 많은 코드를 작성하여 구축된다는 것입니다. 로딩 시간이 길어지고 성능이 저하될 수 있습니다. 또한 프레임워크는 특정 방식에 따라야 하므로, 개발자의 자유도가 제한됩니다.

     

    라이브러리와 프레임워크의 차이점은 제어 반전에 있습니다. 라이브러리를 사용할 때에는 개발자가 애플리케이션 흐름을 직접 설정하고, 라이브러리를 호출합니다. 프레임워크를 사용할 때는 프레임워크가 애플리케이션 흐름을 설정하고, 개발자가 작성한 코드를 호출합니다.

     

    1-8. JavaScript는 싱글 스레드 언어인데, 병렬처리가 가능한 이유

    결론부터 말하자면, JavaScript는 병렬처리를 하지 않습니다. 비동기 함수로 동작을 감싼다고 해서 병렬처리가 되지 않는다. JavaScript의 비동기 함수는 stack가 queue에 입력되어 call stack이 빌 때까지 함수 호출이 지연될 뿐 여전히 직렬처리 됩니다. 병렬처리를 JavaScript로 구현한다면 Promise 객체를 배열로 받는 Promise.all이나 Promise.allSettled을 사용하여 비동기 처리를 통해 병렬 작업을 수행할 수 있다.

     

    JavaScript는 싱글 스레드 언어이다. 이벤트 루프가 메인 스레드로 동작한다. JavaScript 런타임인 웹 브라우저나 Node.js는 멀티 스레드 환경이다. JavaScript를 실행하는 JavaScript Engine은 싱글 스레드로 동작한다. 이벤트 루프는 비동기 작업을 처리하는 데 중요한 역할을 한다. 이벤트 루프는 JavaScript Engine 내부에서 실행되며, 비동기 작업을 관리하고 외부 환경과 상호작용한다.  자바스크립트 엔진 자체는 싱글 스레드이지만, 런타임 환경(웹 브라우저나 Node.js)에서는 멀티 스레드를 활용하여 비동기 작업을 처리합니다.

     

    [이벤트 루프의 주요 역할]

    (1) 이벤트 처리: 이벤트 루프는 이벤트를 감지하고 처리합니다. 예를 들어, 타이머 이벤트, 클릭 이벤트, 네트쿼크 요청 완료 등을 관리합니다.

    (2) 비동기 작업 스케쥴링: 비동기 작업(예: setTimeout, fetch, Promise)은 이벤트 루프를 통해 백그라운드에서 처리됩니다. 이를 통해 메인 스레드는 다른 작업을 수행하면서 비동기 작업이 완료될 때까지 기다리지 않습니다.

    (3) 콜 스택과 큐 관리: 이벤트 루프는 call stack과 task queue를 관리하여 비동기 작업을 순서대로 처리합니다. call stack이 비어있을 때 태스크 큐에서 작업을 가져와 실행합니다.

     

    [비동기 작업]

    비동기 작업(Asynchronous Operations)은 작업이 완료되기를 기다리지 않고 다른 작업을 수행하는 방식입니다. 주로 네트워크 요청, 파일 읽기/쓰기, 타이머 등에서 사용됩니다. 비동기 작업은 이벤트 루프를 통해 백그라운드에서 처리되며, 메인 스레드는 다른 작업을 계속할 수 있습니다.

     

    [병렬처리]

    병렬처리(Parallel Processing)는 크고 복잡한 문제를 작게 나눠 동시에 여러 개의 프로세서나 스레드가 동시에 작업을 병렬적으로 처리하는 방식입니다. 여러 개의 프로세서나 스레드가 동시에 작업을 처리합니다. 병렬 처리는 CPU 연산, 데이터베이스 쿼리, 그래픽 렌더링 등에서 활용됩니다.

     

    요약하자면, 비동기 작업은 순서를 기다리지 않고 다른 작업을 수행하는 것이며, 병렬 처리는 여러 작업을 동시에 실행하여 성능을 향상시키는 것입니다.

     

    [답변]

    1. Web Workers: JavaScript 엔진 외부에서 병렬 처리를 수행하기 위해 Web Workers를 사용합니다. Web Workers는 백그라운드에서 독립적으로 실행되는 스크립트로, 메인 스레드와 별개로 작업을 처리할 수 있습니다.

    2. 이벤트 루프 (Event Loop): JavaScript 엔진은 메모리 할당을 관리하는 heap과 call Stack만 가지고 있습니다. 병렬 처리를 위해 이벤트 루프를 사용하여 JavaScript 엔진과 외부 환경(브라우저나 Node.js의 백그라운드)을 연동합니다.

     

     

    1-9. CS 지식을 프로젝트에 적용해본 경험

    대량의 데이터를 분산하고 병렬 처리하는 프로젝트에 참여한 적이 있습니다.

    postgreSQL을 사용하여 33만건의 문서 데이터를 DB화하는 작업이 있었습니다. 이때 대량의 데이터 쓰기 작업에 최적화된 방식인 라운드 로빈(Round Robin) 방식으로 데이터를 분산 처리하는 옵션을 적용했습니다. 라운드 로빈은 데이터를 무작위로 여러 파티션으로 나누고 순환하며 각 파티션을 병렬로 처리(저장)하는 방식입니다. 이를 통해 데이터를 효율적으로 분산시킬 수 있습니다. 참고로 읽기 작업에서는 데이터를 무자가위로 가져오는 것이 아니기 때문에 읽기 성능에는 영향을 미치지 않습니다.

     

    2. 인성 면접


    2-1. 본인보다 어린 사람이 상사인 상황에서 잘 일할 수 있나요?

    실력위주이며, 상사라면 그에 걸맞은 실력을 가지고 있을 것이라고 생각합니다. 또한 저보다 나이가 많고 적은 사람들과 프로젝트를 수행한 경험을 충분히 가지고 있으면 문제가 없었습니다. 충분히 존중하고 발전적인 관계를 유지하며 프로젝트를 수행할 수 있다고 생각합니다.

     

    2-2. 시간이 부족한 상황에서 효율적으로 작업하기 위한 전략은 무엇인가요?

    팀 컨벤션과 정기정이고 길지 않은 시간의 데일리 스크럽이라고 생각합니다. 각자 맡은 역할을 빠르게 수행하는 것도 중요하지만, 추후 크리티컬한 오류나 문제가 발생하지 않는 코드를 작성하는 것이 중요하다고 생각합니다. 잦은 커뮤니케이션은 중복 코드를 줄이고, 개발 방향을 합의하는 시간이라고 생각합니다.

    제가 프로젝트에 적용해보진 못했지만, CI/CD를 적용하면 처음엔 설정이나 테스팅에 어려움이 있지만 추후 생산성이 향상되는 것으로 알고 있습니다.

     

     

    출처 1. 눈떠보니 기술 면접 전날 - Ridi Books

    출처 2. 자바스크립트는 어떻게 병렬처리를 할까? - Medium, Jaedeok Kim

Designed by Tistory.