From 81f5975e0fe7a796ec3a26425ccc0a9aea22ec60 Mon Sep 17 00:00:00 2001 From: Jaeho Date: Thu, 4 Jun 2026 00:04:56 +0900 Subject: [PATCH] =?UTF-8?q?chore=20:=20=EB=A9=B4=EC=A0=91=20=EC=A0=95?= =?UTF-8?q?=EC=A0=81=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/backend-interview-questions.json | 3013 +++++++++++++++ .../public/data/cs_interview_questions.json | 3077 ++++++++++++++++ .../data/frontend-interview-questions.json | 3265 +++++++++++++++++ 3 files changed, 9355 insertions(+) create mode 100644 frontend/public/data/backend-interview-questions.json create mode 100644 frontend/public/data/cs_interview_questions.json create mode 100644 frontend/public/data/frontend-interview-questions.json diff --git a/frontend/public/data/backend-interview-questions.json b/frontend/public/data/backend-interview-questions.json new file mode 100644 index 00000000..179c9304 --- /dev/null +++ b/frontend/public/data/backend-interview-questions.json @@ -0,0 +1,3013 @@ +{ + "version": "1.0", + "title": "백엔드 개발자 CS 면접 대비 질문 모음", + "description": "서버 없이 인앱(local) JSON으로 사용하기 위한 백엔드 개발자 기술 면접 대비 질문 모음입니다. 컴퓨터구조, 운영체제, 네트워크, 데이터베이스, 자료구조, 알고리즘, 객체지향, 디자인 패턴, 자바, 스프링, 웹/API, 보안 분야를 1depth 카테고리로 구성했습니다.", + "subjects": [ + { + "id": "computer-architecture", + "name": "컴퓨터구조", + "categories": [ + { + "id": "ca-number", + "name": "수의 표현과 연산", + "questions": [ + { + "id": "ca-number-001", + "question": "컴퓨터에서 데이터를 표현하는 최소 단위는 무엇인가요?", + "answer": "비트(bit)입니다. 0 또는 1 두 가지 값만 가지며, 8개가 모이면 1바이트(byte)가 됩니다. 컴퓨터의 모든 데이터는 결국 비트의 조합으로 표현됩니다." + }, + { + "id": "ca-number-002", + "question": "컴퓨터에서 음수를 표현하는 방법에는 어떤 것들이 있나요?", + "answer": "부호-크기 표현, 1의 보수, 2의 보수 방식이 있습니다. 현대 컴퓨터는 대부분 2의 보수를 사용하는데, 0의 표현이 유일하고 덧셈 회로만으로 뺄셈을 처리할 수 있기 때문입니다." + }, + { + "id": "ca-number-003", + "question": "2의 보수를 사용하는 이유는 무엇인가요?", + "answer": "0을 표현하는 방법이 하나뿐이라 모호함이 없고, 뺄셈을 덧셈으로 처리할 수 있어 가산기 회로만으로 연산이 가능합니다. 그 결과 하드웨어 설계가 단순해집니다." + }, + { + "id": "ca-number-004", + "question": "1의 보수와 2의 보수의 차이는 무엇인가요?", + "answer": "1의 보수는 모든 비트를 반전한 값이고, 2의 보수는 1의 보수에 1을 더한 값입니다. 1의 보수는 +0과 -0이 따로 존재하는 단점이 있어 2의 보수가 주로 쓰입니다." + }, + { + "id": "ca-number-005", + "question": "고정소수점과 부동소수점의 차이는 무엇인가요?", + "answer": "고정소수점은 소수점 위치가 고정되어 표현 범위가 좁지만 연산이 빠릅니다. 부동소수점은 가수와 지수로 나눠 표현해 매우 넓은 범위를 다룰 수 있지만 오차가 발생할 수 있습니다." + }, + { + "id": "ca-number-006", + "question": "부동소수점 연산에서 오차가 발생하는 이유는 무엇인가요?", + "answer": "0.1 같은 10진 소수를 2진수로 정확히 표현할 수 없고, 유한한 비트로 근사하기 때문입니다. 그래서 0.1 + 0.2가 정확히 0.3이 되지 않는 현상이 나타납니다." + }, + { + "id": "ca-number-007", + "question": "IEEE 754 표준이란 무엇인가요?", + "answer": "부동소수점 수를 표현하는 국제 표준입니다. 부호 비트, 지수부, 가수부로 구성되며, float은 32비트, double은 64비트를 사용합니다." + }, + { + "id": "ca-number-008", + "question": "오버플로우란 무엇인가요?", + "answer": "연산 결과가 자료형이 표현할 수 있는 범위를 넘어서면서 값이 잘못 표현되는 현상입니다. 예를 들어 int 최댓값에 1을 더하면 음수가 되는 경우가 있습니다." + }, + { + "id": "ca-number-009", + "question": "빅엔디안과 리틀엔디안의 차이는 무엇인가요?", + "answer": "여러 바이트를 메모리에 저장하는 순서의 차이입니다. 빅엔디안은 최상위 바이트부터, 리틀엔디안은 최하위 바이트부터 저장하며, 네트워크 전송에는 빅엔디안을 사용합니다." + }, + { + "id": "ca-number-010", + "question": "ASCII와 유니코드의 차이는 무엇인가요?", + "answer": "ASCII는 7비트로 영문과 기호 위주를 표현하고, 유니코드는 전 세계 문자를 표현하기 위한 표준입니다. UTF-8은 유니코드를 가변 길이로 인코딩하는 대표적 방식입니다." + }, + { + "id": "ca-number-011", + "question": "비트 연산을 사용하면 어떤 이점이 있나요?", + "answer": "연산이 매우 빠르고, 여러 상태를 하나의 정수에 플래그로 관리할 수 있으며 메모리를 절약합니다. 2의 거듭제곱 곱셈과 나눗셈을 시프트 연산으로 빠르게 처리할 수도 있습니다." + } + ] + }, + { + "id": "ca-cpu", + "name": "CPU와 명령어", + "questions": [ + { + "id": "ca-cpu-001", + "question": "CPU의 핵심 구성 요소는 무엇인가요?", + "answer": "산술논리연산장치(ALU), 제어장치(CU), 레지스터로 구성됩니다. ALU는 연산을 수행하고, 제어장치는 명령어를 해석해 동작을 지시하며, 레지스터는 데이터를 임시 저장합니다." + }, + { + "id": "ca-cpu-002", + "question": "레지스터에는 어떤 종류가 있나요?", + "answer": "다음 명령어 주소를 담는 프로그램 카운터(PC), 현재 명령어를 담는 명령어 레지스터(IR), 메모리 주소 레지스터(MAR), 메모리 버퍼 레지스터(MBR), 누산기 등이 있습니다." + }, + { + "id": "ca-cpu-003", + "question": "명령어 사이클이란 무엇인가요?", + "answer": "CPU가 하나의 명령어를 처리하는 과정으로 인출, 해석, 실행 단계로 이루어집니다. 필요에 따라 메모리 접근과 결과 저장 단계가 추가되며 이 과정이 반복됩니다." + }, + { + "id": "ca-cpu-004", + "question": "인터럽트란 무엇인가요?", + "answer": "CPU가 작업을 수행하는 도중 긴급하게 처리해야 할 상황을 알리는 신호입니다. 인터럽트가 발생하면 현재 작업을 잠시 멈추고 인터럽트 서비스 루틴을 실행한 뒤 복귀합니다." + }, + { + "id": "ca-cpu-005", + "question": "프로그램 카운터(PC)의 역할은 무엇인가요?", + "answer": "다음에 실행할 명령어의 메모리 주소를 저장하는 레지스터입니다. 명령어가 인출될 때마다 자동으로 증가하며, 분기 명령에서는 목적지 주소로 변경됩니다." + }, + { + "id": "ca-cpu-006", + "question": "파이프라이닝이란 무엇인가요?", + "answer": "명령어 처리를 여러 단계로 나누고, 서로 다른 명령어의 단계를 동시에 겹쳐 처리해 처리량을 높이는 기법입니다. 공장의 컨베이어 벨트처럼 작동합니다." + }, + { + "id": "ca-cpu-007", + "question": "파이프라인 해저드란 무엇인가요?", + "answer": "파이프라인이 정상적으로 동작하지 못하게 만드는 요인입니다. 데이터 의존성으로 인한 데이터 해저드, 분기로 인한 제어 해저드, 자원 충돌로 인한 구조 해저드가 있습니다." + }, + { + "id": "ca-cpu-008", + "question": "CISC와 RISC의 차이는 무엇인가요?", + "answer": "CISC는 복잡하고 다양한 길이의 명령어를 적은 수로 제공하고, RISC는 단순하고 고정 길이인 명령어를 많이 제공합니다. RISC는 파이프라이닝에 유리해 모바일 칩 등에 많이 쓰입니다." + }, + { + "id": "ca-cpu-009", + "question": "클럭(clock)이란 무엇인가요?", + "answer": "CPU 내부 동작의 박자를 맞추는 주기적인 신호입니다. 클럭 속도(㎓)가 높을수록 단위 시간당 더 많은 명령을 처리할 수 있지만 발열도 함께 증가합니다." + }, + { + "id": "ca-cpu-010", + "question": "멀티코어와 하이퍼스레딩의 차이는 무엇인가요?", + "answer": "멀티코어는 물리적인 연산 코어를 여러 개 두는 것이고, 하이퍼스레딩은 하나의 코어를 논리적으로 둘처럼 보이게 해 유휴 자원을 활용하는 기술입니다." + }, + { + "id": "ca-cpu-011", + "question": "무어의 법칙이란 무엇인가요?", + "answer": "반도체 칩에 집적되는 트랜지스터 수가 약 2년마다 두 배로 증가한다는 경험적 법칙입니다. 최근에는 물리적 한계로 인해 그 속도가 둔화되고 있습니다." + } + ] + }, + { + "id": "ca-memory", + "name": "메모리와 캐시", + "questions": [ + { + "id": "ca-memory-001", + "question": "메모리 계층 구조란 무엇인가요?", + "answer": "속도, 비용, 용량의 트레이드오프에 따라 레지스터, 캐시, 주기억장치, 보조기억장치를 계층적으로 배치한 구조입니다. 위로 갈수록 빠르고 비싸며 용량이 작습니다." + }, + { + "id": "ca-memory-002", + "question": "캐시 메모리의 목적은 무엇인가요?", + "answer": "CPU와 주기억장치 사이의 속도 차이를 완화하기 위함입니다. 자주 사용하는 데이터를 CPU 가까이에 미리 저장해 메모리 접근 시간을 줄입니다." + }, + { + "id": "ca-memory-003", + "question": "지역성(locality)이란 무엇인가요?", + "answer": "프로그램이 데이터를 접근하는 경향성입니다. 최근에 쓴 데이터를 다시 쓰는 시간 지역성과, 인접한 데이터를 함께 쓰는 공간 지역성이 있으며 캐시 효율의 근거가 됩니다." + }, + { + "id": "ca-memory-004", + "question": "캐시 히트와 캐시 미스란 무엇인가요?", + "answer": "CPU가 원하는 데이터가 캐시에 있으면 캐시 히트, 없어서 하위 메모리에서 가져와야 하면 캐시 미스라고 합니다. 히트율이 높을수록 성능이 좋습니다." + }, + { + "id": "ca-memory-005", + "question": "캐시 쓰기 정책에는 어떤 것이 있나요?", + "answer": "데이터 변경 시 즉시 메모리에 반영하는 write-through와, 캐시에만 쓰고 나중에 한꺼번에 반영하는 write-back이 있습니다. write-back이 빠르지만 일관성 관리가 필요합니다." + }, + { + "id": "ca-memory-006", + "question": "RAM과 ROM의 차이는 무엇인가요?", + "answer": "RAM은 전원이 꺼지면 내용이 사라지는 휘발성 메모리로 읽기와 쓰기가 자유롭습니다. ROM은 전원이 꺼져도 유지되는 비휘발성 메모리로 주로 읽기 용도로 사용됩니다." + }, + { + "id": "ca-memory-007", + "question": "SRAM과 DRAM의 차이는 무엇인가요?", + "answer": "SRAM은 빠르지만 비싸서 캐시에 사용하고, DRAM은 느리고 저렴하며 주기적인 리프레시가 필요해 주기억장치에 사용합니다." + }, + { + "id": "ca-memory-008", + "question": "캐시 매핑 방식에는 어떤 것들이 있나요?", + "answer": "주소를 고정 위치에 대응시키는 직접 매핑, 어디든 저장 가능한 완전 연관 매핑, 둘을 절충한 집합 연관 매핑이 있습니다. 대부분 집합 연관 방식을 사용합니다." + }, + { + "id": "ca-memory-009", + "question": "메모리 단편화란 무엇인가요?", + "answer": "사용 가능한 메모리가 작은 조각으로 나뉘어 실제로는 충분해도 할당하지 못하는 현상입니다. 할당 블록 내부의 내부 단편화와 블록 사이의 외부 단편화가 있습니다." + }, + { + "id": "ca-memory-010", + "question": "버퍼와 캐시의 차이는 무엇인가요?", + "answer": "버퍼는 속도 차이가 나는 두 장치 사이에서 데이터를 임시로 모아두는 공간이고, 캐시는 자주 쓰는 데이터를 재사용하기 위해 저장하는 공간입니다." + } + ] + }, + { + "id": "ca-io", + "name": "입출력과 시스템 버스", + "questions": [ + { + "id": "ca-io-001", + "question": "입출력 방식에는 어떤 것들이 있나요?", + "answer": "CPU가 직접 제어하는 프로그램 I/O, 장치가 신호를 보내는 인터럽트 기반 I/O, CPU 없이 직접 메모리에 접근하는 DMA 방식이 있습니다." + }, + { + "id": "ca-io-002", + "question": "DMA란 무엇인가요?", + "answer": "Direct Memory Access의 약자로, CPU의 개입 없이 입출력 장치가 메모리에 직접 접근해 데이터를 전송하는 방식입니다. 대량 전송 시 CPU 부담을 크게 줄여 줍니다." + }, + { + "id": "ca-io-003", + "question": "폴링과 인터럽트의 차이는 무엇인가요?", + "answer": "폴링은 CPU가 주기적으로 장치 상태를 직접 확인하는 방식이고, 인터럽트는 장치가 준비되면 CPU에 신호를 보내는 방식입니다. 인터럽트가 CPU 자원을 더 효율적으로 사용합니다." + }, + { + "id": "ca-io-004", + "question": "버스(bus)란 무엇인가요?", + "answer": "컴퓨터 구성 요소 사이에서 데이터를 주고받는 통로입니다. 데이터를 전송하는 데이터 버스, 주소를 전달하는 주소 버스, 제어 신호를 전달하는 제어 버스로 나뉩니다." + }, + { + "id": "ca-io-005", + "question": "인터럽트 처리 과정은 어떻게 되나요?", + "answer": "인터럽트가 발생하면 현재 작업 상태를 저장하고, 해당 인터럽트 서비스 루틴을 실행한 뒤, 저장한 상태를 복원해 원래 작업으로 돌아갑니다." + }, + { + "id": "ca-io-006", + "question": "메모리 맵 I/O란 무엇인가요?", + "answer": "입출력 장치의 레지스터를 메모리 주소 공간의 일부에 매핑해, 메모리에 접근하듯 동일한 명령어로 장치를 제어하는 방식입니다." + }, + { + "id": "ca-io-007", + "question": "하드웨어 인터럽트와 소프트웨어 인터럽트의 차이는 무엇인가요?", + "answer": "하드웨어 인터럽트는 입출력 장치 등 외부 하드웨어에서 발생하고, 소프트웨어 인터럽트는 프로그램이 명령어로 의도적으로 발생시킵니다. 시스템 콜이 대표적인 소프트웨어 인터럽트입니다." + }, + { + "id": "ca-io-008", + "question": "입출력 버스를 시스템 버스와 분리하는 이유는 무엇인가요?", + "answer": "장치마다 속도가 크게 다른데 이를 흡수하고, 시스템 확장과 장치 추가를 쉽게 하기 위함입니다. 구조를 모듈화해 유지보수성도 높아집니다." + }, + { + "id": "ca-io-009", + "question": "컴퓨터의 5대 구성 요소는 무엇인가요?", + "answer": "연산을 담당하는 제어장치와 연산장치(CPU), 데이터를 저장하는 기억장치, 그리고 데이터를 받아들이는 입력장치와 내보내는 출력장치로 구성됩니다." + }, + { + "id": "ca-io-010", + "question": "폰 노이만 구조의 특징은 무엇인가요?", + "answer": "프로그램과 데이터를 같은 메모리에 저장하고 하나의 버스로 처리하는 구조입니다. 구조가 단순하지만 명령어와 데이터가 같은 통로를 쓰므로 병목이 생기는 한계가 있습니다." + } + ] + } + ] + }, + { + "id": "operating-system", + "name": "운영체제", + "categories": [ + { + "id": "os-process", + "name": "프로세스와 스레드", + "questions": [ + { + "id": "os-process-001", + "question": "프로세스와 스레드의 차이는 무엇인가요?", + "answer": "프로세스는 실행 중인 프로그램으로 독립된 메모리 공간을 가집니다. 스레드는 프로세스 내 실행 흐름의 단위로, 같은 프로세스의 스레드들은 코드와 데이터, 힙 영역을 공유합니다." + }, + { + "id": "os-process-002", + "question": "프로세스의 메모리 구조는 어떻게 구성되나요?", + "answer": "코드 영역, 전역 변수가 저장되는 데이터 영역, 동적 할당이 일어나는 힙 영역, 함수 호출과 지역 변수를 위한 스택 영역으로 구성됩니다." + }, + { + "id": "os-process-003", + "question": "PCB란 무엇인가요?", + "answer": "Process Control Block의 약자로, 운영체제가 프로세스를 관리하기 위해 필요한 정보를 담은 자료구조입니다. 프로세스 상태, PC, 레지스터 값, 우선순위 등이 들어 있습니다." + }, + { + "id": "os-process-004", + "question": "컨텍스트 스위칭이란 무엇인가요?", + "answer": "CPU가 실행하던 프로세스를 멈추고 다른 프로세스로 전환하는 과정입니다. 현재 프로세스의 상태를 PCB에 저장하고 다음 프로세스의 상태를 불러오며, 잦으면 오버헤드가 됩니다." + }, + { + "id": "os-process-005", + "question": "프로세스 상태에는 어떤 것들이 있나요?", + "answer": "생성, 실행 준비가 된 준비 상태, CPU를 점유한 실행 상태, 이벤트를 기다리는 대기 상태, 종료 상태가 있습니다. 스케줄러가 이 상태들 사이의 전이를 관리합니다." + }, + { + "id": "os-process-006", + "question": "멀티프로세스와 멀티스레드의 차이는 무엇인가요?", + "answer": "멀티프로세스는 여러 프로세스로 작업을 처리해 안정적이지만 메모리와 컨텍스트 스위칭 비용이 큽니다. 멀티스레드는 자원을 공유해 효율적이지만 한 스레드 오류가 전체에 영향을 줄 수 있습니다." + }, + { + "id": "os-process-007", + "question": "스레드가 프로세스보다 컨텍스트 스위칭이 빠른 이유는 무엇인가요?", + "answer": "같은 프로세스의 스레드는 메모리 공간을 공유하므로 전환 시 메모리 맵을 바꿀 필요가 없습니다. 스택과 레지스터 등 일부만 교체하면 되어 비용이 적습니다." + }, + { + "id": "os-process-008", + "question": "IPC(프로세스 간 통신)란 무엇인가요?", + "answer": "독립된 메모리를 가진 프로세스들이 데이터를 주고받는 방법입니다. 파이프, 메시지 큐, 공유 메모리, 소켓, 시그널 등의 방식이 있습니다." + }, + { + "id": "os-process-009", + "question": "좀비 프로세스와 고아 프로세스의 차이는 무엇인가요?", + "answer": "좀비 프로세스는 실행을 마쳤지만 부모가 종료 상태를 회수하지 않아 남아 있는 프로세스이고, 고아 프로세스는 부모가 먼저 종료되어 버린 자식 프로세스입니다." + }, + { + "id": "os-process-010", + "question": "fork와 exec의 차이는 무엇인가요?", + "answer": "fork는 현재 프로세스를 복제해 자식 프로세스를 만드는 시스템 콜이고, exec는 현재 프로세스의 메모리를 새로운 프로그램으로 덮어쓰는 시스템 콜입니다." + }, + { + "id": "os-process-011", + "question": "좀비 프로세스란 무엇인가요?", + "answer": "실행을 마쳤지만 부모가 종료 상태를 회수하지 않아 프로세스 테이블에 남아 있는 프로세스입니다. 부모가 wait로 자식의 상태를 거둬야 정리됩니다." + }, + { + "id": "os-process-012", + "question": "고아 프로세스란 무엇인가요?", + "answer": "부모가 먼저 종료되어 부모가 없어진 자식 프로세스입니다. 보통 init 같은 최상위 프로세스가 입양해 관리합니다." + }, + { + "id": "os-process-013", + "question": "컨텍스트 스위칭이란 무엇인가요?", + "answer": "실행 중인 프로세스나 스레드를 바꾸기 위해 현재 상태를 저장하고 다음 작업의 상태를 복원하는 과정입니다. 잦으면 오버헤드가 커집니다." + }, + { + "id": "os-process-014", + "question": "PCB란 무엇인가요?", + "answer": "운영체제가 프로세스를 관리하기 위해 유지하는 자료구조입니다. 프로세스 상태, 레지스터, 스케줄링 정보 등을 담고 컨텍스트 스위칭 시 사용됩니다." + } + ] + }, + { + "id": "os-scheduling", + "name": "CPU 스케줄링", + "questions": [ + { + "id": "os-scheduling-001", + "question": "CPU 스케줄링이란 무엇인가요?", + "answer": "여러 프로세스가 CPU를 사용하려 할 때 어떤 프로세스에 CPU를 할당할지 결정하는 일입니다. 처리량, 응답 시간, 공정성 등을 고려해 효율을 높이는 것이 목표입니다." + }, + { + "id": "os-scheduling-002", + "question": "선점형과 비선점형 스케줄링의 차이는 무엇인가요?", + "answer": "선점형은 실행 중인 프로세스의 CPU를 강제로 빼앗을 수 있는 방식이고, 비선점형은 프로세스가 스스로 CPU를 반납할 때까지 기다리는 방식입니다." + }, + { + "id": "os-scheduling-003", + "question": "FCFS 스케줄링이란 무엇인가요?", + "answer": "First Come First Served의 약자로, 도착한 순서대로 처리하는 비선점 방식입니다. 구현이 단순하지만 긴 작업이 앞에 있으면 뒤 작업이 오래 기다리는 호위 효과가 발생합니다." + }, + { + "id": "os-scheduling-004", + "question": "SJF 스케줄링이란 무엇인가요?", + "answer": "Shortest Job First로, 실행 시간이 가장 짧은 작업을 먼저 처리하는 방식입니다. 평균 대기 시간이 최소가 되지만 실행 시간을 미리 알기 어렵고 긴 작업이 계속 밀릴 수 있습니다." + }, + { + "id": "os-scheduling-005", + "question": "라운드 로빈 스케줄링이란 무엇인가요?", + "answer": "각 프로세스에 동일한 시간 할당량(타임 슬라이스)을 주고 돌아가며 처리하는 선점형 방식입니다. 응답성이 좋아 시분할 시스템에 적합합니다." + }, + { + "id": "os-scheduling-006", + "question": "우선순위 스케줄링의 문제점과 해결책은 무엇인가요?", + "answer": "우선순위가 낮은 프로세스가 계속 밀리는 기아 현상이 발생할 수 있습니다. 이를 해결하기 위해 대기 시간이 길어질수록 우선순위를 높여 주는 에이징 기법을 사용합니다." + }, + { + "id": "os-scheduling-007", + "question": "기아 상태(starvation)란 무엇인가요?", + "answer": "특정 프로세스가 자원을 계속 할당받지 못해 무한정 대기하는 상태입니다. 우선순위가 낮은 프로세스에서 주로 발생하며, 에이징으로 완화할 수 있습니다." + }, + { + "id": "os-scheduling-008", + "question": "처리량과 응답 시간의 차이는 무엇인가요?", + "answer": "처리량은 단위 시간당 완료한 작업의 수이고, 응답 시간은 요청 후 첫 반응이 오기까지 걸리는 시간입니다. 두 지표는 종종 트레이드오프 관계에 있습니다." + }, + { + "id": "os-scheduling-009", + "question": "다단계 큐 스케줄링이란 무엇인가요?", + "answer": "프로세스를 성격에 따라 여러 개의 큐로 나누고, 각 큐마다 다른 스케줄링 정책을 적용하는 방식입니다. 다단계 피드백 큐는 큐 간 이동까지 허용합니다." + }, + { + "id": "os-scheduling-010", + "question": "디스패처란 무엇인가요?", + "answer": "스케줄러가 선택한 프로세스에게 실제로 CPU 제어권을 넘겨주는 모듈입니다. 컨텍스트 스위칭, 사용자 모드 전환, 적절한 위치로의 점프를 수행합니다." + } + ] + }, + { + "id": "os-sync", + "name": "프로세스 동기화", + "questions": [ + { + "id": "os-sync-001", + "question": "경쟁 상태(race condition)란 무엇인가요?", + "answer": "둘 이상의 프로세스나 스레드가 공유 자원에 동시에 접근할 때 실행 순서에 따라 결과가 달라지는 상황입니다. 동기화로 접근을 제어해 막아야 합니다." + }, + { + "id": "os-sync-002", + "question": "임계 영역(critical section)이란 무엇인가요?", + "answer": "공유 자원에 접근하는 코드 영역으로, 한 번에 하나의 프로세스만 진입해야 하는 구간입니다. 상호 배제, 진행, 한정 대기 조건을 만족해야 합니다." + }, + { + "id": "os-sync-003", + "question": "뮤텍스와 세마포어의 차이는 무엇인가요?", + "answer": "뮤텍스는 하나의 자원에 대한 잠금으로 소유 개념이 있어 잠근 주체만 풀 수 있습니다. 세마포어는 정수 카운터로 여러 자원을 관리하며 소유 개념이 없습니다." + }, + { + "id": "os-sync-004", + "question": "세마포어의 wait와 signal 연산은 무엇인가요?", + "answer": "wait(P)는 카운터를 감소시키고 0보다 작으면 대기하며, signal(V)은 카운터를 증가시키고 대기 중인 프로세스를 깨웁니다. 이를 통해 자원 접근을 제어합니다." + }, + { + "id": "os-sync-005", + "question": "바이너리 세마포어와 뮤텍스의 차이는 무엇인가요?", + "answer": "값이 0과 1만 갖는 바이너리 세마포어는 뮤텍스와 비슷하지만, 뮤텍스는 잠근 스레드만 해제할 수 있다는 소유권 개념이 있다는 점에서 다릅니다." + }, + { + "id": "os-sync-006", + "question": "모니터란 무엇인가요?", + "answer": "공유 자원과 그 접근 함수를 하나로 묶어 자동으로 상호 배제를 보장하는 고수준 동기화 도구입니다. 자바의 synchronized가 모니터 개념을 사용합니다." + }, + { + "id": "os-sync-007", + "question": "스핀락이란 무엇인가요?", + "answer": "락을 얻을 때까지 대기 상태로 전환하지 않고 계속 확인하며 도는 방식의 락입니다. 대기 시간이 짧을 때는 효율적이지만 길어지면 CPU를 낭비합니다." + }, + { + "id": "os-sync-008", + "question": "데드락(교착 상태)이란 무엇인가요?", + "answer": "둘 이상의 프로세스가 서로 상대방이 가진 자원을 기다리며 무한정 대기하는 상태입니다. 상호 배제, 점유 대기, 비선점, 순환 대기 네 조건이 모두 충족되면 발생합니다." + }, + { + "id": "os-sync-009", + "question": "생산자-소비자 문제란 무엇인가요?", + "answer": "데이터를 생성하는 생산자와 소비하는 소비자가 유한한 버퍼를 공유할 때 발생하는 동기화 문제입니다. 버퍼가 가득 차거나 비었을 때의 동기화가 핵심입니다." + }, + { + "id": "os-sync-010", + "question": "원자적 연산(atomic operation)이란 무엇인가요?", + "answer": "중간에 끼어들 수 없이 한 번에 수행되는 연산입니다. 실행이 끝까지 완료되거나 아예 일어나지 않는 두 가지 상태만 존재해 동기화 문제를 방지합니다." + } + ] + }, + { + "id": "os-memory", + "name": "메모리 관리", + "questions": [ + { + "id": "os-memory-001", + "question": "스택과 힙의 차이는 무엇인가요?", + "answer": "스택은 함수 호출과 지역 변수를 저장하며 컴파일 타임에 크기가 정해지고 자동으로 관리됩니다. 힙은 런타임에 동적 할당되는 영역으로 개발자나 가비지 컬렉터가 관리합니다." + }, + { + "id": "os-memory-002", + "question": "페이징이란 무엇인가요?", + "answer": "메모리를 고정 크기의 페이지 단위로 나누어 관리하는 기법입니다. 물리 메모리의 비연속적인 공간에도 할당할 수 있어 외부 단편화를 해결합니다." + }, + { + "id": "os-memory-003", + "question": "세그멘테이션이란 무엇인가요?", + "answer": "프로그램을 코드, 데이터, 스택 같은 논리적 의미 단위인 세그먼트로 나누어 관리하는 기법입니다. 크기가 가변적이어서 외부 단편화가 발생할 수 있습니다." + }, + { + "id": "os-memory-004", + "question": "내부 단편화와 외부 단편화의 차이는 무엇인가요?", + "answer": "내부 단편화는 할당된 공간이 실제 사용량보다 커서 내부에 빈 공간이 남는 것이고, 외부 단편화는 빈 공간이 흩어져 있어 충분한데도 연속 할당을 못 하는 것입니다." + }, + { + "id": "os-memory-005", + "question": "페이지 테이블이란 무엇인가요?", + "answer": "가상 주소의 페이지 번호를 물리 메모리의 프레임 번호로 변환하는 매핑 정보를 담은 테이블입니다. 프로세스마다 하나씩 가지며 주소 변환에 사용됩니다." + }, + { + "id": "os-memory-006", + "question": "TLB란 무엇인가요?", + "answer": "Translation Lookaside Buffer로, 페이지 테이블 조회 결과를 캐싱하는 하드웨어입니다. 주소 변환 시 메모리 접근을 줄여 속도를 크게 높여 줍니다." + }, + { + "id": "os-memory-007", + "question": "메모리 할당 알고리즘에는 어떤 것들이 있나요?", + "answer": "처음 만난 빈 공간에 할당하는 최초 적합, 가장 작은 적당한 공간에 할당하는 최적 적합, 가장 큰 공간에 할당하는 최악 적합이 있습니다." + }, + { + "id": "os-memory-008", + "question": "스왑(swap)이란 무엇인가요?", + "answer": "메모리가 부족할 때 당장 쓰지 않는 데이터를 디스크의 스왑 공간으로 내보내고, 필요할 때 다시 메모리로 불러오는 기법입니다. 메모리 부족을 보완하지만 속도가 느려집니다." + }, + { + "id": "os-memory-009", + "question": "메모리 누수(memory leak)란 무엇인가요?", + "answer": "더 이상 사용하지 않는 메모리를 해제하지 않아 계속 점유하는 현상입니다. 누적되면 메모리가 고갈되어 성능 저하나 프로그램 종료로 이어집니다." + }, + { + "id": "os-memory-010", + "question": "단편화를 해결하는 방법에는 무엇이 있나요?", + "answer": "흩어진 빈 공간을 한쪽으로 모으는 압축(컴팩션), 비연속 할당을 가능하게 하는 페이징, 메모리를 2의 거듭제곱 크기로 관리하는 버디 시스템 등이 있습니다." + }, + { + "id": "os-memory-011", + "question": "내부 단편화와 외부 단편화의 차이는 무엇인가요?", + "answer": "내부 단편화는 할당된 공간 안에서 남는 메모리이고, 외부 단편화는 빈 공간이 흩어져 충분한 연속 공간을 못 만드는 경우입니다." + }, + { + "id": "os-memory-012", + "question": "페이징과 세그멘테이션의 차이는 무엇인가요?", + "answer": "페이징은 메모리를 고정 크기로 나눠 외부 단편화를 없애고, 세그멘테이션은 논리 단위로 나눠 의미는 살리지만 외부 단편화가 생길 수 있습니다." + } + ] + }, + { + "id": "os-vm", + "name": "가상 메모리", + "questions": [ + { + "id": "os-vm-001", + "question": "가상 메모리란 무엇인가요?", + "answer": "물리 메모리보다 큰 주소 공간을 프로그램에 제공하는 기법입니다. 실제로 필요한 부분만 메모리에 올리고 나머지는 디스크에 두어 메모리를 효율적으로 사용합니다." + }, + { + "id": "os-vm-002", + "question": "요구 페이징이란 무엇인가요?", + "answer": "프로세스 실행에 실제로 필요한 페이지만 메모리에 적재하는 방식입니다. 미리 모든 페이지를 올리지 않아 메모리를 절약하고 초기 적재 시간을 줄입니다." + }, + { + "id": "os-vm-003", + "question": "페이지 폴트란 무엇인가요?", + "answer": "접근하려는 페이지가 물리 메모리에 없을 때 발생하는 인터럽트입니다. 운영체제가 디스크에서 해당 페이지를 메모리로 가져온 뒤 명령을 재실행합니다." + }, + { + "id": "os-vm-004", + "question": "페이지 교체 알고리즘에는 어떤 것들이 있나요?", + "answer": "가장 오래된 페이지를 교체하는 FIFO, 앞으로 가장 늦게 쓸 페이지를 교체하는 최적(OPT), 가장 오래 사용되지 않은 페이지를 교체하는 LRU 등이 있습니다." + }, + { + "id": "os-vm-005", + "question": "LRU 알고리즘이란 무엇인가요?", + "answer": "Least Recently Used로, 가장 오랫동안 사용되지 않은 페이지를 교체하는 알고리즘입니다. 시간 지역성을 활용해 성능이 좋지만 구현 비용이 다소 큽니다." + }, + { + "id": "os-vm-006", + "question": "스래싱(thrashing)이란 무엇인가요?", + "answer": "페이지 교체가 지나치게 자주 일어나 CPU가 실제 작업보다 페이지 처리에 더 많은 시간을 쓰는 현상입니다. 다중 프로그래밍 정도가 과도할 때 발생합니다." + }, + { + "id": "os-vm-007", + "question": "워킹셋(working set)이란 무엇인가요?", + "answer": "프로세스가 특정 시간 동안 실제로 참조하는 페이지 집합입니다. 이 집합을 메모리에 유지하면 페이지 폴트를 줄이고 스래싱을 방지할 수 있습니다." + }, + { + "id": "os-vm-008", + "question": "벨라디의 모순(Belady's anomaly)이란 무엇인가요?", + "answer": "프레임 수를 늘렸는데도 페이지 폴트가 오히려 증가하는 현상입니다. FIFO 알고리즘에서 나타날 수 있으며, LRU 같은 스택 알고리즘에서는 발생하지 않습니다." + }, + { + "id": "os-vm-009", + "question": "지역성이 가상 메모리 성능에 미치는 영향은 무엇인가요?", + "answer": "지역성이 높으면 자주 쓰는 페이지가 메모리에 머물러 페이지 폴트가 줄어듭니다. 그래서 LRU 같은 알고리즘이 효과적이고 스래싱도 줄어듭니다." + }, + { + "id": "os-vm-010", + "question": "메모리 매핑 파일이란 무엇인가요?", + "answer": "파일을 프로세스의 가상 주소 공간에 매핑해 메모리에 접근하듯 파일을 읽고 쓰는 기법입니다. 입출력 시스템 콜 호출을 줄여 성능을 높일 수 있습니다." + } + ] + }, + { + "id": "os-deadlock", + "name": "교착 상태와 부팅", + "questions": [ + { + "id": "os-deadlock-001", + "question": "교착 상태가 발생하는 네 가지 조건은 무엇인가요?", + "answer": "자원을 한 번에 하나만 쓸 수 있는 상호 배제, 자원을 쥔 채 다른 자원을 기다리는 점유 대기, 강제로 빼앗을 수 없는 비선점, 서로 꼬리를 무는 순환 대기입니다. 모두 충족되어야 발생합니다." + }, + { + "id": "os-deadlock-002", + "question": "교착 상태를 예방하는 방법은 무엇인가요?", + "answer": "네 가지 조건 중 하나 이상을 성립하지 않게 만드는 것입니다. 자원을 한꺼번에 할당하거나, 자원에 순서를 부여해 순환 대기를 막는 방식 등이 있습니다." + }, + { + "id": "os-deadlock-003", + "question": "교착 상태 회피 기법인 은행원 알고리즘이란 무엇인가요?", + "answer": "자원을 할당하기 전에 시스템이 안전 상태를 유지할 수 있는지 미리 검사해, 안전할 때만 할당하는 알고리즘입니다. 최대 요구량을 미리 알아야 한다는 제약이 있습니다." + }, + { + "id": "os-deadlock-004", + "question": "교착 상태의 탐지와 회복 방식은 무엇인가요?", + "answer": "교착 상태를 허용한 뒤 주기적으로 자원 할당 그래프 등으로 탐지하고, 발견되면 프로세스를 강제 종료하거나 자원을 선점해 회복하는 방식입니다." + }, + { + "id": "os-deadlock-005", + "question": "교착 상태와 기아 상태의 차이는 무엇인가요?", + "answer": "교착 상태는 여러 프로세스가 서로를 기다려 모두 진행하지 못하는 상태이고, 기아 상태는 특정 프로세스만 자원을 계속 받지 못해 진행하지 못하는 상태입니다." + }, + { + "id": "os-deadlock-006", + "question": "시스템 콜이란 무엇인가요?", + "answer": "사용자 프로그램이 운영체제의 커널 기능을 사용하기 위해 호출하는 인터페이스입니다. 파일 입출력, 프로세스 생성 등 권한이 필요한 작업을 안전하게 요청할 수 있게 합니다." + }, + { + "id": "os-deadlock-007", + "question": "커널 모드와 사용자 모드의 차이는 무엇인가요?", + "answer": "커널 모드는 하드웨어에 직접 접근하는 등 모든 권한을 가진 모드이고, 사용자 모드는 제한된 권한만 갖는 모드입니다. 안전을 위해 일반 프로그램은 사용자 모드로 동작합니다." + }, + { + "id": "os-deadlock-008", + "question": "운영체제의 역할은 무엇인가요?", + "answer": "하드웨어 자원을 관리하고 사용자와 하드웨어 사이의 인터페이스를 제공합니다. 프로세스, 메모리, 파일, 입출력 장치를 관리하며 자원을 효율적으로 배분합니다." + }, + { + "id": "os-deadlock-009", + "question": "인터럽트와 시스템 콜의 관계는 무엇인가요?", + "answer": "시스템 콜은 소프트웨어 인터럽트를 통해 커널 모드로 전환되어 처리됩니다. 사용자 프로그램이 트랩을 발생시키면 운영체제가 해당 기능을 수행하고 결과를 반환합니다." + }, + { + "id": "os-deadlock-010", + "question": "부팅 과정은 어떻게 진행되나요?", + "answer": "전원이 켜지면 ROM의 펌웨어가 하드웨어를 점검하고, 부트로더가 디스크에서 운영체제 커널을 메모리로 적재한 뒤 실행 제어권을 넘깁니다." + } + ] + } + ] + }, + { + "id": "network", + "name": "네트워크", + "categories": [ + { + "id": "net-basic", + "name": "네트워크 기초와 계층 모델", + "questions": [ + { + "id": "net-basic-001", + "question": "OSI 7계층이란 무엇인가요?", + "answer": "네트워크 통신 과정을 7단계로 나눈 표준 모델입니다. 물리, 데이터링크, 네트워크, 전송, 세션, 표현, 응용 계층으로 구성되어 각 계층이 독립적인 역할을 담당합니다." + }, + { + "id": "net-basic-002", + "question": "OSI 7계층과 TCP/IP 4계층의 차이는 무엇인가요?", + "answer": "OSI는 통신을 7계층으로 세분한 이론적 참조 모델이고, TCP/IP는 실제 인터넷에서 쓰이는 4계층(네트워크 액세스, 인터넷, 전송, 응용) 실용 모델입니다." + }, + { + "id": "net-basic-003", + "question": "캡슐화와 역캡슐화란 무엇인가요?", + "answer": "송신 시 각 계층을 내려가며 헤더를 붙이는 과정이 캡슐화이고, 수신 시 각 계층을 올라가며 헤더를 떼어내는 과정이 역캡슐화입니다." + }, + { + "id": "net-basic-004", + "question": "MAC 주소와 IP 주소의 차이는 무엇인가요?", + "answer": "MAC 주소는 네트워크 장비에 부여된 변하지 않는 물리 주소이고, IP 주소는 네트워크 환경에 따라 부여되는 논리 주소입니다. MAC은 같은 네트워크 내 식별, IP는 네트워크 간 식별에 쓰입니다." + }, + { + "id": "net-basic-005", + "question": "허브, 스위치, 라우터의 차이는 무엇인가요?", + "answer": "허브는 신호를 모든 포트로 보내고, 스위치는 MAC 주소를 보고 해당 포트로만 보내며, 라우터는 IP 주소를 보고 서로 다른 네트워크 사이의 경로를 정해 전달합니다." + }, + { + "id": "net-basic-006", + "question": "ARP란 무엇인가요?", + "answer": "Address Resolution Protocol로, IP 주소를 통해 해당 장치의 MAC 주소를 알아내는 프로토콜입니다. 같은 네트워크 내에서 실제 통신을 하기 위해 필요합니다." + }, + { + "id": "net-basic-007", + "question": "대역폭과 처리량의 차이는 무엇인가요?", + "answer": "대역폭은 네트워크가 이론적으로 전송 가능한 최대 데이터 양이고, 처리량은 실제로 전송된 데이터 양입니다. 혼잡이나 오류로 처리량은 대역폭보다 작은 경우가 많습니다." + }, + { + "id": "net-basic-008", + "question": "LAN과 WAN의 차이는 무엇인가요?", + "answer": "LAN은 가정이나 사무실처럼 좁은 지역의 네트워크이고, WAN은 도시나 국가를 넘나드는 넓은 지역의 네트워크입니다. 인터넷은 대표적인 WAN입니다." + }, + { + "id": "net-basic-009", + "question": "유니캐스트, 멀티캐스트, 브로드캐스트의 차이는 무엇인가요?", + "answer": "유니캐스트는 일대일 전송, 멀티캐스트는 특정 그룹에 대한 전송, 브로드캐스트는 네트워크 내 모든 대상에 대한 전송입니다." + }, + { + "id": "net-basic-010", + "question": "RTT란 무엇인가요?", + "answer": "Round Trip Time으로, 데이터가 목적지까지 갔다가 응답이 돌아오기까지 걸리는 왕복 시간입니다. 네트워크 지연을 측정하는 중요한 지표입니다." + } + ] + }, + { + "id": "net-transport", + "name": "TCP와 UDP", + "questions": [ + { + "id": "net-transport-001", + "question": "TCP와 UDP의 차이는 무엇인가요?", + "answer": "TCP는 연결을 맺고 데이터를 순서대로 신뢰성 있게 전달하는 프로토콜이고, UDP는 연결 없이 빠르게 전송하지만 신뢰성을 보장하지 않는 프로토콜입니다." + }, + { + "id": "net-transport-002", + "question": "TCP 3-way handshake란 무엇인가요?", + "answer": "TCP 연결을 맺기 위한 세 단계 과정입니다. 클라이언트가 SYN을 보내고, 서버가 SYN과 ACK로 응답하며, 클라이언트가 다시 ACK를 보내 연결을 확립합니다." + }, + { + "id": "net-transport-003", + "question": "TCP 4-way handshake란 무엇인가요?", + "answer": "TCP 연결을 종료하는 네 단계 과정입니다. 양쪽이 각각 FIN과 ACK를 주고받아 연결을 끊으며, 마지막에 TIME_WAIT 상태를 두어 지연 패킷을 처리합니다." + }, + { + "id": "net-transport-004", + "question": "TCP가 신뢰성을 보장하는 방법은 무엇인가요?", + "answer": "데이터에 순서 번호를 붙이고 수신 확인(ACK)을 받으며, 응답이 없으면 재전송합니다. 또한 흐름 제어와 혼잡 제어로 안정적인 전송을 유지합니다." + }, + { + "id": "net-transport-005", + "question": "흐름 제어란 무엇인가요?", + "answer": "수신자가 처리할 수 있는 양보다 송신자가 데이터를 너무 빨리 보내지 않도록 조절하는 기능입니다. 슬라이딩 윈도우 방식으로 수신 버퍼에 맞춰 전송량을 제어합니다." + }, + { + "id": "net-transport-006", + "question": "혼잡 제어란 무엇인가요?", + "answer": "네트워크가 혼잡해지지 않도록 송신 데이터 양을 조절하는 기능입니다. 슬로우 스타트로 천천히 늘리다가 혼잡이 감지되면 전송량을 줄이는 방식으로 동작합니다." + }, + { + "id": "net-transport-007", + "question": "UDP는 어떤 경우에 사용하나요?", + "answer": "실시간성이 중요해 약간의 손실을 감수할 수 있는 경우에 사용합니다. 화상 통화, 실시간 스트리밍, 온라인 게임, DNS 조회 등이 대표적입니다." + }, + { + "id": "net-transport-008", + "question": "포트 번호란 무엇인가요?", + "answer": "한 호스트 내에서 실행되는 여러 프로세스를 구분하기 위한 번호입니다. IP 주소가 호스트를 식별한다면, 포트는 그 안의 특정 애플리케이션을 식별합니다." + }, + { + "id": "net-transport-009", + "question": "TIME_WAIT 상태가 필요한 이유는 무엇인가요?", + "answer": "지연되어 도착하는 패킷이 다음 연결에 섞이는 것을 막고, 마지막 ACK가 유실되었을 때 재전송에 대응하기 위함입니다. 일정 시간 대기 후 연결을 완전히 닫습니다." + }, + { + "id": "net-transport-010", + "question": "TCP 헤더의 주요 필드는 무엇인가요?", + "answer": "출발지와 목적지 포트, 데이터 순서를 나타내는 순서 번호, 다음 기대 바이트를 알리는 확인 응답 번호, 연결 상태를 제어하는 플래그(SYN, ACK, FIN 등)가 있습니다." + } + ] + }, + { + "id": "net-ip", + "name": "IP와 라우팅", + "questions": [ + { + "id": "net-ip-001", + "question": "IPv4와 IPv6의 차이는 무엇인가요?", + "answer": "IPv4는 32비트 주소로 약 43억 개를 표현하고, IPv6는 128비트 주소로 사실상 무제한입니다. IPv6는 주소 고갈 문제를 해결하고 헤더 구조도 단순화했습니다." + }, + { + "id": "net-ip-002", + "question": "공인 IP와 사설 IP의 차이는 무엇인가요?", + "answer": "공인 IP는 인터넷에서 유일하게 식별되는 주소이고, 사설 IP는 내부 네트워크에서만 쓰이는 주소입니다. 사설 IP는 NAT를 통해 공인 IP로 변환되어 인터넷에 접속합니다." + }, + { + "id": "net-ip-003", + "question": "NAT란 무엇인가요?", + "answer": "Network Address Translation으로, 사설 IP와 공인 IP를 변환해 주는 기술입니다. 여러 기기가 하나의 공인 IP를 공유할 수 있게 해 IP 부족 문제를 완화합니다." + }, + { + "id": "net-ip-004", + "question": "서브넷 마스크란 무엇인가요?", + "answer": "IP 주소에서 네트워크 부분과 호스트 부분을 구분하는 값입니다. 이를 통해 하나의 큰 네트워크를 여러 작은 서브넷으로 나눌 수 있습니다." + }, + { + "id": "net-ip-005", + "question": "라우팅이란 무엇인가요?", + "answer": "출발지에서 목적지까지 데이터가 거쳐갈 최적의 경로를 결정하는 과정입니다. 라우터가 라우팅 테이블을 참고해 다음에 보낼 곳을 정합니다." + }, + { + "id": "net-ip-006", + "question": "DHCP란 무엇인가요?", + "answer": "Dynamic Host Configuration Protocol로, 네트워크에 접속하는 기기에 IP 주소 등 설정 정보를 자동으로 할당해 주는 프로토콜입니다. 수동 설정 없이 네트워크를 쓸 수 있게 합니다." + }, + { + "id": "net-ip-007", + "question": "ICMP란 무엇인가요?", + "answer": "네트워크 상태나 오류를 알리는 데 쓰이는 프로토콜입니다. ping 명령으로 상대 호스트의 연결 여부를 확인할 때 ICMP가 사용됩니다." + }, + { + "id": "net-ip-008", + "question": "게이트웨이란 무엇인가요?", + "answer": "서로 다른 네트워크를 연결하는 출입구 역할을 하는 장치입니다. 내부 네트워크에서 외부로 나가는 트래픽은 기본 게이트웨이를 통해 전달됩니다." + }, + { + "id": "net-ip-009", + "question": "패킷이란 무엇인가요?", + "answer": "네트워크에서 데이터를 전송하기 위해 일정 크기로 나눈 단위입니다. 각 패킷은 헤더에 출발지와 목적지 정보를 담아 독립적으로 전송될 수 있습니다." + }, + { + "id": "net-ip-010", + "question": "라우터와 L3 스위치의 차이는 무엇인가요?", + "answer": "둘 다 IP 기반 라우팅을 수행하지만, L3 스위치는 하드웨어로 빠르게 처리해 내부망에 적합하고, 라우터는 다양한 프로토콜과 외부망 연결 기능이 풍부합니다." + } + ] + }, + { + "id": "net-http", + "name": "HTTP와 HTTPS", + "questions": [ + { + "id": "net-http-001", + "question": "HTTP란 무엇인가요?", + "answer": "웹에서 클라이언트와 서버가 데이터를 주고받기 위한 응용 계층 프로토콜입니다. 요청과 응답 구조로 동작하며 기본적으로 상태를 저장하지 않는 무상태 특성을 가집니다." + }, + { + "id": "net-http-002", + "question": "HTTP와 HTTPS의 차이는 무엇인가요?", + "answer": "HTTPS는 HTTP에 SSL/TLS 암호화를 적용한 것입니다. 데이터를 암호화해 도청과 변조를 막고 서버 신원을 인증하므로 보안이 중요한 통신에 사용됩니다." + }, + { + "id": "net-http-003", + "question": "HTTP 메서드에는 어떤 것들이 있나요?", + "answer": "자원 조회의 GET, 생성의 POST, 전체 수정의 PUT, 부분 수정의 PATCH, 삭제의 DELETE 등이 있습니다. 각 메서드는 자원에 대한 행위를 의미적으로 표현합니다." + }, + { + "id": "net-http-004", + "question": "GET과 POST의 차이는 무엇인가요?", + "answer": "GET은 데이터를 URL 쿼리에 담아 조회 목적으로 쓰며 캐싱이 가능합니다. POST는 데이터를 본문에 담아 생성이나 변경에 쓰며 본문 크기 제한이 사실상 없습니다." + }, + { + "id": "net-http-005", + "question": "주요 HTTP 상태 코드에는 어떤 것들이 있나요?", + "answer": "성공을 뜻하는 2xx, 리다이렉션의 3xx, 클라이언트 오류의 4xx, 서버 오류의 5xx로 분류됩니다. 200, 301, 404, 500이 대표적입니다." + }, + { + "id": "net-http-006", + "question": "HTTP가 무상태라는 것은 무슨 의미인가요?", + "answer": "서버가 이전 요청의 상태를 기억하지 않고 각 요청을 독립적으로 처리한다는 의미입니다. 그래서 상태 유지를 위해 쿠키나 세션, 토큰 같은 별도 수단이 필요합니다." + }, + { + "id": "net-http-007", + "question": "HTTP/1.1과 HTTP/2의 차이는 무엇인가요?", + "answer": "HTTP/2는 하나의 연결에서 여러 요청을 병렬 처리하는 멀티플렉싱, 헤더 압축, 서버 푸시를 지원합니다. 그 결과 HTTP/1.1의 대기 행렬 문제를 크게 개선했습니다." + }, + { + "id": "net-http-008", + "question": "SSL/TLS 핸드셰이크는 어떻게 동작하나요?", + "answer": "서버 인증서로 신원을 확인하고, 비대칭 암호로 대칭 키를 안전하게 교환한 뒤, 이후 통신은 빠른 대칭 키로 암호화합니다. 보안과 성능을 동시에 얻는 방식입니다." + }, + { + "id": "net-http-009", + "question": "쿠키와 세션의 차이는 무엇인가요?", + "answer": "쿠키는 클라이언트에 저장되는 작은 데이터이고, 세션은 서버에 저장되고 식별자만 쿠키로 주고받습니다. 쿠키는 가볍지만 보안이 약하고, 세션은 안전하지만 서버 자원을 씁니다." + }, + { + "id": "net-http-010", + "question": "HTTP keep-alive란 무엇인가요?", + "answer": "하나의 TCP 연결을 여러 요청과 응답에 재사용하는 기능입니다. 매 요청마다 연결을 새로 맺는 비용을 줄여 성능을 높입니다." + }, + { + "id": "net-http-011", + "question": "HTTP와 HTTPS의 차이는 무엇인가요?", + "answer": "HTTP는 평문으로 통신하고, HTTPS는 TLS로 암호화해 도청과 변조를 막습니다. HTTPS는 인증서로 서버 신원도 검증합니다." + }, + { + "id": "net-http-012", + "question": "HTTP 1.1과 HTTP 2의 차이는 무엇인가요?", + "answer": "HTTP 2는 하나의 연결에서 여러 요청을 병렬 처리하는 멀티플렉싱과 헤더 압축을 지원합니다. 그래서 1.1의 대기 지연 문제를 완화합니다." + }, + { + "id": "net-http-013", + "question": "쿠키와 세션을 HTTP에서 쓰는 이유는 무엇인가요?", + "answer": "HTTP는 무상태라 요청 간 상태가 유지되지 않기 때문입니다. 쿠키와 세션으로 로그인 같은 상태를 이어 갑니다." + }, + { + "id": "net-http-014", + "question": "HTTP 메서드 중 GET과 POST의 차이는 무엇인가요?", + "answer": "GET은 데이터를 URL에 담아 조회하며 멱등하고 캐시됩니다. POST는 본문에 데이터를 담아 생성이나 변경에 쓰며 멱등하지 않습니다." + } + ] + }, + { + "id": "net-dns", + "name": "DNS와 웹 동작 원리", + "questions": [ + { + "id": "net-dns-001", + "question": "DNS란 무엇인가요?", + "answer": "사람이 읽기 쉬운 도메인 이름을 컴퓨터가 사용하는 IP 주소로 변환해 주는 시스템입니다. 인터넷의 전화번호부 역할을 한다고 볼 수 있습니다." + }, + { + "id": "net-dns-002", + "question": "브라우저에 URL을 입력하면 어떤 일이 일어나나요?", + "answer": "DNS로 도메인을 IP로 변환하고, 해당 서버와 TCP 연결 및 TLS 핸드셰이크를 맺은 뒤, HTTP 요청을 보내고 응답을 받아 렌더링합니다. 캐시와 라우팅도 중간에 관여합니다." + }, + { + "id": "net-dns-003", + "question": "DNS 조회 과정은 어떻게 되나요?", + "answer": "브라우저와 OS 캐시를 먼저 확인하고, 없으면 재귀 DNS 서버가 루트, TLD, 권한 있는 네임서버를 차례로 질의해 IP를 알아냅니다." + }, + { + "id": "net-dns-004", + "question": "A 레코드와 CNAME 레코드의 차이는 무엇인가요?", + "answer": "A 레코드는 도메인을 IP 주소에 직접 연결하고, CNAME 레코드는 도메인을 다른 도메인의 별칭으로 연결합니다. CNAME은 여러 서브도메인을 한곳으로 모을 때 유용합니다." + }, + { + "id": "net-dns-005", + "question": "DNS 캐싱이 필요한 이유는 무엇인가요?", + "answer": "매번 전체 조회를 하면 지연이 크기 때문에, 한 번 조회한 결과를 일정 시간(TTL) 동안 저장해 재사용합니다. 이를 통해 응답 속도와 DNS 서버 부하를 모두 개선합니다." + }, + { + "id": "net-dns-006", + "question": "CDN이란 무엇인가요?", + "answer": "Content Delivery Network로, 콘텐츠를 사용자와 지리적으로 가까운 서버에 분산 저장해 전달하는 기술입니다. 응답 속도를 높이고 원본 서버의 부하를 줄입니다." + }, + { + "id": "net-dns-007", + "question": "로드 밸런서란 무엇인가요?", + "answer": "들어오는 트래픽을 여러 서버에 분산해 부하를 고르게 나누는 장치나 소프트웨어입니다. 가용성과 확장성을 높이며 라운드 로빈 등 다양한 분산 방식을 사용합니다." + }, + { + "id": "net-dns-008", + "question": "포워드 프록시와 리버스 프록시의 차이는 무엇인가요?", + "answer": "포워드 프록시는 클라이언트를 대신해 요청을 보내고, 리버스 프록시는 서버 앞단에서 요청을 받아 내부 서버로 전달합니다. 리버스 프록시는 로드 밸런싱과 캐싱에 쓰입니다." + }, + { + "id": "net-dns-009", + "question": "웹소켓이란 무엇인가요?", + "answer": "클라이언트와 서버가 하나의 연결로 양방향 실시간 통신을 하는 프로토콜입니다. HTTP와 달리 연결을 유지하므로 채팅이나 실시간 알림에 적합합니다." + }, + { + "id": "net-dns-010", + "question": "폴링, 롱폴링, 웹소켓의 차이는 무엇인가요?", + "answer": "폴링은 주기적으로 요청해 확인하고, 롱폴링은 응답을 지연시켜 변화가 있을 때 반환하며, 웹소켓은 연결을 유지해 실시간 양방향 통신을 합니다. 실시간성이 높을수록 웹소켓이 유리합니다." + }, + { + "id": "net-dns-011", + "question": "DNS 캐싱은 왜 사용하나요?", + "answer": "도메인 조회 결과를 일정 시간 저장해 반복 질의를 줄이기 위해서입니다. 응답 속도가 빨라지고 DNS 서버 부하도 줄어듭니다." + }, + { + "id": "net-dns-012", + "question": "DNS 질의 과정은 어떻게 되나요?", + "answer": "로컬 캐시를 먼저 확인하고 없으면 루트, 최상위 도메인, 권한 있는 네임 서버 순으로 물어 IP를 알아냅니다. 이를 재귀 질의라고 합니다." + } + ] + } + ] + }, + { + "id": "database", + "name": "데이터베이스", + "categories": [ + { + "id": "db-basic", + "name": "데이터베이스 기초", + "questions": [ + { + "id": "db-basic-001", + "question": "데이터베이스와 DBMS의 차이는 무엇인가요?", + "answer": "데이터베이스는 체계적으로 저장된 데이터의 집합이고, DBMS는 그 데이터베이스를 관리하고 접근을 제어하는 소프트웨어입니다. MySQL, PostgreSQL이 대표적인 DBMS입니다." + }, + { + "id": "db-basic-002", + "question": "관계형 데이터베이스란 무엇인가요?", + "answer": "데이터를 행과 열로 이루어진 테이블 형태로 저장하고, 테이블 간 관계를 키로 연결하는 데이터베이스입니다. SQL로 데이터를 조작하며 정합성 유지에 강합니다." + }, + { + "id": "db-basic-003", + "question": "기본키와 외래키의 차이는 무엇인가요?", + "answer": "기본키는 테이블에서 각 행을 유일하게 식별하는 키이고, 외래키는 다른 테이블의 기본키를 참조해 테이블 간 관계를 맺는 키입니다." + }, + { + "id": "db-basic-004", + "question": "기본키가 갖춰야 할 조건은 무엇인가요?", + "answer": "각 행을 유일하게 식별할 수 있어야 하는 유일성과, 값이 비어 있으면 안 되는 최소성 및 NOT NULL 조건을 만족해야 합니다. 또한 값이 자주 변하지 않는 것이 좋습니다." + }, + { + "id": "db-basic-005", + "question": "후보키, 슈퍼키, 대체키의 차이는 무엇인가요?", + "answer": "슈퍼키는 유일성을 만족하는 모든 키, 후보키는 그중 최소성까지 만족하는 키, 대체키는 후보키 중 기본키로 선택되지 않은 나머지 키를 말합니다." + }, + { + "id": "db-basic-006", + "question": "DDL, DML, DCL의 차이는 무엇인가요?", + "answer": "DDL은 테이블 구조를 정의하는 명령(CREATE, ALTER), DML은 데이터를 조작하는 명령(SELECT, INSERT), DCL은 권한을 제어하는 명령(GRANT, REVOKE)입니다." + }, + { + "id": "db-basic-007", + "question": "JOIN의 종류에는 어떤 것들이 있나요?", + "answer": "양쪽 모두 일치하는 행만 반환하는 INNER JOIN, 한쪽 테이블 전체를 포함하는 LEFT/RIGHT OUTER JOIN, 양쪽 전체를 포함하는 FULL OUTER JOIN 등이 있습니다." + }, + { + "id": "db-basic-008", + "question": "WHERE와 HAVING의 차이는 무엇인가요?", + "answer": "WHERE는 그룹화 이전에 개별 행을 필터링하고, HAVING은 GROUP BY로 그룹화한 이후 그룹을 필터링합니다. 집계 함수 조건은 HAVING에 사용합니다." + }, + { + "id": "db-basic-009", + "question": "DELETE, TRUNCATE, DROP의 차이는 무엇인가요?", + "answer": "DELETE는 조건에 맞는 행을 삭제하고 롤백 가능하며, TRUNCATE는 모든 행을 빠르게 삭제하고, DROP은 테이블 구조 자체를 제거합니다." + }, + { + "id": "db-basic-010", + "question": "뷰(View)란 무엇인가요?", + "answer": "하나 이상의 테이블에서 유도된 가상의 테이블입니다. 실제 데이터를 저장하지 않고 쿼리만 저장하며, 복잡한 조회를 단순화하고 보안을 강화하는 데 쓰입니다." + } + ] + }, + { + "id": "db-normalization", + "name": "정규화", + "questions": [ + { + "id": "db-normalization-001", + "question": "정규화란 무엇인가요?", + "answer": "데이터 중복을 줄이고 무결성을 높이기 위해 테이블을 작은 단위로 나누는 과정입니다. 이상 현상을 방지하는 것이 주된 목적입니다." + }, + { + "id": "db-normalization-002", + "question": "이상 현상(anomaly)이란 무엇인가요?", + "answer": "데이터 중복으로 인해 삽입, 갱신, 삭제 시 의도치 않은 문제가 생기는 현상입니다. 삽입 이상, 갱신 이상, 삭제 이상 세 가지가 있습니다." + }, + { + "id": "db-normalization-003", + "question": "제1정규형이란 무엇인가요?", + "answer": "모든 속성이 더 이상 나눌 수 없는 원자값만 가지도록 하는 정규형입니다. 하나의 칸에 여러 값이 들어 있으면 제1정규형을 위반합니다." + }, + { + "id": "db-normalization-004", + "question": "제2정규형이란 무엇인가요?", + "answer": "제1정규형을 만족하면서 기본키가 아닌 모든 속성이 기본키 전체에 완전히 종속되도록 하는 정규형입니다. 부분 함수 종속을 제거합니다." + }, + { + "id": "db-normalization-005", + "question": "제3정규형이란 무엇인가요?", + "answer": "제2정규형을 만족하면서 기본키가 아닌 속성들 사이의 이행적 종속을 제거한 정규형입니다. A가 B를 결정하고 B가 C를 결정하는 관계를 분리합니다." + }, + { + "id": "db-normalization-006", + "question": "BCNF란 무엇인가요?", + "answer": "제3정규형을 더 엄격하게 만든 형태로, 모든 결정자가 후보키가 되도록 하는 정규형입니다. 후보키가 여러 개로 겹칠 때 발생하는 이상을 해결합니다." + }, + { + "id": "db-normalization-007", + "question": "함수 종속이란 무엇인가요?", + "answer": "한 속성의 값이 정해지면 다른 속성의 값이 유일하게 결정되는 관계입니다. 정규화의 기준이 되며, 학번이 정해지면 이름이 결정되는 것이 예입니다." + }, + { + "id": "db-normalization-008", + "question": "반정규화(역정규화)란 무엇인가요?", + "answer": "성능 향상을 위해 의도적으로 정규화를 완화해 중복을 허용하는 기법입니다. 잦은 조인으로 인한 성능 저하를 줄이려 할 때 사용하지만 무결성 관리 부담이 늘어납니다." + }, + { + "id": "db-normalization-009", + "question": "정규화의 장단점은 무엇인가요?", + "answer": "장점은 데이터 중복 감소와 무결성 향상, 저장 공간 절약입니다. 단점은 테이블이 늘어나 조인이 많아지고, 그로 인해 조회 성능이 떨어질 수 있다는 점입니다." + }, + { + "id": "db-normalization-010", + "question": "정규화와 성능의 관계는 무엇인가요?", + "answer": "정규화는 무결성을 높이지만 조인 증가로 조회가 느려질 수 있습니다. 그래서 실무에서는 무결성과 성능을 따져 적절한 수준의 정규화와 반정규화를 절충합니다." + } + ] + }, + { + "id": "db-transaction", + "name": "트랜잭션", + "questions": [ + { + "id": "db-transaction-001", + "question": "트랜잭션이란 무엇인가요?", + "answer": "데이터베이스의 상태를 변화시키는 하나의 논리적 작업 단위입니다. 여러 연산을 묶어 전부 성공하거나 전부 실패하도록 보장합니다." + }, + { + "id": "db-transaction-002", + "question": "트랜잭션의 ACID 특성은 무엇인가요?", + "answer": "전부 실행되거나 전부 취소되는 원자성, 일관성을 유지하는 일관성, 동시 실행이 서로 영향을 주지 않는 격리성, 완료된 결과가 보존되는 지속성을 의미합니다." + }, + { + "id": "db-transaction-003", + "question": "커밋과 롤백의 차이는 무엇인가요?", + "answer": "커밋은 트랜잭션의 변경 내용을 확정해 데이터베이스에 영구 반영하는 것이고, 롤백은 변경을 취소해 트랜잭션 시작 이전 상태로 되돌리는 것입니다." + }, + { + "id": "db-transaction-004", + "question": "트랜잭션 격리 수준에는 어떤 것들이 있나요?", + "answer": "READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE 네 단계가 있습니다. 수준이 높을수록 일관성은 좋아지지만 동시성은 떨어집니다." + }, + { + "id": "db-transaction-005", + "question": "더티 리드란 무엇인가요?", + "answer": "다른 트랜잭션이 아직 커밋하지 않은 변경 데이터를 읽는 현상입니다. 그 트랜잭션이 롤백되면 존재하지 않는 값을 읽은 셈이 되어 문제가 됩니다." + }, + { + "id": "db-transaction-006", + "question": "논리피티블 리드와 팬텀 리드의 차이는 무엇인가요?", + "answer": "반복 불가능한 읽기는 같은 행을 다시 읽었을 때 값이 바뀐 것이고, 팬텀 리드는 같은 조건으로 다시 조회했을 때 없던 행이 새로 나타나는 것입니다." + }, + { + "id": "db-transaction-007", + "question": "각 격리 수준에서 발생하는 문제는 무엇인가요?", + "answer": "READ UNCOMMITTED는 더티 리드, READ COMMITTED는 반복 불가능한 읽기, REPEATABLE READ는 팬텀 리드가 발생할 수 있습니다. SERIALIZABLE은 이를 모두 막습니다." + }, + { + "id": "db-transaction-008", + "question": "낙관적 락과 비관적 락의 차이는 무엇인가요?", + "answer": "비관적 락은 충돌을 가정해 미리 락을 거는 방식이고, 낙관적 락은 충돌이 드물다고 보고 버전 정보로 변경 시점에 충돌을 검사하는 방식입니다." + }, + { + "id": "db-transaction-009", + "question": "데드락은 데이터베이스에서 어떻게 발생하나요?", + "answer": "두 트랜잭션이 서로가 잠근 자원을 기다리며 무한 대기하는 상황입니다. 대부분의 DBMS는 이를 감지해 한쪽 트랜잭션을 강제 종료하는 방식으로 해결합니다." + }, + { + "id": "db-transaction-010", + "question": "2단계 커밋이란 무엇인가요?", + "answer": "여러 노드에 걸친 분산 트랜잭션의 일관성을 위해 준비 단계와 커밋 단계로 나누어 처리하는 프로토콜입니다. 모든 참여자가 준비되어야 최종 커밋합니다." + }, + { + "id": "db-transaction-011", + "question": "교착 상태는 데이터베이스에서 어떻게 처리하나요?", + "answer": "트랜잭션이 서로의 잠금을 기다릴 때 발생합니다. DBMS가 주기적으로 탐지해 한쪽을 강제 종료하거나 타임아웃으로 해소합니다." + }, + { + "id": "db-transaction-012", + "question": "낙관적 잠금과 비관적 잠금의 차이는 무엇인가요?", + "answer": "비관적 잠금은 충돌을 가정해 미리 잠그고, 낙관적 잠금은 충돌이 드물다고 보고 버전으로 변경 시점에 검증합니다." + }, + { + "id": "db-transaction-013", + "question": "2단계 커밋이란 무엇인가요?", + "answer": "분산 트랜잭션에서 모든 참여자에게 준비를 요청한 뒤 모두 동의하면 커밋하는 방식입니다. 분산 환경의 원자성을 보장합니다." + }, + { + "id": "db-transaction-014", + "question": "트랜잭션 전파란 무엇인가요?", + "answer": "트랜잭션이 진행 중일 때 다른 트랜잭션 메서드를 호출하면 어떻게 동작할지를 정하는 규칙입니다. 기존에 참여하거나 새로 시작하는 등 옵션이 있습니다." + } + ] + }, + { + "id": "db-index", + "name": "인덱스", + "questions": [ + { + "id": "db-index-001", + "question": "인덱스란 무엇인가요?", + "answer": "데이터 검색 속도를 높이기 위해 특정 칼럼의 값과 위치를 별도로 정렬해 둔 자료구조입니다. 책의 색인처럼 원하는 데이터를 빠르게 찾도록 돕습니다." + }, + { + "id": "db-index-002", + "question": "인덱스의 장단점은 무엇인가요?", + "answer": "조회 속도가 빨라지는 장점이 있지만, 인덱스를 위한 저장 공간이 추가로 필요하고 삽입, 수정, 삭제 시 인덱스도 갱신해야 해서 쓰기 성능이 떨어집니다." + }, + { + "id": "db-index-003", + "question": "인덱스에 주로 사용되는 자료구조는 무엇인가요?", + "answer": "B-Tree와 그 변형인 B+Tree가 대표적입니다. 균형 트리 구조로 정렬을 유지하며 범위 검색에 강하고, 해시 인덱스는 동등 비교에 빠릅니다." + }, + { + "id": "db-index-004", + "question": "B-Tree와 B+Tree의 차이는 무엇인가요?", + "answer": "B+Tree는 실제 데이터를 리프 노드에만 저장하고 리프끼리 연결 리스트로 이어져 있습니다. 그래서 범위 검색과 순차 접근에서 B-Tree보다 유리합니다." + }, + { + "id": "db-index-005", + "question": "클러스터형 인덱스와 비클러스터형 인덱스의 차이는 무엇인가요?", + "answer": "클러스터형 인덱스는 인덱스 순서대로 실제 데이터가 정렬되어 저장되며 테이블당 하나만 존재합니다. 비클러스터형은 데이터 위치를 가리키는 별도 구조로 여러 개 만들 수 있습니다." + }, + { + "id": "db-index-006", + "question": "복합 인덱스란 무엇이고 칼럼 순서가 왜 중요한가요?", + "answer": "여러 칼럼을 묶어 만든 인덱스입니다. 앞쪽 칼럼부터 정렬되므로, 선행 칼럼 조건이 있어야 인덱스를 효율적으로 탈 수 있어 칼럼 순서가 중요합니다." + }, + { + "id": "db-index-007", + "question": "인덱스를 사용하지 못하는 경우는 언제인가요?", + "answer": "칼럼에 함수나 연산을 적용하거나, 앞에 와일드카드를 둔 LIKE 검색, 데이터 분포가 한쪽으로 치우친 경우 등에서는 인덱스를 못 타거나 비효율적입니다." + }, + { + "id": "db-index-008", + "question": "카디널리티가 인덱스에 미치는 영향은 무엇인가요?", + "answer": "카디널리티는 칼럼의 고유값 개수입니다. 카디널리티가 높을수록 인덱스로 데이터를 잘 걸러낼 수 있어 효율적이고, 성별처럼 낮으면 효과가 적습니다." + }, + { + "id": "db-index-009", + "question": "커버링 인덱스란 무엇인가요?", + "answer": "쿼리에 필요한 모든 칼럼을 인덱스만으로 처리할 수 있는 인덱스입니다. 실제 테이블에 접근할 필요가 없어 조회 성능이 크게 향상됩니다." + }, + { + "id": "db-index-010", + "question": "인덱스를 무조건 많이 만들면 안 되는 이유는 무엇인가요?", + "answer": "인덱스마다 저장 공간이 들고, 데이터 변경 시 모든 관련 인덱스를 갱신해야 해서 쓰기 성능이 떨어집니다. 그래서 자주 조회되는 칼럼 위주로 신중히 설계해야 합니다." + }, + { + "id": "db-index-011", + "question": "클러스터형 인덱스와 비클러스터형 인덱스의 차이는 무엇인가요?", + "answer": "클러스터형은 데이터가 인덱스 순서로 정렬되어 저장되며 테이블당 하나입니다. 비클러스터형은 별도 구조로 위치를 가리키며 여러 개 만들 수 있습니다." + }, + { + "id": "db-index-012", + "question": "복합 인덱스에서 컬럼 순서가 중요한 이유는 무엇인가요?", + "answer": "인덱스는 왼쪽 컬럼부터 정렬되므로 선행 컬럼 조건이 있어야 효율적으로 탐색됩니다. 순서가 맞지 않으면 인덱스를 제대로 못 탑니다." + }, + { + "id": "db-index-013", + "question": "커버링 인덱스란 무엇인가요?", + "answer": "쿼리가 필요로 하는 모든 컬럼을 인덱스만으로 충족하는 경우입니다. 테이블에 접근하지 않아 조회 성능이 크게 향상됩니다." + }, + { + "id": "db-index-014", + "question": "인덱스를 무조건 많이 만들면 안 되는 이유는 무엇인가요?", + "answer": "조회는 빨라지지만 삽입, 수정, 삭제 시 인덱스도 갱신해야 해 쓰기 성능이 떨어집니다. 저장 공간도 추가로 소모합니다." + } + ] + }, + { + "id": "db-nosql", + "name": "SQL과 NoSQL", + "questions": [ + { + "id": "db-nosql-001", + "question": "SQL과 NoSQL의 차이는 무엇인가요?", + "answer": "SQL은 정해진 스키마와 테이블 구조를 가진 관계형 데이터베이스이고, NoSQL은 스키마가 유연하고 다양한 데이터 모델을 지원하는 비관계형 데이터베이스입니다." + }, + { + "id": "db-nosql-002", + "question": "NoSQL의 데이터 모델에는 어떤 종류가 있나요?", + "answer": "키-값, 문서(document), 칼럼 기반(column-family), 그래프 모델이 있습니다. 각각 Redis, MongoDB, Cassandra, Neo4j가 대표적입니다." + }, + { + "id": "db-nosql-003", + "question": "NoSQL은 언제 사용하는 것이 좋나요?", + "answer": "데이터 구조가 자주 바뀌거나 정형화하기 어렵고, 대용량 데이터를 빠르게 수평 확장해야 할 때 적합합니다. 반면 복잡한 조인과 강한 정합성이 필요하면 SQL이 낫습니다." + }, + { + "id": "db-nosql-004", + "question": "CAP 이론이란 무엇인가요?", + "answer": "분산 시스템은 일관성, 가용성, 분할 내성 셋 중 동시에 둘까지만 보장할 수 있다는 이론입니다. 네트워크 분할이 불가피하므로 보통 일관성과 가용성 중 선택합니다." + }, + { + "id": "db-nosql-005", + "question": "수직 확장과 수평 확장의 차이는 무엇인가요?", + "answer": "수직 확장은 서버 한 대의 성능을 높이는 것이고, 수평 확장은 서버 대수를 늘려 부하를 분산하는 것입니다. NoSQL은 수평 확장에 더 적합합니다." + }, + { + "id": "db-nosql-006", + "question": "샤딩이란 무엇인가요?", + "answer": "데이터를 여러 데이터베이스 서버에 분산 저장하는 수평 분할 기법입니다. 단일 서버의 용량과 부하 한계를 넘어 대규모 데이터를 처리할 수 있게 합니다." + }, + { + "id": "db-nosql-007", + "question": "복제(replication)란 무엇인가요?", + "answer": "동일한 데이터를 여러 서버에 복사해 두는 기법입니다. 읽기 부하를 분산하고 한 서버 장애 시에도 서비스를 이어갈 수 있어 가용성을 높입니다." + }, + { + "id": "db-nosql-008", + "question": "마스터-슬레이브 구조란 무엇인가요?", + "answer": "쓰기를 담당하는 마스터와 읽기를 담당하는 슬레이브로 역할을 나눈 복제 구조입니다. 읽기 부하를 분산하며, 마스터 변경 내용이 슬레이브로 전파됩니다." + }, + { + "id": "db-nosql-009", + "question": "Redis를 캐시로 사용하는 이유는 무엇인가요?", + "answer": "메모리 기반이라 매우 빠르고 다양한 자료구조를 지원하기 때문입니다. 자주 조회되는 데이터를 캐싱해 데이터베이스 부하를 줄이고 응답 속도를 높입니다." + }, + { + "id": "db-nosql-010", + "question": "데이터 정합성을 유지하면서 캐시를 사용하는 방법은 무엇인가요?", + "answer": "원본 변경 시 캐시를 갱신하거나 무효화하는 전략이 필요합니다. 조회 시 캐시를 먼저 보는 look-aside, 쓰기 시 함께 반영하는 write-through 등을 사용합니다." + } + ] + } + ] + }, + { + "id": "data-structure", + "name": "자료구조", + "categories": [ + { + "id": "ds-linear", + "name": "선형 자료구조", + "questions": [ + { + "id": "ds-linear-001", + "question": "배열과 연결 리스트의 차이는 무엇인가요?", + "answer": "배열은 메모리에 연속 저장되어 인덱스 접근이 빠르지만 삽입과 삭제가 느립니다. 연결 리스트는 노드가 포인터로 연결되어 삽입과 삭제가 빠르지만 임의 접근이 느립니다." + }, + { + "id": "ds-linear-002", + "question": "스택이란 무엇인가요?", + "answer": "마지막에 넣은 데이터가 가장 먼저 나오는 후입선출(LIFO) 구조입니다. push로 넣고 pop으로 꺼내며, 함수 호출 스택이나 되돌리기 기능에 쓰입니다." + }, + { + "id": "ds-linear-003", + "question": "큐란 무엇인가요?", + "answer": "먼저 넣은 데이터가 먼저 나오는 선입선출(FIFO) 구조입니다. enqueue로 뒤에 넣고 dequeue로 앞에서 꺼내며, 작업 대기열이나 BFS에 쓰입니다." + }, + { + "id": "ds-linear-004", + "question": "스택과 큐의 활용 사례는 무엇인가요?", + "answer": "스택은 함수 호출 관리, 괄호 검사, 수식 계산, 뒤로 가기에 쓰입니다. 큐는 프로세스 스케줄링, 너비 우선 탐색, 메시지 처리 대기열에 쓰입니다." + }, + { + "id": "ds-linear-005", + "question": "원형 큐란 무엇인가요?", + "answer": "배열의 끝과 처음을 논리적으로 연결한 큐입니다. 일반 큐에서 앞쪽 빈 공간을 재사용하지 못하는 문제를 해결해 공간을 효율적으로 활용합니다." + }, + { + "id": "ds-linear-006", + "question": "덱(Deque)이란 무엇인가요?", + "answer": "양쪽 끝에서 모두 삽입과 삭제가 가능한 자료구조입니다. 스택과 큐의 기능을 모두 제공하며, 슬라이딩 윈도우 문제 등에 유용하게 쓰입니다." + }, + { + "id": "ds-linear-007", + "question": "단일 연결 리스트와 이중 연결 리스트의 차이는 무엇인가요?", + "answer": "단일 연결 리스트는 다음 노드만 가리키고, 이중 연결 리스트는 이전과 다음 노드를 모두 가리킵니다. 이중 연결 리스트는 양방향 탐색이 가능하지만 메모리를 더 씁니다." + }, + { + "id": "ds-linear-008", + "question": "동적 배열은 어떻게 크기를 늘리나요?", + "answer": "용량이 가득 차면 보통 두 배 크기의 새 배열을 할당하고 기존 데이터를 복사합니다. 평균적으로 보면 삽입 비용이 상수에 가깝게 유지됩니다." + }, + { + "id": "ds-linear-009", + "question": "배열의 시간 복잡도는 어떻게 되나요?", + "answer": "인덱스를 통한 접근은 O(1)이지만, 중간 삽입과 삭제는 뒤 요소를 이동해야 해서 O(n)입니다. 끝에서의 삽입은 평균 O(1)입니다." + }, + { + "id": "ds-linear-010", + "question": "연결 리스트의 시간 복잡도는 어떻게 되나요?", + "answer": "위치를 알고 있을 때 삽입과 삭제는 O(1)이지만, 특정 요소를 찾으려면 순차 탐색이 필요해 O(n)입니다. 임의 접근에 불리합니다." + } + ] + }, + { + "id": "ds-tree", + "name": "트리", + "questions": [ + { + "id": "ds-tree-001", + "question": "트리란 무엇인가요?", + "answer": "노드와 간선으로 이루어진 계층적 비선형 자료구조입니다. 사이클이 없으며 하나의 루트에서 시작해 부모-자식 관계로 뻗어 나갑니다." + }, + { + "id": "ds-tree-002", + "question": "이진 트리란 무엇인가요?", + "answer": "각 노드가 최대 두 개의 자식을 갖는 트리입니다. 왼쪽과 오른쪽 자식으로 구분되며, 탐색과 정렬 등 다양한 알고리즘의 기반이 됩니다." + }, + { + "id": "ds-tree-003", + "question": "이진 탐색 트리(BST)란 무엇인가요?", + "answer": "왼쪽 자식은 부모보다 작고 오른쪽 자식은 부모보다 큰 규칙을 가진 이진 트리입니다. 이 규칙 덕분에 평균 O(log n)에 탐색, 삽입, 삭제가 가능합니다." + }, + { + "id": "ds-tree-004", + "question": "이진 탐색 트리의 단점은 무엇인가요?", + "answer": "데이터가 정렬된 순서로 삽입되면 한쪽으로 치우쳐 사실상 연결 리스트가 됩니다. 그러면 탐색 성능이 O(n)으로 떨어지므로 균형 트리가 필요합니다." + }, + { + "id": "ds-tree-005", + "question": "균형 이진 트리란 무엇인가요?", + "answer": "좌우 서브트리의 높이 차이를 일정 범위로 유지해 한쪽으로 치우치지 않게 한 트리입니다. AVL 트리와 레드-블랙 트리가 대표적입니다." + }, + { + "id": "ds-tree-006", + "question": "AVL 트리와 레드-블랙 트리의 차이는 무엇인가요?", + "answer": "AVL 트리는 높이 차이를 1 이하로 엄격히 유지해 조회가 빠르고, 레드-블랙 트리는 더 느슨하게 균형을 유지해 삽입과 삭제가 빠릅니다." + }, + { + "id": "ds-tree-007", + "question": "트리 순회 방법에는 어떤 것들이 있나요?", + "answer": "루트를 언제 방문하느냐에 따라 전위, 중위, 후위 순회가 있고, 레벨 순서대로 방문하는 레벨 순회가 있습니다. 이진 탐색 트리의 중위 순회는 정렬된 결과를 줍니다." + }, + { + "id": "ds-tree-008", + "question": "힙(Heap)이란 무엇인가요?", + "answer": "부모가 자식보다 항상 크거나 작은 완전 이진 트리입니다. 최댓값이나 최솟값을 O(1)에 얻을 수 있어 우선순위 큐 구현에 사용됩니다." + }, + { + "id": "ds-tree-009", + "question": "최소 힙과 최대 힙의 차이는 무엇인가요?", + "answer": "최소 힙은 부모가 자식보다 작아 루트에 최솟값이 오고, 최대 힙은 부모가 자식보다 커 루트에 최댓값이 옵니다. 목적에 따라 골라 사용합니다." + }, + { + "id": "ds-tree-010", + "question": "B-Tree가 데이터베이스 인덱스에 쓰이는 이유는 무엇인가요?", + "answer": "한 노드가 여러 자식을 가져 트리 높이가 낮으므로 디스크 접근 횟수를 줄일 수 있습니다. 정렬 상태를 유지해 범위 검색에도 효율적입니다." + }, + { + "id": "ds-tree-011", + "question": "힙이란 무엇인가요?", + "answer": "부모와 자식 간 크기 순서가 유지되는 완전 이진 트리입니다. 최댓값이나 최솟값을 빠르게 꺼낼 수 있어 우선순위 큐 구현에 쓰입니다." + }, + { + "id": "ds-tree-012", + "question": "B 트리와 B+ 트리의 차이는 무엇인가요?", + "answer": "B+ 트리는 실제 데이터를 리프 노드에만 저장하고 리프끼리 연결되어 범위 검색에 유리합니다. 데이터베이스 인덱스에 널리 쓰입니다." + }, + { + "id": "ds-tree-013", + "question": "트리 순회 방식에는 무엇이 있나요?", + "answer": "전위, 중위, 후위 순회 같은 깊이 우선 방식과 레벨 순으로 도는 너비 우선 방식이 있습니다. 중위 순회는 이진 탐색 트리에서 정렬된 결과를 줍니다." + }, + { + "id": "ds-tree-014", + "question": "AVL 트리란 무엇인가요?", + "answer": "노드의 좌우 높이 차이를 1 이하로 유지하는 자가 균형 이진 탐색 트리입니다. 회전으로 균형을 맞춰 탐색 성능을 보장합니다." + } + ] + }, + { + "id": "ds-hash", + "name": "해시", + "questions": [ + { + "id": "ds-hash-001", + "question": "해시 테이블이란 무엇인가요?", + "answer": "키를 해시 함수로 변환한 값을 인덱스로 사용해 데이터를 저장하는 자료구조입니다. 평균적으로 O(1)에 삽입, 삭제, 검색이 가능합니다." + }, + { + "id": "ds-hash-002", + "question": "해시 함수란 무엇인가요?", + "answer": "임의 크기의 데이터를 고정 크기의 값으로 변환하는 함수입니다. 좋은 해시 함수는 값을 고르게 분포시키고 충돌이 적으며 빠르게 계산됩니다." + }, + { + "id": "ds-hash-003", + "question": "해시 충돌이란 무엇인가요?", + "answer": "서로 다른 키가 같은 해시 값을 갖는 현상입니다. 비둘기집 원리상 피할 수 없으므로 체이닝이나 개방 주소법 같은 해결 기법이 필요합니다." + }, + { + "id": "ds-hash-004", + "question": "체이닝과 개방 주소법의 차이는 무엇인가요?", + "answer": "체이닝은 같은 위치에 충돌한 값들을 연결 리스트로 이어 저장하고, 개방 주소법은 비어 있는 다른 위치를 찾아 저장합니다. 각각 메모리와 캐시 효율에 차이가 있습니다." + }, + { + "id": "ds-hash-005", + "question": "개방 주소법의 종류에는 어떤 것들이 있나요?", + "answer": "충돌 시 다음 칸을 차례로 찾는 선형 탐사, 간격을 제곱으로 늘리는 제곱 탐사, 두 번째 해시 함수를 쓰는 이중 해싱이 있습니다." + }, + { + "id": "ds-hash-006", + "question": "로드 팩터란 무엇인가요?", + "answer": "해시 테이블에서 저장된 데이터 수를 전체 버킷 수로 나눈 값입니다. 이 값이 커지면 충돌이 늘어나므로, 일정 임계치를 넘으면 테이블 크기를 늘리는 리해싱을 합니다." + }, + { + "id": "ds-hash-007", + "question": "리해싱이란 무엇인가요?", + "answer": "로드 팩터가 임계치를 넘으면 더 큰 테이블을 만들고 기존 데이터를 다시 해싱해 재배치하는 작업입니다. 충돌을 줄여 성능을 유지하기 위함입니다." + }, + { + "id": "ds-hash-008", + "question": "해시 테이블의 최악 시간 복잡도는 왜 O(n)인가요?", + "answer": "모든 키가 같은 위치로 충돌하면 한 버킷에 데이터가 몰려 사실상 선형 탐색이 되기 때문입니다. 좋은 해시 함수와 적절한 로드 팩터 관리로 이를 방지합니다." + }, + { + "id": "ds-hash-009", + "question": "해시가 사용되는 사례는 무엇인가요?", + "answer": "맵과 셋 같은 자료구조 구현, 데이터베이스 인덱싱, 캐시 키 관리, 비밀번호 저장, 데이터 무결성 검증 등 다양한 곳에 쓰입니다." + }, + { + "id": "ds-hash-010", + "question": "해시맵과 트리맵의 차이는 무엇인가요?", + "answer": "해시맵은 해시로 저장해 순서가 없지만 평균 O(1) 접근이 가능하고, 트리맵은 정렬 순서를 유지하지만 O(log n) 접근입니다. 정렬이 필요하면 트리맵을 씁니다." + } + ] + }, + { + "id": "ds-graph", + "name": "그래프", + "questions": [ + { + "id": "ds-graph-001", + "question": "그래프란 무엇인가요?", + "answer": "정점(노드)과 그 정점을 잇는 간선으로 이루어진 자료구조입니다. 트리와 달리 사이클이 있을 수 있으며 객체 간 관계를 표현하는 데 적합합니다." + }, + { + "id": "ds-graph-002", + "question": "방향 그래프와 무방향 그래프의 차이는 무엇인가요?", + "answer": "방향 그래프는 간선에 방향이 있어 한쪽으로만 이동할 수 있고, 무방향 그래프는 방향이 없어 양방향으로 이동할 수 있습니다. SNS 팔로우는 방향 그래프로 표현됩니다." + }, + { + "id": "ds-graph-003", + "question": "인접 행렬과 인접 리스트의 차이는 무엇인가요?", + "answer": "인접 행렬은 2차원 배열로 연결을 표현해 간선 확인이 O(1)이지만 공간을 많이 씁니다. 인접 리스트는 연결된 정점만 저장해 희소 그래프에서 공간 효율이 좋습니다." + }, + { + "id": "ds-graph-004", + "question": "DFS와 BFS의 차이는 무엇인가요?", + "answer": "DFS는 한 방향으로 깊이 끝까지 탐색한 뒤 되돌아오며 스택을 쓰고, BFS는 가까운 노드부터 너비 우선으로 탐색하며 큐를 씁니다. BFS는 최단 경로 탐색에 유리합니다." + }, + { + "id": "ds-graph-005", + "question": "DFS는 어떻게 구현하나요?", + "answer": "재귀 호출이나 명시적 스택을 사용해 구현합니다. 한 정점에서 인접한 정점으로 깊이 들어가고, 더 갈 곳이 없으면 이전으로 되돌아가며 방문 여부를 기록합니다." + }, + { + "id": "ds-graph-006", + "question": "BFS가 최단 경로를 보장하는 이유는 무엇인가요?", + "answer": "가까운 정점부터 단계별로 탐색하므로, 가중치가 없는 그래프에서 처음 도달한 경로가 곧 최단 경로가 되기 때문입니다." + }, + { + "id": "ds-graph-007", + "question": "최단 경로 알고리즘에는 어떤 것들이 있나요?", + "answer": "한 정점에서 다른 모든 정점까지의 다익스트라, 음수 간선을 다루는 벨만-포드, 모든 쌍 최단 경로를 구하는 플로이드-워셜 등이 있습니다." + }, + { + "id": "ds-graph-008", + "question": "위상 정렬이란 무엇인가요?", + "answer": "방향 그래프에서 선후 관계를 어기지 않도록 정점을 일렬로 나열하는 것입니다. 작업 순서나 선수 과목처럼 의존 관계가 있는 일정에 사용됩니다." + }, + { + "id": "ds-graph-009", + "question": "최소 신장 트리란 무엇인가요?", + "answer": "그래프의 모든 정점을 사이클 없이 연결하면서 간선 가중치의 합이 최소가 되는 트리입니다. 크루스칼과 프림 알고리즘으로 구할 수 있습니다." + }, + { + "id": "ds-graph-010", + "question": "그래프에서 사이클을 어떻게 탐지하나요?", + "answer": "무방향 그래프는 DFS 중 방문한 정점을 다시 만나면 사이클로 보고, 방향 그래프는 DFS 재귀 경로에 있는 정점을 다시 만나거나 위상 정렬 실패로 판단합니다." + } + ] + } + ] + }, + { + "id": "algorithm", + "name": "알고리즘", + "categories": [ + { + "id": "algo-complexity", + "name": "복잡도", + "questions": [ + { + "id": "algo-complexity-001", + "question": "시간 복잡도란 무엇인가요?", + "answer": "입력 크기에 따라 알고리즘의 실행 시간이 어떻게 증가하는지를 나타내는 척도입니다. 실제 시간이 아니라 연산 횟수의 증가 추세를 분석합니다." + }, + { + "id": "algo-complexity-002", + "question": "빅오 표기법이란 무엇인가요?", + "answer": "알고리즘의 성능을 입력 크기에 대한 최악의 증가율로 표현하는 표기법입니다. 상수와 낮은 차수 항을 무시하고 가장 영향이 큰 항만 남깁니다." + }, + { + "id": "algo-complexity-003", + "question": "빅오, 빅오메가, 빅세타의 차이는 무엇인가요?", + "answer": "빅오는 상한(최악), 빅오메가는 하한(최선), 빅세타는 상한과 하한이 같은 정확한 경계를 나타냅니다. 실무에서는 주로 빅오를 사용합니다." + }, + { + "id": "algo-complexity-004", + "question": "O(1), O(log n), O(n), O(n^2)의 차이는 무엇인가요?", + "answer": "O(1)은 입력과 무관한 상수 시간, O(log n)은 입력이 커도 천천히 증가, O(n)은 입력에 비례, O(n^2)는 입력의 제곱에 비례합니다. 뒤로 갈수록 느립니다." + }, + { + "id": "algo-complexity-005", + "question": "공간 복잡도란 무엇인가요?", + "answer": "알고리즘이 실행되는 동안 필요한 메모리 양이 입력 크기에 따라 어떻게 증가하는지를 나타내는 척도입니다. 시간과 공간은 종종 트레이드오프 관계입니다." + }, + { + "id": "algo-complexity-006", + "question": "최선, 평균, 최악의 시간 복잡도는 무엇인가요?", + "answer": "입력에 따라 달라지는 실행 시간을 가장 좋은 경우, 평균적인 경우, 가장 나쁜 경우로 나눈 것입니다. 보통 최악의 경우를 기준으로 성능을 보장합니다." + }, + { + "id": "algo-complexity-007", + "question": "분할 상환 분석(amortized analysis)이란 무엇인가요?", + "answer": "개별 연산이 가끔 오래 걸려도 여러 연산에 걸쳐 평균을 내면 비용이 작은 경우를 분석하는 방법입니다. 동적 배열의 삽입 비용 분석이 대표적입니다." + }, + { + "id": "algo-complexity-008", + "question": "지수 시간 복잡도가 문제가 되는 이유는 무엇인가요?", + "answer": "O(2^n) 같은 지수 시간은 입력이 조금만 커져도 연산량이 폭발적으로 늘어 현실적인 시간 안에 끝나지 않기 때문입니다. 그래서 더 효율적인 알고리즘이 필요합니다." + }, + { + "id": "algo-complexity-009", + "question": "재귀 알고리즘의 시간 복잡도는 어떻게 분석하나요?", + "answer": "호출 횟수와 각 호출의 작업량을 점화식으로 세운 뒤 마스터 정리 등으로 풀어 분석합니다. 재귀 호출 트리를 그려 전체 비용을 합산하기도 합니다." + }, + { + "id": "algo-complexity-010", + "question": "알고리즘 성능에서 상수를 무시하는 이유는 무엇인가요?", + "answer": "입력이 충분히 커지면 증가율이 전체 성능을 좌우하기 때문입니다. 상수 차이는 큰 규모에서 영향이 작아져 점근적 분석에서는 무시합니다." + } + ] + }, + { + "id": "algo-sort", + "name": "정렬", + "questions": [ + { + "id": "algo-sort-001", + "question": "버블 정렬은 어떻게 동작하나요?", + "answer": "인접한 두 원소를 비교해 순서가 잘못되면 교환하는 과정을 반복합니다. 구현이 단순하지만 시간 복잡도가 O(n^2)이라 비효율적입니다." + }, + { + "id": "algo-sort-002", + "question": "선택 정렬은 어떻게 동작하나요?", + "answer": "남은 원소 중 최솟값을 찾아 맨 앞과 교환하는 과정을 반복합니다. 교환 횟수가 적지만 비교는 항상 O(n^2)만큼 수행합니다." + }, + { + "id": "algo-sort-003", + "question": "삽입 정렬은 어떻게 동작하나요?", + "answer": "정렬된 부분에 새 원소를 적절한 위치에 끼워 넣는 과정을 반복합니다. 거의 정렬된 데이터에서는 O(n)에 가까워 매우 빠릅니다." + }, + { + "id": "algo-sort-004", + "question": "퀵 정렬은 어떻게 동작하나요?", + "answer": "기준값(피벗)을 정해 그보다 작은 값과 큰 값으로 분할한 뒤 각 부분을 재귀적으로 정렬합니다. 평균 O(n log n)으로 빠르지만 최악에는 O(n^2)이 됩니다." + }, + { + "id": "algo-sort-005", + "question": "병합 정렬은 어떻게 동작하나요?", + "answer": "배열을 반으로 나누어 각각 정렬한 뒤 두 정렬된 배열을 병합합니다. 항상 O(n log n)을 보장하고 안정 정렬이지만 추가 메모리가 필요합니다." + }, + { + "id": "algo-sort-006", + "question": "힙 정렬은 어떻게 동작하나요?", + "answer": "데이터를 최대 힙으로 만든 뒤 루트의 최댓값을 꺼내 뒤로 보내는 과정을 반복합니다. O(n log n)을 보장하고 추가 메모리가 거의 필요 없습니다." + }, + { + "id": "algo-sort-007", + "question": "퀵 정렬이 평균적으로 병합 정렬보다 빠른 이유는 무엇인가요?", + "answer": "제자리에서 정렬해 추가 메모리 이동이 적고, 캐시 적중률이 높으며 상수 인자가 작기 때문입니다. 그래서 평균적인 실제 성능이 좋습니다." + }, + { + "id": "algo-sort-008", + "question": "안정 정렬과 불안정 정렬의 차이는 무엇인가요?", + "answer": "안정 정렬은 값이 같은 원소들의 원래 순서를 유지하고, 불안정 정렬은 그렇지 않습니다. 병합 정렬은 안정, 퀵 정렬과 힙 정렬은 불안정합니다." + }, + { + "id": "algo-sort-009", + "question": "기수 정렬과 계수 정렬은 무엇인가요?", + "answer": "비교가 아니라 자릿수나 값의 빈도를 이용해 정렬하는 방식입니다. 특정 조건에서 O(n)에 가까운 성능을 내지만 데이터 범위에 제약이 있습니다." + }, + { + "id": "algo-sort-010", + "question": "상황에 따라 정렬 알고리즘을 어떻게 선택하나요?", + "answer": "데이터가 거의 정렬됐으면 삽입 정렬, 안정성이 필요하면 병합 정렬, 메모리가 빠듯하면 힙 정렬, 일반적으로는 평균 성능이 좋은 퀵 정렬을 고려합니다." + }, + { + "id": "algo-sort-011", + "question": "퀵 정렬의 동작 원리는 무엇인가요?", + "answer": "피벗을 기준으로 작은 값과 큰 값으로 분할한 뒤 각 부분을 재귀적으로 정렬합니다. 평균 O(n log n)이지만 최악은 O(n제곱)입니다." + }, + { + "id": "algo-sort-012", + "question": "병합 정렬의 특징은 무엇인가요?", + "answer": "분할 정복으로 나눈 뒤 정렬하며 병합합니다. 항상 O(n log n)을 보장하고 안정 정렬이지만 추가 메모리가 필요합니다." + }, + { + "id": "algo-sort-013", + "question": "안정 정렬이란 무엇인가요?", + "answer": "값이 같은 원소들의 원래 순서가 정렬 후에도 유지되는 정렬입니다. 병합 정렬과 삽입 정렬이 안정 정렬에 해당합니다." + }, + { + "id": "algo-sort-014", + "question": "힙 정렬은 어떻게 동작하나요?", + "answer": "데이터를 힙으로 구성한 뒤 최댓값을 하나씩 꺼내 정렬합니다. O(n log n)을 보장하며 추가 메모리가 거의 필요 없습니다." + } + ] + }, + { + "id": "algo-search", + "name": "탐색", + "questions": [ + { + "id": "algo-search-001", + "question": "선형 탐색과 이진 탐색의 차이는 무엇인가요?", + "answer": "선형 탐색은 처음부터 하나씩 비교해 O(n)이고, 이진 탐색은 정렬된 데이터를 절반씩 줄이며 비교해 O(log n)입니다. 이진 탐색은 정렬이 전제됩니다." + }, + { + "id": "algo-search-002", + "question": "이진 탐색의 동작 원리는 무엇인가요?", + "answer": "정렬된 배열의 중간값과 목표값을 비교해 작으면 왼쪽, 크면 오른쪽 절반만 다시 탐색합니다. 매 단계마다 범위가 절반으로 줄어 빠르게 찾습니다." + }, + { + "id": "algo-search-003", + "question": "이진 탐색을 사용하기 위한 전제 조건은 무엇인가요?", + "answer": "데이터가 정렬되어 있어야 하고, 인덱스로 임의 접근이 가능해야 합니다. 정렬되지 않았다면 먼저 정렬하거나 다른 탐색을 써야 합니다." + }, + { + "id": "algo-search-004", + "question": "해시 탐색은 왜 빠른가요?", + "answer": "해시 함수로 키를 위치로 즉시 변환해 한 번에 접근하기 때문입니다. 충돌이 없다면 평균 O(1)에 데이터를 찾을 수 있습니다." + }, + { + "id": "algo-search-005", + "question": "완전 탐색(브루트 포스)이란 무엇인가요?", + "answer": "가능한 모든 경우를 빠짐없이 시도해 답을 찾는 방법입니다. 확실하지만 경우의 수가 많으면 매우 느려져 입력이 작을 때 주로 사용합니다." + }, + { + "id": "algo-search-006", + "question": "백트래킹이란 무엇인가요?", + "answer": "해를 찾는 도중 조건에 맞지 않으면 이전 단계로 되돌아가 다른 경로를 시도하는 방법입니다. 불필요한 탐색을 가지치기해 완전 탐색보다 효율적입니다." + }, + { + "id": "algo-search-007", + "question": "DFS와 백트래킹의 관계는 무엇인가요?", + "answer": "백트래킹은 DFS 기반으로 해를 탐색하면서, 가망이 없는 분기를 미리 잘라내는 가지치기를 추가한 것입니다. 그래서 탐색 공간을 크게 줄입니다." + }, + { + "id": "algo-search-008", + "question": "이분 탐색을 응용하는 파라메트릭 서치란 무엇인가요?", + "answer": "최적화 문제를 결정 문제로 바꾼 뒤, 답이 될 수 있는 값의 범위에서 이진 탐색으로 경계를 찾는 기법입니다. 조건을 만족하는 최솟값이나 최댓값을 구할 때 씁니다." + }, + { + "id": "algo-search-009", + "question": "투 포인터 기법이란 무엇인가요?", + "answer": "배열에 두 개의 포인터를 두고 조건에 따라 이동시키며 탐색하는 기법입니다. 정렬된 배열에서 합이나 구간 문제를 O(n)에 푸는 데 효과적입니다." + }, + { + "id": "algo-search-010", + "question": "슬라이딩 윈도우 기법이란 무엇인가요?", + "answer": "고정되거나 변하는 구간을 한 칸씩 이동시키며 부분 합이나 최댓값을 효율적으로 구하는 기법입니다. 매번 다시 계산하지 않아 시간을 크게 줄입니다." + } + ] + }, + { + "id": "algo-paradigm", + "name": "알고리즘 설계 기법", + "questions": [ + { + "id": "algo-paradigm-001", + "question": "분할 정복이란 무엇인가요?", + "answer": "큰 문제를 작은 부분 문제로 나누어 각각 해결한 뒤 합쳐 전체 답을 구하는 기법입니다. 병합 정렬과 퀵 정렬이 대표적인 예입니다." + }, + { + "id": "algo-paradigm-002", + "question": "동적 계획법이란 무엇인가요?", + "answer": "큰 문제를 작은 부분 문제로 나누되, 한 번 계산한 결과를 저장해 재사용함으로써 중복 계산을 피하는 기법입니다. 피보나치 수열 계산이 대표적입니다." + }, + { + "id": "algo-paradigm-003", + "question": "동적 계획법을 적용하기 위한 조건은 무엇인가요?", + "answer": "큰 문제가 작은 부분 문제로 나뉘는 최적 부분 구조와, 같은 부분 문제가 반복되는 중복 부분 문제 두 조건을 만족해야 합니다." + }, + { + "id": "algo-paradigm-004", + "question": "메모이제이션과 타뷸레이션의 차이는 무엇인가요?", + "answer": "메모이제이션은 재귀 호출 결과를 저장하는 하향식 방식이고, 타뷸레이션은 작은 문제부터 표를 채워 올라가는 상향식 방식입니다. 둘 다 중복 계산을 막습니다." + }, + { + "id": "algo-paradigm-005", + "question": "그리디 알고리즘이란 무엇인가요?", + "answer": "매 순간 가장 좋아 보이는 선택을 하는 방법입니다. 구현이 간단하고 빠르지만, 항상 전체 최적해를 보장하지는 않아 적용 조건을 확인해야 합니다." + }, + { + "id": "algo-paradigm-006", + "question": "그리디 알고리즘이 최적해를 보장하는 조건은 무엇인가요?", + "answer": "지역적 최적 선택이 전체 최적해로 이어지는 탐욕적 선택 속성과 최적 부분 구조를 만족할 때입니다. 동전 거스름돈 문제 등에서 성립합니다." + }, + { + "id": "algo-paradigm-007", + "question": "동적 계획법과 그리디의 차이는 무엇인가요?", + "answer": "동적 계획법은 모든 부분 문제를 고려해 최적해를 찾고, 그리디는 매 단계 최선만 골라 빠르게 진행합니다. 그리디가 빠르지만 적용 범위가 제한적입니다." + }, + { + "id": "algo-paradigm-008", + "question": "분할 정복과 동적 계획법의 차이는 무엇인가요?", + "answer": "둘 다 문제를 나누지만, 분할 정복은 부분 문제가 겹치지 않고, 동적 계획법은 부분 문제가 겹쳐 결과를 저장해 재사용합니다." + }, + { + "id": "algo-paradigm-009", + "question": "다익스트라 알고리즘은 어떻게 동작하나요?", + "answer": "시작 정점에서 가장 가까운 정점부터 확정해 나가며 최단 거리를 갱신합니다. 우선순위 큐를 사용하면 효율적이며, 음수 가중치가 없어야 동작합니다." + }, + { + "id": "algo-paradigm-010", + "question": "비트마스킹을 알고리즘에 어떻게 활용하나요?", + "answer": "여러 원소의 포함 여부를 하나의 정수 비트로 표현해 집합 상태를 효율적으로 관리합니다. 부분집합 순회나 동적 계획법의 상태 표현에 자주 쓰입니다." + } + ] + } + ] + }, + { + "id": "oop", + "name": "객체지향 프로그래밍", + "categories": [ + { + "id": "oop-basic", + "name": "객체지향 기초", + "questions": [ + { + "id": "oop-basic-001", + "question": "객체지향 프로그래밍이란 무엇인가요?", + "answer": "프로그램을 객체들의 상호작용으로 구성하는 패러다임입니다. 데이터와 그 데이터를 다루는 동작을 하나의 객체로 묶어 현실 세계를 모델링하는 데 유리합니다." + }, + { + "id": "oop-basic-002", + "question": "절차지향과 객체지향의 차이는 무엇인가요?", + "answer": "절차지향은 함수와 순차적 처리 흐름을 중심으로 프로그램을 구성하고, 객체지향은 데이터와 동작을 묶은 객체를 중심으로 구성합니다. 객체지향이 유지보수와 재사용에 유리합니다." + }, + { + "id": "oop-basic-003", + "question": "클래스와 객체의 차이는 무엇인가요?", + "answer": "클래스는 객체를 만들기 위한 설계도이고, 객체는 그 설계도로 생성된 실체입니다. 붕어빵 틀이 클래스라면 구워진 붕어빵이 객체에 해당합니다." + }, + { + "id": "oop-basic-004", + "question": "인스턴스란 무엇인가요?", + "answer": "클래스를 바탕으로 메모리에 실제로 할당된 객체를 의미합니다. 객체가 메모리에 구체적으로 존재하게 된 상태를 강조할 때 인스턴스라는 표현을 씁니다." + }, + { + "id": "oop-basic-005", + "question": "메서드와 필드의 차이는 무엇인가요?", + "answer": "필드는 객체의 상태를 나타내는 데이터이고, 메서드는 객체가 수행하는 동작입니다. 필드는 명사적 속성, 메서드는 동사적 행위로 이해할 수 있습니다." + }, + { + "id": "oop-basic-006", + "question": "생성자란 무엇인가요?", + "answer": "객체가 생성될 때 호출되어 초기 상태를 설정하는 특수 메서드입니다. 클래스 이름과 같으며 반환형이 없고, 필요한 초기값을 인자로 받을 수 있습니다." + }, + { + "id": "oop-basic-007", + "question": "객체지향의 장점은 무엇인가요?", + "answer": "코드 재사용성이 높고, 변경이 특정 객체에 국한되어 유지보수가 쉬우며, 현실 세계를 직관적으로 모델링할 수 있습니다. 또한 확장에 유연합니다." + }, + { + "id": "oop-basic-008", + "question": "객체지향의 단점은 무엇인가요?", + "answer": "설계가 복잡하고 학습 곡선이 가파르며, 객체 간 관계 설계에 시간이 듭니다. 또한 절차지향에 비해 실행 속도와 메모리 면에서 약간의 오버헤드가 있을 수 있습니다." + }, + { + "id": "oop-basic-009", + "question": "메시지 전달이란 무엇인가요?", + "answer": "객체가 다른 객체의 메서드를 호출해 협력하는 것을 객체지향에서는 메시지 전달이라고 봅니다. 객체들은 메시지를 주고받으며 전체 기능을 완성합니다." + }, + { + "id": "oop-basic-010", + "question": "객체지향에서 책임이란 무엇을 의미하나요?", + "answer": "객체가 맡아 수행해야 하는 역할과 행위를 의미합니다. 책임을 적절히 분배하면 응집도가 높아지고 객체 간 결합이 느슨해져 좋은 설계가 됩니다." + } + ] + }, + { + "id": "oop-feature", + "name": "객체지향 4대 특징", + "questions": [ + { + "id": "oop-feature-001", + "question": "객체지향의 4대 특징은 무엇인가요?", + "answer": "캡슐화, 상속, 다형성, 추상화입니다. 이 네 가지 특징을 통해 재사용성, 확장성, 유지보수성을 높이는 것이 객체지향의 핵심입니다." + }, + { + "id": "oop-feature-002", + "question": "캡슐화란 무엇인가요?", + "answer": "데이터와 그 데이터를 다루는 메서드를 하나로 묶고, 내부 구현을 외부로부터 숨기는 것입니다. 접근 제어자로 직접 접근을 막아 데이터를 안전하게 보호합니다." + }, + { + "id": "oop-feature-003", + "question": "정보 은닉이란 무엇인가요?", + "answer": "객체의 내부 구현과 데이터를 외부에서 직접 접근하지 못하게 감추는 것입니다. 공개된 메서드를 통해서만 접근하게 해 변경의 영향을 줄이고 무결성을 지킵니다." + }, + { + "id": "oop-feature-004", + "question": "상속이란 무엇인가요?", + "answer": "기존 클래스의 속성과 기능을 물려받아 새 클래스를 만드는 것입니다. 코드를 재사용하고 공통 기능을 부모에 모아 계층 구조를 만들 수 있습니다." + }, + { + "id": "oop-feature-005", + "question": "상속의 단점은 무엇인가요?", + "answer": "부모와 자식의 결합도가 높아져 부모 변경이 자식에 영향을 주고, 캡슐화를 약화시킬 수 있습니다. 그래서 상속보다 합성을 권장하는 경우가 많습니다." + }, + { + "id": "oop-feature-006", + "question": "다형성이란 무엇인가요?", + "answer": "같은 메시지에 대해 객체마다 다르게 동작할 수 있는 성질입니다. 같은 메서드 호출이 실제 객체의 타입에 따라 다른 결과를 내어 유연한 코드를 가능하게 합니다." + }, + { + "id": "oop-feature-007", + "question": "오버로딩과 오버라이딩의 차이는 무엇인가요?", + "answer": "오버로딩은 같은 이름의 메서드를 매개변수를 달리해 여러 개 정의하는 것이고, 오버라이딩은 부모의 메서드를 자식이 같은 형태로 재정의하는 것입니다." + }, + { + "id": "oop-feature-008", + "question": "추상화란 무엇인가요?", + "answer": "복잡한 대상에서 핵심적인 개념과 기능만 추출해 단순화하는 것입니다. 불필요한 세부 사항을 감추고 공통의 인터페이스를 정의해 다룰 수 있게 합니다." + }, + { + "id": "oop-feature-009", + "question": "추상 클래스와 인터페이스의 차이는 무엇인가요?", + "answer": "추상 클래스는 공통 기능을 일부 구현해 물려줄 수 있고 단일 상속만 됩니다. 인터페이스는 구현을 강제하는 규약 중심이며 다중 구현이 가능합니다." + }, + { + "id": "oop-feature-010", + "question": "상속과 합성 중 무엇을 선호해야 하나요?", + "answer": "일반적으로 합성을 선호합니다. 상속은 결합도가 높아 변경에 취약한 반면, 합성은 객체를 조립하듯 사용해 유연하고 결합을 느슨하게 유지할 수 있기 때문입니다." + } + ] + }, + { + "id": "oop-solid", + "name": "SOLID 원칙", + "questions": [ + { + "id": "oop-solid-001", + "question": "SOLID 원칙이란 무엇인가요?", + "answer": "객체지향 설계를 잘하기 위한 다섯 가지 원칙의 앞 글자를 딴 것입니다. 단일 책임, 개방-폐쇄, 리스코프 치환, 인터페이스 분리, 의존성 역전 원칙으로 구성됩니다." + }, + { + "id": "oop-solid-002", + "question": "단일 책임 원칙(SRP)이란 무엇인가요?", + "answer": "하나의 클래스는 하나의 책임만 가져야 한다는 원칙입니다. 변경의 이유가 하나여야 하며, 책임이 분리되면 변경의 영향 범위가 줄어 유지보수가 쉬워집니다." + }, + { + "id": "oop-solid-003", + "question": "개방-폐쇄 원칙(OCP)이란 무엇인가요?", + "answer": "확장에는 열려 있고 변경에는 닫혀 있어야 한다는 원칙입니다. 기존 코드를 수정하지 않고 새 기능을 추가할 수 있도록 추상화와 다형성을 활용합니다." + }, + { + "id": "oop-solid-004", + "question": "리스코프 치환 원칙(LSP)이란 무엇인가요?", + "answer": "자식 클래스는 부모 클래스를 대체할 수 있어야 한다는 원칙입니다. 자식이 부모의 기대 동작을 위반하지 않아야 다형성이 안전하게 동작합니다." + }, + { + "id": "oop-solid-005", + "question": "인터페이스 분리 원칙(ISP)이란 무엇인가요?", + "answer": "클라이언트가 사용하지 않는 메서드에 의존하지 않도록 인터페이스를 작게 나눠야 한다는 원칙입니다. 거대한 인터페이스 하나보다 목적별 작은 인터페이스가 좋습니다." + }, + { + "id": "oop-solid-006", + "question": "의존성 역전 원칙(DIP)이란 무엇인가요?", + "answer": "상위 모듈이 하위 모듈의 구체 구현이 아니라 추상화에 의존해야 한다는 원칙입니다. 인터페이스에 의존하면 구현 변경에 유연해지고 결합이 느슨해집니다." + }, + { + "id": "oop-solid-007", + "question": "SOLID 원칙을 지키면 어떤 이점이 있나요?", + "answer": "코드의 결합도가 낮아지고 응집도가 높아져 변경과 확장이 쉬워집니다. 그 결과 유지보수성, 재사용성, 테스트 용이성이 모두 향상됩니다." + }, + { + "id": "oop-solid-008", + "question": "응집도와 결합도란 무엇인가요?", + "answer": "응집도는 한 모듈 내부 요소들이 얼마나 밀접하게 관련됐는지를, 결합도는 모듈 간 의존 정도를 나타냅니다. 좋은 설계는 응집도가 높고 결합도가 낮습니다." + }, + { + "id": "oop-solid-009", + "question": "개방-폐쇄 원칙은 어떻게 구현하나요?", + "answer": "변하는 부분을 인터페이스나 추상 클래스로 추상화하고, 새로운 기능은 이를 구현한 새 클래스로 추가합니다. 그러면 기존 코드 수정 없이 확장할 수 있습니다." + }, + { + "id": "oop-solid-010", + "question": "리스코프 치환 원칙을 위반하는 예는 무엇인가요?", + "answer": "직사각형을 상속한 정사각형이 너비와 높이를 독립적으로 못 바꾸는 경우입니다. 부모를 기대하는 코드가 자식에서 다르게 동작하면 원칙을 위반한 것입니다." + } + ] + } + ] + }, + { + "id": "design-pattern", + "name": "디자인 패턴", + "categories": [ + { + "id": "dp-basic", + "name": "디자인 패턴 기초", + "questions": [ + { + "id": "dp-basic-001", + "question": "디자인 패턴이란 무엇인가요?", + "answer": "소프트웨어 설계에서 자주 발생하는 문제에 대한 검증된 해결 방법을 정리한 것입니다. 특정 코드가 아니라 설계 아이디어이며, 개발자 간 의사소통을 돕는 공통 언어 역할도 합니다." + }, + { + "id": "dp-basic-002", + "question": "디자인 패턴을 사용하면 어떤 이점이 있나요?", + "answer": "검증된 구조를 재사용해 유지보수성과 확장성을 높일 수 있습니다. 또한 패턴 이름으로 설계 의도를 빠르게 공유할 수 있어 협업이 쉬워집니다." + }, + { + "id": "dp-basic-003", + "question": "GoF 디자인 패턴이란 무엇인가요?", + "answer": "네 명의 저자가 정리한 23가지 대표적인 객체지향 디자인 패턴을 말합니다. 생성, 구조, 행위 세 가지 분류로 나뉩니다." + }, + { + "id": "dp-basic-004", + "question": "디자인 패턴의 세 가지 분류는 무엇인가요?", + "answer": "객체 생성을 다루는 생성 패턴, 클래스와 객체의 조합을 다루는 구조 패턴, 객체 간 상호작용과 책임 분배를 다루는 행위 패턴으로 나뉩니다." + }, + { + "id": "dp-basic-005", + "question": "생성 패턴이란 무엇인가요?", + "answer": "객체를 생성하는 방법을 다루는 패턴입니다. 객체 생성 로직을 캡슐화해 유연성을 높이며, 싱글톤, 팩토리 메서드, 추상 팩토리, 빌더, 프로토타입 등이 있습니다." + }, + { + "id": "dp-basic-006", + "question": "구조 패턴이란 무엇인가요?", + "answer": "클래스나 객체를 조합해 더 큰 구조를 만드는 패턴입니다. 어댑터, 데코레이터, 프록시, 퍼사드, 컴포지트 등이 대표적입니다." + }, + { + "id": "dp-basic-007", + "question": "행위 패턴이란 무엇인가요?", + "answer": "객체 사이의 책임 분배와 알고리즘, 상호작용을 다루는 패턴입니다. 옵저버, 전략, 템플릿 메서드, 커맨드, 상태 패턴 등이 있습니다." + }, + { + "id": "dp-basic-008", + "question": "디자인 패턴과 아키텍처 패턴의 차이는 무엇인가요?", + "answer": "디자인 패턴은 클래스와 객체 수준의 설계 문제를 다루고, 아키텍처 패턴은 MVC나 레이어드 아키텍처처럼 시스템 전체 구조를 다룹니다. 적용 범위의 크기가 다릅니다." + } + ] + }, + { + "id": "dp-creational", + "name": "생성 패턴", + "questions": [ + { + "id": "dp-creational-001", + "question": "싱글톤 패턴이란 무엇인가요?", + "answer": "클래스의 인스턴스가 하나만 생성되도록 보장하고 전역적인 접근점을 제공하는 패턴입니다. 설정 정보나 커넥션 풀처럼 공유 자원에 자주 쓰입니다." + }, + { + "id": "dp-creational-002", + "question": "싱글톤 패턴의 단점은 무엇인가요?", + "answer": "전역 상태를 만들어 결합도를 높이고 테스트를 어렵게 만들 수 있습니다. 또한 멀티스레드 환경에서 동기화를 신경 쓰지 않으면 인스턴스가 여러 개 생길 수 있습니다." + }, + { + "id": "dp-creational-003", + "question": "멀티스레드 환경에서 싱글톤을 안전하게 만드는 방법은 무엇인가요?", + "answer": "정적 초기화로 클래스 로딩 시점에 생성하거나, 이중 검사 잠금에 volatile을 사용하거나, 자바에서는 enum 또는 holder 클래스를 활용하는 방법이 있습니다." + }, + { + "id": "dp-creational-004", + "question": "팩토리 메서드 패턴이란 무엇인가요?", + "answer": "객체 생성을 서브클래스에 위임해 어떤 객체를 만들지 결정하게 하는 패턴입니다. 생성 로직과 사용 로직을 분리해 새 타입 추가가 쉬워집니다." + }, + { + "id": "dp-creational-005", + "question": "추상 팩토리 패턴이란 무엇인가요?", + "answer": "서로 관련된 객체들의 집합을 일관되게 생성하는 인터페이스를 제공하는 패턴입니다. 구체 클래스를 지정하지 않고 제품군을 통째로 교체할 수 있습니다." + }, + { + "id": "dp-creational-006", + "question": "빌더 패턴이란 무엇인가요?", + "answer": "복잡한 객체를 단계별로 생성하도록 분리하는 패턴입니다. 선택적 파라미터가 많을 때 생성자 오버로딩 없이 가독성 좋게 객체를 만들 수 있습니다." + }, + { + "id": "dp-creational-007", + "question": "빌더 패턴은 언제 사용하나요?", + "answer": "생성자 인자가 많거나 선택적 필드가 많아 생성자가 복잡해질 때 사용합니다. 메서드 체이닝으로 어떤 값을 설정하는지 명확하게 표현할 수 있습니다." + }, + { + "id": "dp-creational-008", + "question": "프로토타입 패턴이란 무엇인가요?", + "answer": "기존 객체를 복제해 새 객체를 만드는 패턴입니다. 생성 비용이 큰 객체를 새로 만들지 않고 복사해 사용하며, 자바에서는 clone으로 구현할 수 있습니다." + }, + { + "id": "dp-creational-009", + "question": "팩토리 메서드와 추상 팩토리의 차이는 무엇인가요?", + "answer": "팩토리 메서드는 하나의 객체 생성을 서브클래스에 위임하고, 추상 팩토리는 관련된 여러 객체의 집합을 생성합니다. 추상 팩토리가 더 큰 단위의 생성을 다룹니다." + }, + { + "id": "dp-creational-010", + "question": "객체 생성을 캡슐화하면 어떤 이점이 있나요?", + "answer": "생성 로직이 한 곳에 모여 변경이 쉬워지고, 클라이언트는 구체 클래스를 몰라도 됩니다. 결합도가 낮아져 새로운 구현으로 교체하기 편해집니다." + } + ] + }, + { + "id": "dp-structural", + "name": "구조 패턴", + "questions": [ + { + "id": "dp-structural-001", + "question": "어댑터 패턴이란 무엇인가요?", + "answer": "호환되지 않는 인터페이스를 클라이언트가 기대하는 형태로 변환해 주는 패턴입니다. 기존 코드를 수정하지 않고 다른 인터페이스와 연결할 때 사용합니다." + }, + { + "id": "dp-structural-002", + "question": "데코레이터 패턴이란 무엇인가요?", + "answer": "객체에 동적으로 기능을 덧붙이는 패턴입니다. 상속 대신 위임을 사용해 기능을 조합하며, 원본 객체를 감싸 같은 인터페이스를 유지합니다." + }, + { + "id": "dp-structural-003", + "question": "프록시 패턴이란 무엇인가요?", + "answer": "실제 객체에 대한 접근을 제어하는 대리 객체를 두는 패턴입니다. 지연 초기화, 접근 제어, 로깅, 캐싱 등의 부가 기능을 투명하게 추가할 수 있습니다." + }, + { + "id": "dp-structural-004", + "question": "퍼사드 패턴이란 무엇인가요?", + "answer": "복잡한 서브시스템에 대한 단순한 통합 인터페이스를 제공하는 패턴입니다. 클라이언트는 내부 구조를 몰라도 간단한 진입점으로 기능을 사용할 수 있습니다." + }, + { + "id": "dp-structural-005", + "question": "컴포지트 패턴이란 무엇인가요?", + "answer": "개별 객체와 객체들의 묶음을 동일하게 다루도록 트리 구조로 구성하는 패턴입니다. 파일과 폴더처럼 부분과 전체를 같은 방식으로 처리할 때 유용합니다." + }, + { + "id": "dp-structural-006", + "question": "데코레이터 패턴과 상속의 차이는 무엇인가요?", + "answer": "상속은 컴파일 시점에 기능이 고정되지만, 데코레이터는 런타임에 기능을 조합할 수 있습니다. 여러 기능을 유연하게 중첩할 수 있다는 점이 장점입니다." + }, + { + "id": "dp-structural-007", + "question": "프록시 패턴의 종류에는 무엇이 있나요?", + "answer": "객체 생성을 미루는 가상 프록시, 권한을 검사하는 보호 프록시, 원격 객체에 접근하는 원격 프록시 등이 있습니다. 스프링 AOP도 프록시를 활용합니다." + }, + { + "id": "dp-structural-008", + "question": "어댑터 패턴은 실무에서 어떻게 쓰이나요?", + "answer": "외부 라이브러리나 레거시 코드의 인터페이스를 현재 시스템에 맞춰 감쌀 때 사용합니다. 예를 들어 서로 다른 결제 API를 공통 인터페이스로 통합할 수 있습니다." + } + ] + }, + { + "id": "dp-behavioral", + "name": "행위 패턴", + "questions": [ + { + "id": "dp-behavioral-001", + "question": "옵저버 패턴이란 무엇인가요?", + "answer": "한 객체의 상태가 변하면 의존하는 객체들에게 자동으로 통지하는 패턴입니다. 발행-구독 구조로 일대다 관계를 느슨하게 연결할 때 사용합니다." + }, + { + "id": "dp-behavioral-002", + "question": "전략 패턴이란 무엇인가요?", + "answer": "알고리즘을 인터페이스로 정의하고 런타임에 교체할 수 있게 하는 패턴입니다. 조건문으로 분기하는 대신 동작을 캡슐화해 유연하게 바꿀 수 있습니다." + }, + { + "id": "dp-behavioral-003", + "question": "템플릿 메서드 패턴이란 무엇인가요?", + "answer": "알고리즘의 골격을 상위 클래스에서 정의하고 일부 단계를 하위 클래스에서 구현하게 하는 패턴입니다. 공통 흐름은 재사용하고 세부만 변경할 수 있습니다." + }, + { + "id": "dp-behavioral-004", + "question": "커맨드 패턴이란 무엇인가요?", + "answer": "요청을 객체로 캡슐화해 실행, 취소, 큐잉, 로깅을 가능하게 하는 패턴입니다. 요청을 보내는 쪽과 처리하는 쪽을 분리합니다." + }, + { + "id": "dp-behavioral-005", + "question": "상태 패턴이란 무엇인가요?", + "answer": "객체의 상태에 따라 행동이 달라지도록 상태를 객체로 분리하는 패턴입니다. 상태별 분기문을 제거하고 상태 전이를 명확하게 표현할 수 있습니다." + }, + { + "id": "dp-behavioral-006", + "question": "전략 패턴과 상태 패턴의 차이는 무엇인가요?", + "answer": "둘 다 동작을 객체로 분리하지만, 전략은 클라이언트가 알고리즘을 선택하고, 상태는 내부 상태 변화에 따라 스스로 행동이 바뀝니다." + }, + { + "id": "dp-behavioral-007", + "question": "이터레이터 패턴이란 무엇인가요?", + "answer": "컬렉션의 내부 구조를 노출하지 않고 요소를 순차적으로 접근하는 방법을 제공하는 패턴입니다. 자바의 Iterator 인터페이스가 대표적인 예입니다." + }, + { + "id": "dp-behavioral-008", + "question": "옵저버 패턴은 어디에 활용되나요?", + "answer": "이벤트 처리, GUI 리스너, 발행-구독 메시징 등에 활용됩니다. 스프링의 ApplicationEvent와 리스너 구조도 옵저버 패턴의 한 예입니다." + } + ] + } + ] + }, + { + "id": "java", + "name": "자바", + "categories": [ + { + "id": "java-jvm", + "name": "JVM과 메모리", + "questions": [ + { + "id": "java-jvm-001", + "question": "JVM이란 무엇인가요?", + "answer": "자바 바이트코드를 실행하는 가상 머신입니다. 운영체제에 독립적으로 동작하게 해 주어, 한 번 컴파일한 코드를 여러 플랫폼에서 실행할 수 있게 합니다." + }, + { + "id": "java-jvm-002", + "question": "JVM, JRE, JDK의 차이는 무엇인가요?", + "answer": "JVM은 바이트코드 실행 엔진이고, JRE는 JVM과 실행에 필요한 라이브러리를 포함하며, JDK는 JRE에 컴파일러 같은 개발 도구까지 더한 개발 키트입니다." + }, + { + "id": "java-jvm-003", + "question": "자바 코드가 실행되는 과정은 어떻게 되나요?", + "answer": "자바 소스를 컴파일러가 바이트코드(.class)로 변환하고, JVM이 이를 로딩한 뒤 인터프리터와 JIT 컴파일러로 기계어로 바꿔 실행합니다." + }, + { + "id": "java-jvm-004", + "question": "JVM 메모리 구조는 어떻게 구성되나요?", + "answer": "메서드 영역, 힙, 스택, PC 레지스터, 네이티브 메서드 스택으로 구성됩니다. 객체는 힙에, 지역 변수와 호출 정보는 스택에 저장됩니다." + }, + { + "id": "java-jvm-005", + "question": "힙 영역과 스택 영역의 차이는 무엇인가요?", + "answer": "힙은 객체와 배열이 저장되며 모든 스레드가 공유합니다. 스택은 메서드 호출의 지역 변수와 매개변수를 저장하며 스레드마다 별도로 생성됩니다." + }, + { + "id": "java-jvm-006", + "question": "가비지 컬렉션이란 무엇인가요?", + "answer": "더 이상 참조되지 않는 객체를 자동으로 찾아 메모리를 회수하는 기능입니다. 개발자가 직접 메모리를 해제하지 않아도 되도록 돕습니다." + }, + { + "id": "java-jvm-007", + "question": "가비지 컬렉션은 어떤 객체를 회수 대상으로 판단하나요?", + "answer": "GC 루트에서 시작해 참조를 따라가며 도달 가능한 객체를 표시하고, 도달할 수 없는 객체를 회수 대상으로 판단합니다. 이를 도달 가능성 분석이라고 합니다." + }, + { + "id": "java-jvm-008", + "question": "Minor GC와 Major GC의 차이는 무엇인가요?", + "answer": "Minor GC는 새 객체가 모인 Young 영역을 청소하고 비교적 빠릅니다. Major GC는 오래 살아남은 객체가 있는 Old 영역을 청소하며 더 오래 걸립니다." + }, + { + "id": "java-jvm-009", + "question": "JIT 컴파일러란 무엇인가요?", + "answer": "실행 중 자주 사용되는 바이트코드를 기계어로 미리 컴파일해 성능을 높이는 컴파일러입니다. 인터프리터 방식의 느린 점을 보완합니다." + }, + { + "id": "java-jvm-010", + "question": "메모리 누수는 자바에서도 발생하나요?", + "answer": "GC가 있어도 발생할 수 있습니다. 사용하지 않는 객체를 컬렉션이나 정적 필드가 계속 참조하면 회수되지 않아 누수가 생깁니다." + }, + { + "id": "java-jvm-011", + "question": "클래스 로더란 무엇인가요?", + "answer": "클래스 파일을 JVM 메모리에 적재하는 역할을 합니다. 로딩, 링크, 초기화 단계를 거치며 부모에게 먼저 위임하는 구조로 동작합니다." + }, + { + "id": "java-jvm-012", + "question": "Stop the world란 무엇인가요?", + "answer": "가비지 컬렉션을 수행하기 위해 모든 애플리케이션 스레드를 잠시 멈추는 현상입니다. 이 시간이 길면 응답 지연이 발생합니다." + }, + { + "id": "java-jvm-013", + "question": "String 풀이란 무엇인가요?", + "answer": "동일한 문자열 리터럴을 공유해 재사용하는 메모리 영역입니다. 같은 리터럴은 하나의 객체를 가리켜 메모리를 절약합니다." + } + ] + }, + { + "id": "java-lang", + "name": "자바 언어 기초", + "questions": [ + { + "id": "java-lang-001", + "question": "기본형과 참조형의 차이는 무엇인가요?", + "answer": "기본형은 int나 double처럼 값 자체를 저장하고, 참조형은 객체의 주소를 저장합니다. 기본형은 스택에, 참조형이 가리키는 객체는 힙에 위치합니다." + }, + { + "id": "java-lang-002", + "question": "== 와 equals의 차이는 무엇인가요?", + "answer": "==는 기본형은 값을, 참조형은 주소를 비교합니다. equals는 객체의 내용이 같은지 비교하며, 필요에 따라 재정의해 동등성 기준을 정합니다." + }, + { + "id": "java-lang-003", + "question": "String이 불변인 이유는 무엇인가요?", + "answer": "보안, 캐싱, 스레드 안전성 때문입니다. 불변이기에 문자열 풀에서 공유할 수 있고, 여러 스레드가 동시에 사용해도 안전합니다." + }, + { + "id": "java-lang-004", + "question": "String, StringBuilder, StringBuffer의 차이는 무엇인가요?", + "answer": "String은 불변이라 연결 시 새 객체를 만듭니다. StringBuilder는 가변이며 단일 스레드에서 빠르고, StringBuffer는 동기화되어 스레드 안전합니다." + }, + { + "id": "java-lang-005", + "question": "오버로딩과 오버라이딩의 차이는 무엇인가요?", + "answer": "오버로딩은 같은 이름의 메서드를 매개변수를 달리해 여러 개 정의하는 것이고, 오버라이딩은 상위 클래스의 메서드를 하위 클래스에서 재정의하는 것입니다." + }, + { + "id": "java-lang-006", + "question": "추상 클래스와 인터페이스의 차이는 무엇인가요?", + "answer": "추상 클래스는 상태와 구현을 가질 수 있고 단일 상속만 됩니다. 인터페이스는 주로 동작 명세를 정의하며 다중 구현이 가능합니다." + }, + { + "id": "java-lang-007", + "question": "오토박싱과 언박싱이란 무엇인가요?", + "answer": "기본형과 래퍼 클래스 사이의 자동 변환을 말합니다. int가 Integer로 바뀌는 것이 오토박싱, 반대로 풀리는 것이 언박싱입니다." + }, + { + "id": "java-lang-008", + "question": "제네릭이란 무엇인가요?", + "answer": "타입을 파라미터로 받아 컴파일 시점에 타입 안정성을 보장하는 기능입니다. 형 변환을 줄이고 잘못된 타입 사용을 컴파일 단계에서 막아 줍니다." + }, + { + "id": "java-lang-009", + "question": "예외의 종류에는 무엇이 있나요?", + "answer": "컴파일러가 처리를 강제하는 검사 예외, 런타임에 발생하는 비검사 예외(RuntimeException), 그리고 복구하기 어려운 Error가 있습니다." + }, + { + "id": "java-lang-010", + "question": "final 키워드는 어떤 역할을 하나요?", + "answer": "변수에 쓰면 값을 바꿀 수 없게, 메서드에 쓰면 재정의를 막고, 클래스에 쓰면 상속을 금지합니다. 불변성과 안정성을 보장할 때 사용합니다." + } + ] + }, + { + "id": "java-collection", + "name": "컬렉션 프레임워크", + "questions": [ + { + "id": "java-collection-001", + "question": "자바 컬렉션 프레임워크란 무엇인가요?", + "answer": "데이터의 집합을 다루기 위한 표준화된 자료구조와 알고리즘의 모음입니다. List, Set, Map, Queue 등의 인터페이스와 구현 클래스로 구성됩니다." + }, + { + "id": "java-collection-002", + "question": "List, Set, Map의 차이는 무엇인가요?", + "answer": "List는 순서가 있고 중복을 허용하며, Set은 중복을 허용하지 않고, Map은 키-값 쌍으로 데이터를 저장합니다." + }, + { + "id": "java-collection-003", + "question": "ArrayList와 LinkedList의 차이는 무엇인가요?", + "answer": "ArrayList는 배열 기반이라 인덱스 조회가 빠르고 중간 삽입이 느립니다. LinkedList는 노드 연결 기반이라 삽입과 삭제가 유리하고 인덱스 조회가 느립니다." + }, + { + "id": "java-collection-004", + "question": "HashMap은 어떻게 동작하나요?", + "answer": "키의 해시코드로 버킷 위치를 정하고 값을 저장합니다. 해시 충돌이 나면 같은 버킷에 연결 리스트나 트리 형태로 저장합니다." + }, + { + "id": "java-collection-005", + "question": "HashMap과 HashTable의 차이는 무엇인가요?", + "answer": "HashTable은 메서드가 동기화되어 스레드 안전하지만 느리고, HashMap은 동기화되지 않아 단일 스레드에서 빠릅니다. HashMap은 null 키와 값을 허용합니다." + }, + { + "id": "java-collection-006", + "question": "HashSet은 중복을 어떻게 제거하나요?", + "answer": "내부적으로 HashMap을 사용해 요소를 키로 저장합니다. 추가 시 hashCode와 equals로 같은 객체인지 판단해 중복을 걸러냅니다." + }, + { + "id": "java-collection-007", + "question": "HashMap, TreeMap, LinkedHashMap의 차이는 무엇인가요?", + "answer": "HashMap은 순서를 보장하지 않고, TreeMap은 키를 정렬된 순서로 유지하며, LinkedHashMap은 입력 순서를 유지합니다." + }, + { + "id": "java-collection-008", + "question": "hashCode와 equals를 함께 재정의해야 하는 이유는 무엇인가요?", + "answer": "해시 기반 컬렉션은 hashCode로 버킷을 찾고 equals로 동일성을 비교합니다. 두 메서드의 규약이 어긋나면 같은 객체를 다르게 판단해 오작동합니다." + }, + { + "id": "java-collection-009", + "question": "동기화된 컬렉션을 사용하려면 어떻게 하나요?", + "answer": "Collections.synchronizedList 같은 래퍼를 쓰거나, 동시성 패키지의 ConcurrentHashMap, CopyOnWriteArrayList 등을 사용합니다. 후자가 성능 면에서 유리합니다." + }, + { + "id": "java-collection-010", + "question": "Iterator와 ListIterator의 차이는 무엇인가요?", + "answer": "Iterator는 단방향 순회만 가능하고, ListIterator는 양방향 순회와 순회 중 요소 추가, 수정이 가능합니다. ListIterator는 List에서만 사용합니다." + }, + { + "id": "java-collection-011", + "question": "fail-fast와 fail-safe의 차이는 무엇인가요?", + "answer": "fail-fast는 순회 중 컬렉션이 변경되면 즉시 예외를 던지고, fail-safe는 복사본을 순회해 예외 없이 동작합니다." + }, + { + "id": "java-collection-012", + "question": "Comparable과 Comparator의 차이는 무엇인가요?", + "answer": "Comparable은 객체 자신의 기본 정렬 기준을 정의하고, Comparator는 외부에서 별도의 정렬 기준을 제공합니다." + }, + { + "id": "java-collection-013", + "question": "List에서 요소를 순회하며 삭제할 때 주의할 점은 무엇인가요?", + "answer": "일반 for-each에서 직접 삭제하면 ConcurrentModificationException이 납니다. Iterator의 remove를 쓰거나 removeIf를 사용해야 합니다." + } + ] + }, + { + "id": "java-concurrency", + "name": "멀티스레드", + "questions": [ + { + "id": "java-concurrency-001", + "question": "프로세스와 스레드의 차이는 무엇인가요?", + "answer": "프로세스는 독립된 메모리를 가진 실행 단위이고, 스레드는 프로세스 내에서 메모리를 공유하며 동작하는 실행 흐름입니다. 스레드 생성이 더 가볍습니다." + }, + { + "id": "java-concurrency-002", + "question": "자바에서 스레드를 만드는 방법은 무엇인가요?", + "answer": "Thread 클래스를 상속하거나 Runnable 인터페이스를 구현하는 방법이 있습니다. 실무에서는 보통 ExecutorService 같은 스레드 풀을 사용합니다." + }, + { + "id": "java-concurrency-003", + "question": "synchronized 키워드는 어떤 역할을 하나요?", + "answer": "한 번에 하나의 스레드만 임계 영역에 접근하도록 잠금을 거는 키워드입니다. 메서드나 블록 단위로 적용해 데이터 경쟁을 방지합니다." + }, + { + "id": "java-concurrency-004", + "question": "volatile 키워드란 무엇인가요?", + "answer": "변수를 항상 메인 메모리에서 읽고 쓰도록 보장하는 키워드입니다. 스레드 간 가시성 문제를 해결하지만 원자성은 보장하지 않습니다." + }, + { + "id": "java-concurrency-005", + "question": "동기화에서 가시성과 원자성이란 무엇인가요?", + "answer": "가시성은 한 스레드의 변경이 다른 스레드에 보이는지를, 원자성은 연산이 중간에 끼어들 수 없이 한 번에 수행되는지를 뜻합니다." + }, + { + "id": "java-concurrency-006", + "question": "교착 상태는 자바에서 왜 발생하나요?", + "answer": "여러 스레드가 서로가 가진 잠금을 기다리며 무한 대기에 빠질 때 발생합니다. 잠금 획득 순서를 일관되게 하면 예방할 수 있습니다." + }, + { + "id": "java-concurrency-007", + "question": "스레드 풀을 사용하는 이유는 무엇인가요?", + "answer": "스레드 생성과 소멸 비용을 줄이고 동시에 실행되는 스레드 수를 제어할 수 있기 때문입니다. 자원을 효율적으로 관리하고 응답성을 높입니다." + }, + { + "id": "java-concurrency-008", + "question": "ConcurrentHashMap은 어떻게 동시성을 처리하나요?", + "answer": "맵 전체가 아니라 일부 영역 단위로만 잠금을 걸어 동시 접근 성능을 높입니다. 읽기는 잠금 없이 가능해 처리량이 좋습니다." + }, + { + "id": "java-concurrency-009", + "question": "스레드의 상태에는 무엇이 있나요?", + "answer": "생성(NEW), 실행 가능(RUNNABLE), 대기(WAITING), 시간 제한 대기(TIMED_WAITING), 차단(BLOCKED), 종료(TERMINATED) 상태가 있습니다." + }, + { + "id": "java-concurrency-010", + "question": "원자적 연산을 위한 Atomic 클래스란 무엇인가요?", + "answer": "락 없이 원자적 연산을 지원하는 클래스입니다. AtomicInteger 등이 CAS 연산을 활용해 동기화 오버헤드 없이 안전하게 값을 갱신합니다." + } + ] + } + ] + }, + { + "id": "spring", + "name": "스프링", + "categories": [ + { + "id": "spring-core", + "name": "스프링 핵심", + "questions": [ + { + "id": "spring-core-001", + "question": "스프링 프레임워크란 무엇인가요?", + "answer": "자바 엔터프라이즈 애플리케이션 개발을 위한 경량 프레임워크입니다. 제어의 역전과 의존성 주입을 핵심으로, 느슨한 결합과 테스트 용이성을 제공합니다." + }, + { + "id": "spring-core-002", + "question": "스프링의 주요 특징은 무엇인가요?", + "answer": "IoC 컨테이너 기반의 의존성 주입, AOP를 통한 관심사 분리, PSA로 일관된 추상화, 그리고 다양한 모듈로 구성된 생태계가 특징입니다." + }, + { + "id": "spring-core-003", + "question": "스프링 빈이란 무엇인가요?", + "answer": "스프링 IoC 컨테이너가 생성하고 관리하는 객체입니다. 개발자가 직접 new로 만들지 않고 컨테이너가 생명주기를 관리합니다." + }, + { + "id": "spring-core-004", + "question": "스프링 컨테이너란 무엇인가요?", + "answer": "빈의 생성, 의존성 주입, 생명주기를 관리하는 핵심 요소입니다. ApplicationContext가 대표적이며 설정 정보를 바탕으로 빈을 관리합니다." + }, + { + "id": "spring-core-005", + "question": "빈의 스코프에는 무엇이 있나요?", + "answer": "컨테이너당 하나만 생성되는 싱글톤이 기본이며, 요청마다 생성되는 프로토타입, 웹 환경의 request, session 스코프 등이 있습니다." + }, + { + "id": "spring-core-006", + "question": "스프링 빈이 싱글톤으로 관리되면 어떤 점을 주의해야 하나요?", + "answer": "여러 요청이 같은 인스턴스를 공유하므로 상태를 가지면 안 됩니다. 공유 가변 필드가 있으면 동시성 문제가 생길 수 있어 무상태로 설계해야 합니다." + }, + { + "id": "spring-core-007", + "question": "빈의 생명주기 콜백은 어떻게 처리하나요?", + "answer": "초기화와 소멸 시점에 콜백을 받을 수 있습니다. @PostConstruct와 @PreDestroy 애너테이션이나 InitializingBean, DisposableBean 인터페이스를 사용합니다." + }, + { + "id": "spring-core-008", + "question": "스프링과 스프링 부트의 차이는 무엇인가요?", + "answer": "스프링 부트는 스프링 위에서 자동 설정과 내장 서버, 스타터 의존성을 제공해 설정 부담을 줄여 줍니다. 빠르게 실행 가능한 애플리케이션을 만들 수 있습니다." + }, + { + "id": "spring-core-009", + "question": "스프링 부트의 자동 설정이란 무엇인가요?", + "answer": "클래스패스와 설정을 기반으로 필요한 빈을 자동으로 구성해 주는 기능입니다. 개발자가 반복적인 설정을 직접 작성하지 않아도 됩니다." + }, + { + "id": "spring-core-010", + "question": "PSA란 무엇인가요?", + "answer": "이식 가능한 서비스 추상화로, 특정 기술에 종속되지 않는 일관된 인터페이스를 제공하는 것입니다. 트랜잭션이나 캐시 추상화가 대표적인 예입니다." + }, + { + "id": "spring-core-011", + "question": "스프링 부트 스타터란 무엇인가요?", + "answer": "특정 기능에 필요한 의존성을 묶어 둔 패키지입니다. 스타터 하나만 추가하면 관련 라이브러리가 함께 구성되어 설정이 간편해집니다." + }, + { + "id": "spring-core-012", + "question": "@SpringBootApplication은 어떤 역할을 하나요?", + "answer": "자동 설정, 컴포넌트 스캔, 설정 클래스 기능을 합친 애너테이션입니다. 보통 메인 클래스에 붙여 애플리케이션의 시작점을 정의합니다." + }, + { + "id": "spring-core-013", + "question": "프로파일이란 무엇인가요?", + "answer": "개발, 운영처럼 환경별로 다른 설정을 적용하는 기능입니다. 활성 프로파일에 따라 알맞은 빈과 설정값을 사용할 수 있습니다." + } + ] + }, + { + "id": "spring-di", + "name": "DI와 IoC", + "questions": [ + { + "id": "spring-di-001", + "question": "제어의 역전(IoC)이란 무엇인가요?", + "answer": "객체의 생성과 생명주기 제어 권한을 개발자가 아닌 프레임워크가 갖는 것입니다. 객체가 자신의 의존성을 직접 만들지 않고 외부에서 주입받습니다." + }, + { + "id": "spring-di-002", + "question": "의존성 주입(DI)이란 무엇인가요?", + "answer": "객체가 필요로 하는 의존 객체를 외부에서 주입해 주는 방식입니다. 결합도를 낮추고 테스트와 교체를 쉽게 만듭니다." + }, + { + "id": "spring-di-003", + "question": "의존성 주입의 방법에는 무엇이 있나요?", + "answer": "생성자 주입, 세터 주입, 필드 주입이 있습니다. 스프링은 불변성과 테스트 용이성 때문에 생성자 주입을 권장합니다." + }, + { + "id": "spring-di-004", + "question": "생성자 주입을 권장하는 이유는 무엇인가요?", + "answer": "필수 의존성을 명확히 하고 객체를 불변으로 만들 수 있기 때문입니다. 또한 순환 참조를 컴파일 시점에 발견할 수 있고 테스트가 쉬워집니다." + }, + { + "id": "spring-di-005", + "question": "@Autowired는 어떻게 동작하나요?", + "answer": "스프링 컨테이너에서 타입에 맞는 빈을 찾아 자동으로 주입합니다. 타입이 같은 빈이 여러 개면 @Qualifier나 이름으로 구분합니다." + }, + { + "id": "spring-di-006", + "question": "@Component와 @Bean의 차이는 무엇인가요?", + "answer": "@Component는 클래스에 붙여 컴포넌트 스캔으로 빈을 등록하고, @Bean은 설정 클래스의 메서드에 붙여 반환 객체를 빈으로 등록합니다." + }, + { + "id": "spring-di-007", + "question": "컴포넌트 스캔이란 무엇인가요?", + "answer": "@Component 계열 애너테이션이 붙은 클래스를 자동으로 찾아 빈으로 등록하는 기능입니다. 일일이 빈을 등록하지 않아도 됩니다." + }, + { + "id": "spring-di-008", + "question": "같은 타입의 빈이 여러 개일 때 어떻게 구분하나요?", + "answer": "@Qualifier로 이름을 지정하거나, @Primary로 우선순위를 부여하거나, 주입받는 변수명을 빈 이름과 맞추는 방법을 사용합니다." + }, + { + "id": "spring-di-009", + "question": "순환 참조란 무엇이고 어떻게 해결하나요?", + "answer": "두 빈이 서로를 의존해 생성이 막히는 상황입니다. 설계를 개선해 의존을 끊거나, 지연 주입(@Lazy)이나 세터 주입으로 우회할 수 있습니다." + }, + { + "id": "spring-di-010", + "question": "DI를 사용하면 어떤 이점이 있나요?", + "answer": "결합도가 낮아져 구현 교체가 쉽고, 의존성을 모의 객체로 바꿀 수 있어 단위 테스트가 수월해집니다. 코드 재사용성과 유지보수성도 향상됩니다." + } + ] + }, + { + "id": "spring-aop", + "name": "AOP", + "questions": [ + { + "id": "spring-aop-001", + "question": "AOP란 무엇인가요?", + "answer": "관점 지향 프로그래밍으로, 로깅이나 트랜잭션처럼 여러 곳에 흩어진 공통 관심사를 분리하는 기법입니다. 핵심 로직과 부가 기능을 나눠 모듈화합니다." + }, + { + "id": "spring-aop-002", + "question": "횡단 관심사란 무엇인가요?", + "answer": "여러 모듈에 걸쳐 공통으로 나타나는 기능을 말합니다. 로깅, 보안, 트랜잭션, 성능 측정 등이 대표적인 횡단 관심사입니다." + }, + { + "id": "spring-aop-003", + "question": "AOP의 주요 용어에는 무엇이 있나요?", + "answer": "부가 기능인 Advice, 적용 지점인 Pointcut, 적용 가능한 위치인 Joinpoint, 그리고 Advice와 Pointcut을 묶은 Aspect가 있습니다." + }, + { + "id": "spring-aop-004", + "question": "Advice의 종류에는 무엇이 있나요?", + "answer": "메서드 실행 전 Before, 후 After, 정상 반환 시 AfterReturning, 예외 시 AfterThrowing, 전후를 모두 감싸는 Around가 있습니다." + }, + { + "id": "spring-aop-005", + "question": "스프링 AOP는 어떻게 구현되나요?", + "answer": "프록시 기반으로 동작합니다. 대상 객체를 감싸는 프록시를 만들어 메서드 호출 전후에 부가 기능을 끼워 넣습니다." + }, + { + "id": "spring-aop-006", + "question": "스프링 AOP에서 프록시는 어떻게 생성되나요?", + "answer": "인터페이스가 있으면 JDK 동적 프록시를, 없으면 CGLIB로 클래스 기반 프록시를 만듭니다. 스프링 부트는 기본적으로 CGLIB를 사용합니다." + }, + { + "id": "spring-aop-007", + "question": "스프링 AOP의 한계는 무엇인가요?", + "answer": "프록시 기반이라 외부에서 들어오는 호출에만 적용됩니다. 같은 객체 내부에서 메서드를 직접 호출하면 프록시를 거치지 않아 적용되지 않습니다." + }, + { + "id": "spring-aop-008", + "question": "트랜잭션 관리에 AOP가 어떻게 쓰이나요?", + "answer": "@Transactional이 붙은 메서드를 프록시가 감싸 시작과 커밋, 롤백을 자동으로 처리합니다. 비즈니스 로직과 트랜잭션 처리를 분리합니다." + } + ] + }, + { + "id": "spring-mvc", + "name": "Spring MVC", + "questions": [ + { + "id": "spring-mvc-001", + "question": "Spring MVC란 무엇인가요?", + "answer": "웹 요청을 처리하기 위한 스프링의 모듈로, 모델-뷰-컨트롤러 패턴을 따릅니다. 요청 분배와 응답 생성을 구조적으로 처리합니다." + }, + { + "id": "spring-mvc-002", + "question": "DispatcherServlet이란 무엇인가요?", + "answer": "모든 요청을 가장 먼저 받아 적절한 컨트롤러로 분배하는 프런트 컨트롤러입니다. 요청 처리의 흐름을 중앙에서 관리합니다." + }, + { + "id": "spring-mvc-003", + "question": "Spring MVC의 요청 처리 흐름은 어떻게 되나요?", + "answer": "DispatcherServlet이 요청을 받아 HandlerMapping으로 컨트롤러를 찾고, 실행 후 ViewResolver로 뷰를 결정해 응답을 렌더링합니다." + }, + { + "id": "spring-mvc-004", + "question": "@Controller와 @RestController의 차이는 무엇인가요?", + "answer": "@Controller는 주로 뷰 이름을 반환하고, @RestController는 @ResponseBody가 포함되어 객체를 JSON 같은 데이터로 직접 반환합니다." + }, + { + "id": "spring-mvc-005", + "question": "@RequestMapping이란 무엇인가요?", + "answer": "특정 URL과 HTTP 메서드를 컨트롤러 메서드에 연결하는 애너테이션입니다. @GetMapping, @PostMapping 등은 이를 메서드별로 특화한 것입니다." + }, + { + "id": "spring-mvc-006", + "question": "@RequestParam과 @PathVariable의 차이는 무엇인가요?", + "answer": "@RequestParam은 쿼리 스트링이나 폼 데이터의 값을 받고, @PathVariable은 URL 경로에 포함된 값을 받습니다." + }, + { + "id": "spring-mvc-007", + "question": "@RequestBody와 @ResponseBody란 무엇인가요?", + "answer": "@RequestBody는 요청 본문을 객체로 변환해 받고, @ResponseBody는 반환 객체를 응답 본문으로 직렬화합니다. 주로 JSON 처리에 사용합니다." + }, + { + "id": "spring-mvc-008", + "question": "필터와 인터셉터의 차이는 무엇인가요?", + "answer": "필터는 서블릿 컨테이너 수준에서 동작해 DispatcherServlet 이전에 실행되고, 인터셉터는 스프링 컨텍스트에서 컨트롤러 호출 전후에 동작합니다." + }, + { + "id": "spring-mvc-009", + "question": "예외를 전역적으로 처리하려면 어떻게 하나요?", + "answer": "@ControllerAdvice와 @ExceptionHandler를 사용합니다. 여러 컨트롤러에서 발생하는 예외를 한 곳에서 일관되게 처리할 수 있습니다." + }, + { + "id": "spring-mvc-010", + "question": "DTO를 사용하는 이유는 무엇인가요?", + "answer": "계층 간 데이터 전달을 위해 사용하며, 엔티티를 직접 노출하지 않아 보안과 유연성이 좋아집니다. 필요한 데이터만 담아 전송할 수 있습니다." + } + ] + }, + { + "id": "spring-data", + "name": "데이터 접근과 JPA", + "questions": [ + { + "id": "spring-data-001", + "question": "ORM이란 무엇인가요?", + "answer": "객체와 관계형 데이터베이스의 테이블을 매핑해 주는 기술입니다. SQL을 직접 작성하지 않고 객체 중심으로 데이터를 다룰 수 있게 합니다." + }, + { + "id": "spring-data-002", + "question": "JPA란 무엇인가요?", + "answer": "자바의 ORM 표준 명세입니다. 인터페이스 집합이며 실제 구현체로 하이버네이트 등이 사용됩니다." + }, + { + "id": "spring-data-003", + "question": "JPA와 하이버네이트의 관계는 무엇인가요?", + "answer": "JPA는 표준 인터페이스이고, 하이버네이트는 이를 구현한 가장 널리 쓰이는 구현체입니다. JPA로 코딩하면 구현체 교체가 쉬워집니다." + }, + { + "id": "spring-data-004", + "question": "영속성 컨텍스트란 무엇인가요?", + "answer": "엔티티를 보관하고 관리하는 논리적 공간입니다. 1차 캐시, 변경 감지, 쓰기 지연 같은 기능으로 데이터 접근을 효율화합니다." + }, + { + "id": "spring-data-005", + "question": "변경 감지(dirty checking)란 무엇인가요?", + "answer": "영속 상태 엔티티의 변경을 트랜잭션 커밋 시점에 자동으로 감지해 UPDATE 쿼리를 실행하는 기능입니다. 별도 저장 호출이 필요 없습니다." + }, + { + "id": "spring-data-006", + "question": "지연 로딩과 즉시 로딩의 차이는 무엇인가요?", + "answer": "지연 로딩은 연관 엔티티를 실제 사용할 때 조회하고, 즉시 로딩은 처음 조회 시 함께 가져옵니다. 성능을 위해 주로 지연 로딩을 권장합니다." + }, + { + "id": "spring-data-007", + "question": "N+1 문제란 무엇인가요?", + "answer": "연관 엔티티를 조회할 때 쿼리 한 번에 더해 추가로 N번의 쿼리가 발생하는 문제입니다. 페치 조인이나 엔티티 그래프로 해결합니다." + }, + { + "id": "spring-data-008", + "question": "Spring Data JPA의 Repository란 무엇인가요?", + "answer": "인터페이스만 정의하면 기본 CRUD 메서드를 자동으로 제공하는 추상화입니다. 메서드 이름 규칙만으로 쿼리를 생성할 수도 있습니다." + }, + { + "id": "spring-data-009", + "question": "JPA에서 트랜잭션은 왜 중요한가요?", + "answer": "영속성 컨텍스트의 변경 감지와 쓰기 지연이 트랜잭션 범위에서 동작하기 때문입니다. 트랜잭션이 없으면 변경 내용이 데이터베이스에 반영되지 않습니다." + }, + { + "id": "spring-data-010", + "question": "JPA와 MyBatis의 차이는 무엇인가요?", + "answer": "JPA는 객체 중심의 ORM으로 SQL을 자동 생성하고, MyBatis는 SQL을 직접 작성하는 매퍼 프레임워크입니다. 복잡한 쿼리는 MyBatis가 다루기 편할 수 있습니다." + }, + { + "id": "spring-data-011", + "question": "@Transactional은 어떻게 동작하나요?", + "answer": "프록시가 메서드를 감싸 트랜잭션을 시작하고, 정상 종료 시 커밋, 예외 발생 시 롤백합니다. 비즈니스 로직과 트랜잭션 처리를 분리합니다." + }, + { + "id": "spring-data-012", + "question": "JPA 엔티티의 생명주기에는 어떤 상태가 있나요?", + "answer": "영속성 컨텍스트와 무관한 비영속, 관리되는 영속, 분리된 준영속, 삭제 예정인 삭제 상태가 있습니다." + }, + { + "id": "spring-data-013", + "question": "페치 조인이란 무엇인가요?", + "answer": "연관된 엔티티를 한 번의 쿼리로 함께 조회하는 JPQL 기능입니다. N+1 문제를 해결하는 대표적인 방법입니다." + } + ] + } + ] + }, + { + "id": "web", + "name": "웹/API", + "categories": [ + { + "id": "web-rest", + "name": "REST API", + "questions": [ + { + "id": "web-rest-001", + "question": "REST란 무엇인가요?", + "answer": "자원을 URI로 표현하고 HTTP 메서드로 상태를 주고받는 아키텍처 스타일입니다. 자원 중심으로 일관된 인터페이스를 제공하는 것이 핵심입니다." + }, + { + "id": "web-rest-002", + "question": "REST API란 무엇인가요?", + "answer": "REST 원칙을 따르는 API입니다. 자원을 URI로 식별하고 HTTP 메서드로 조회, 생성, 수정, 삭제를 수행합니다." + }, + { + "id": "web-rest-003", + "question": "RESTful API 설계 원칙은 무엇인가요?", + "answer": "자원은 명사로 표현하고, 행위는 HTTP 메서드로 나타내며, URI에 동사를 쓰지 않습니다. 또한 계층 구조와 일관된 명명 규칙을 따릅니다." + }, + { + "id": "web-rest-004", + "question": "HTTP 메서드는 어떻게 사용하나요?", + "answer": "조회는 GET, 생성은 POST, 전체 수정은 PUT, 부분 수정은 PATCH, 삭제는 DELETE를 사용합니다. 메서드 의미에 맞게 자원을 다룹니다." + }, + { + "id": "web-rest-005", + "question": "PUT과 PATCH의 차이는 무엇인가요?", + "answer": "PUT은 자원 전체를 교체하고, PATCH는 일부 필드만 수정합니다. PUT은 멱등하지만 PATCH는 구현에 따라 멱등하지 않을 수 있습니다." + }, + { + "id": "web-rest-006", + "question": "멱등성이란 무엇인가요?", + "answer": "같은 요청을 여러 번 보내도 결과 상태가 동일한 성질입니다. GET, PUT, DELETE는 멱등하고 POST는 일반적으로 멱등하지 않습니다." + }, + { + "id": "web-rest-007", + "question": "주요 HTTP 상태 코드는 무엇이 있나요?", + "answer": "성공은 200번대, 리다이렉션은 300번대, 클라이언트 오류는 400번대, 서버 오류는 500번대입니다. 200, 201, 400, 401, 404, 500이 자주 쓰입니다." + }, + { + "id": "web-rest-008", + "question": "REST의 무상태성이란 무엇인가요?", + "answer": "서버가 클라이언트의 상태를 저장하지 않고 각 요청이 필요한 정보를 모두 담는 성질입니다. 확장성이 좋아지고 서버 간 부하 분산이 쉬워집니다." + }, + { + "id": "web-rest-009", + "question": "REST와 GraphQL의 차이는 무엇인가요?", + "answer": "REST는 여러 엔드포인트로 고정된 응답을 주고, GraphQL은 단일 엔드포인트에서 클라이언트가 필요한 데이터만 골라 요청합니다. 오버페칭을 줄일 수 있습니다." + }, + { + "id": "web-rest-010", + "question": "API 버전 관리는 왜 필요한가요?", + "answer": "기존 클라이언트를 깨뜨리지 않고 API를 발전시키기 위해서입니다. URI 경로나 헤더에 버전을 명시해 하위 호환성을 유지합니다." + }, + { + "id": "web-rest-011", + "question": "DTO와 엔티티를 분리하는 이유는 무엇인가요?", + "answer": "엔티티를 직접 노출하면 내부 구조가 드러나고 변경에 취약해집니다. DTO로 필요한 데이터만 전달하면 보안과 유연성이 좋아집니다." + }, + { + "id": "web-rest-012", + "question": "HATEOAS란 무엇인가요?", + "answer": "응답에 다음에 할 수 있는 행동의 링크를 함께 제공하는 REST 성숙도의 한 단계입니다. 클라이언트가 링크를 따라 상태를 전이할 수 있습니다." + }, + { + "id": "web-rest-013", + "question": "API에서 페이지네이션은 왜 필요한가요?", + "answer": "대량의 데이터를 한 번에 반환하면 성능과 메모리에 부담이 되기 때문입니다. 데이터를 나눠 응답해 효율과 응답 속도를 높입니다." + } + ] + }, + { + "id": "web-auth", + "name": "인증과 인가", + "questions": [ + { + "id": "web-auth-001", + "question": "인증과 인가의 차이는 무엇인가요?", + "answer": "인증은 사용자가 누구인지 신원을 확인하는 것이고, 인가는 인증된 사용자가 어떤 권한을 가지는지 확인하는 것입니다. 인증이 먼저 이뤄집니다." + }, + { + "id": "web-auth-002", + "question": "쿠키 기반 인증과 토큰 기반 인증의 차이는 무엇인가요?", + "answer": "쿠키 기반은 서버가 세션을 저장하고 상태를 가집니다. 토큰 기반은 토큰 자체에 정보를 담아 서버가 무상태로 동작할 수 있습니다." + }, + { + "id": "web-auth-003", + "question": "JWT란 무엇인가요?", + "answer": "정보를 JSON으로 담아 서명한 토큰입니다. 헤더, 페이로드, 서명 세 부분으로 구성되며 서버가 세션을 저장하지 않고 검증할 수 있습니다." + }, + { + "id": "web-auth-004", + "question": "JWT의 구조는 어떻게 되나요?", + "answer": "헤더, 페이로드, 서명 세 부분이 점으로 구분됩니다. 헤더는 타입과 알고리즘, 페이로드는 클레임 정보, 서명은 위변조 검증용입니다." + }, + { + "id": "web-auth-005", + "question": "JWT의 장단점은 무엇인가요?", + "answer": "서버가 무상태로 확장하기 쉽다는 장점이 있지만, 한 번 발급하면 만료 전 강제 폐기가 어렵습니다. 페이로드는 누구나 디코딩할 수 있어 민감 정보를 담으면 안 됩니다." + }, + { + "id": "web-auth-006", + "question": "액세스 토큰과 리프레시 토큰의 차이는 무엇인가요?", + "answer": "액세스 토큰은 짧은 수명으로 자원 접근에 사용하고, 리프레시 토큰은 긴 수명으로 액세스 토큰을 재발급받는 데 사용합니다. 탈취 위험을 줄이기 위함입니다." + }, + { + "id": "web-auth-007", + "question": "OAuth 2.0이란 무엇인가요?", + "answer": "제3자 애플리케이션에 비밀번호를 노출하지 않고 권한을 위임하는 인가 프로토콜입니다. 소셜 로그인이 대표적인 활용 사례입니다." + }, + { + "id": "web-auth-008", + "question": "세션 방식의 단점은 무엇인가요?", + "answer": "서버가 세션을 저장하므로 사용자가 늘면 메모리 부담이 커집니다. 또한 여러 서버로 확장할 때 세션 공유를 위한 별도 저장소가 필요합니다." + }, + { + "id": "web-auth-009", + "question": "토큰을 안전하게 저장하려면 어떻게 해야 하나요?", + "answer": "자바스크립트 접근을 막는 HttpOnly 쿠키에 저장하면 XSS에 강합니다. 로컬 스토리지는 접근이 쉬워 XSS에 취약하므로 주의가 필요합니다." + }, + { + "id": "web-auth-010", + "question": "RBAC이란 무엇인가요?", + "answer": "역할 기반 접근 제어로, 사용자에게 직접 권한을 주지 않고 역할에 권한을 부여한 뒤 사용자에게 역할을 할당하는 방식입니다. 권한 관리가 단순해집니다." + } + ] + }, + { + "id": "web-session", + "name": "쿠키와 세션", + "questions": [ + { + "id": "web-session-001", + "question": "쿠키란 무엇인가요?", + "answer": "서버가 클라이언트 브라우저에 저장하는 작은 데이터입니다. 이후 요청마다 자동으로 함께 전송되어 상태를 유지하는 데 사용됩니다." + }, + { + "id": "web-session-002", + "question": "세션이란 무엇인가요?", + "answer": "서버가 클라이언트의 상태를 저장하고 관리하는 방식입니다. 보통 세션 ID를 쿠키로 주고받으며 실제 데이터는 서버에 보관합니다." + }, + { + "id": "web-session-003", + "question": "쿠키와 세션의 차이는 무엇인가요?", + "answer": "쿠키는 데이터를 클라이언트에 저장하고, 세션은 서버에 저장합니다. 세션이 보안에 유리하지만 서버 자원을 사용합니다." + }, + { + "id": "web-session-004", + "question": "세션은 어떻게 동작하나요?", + "answer": "로그인 시 서버가 세션을 만들고 세션 ID를 쿠키로 전달합니다. 이후 요청마다 그 ID로 서버에 저장된 사용자 정보를 찾아 인증을 유지합니다." + }, + { + "id": "web-session-005", + "question": "쿠키의 보안 속성에는 무엇이 있나요?", + "answer": "자바스크립트 접근을 막는 HttpOnly, HTTPS에서만 전송하는 Secure, 크로스 사이트 전송을 제한하는 SameSite 속성이 있습니다." + }, + { + "id": "web-session-006", + "question": "여러 서버 환경에서 세션은 어떻게 관리하나요?", + "answer": "서버마다 세션이 다르면 문제가 되므로, 레디스 같은 중앙 저장소에 세션을 보관하거나 같은 서버로 보내는 고정 세션 방식을 사용합니다." + }, + { + "id": "web-session-007", + "question": "세션 클러스터링이란 무엇인가요?", + "answer": "여러 서버가 세션 정보를 공유하도록 구성하는 것입니다. 한 서버에 장애가 생겨도 다른 서버가 세션을 이어받아 처리할 수 있습니다." + }, + { + "id": "web-session-008", + "question": "토큰 방식이 세션 방식보다 확장에 유리한 이유는 무엇인가요?", + "answer": "토큰은 정보를 자체에 담아 서버가 상태를 저장하지 않으므로, 서버를 늘려도 세션 공유 부담이 없습니다. 무상태라서 수평 확장이 쉽습니다." + } + ] + } + ] + }, + { + "id": "security", + "name": "보안", + "categories": [ + { + "id": "sec-crypto", + "name": "암호화", + "questions": [ + { + "id": "sec-crypto-001", + "question": "대칭키 암호화와 비대칭키 암호화의 차이는 무엇인가요?", + "answer": "대칭키는 암호화와 복호화에 같은 키를 쓰고 빠르지만 키 공유가 어렵습니다. 비대칭키는 공개키와 개인키 쌍을 사용해 키 공유 문제를 해결합니다." + }, + { + "id": "sec-crypto-002", + "question": "해시 함수란 무엇인가요?", + "answer": "임의 길이의 입력을 고정 길이 값으로 변환하는 단방향 함수입니다. 같은 입력은 항상 같은 결과를 내며 역으로 원본을 구하기 어렵습니다." + }, + { + "id": "sec-crypto-003", + "question": "암호화와 해싱의 차이는 무엇인가요?", + "answer": "암호화는 키로 복호화해 원본을 되돌릴 수 있는 양방향이고, 해싱은 원본 복원이 불가능한 단방향입니다. 비밀번호 저장에는 해싱을 사용합니다." + }, + { + "id": "sec-crypto-004", + "question": "비밀번호를 안전하게 저장하는 방법은 무엇인가요?", + "answer": "평문이 아니라 솔트를 더한 단방향 해시로 저장합니다. bcrypt처럼 의도적으로 느린 해시 함수를 사용해 무차별 대입을 어렵게 만듭니다." + }, + { + "id": "sec-crypto-005", + "question": "솔트란 무엇인가요?", + "answer": "비밀번호를 해싱하기 전에 덧붙이는 임의의 값입니다. 같은 비밀번호라도 다른 해시가 나오게 해 미리 계산된 공격을 막습니다." + }, + { + "id": "sec-crypto-006", + "question": "레인보우 테이블 공격이란 무엇인가요?", + "answer": "미리 계산해 둔 해시-원문 대응표로 비밀번호를 역추적하는 공격입니다. 사용자마다 다른 솔트를 적용하면 이 공격을 무력화할 수 있습니다." + }, + { + "id": "sec-crypto-007", + "question": "HTTPS는 어떻게 통신을 보호하나요?", + "answer": "TLS로 데이터를 암호화해 도청과 변조를 막습니다. 비대칭키로 안전하게 대칭키를 교환한 뒤 빠른 대칭키 암호화로 실제 데이터를 주고받습니다." + }, + { + "id": "sec-crypto-008", + "question": "디지털 서명이란 무엇인가요?", + "answer": "개인키로 데이터의 해시를 암호화해 만든 서명입니다. 공개키로 검증해 데이터의 무결성과 발신자의 신원을 확인할 수 있습니다." + }, + { + "id": "sec-crypto-009", + "question": "전자 인증서란 무엇인가요?", + "answer": "공개키가 특정 주체의 것임을 인증기관이 보증하는 문서입니다. HTTPS에서 서버의 신원을 검증하는 데 사용됩니다." + }, + { + "id": "sec-crypto-010", + "question": "TLS 핸드셰이크는 어떻게 이뤄지나요?", + "answer": "서버 인증서를 검증하고, 비대칭키로 세션 키를 안전하게 합의한 뒤, 이후 통신은 대칭키로 암호화합니다. 이렇게 보안과 성능을 모두 확보합니다." + } + ] + }, + { + "id": "sec-web", + "name": "웹 취약점", + "questions": [ + { + "id": "sec-web-001", + "question": "SQL 인젝션이란 무엇인가요?", + "answer": "사용자 입력에 악의적인 SQL을 삽입해 데이터베이스를 조작하는 공격입니다. 입력값 검증과 파라미터 바인딩으로 방어할 수 있습니다." + }, + { + "id": "sec-web-002", + "question": "SQL 인젝션을 어떻게 방어하나요?", + "answer": "사용자 입력을 쿼리에 직접 붙이지 않고 PreparedStatement의 파라미터 바인딩을 사용합니다. 입력값 검증과 최소 권한 원칙도 함께 적용합니다." + }, + { + "id": "sec-web-003", + "question": "XSS란 무엇인가요?", + "answer": "악성 스크립트를 웹 페이지에 삽입해 다른 사용자 브라우저에서 실행시키는 공격입니다. 쿠키 탈취나 세션 하이재킹으로 이어질 수 있습니다." + }, + { + "id": "sec-web-004", + "question": "XSS를 어떻게 방어하나요?", + "answer": "출력 시 HTML 특수문자를 이스케이프하고 입력값을 검증합니다. 또한 HttpOnly 쿠키와 콘텐츠 보안 정책(CSP)을 적용해 피해를 줄입니다." + }, + { + "id": "sec-web-005", + "question": "CSRF란 무엇인가요?", + "answer": "사용자가 인증된 상태를 악용해 의도하지 않은 요청을 보내게 만드는 공격입니다. 사용자 모르게 자금 이체 같은 행위가 실행될 수 있습니다." + }, + { + "id": "sec-web-006", + "question": "CSRF를 어떻게 방어하나요?", + "answer": "예측 불가능한 CSRF 토큰을 요청에 포함시켜 검증하고, SameSite 쿠키 속성을 설정합니다. 중요한 작업에는 재인증을 요구하기도 합니다." + }, + { + "id": "sec-web-007", + "question": "XSS와 CSRF의 차이는 무엇인가요?", + "answer": "XSS는 악성 스크립트를 실행시켜 정보를 탈취하고, CSRF는 사용자의 인증 정보를 이용해 위조 요청을 보냅니다. 공격 방식과 대상이 다릅니다." + }, + { + "id": "sec-web-008", + "question": "최소 권한 원칙이란 무엇인가요?", + "answer": "사용자나 프로세스에게 필요한 최소한의 권한만 부여하는 보안 원칙입니다. 침해가 발생해도 피해 범위를 줄일 수 있습니다." + }, + { + "id": "sec-web-009", + "question": "민감 정보는 어떻게 관리해야 하나요?", + "answer": "코드에 직접 넣지 않고 환경 변수나 비밀 관리 도구로 분리합니다. 전송과 저장 시 암호화하고 접근 권한을 제한합니다." + }, + { + "id": "sec-web-010", + "question": "CORS란 무엇인가요?", + "answer": "다른 출처의 자원 요청을 제어하는 브라우저 보안 정책입니다. 서버가 허용한 출처만 응답에 접근할 수 있게 해 무단 요청을 막습니다." + }, + { + "id": "sec-web-011", + "question": "인증과 세션 고정 공격이란 무엇인가요?", + "answer": "공격자가 미리 만든 세션 ID를 피해자가 사용하게 만들어 세션을 가로채는 공격입니다. 로그인 시 세션 ID를 새로 발급해 방어합니다." + }, + { + "id": "sec-web-012", + "question": "브루트 포스 공격을 어떻게 막나요?", + "answer": "로그인 시도 횟수를 제한하고, 일정 횟수 실패 시 계정을 잠그거나 캡차를 요구합니다. 느린 해시와 다중 인증도 도움이 됩니다." + }, + { + "id": "sec-web-013", + "question": "입력값 검증은 어디에서 해야 하나요?", + "answer": "클라이언트 검증은 우회될 수 있으므로 반드시 서버에서 검증해야 합니다. 화이트리스트 방식으로 허용된 값만 받는 것이 안전합니다." + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/frontend/public/data/cs_interview_questions.json b/frontend/public/data/cs_interview_questions.json new file mode 100644 index 00000000..6a1de103 --- /dev/null +++ b/frontend/public/data/cs_interview_questions.json @@ -0,0 +1,3077 @@ +{ + "version": "1.0", + "title": "CS 면접 대비 질문 모음", + "description": "컴퓨터구조, 네트워크, 운영체제, 알고리즘/자료구조 분야별 면접 빈출 질문과 핵심 답변", + "subjects": [ + { + "id": "computer-architecture", + "name": "컴퓨터구조", + "categories": [ + { + "id": "ca-number", + "name": "수의 표현과 연산", + "questions": [ + { + "id": "ca-number-001", + "question": "2의 보수(2's complement)란 무엇이며 왜 사용하나요?", + "answer": "음수를 표현하기 위한 방식으로, 양수의 모든 비트를 반전한 뒤 1을 더해 만듭니다. 덧셈 회로 하나로 뺄셈까지 처리할 수 있고 0의 표현이 하나뿐이라 대부분의 컴퓨터가 정수 표현에 사용합니다." + }, + { + "id": "ca-number-002", + "question": "부동소수점(floating point)은 어떻게 표현되나요?", + "answer": "IEEE 754 표준에 따라 부호 비트, 지수부(exponent), 가수부(mantissa)로 나누어 표현합니다. 넓은 범위의 수를 표현할 수 있지만 실수를 근사값으로 저장하기 때문에 미세한 오차가 발생할 수 있습니다." + }, + { + "id": "ca-number-003", + "question": "비트(bit)와 바이트(byte)의 차이는 무엇인가요?", + "answer": "비트는 0 또는 1을 표현하는 정보의 최소 단위이고, 바이트는 8비트를 묶은 단위입니다. 1바이트로 256가지 값을 표현할 수 있으며 메모리 주소 지정의 기본 단위로 쓰입니다." + }, + { + "id": "ca-number-004", + "question": "오버플로우(overflow)는 언제 발생하나요?", + "answer": "연산 결과가 해당 자료형이 표현할 수 있는 범위를 넘어설 때 발생합니다. 예를 들어 부호 있는 8비트에서 127에 1을 더하면 -128이 되는 식으로 값이 뒤집힙니다." + }, + { + "id": "ca-number-005", + "question": "빅 엔디안과 리틀 엔디안의 차이는 무엇인가요?", + "answer": "여러 바이트를 메모리에 저장하는 순서의 차이입니다. 빅 엔디안은 최상위 바이트를 낮은 주소에, 리틀 엔디안은 최하위 바이트를 낮은 주소에 저장하며 x86은 리틀 엔디안을 사용합니다." + }, + { + "id": "ca-number-006", + "question": "진법 변환(2진수, 8진수, 16진수)은 어떻게 하나요?", + "answer": "10진수를 다른 진법으로 바꿀 때는 그 수로 나눈 나머지를 역순으로 읽고, 반대로는 각 자릿값을 곱해 더합니다. 2진수 네 자리가 16진수 한 자리에 대응해 변환이 편리합니다." + }, + { + "id": "ca-number-007", + "question": "부호 비트(sign bit)란 무엇인가요?", + "answer": "수의 양수와 음수를 나타내는 가장 왼쪽 비트입니다. 0이면 양수, 1이면 음수를 의미하며 나머지 비트로 크기를 표현합니다." + }, + { + "id": "ca-number-008", + "question": "1의 보수와 2의 보수의 차이는 무엇인가요?", + "answer": "1의 보수는 모든 비트를 반전한 값이고, 2의 보수는 거기에 1을 더한 값입니다. 1의 보수는 0의 표현이 두 개라 문제가 있어 보통 2의 보수를 사용합니다." + }, + { + "id": "ca-number-009", + "question": "ASCII와 유니코드의 차이는 무엇인가요?", + "answer": "ASCII는 7비트로 영문과 기호 128자만 표현하고, 유니코드는 전 세계 문자를 담기 위한 표준입니다. UTF-8은 유니코드를 가변 길이로 인코딩하는 방식입니다." + }, + { + "id": "ca-number-010", + "question": "고정소수점과 부동소수점의 차이는 무엇인가요?", + "answer": "고정소수점은 소수점 위치가 고정되어 정확하지만 범위가 좁고, 부동소수점은 지수로 소수점을 이동시켜 넓은 범위를 표현하지만 근사 오차가 생길 수 있습니다." + }, + { + "id": "ca-number-011", + "question": "비트 연산(AND, OR, XOR, 시프트)은 어떻게 활용되나요?", + "answer": "특정 비트를 켜거나 끄고, 시프트로 곱셈과 나눗셈을 빠르게 하며, 플래그나 권한을 관리할 때 씁니다. 마스킹과 상태 표현에 자주 활용됩니다." + } + ] + }, + { + "id": "ca-cpu", + "name": "CPU와 명령어 처리", + "questions": [ + { + "id": "ca-cpu-001", + "question": "CPU의 기본 구성요소는 무엇인가요?", + "answer": "산술논리연산을 담당하는 ALU, 명령어 해석과 제어 신호를 보내는 제어장치(CU), 그리고 데이터를 임시 저장하는 레지스터로 구성됩니다. 이 세 요소가 협력해 명령어를 처리합니다." + }, + { + "id": "ca-cpu-002", + "question": "명령어 사이클(instruction cycle)을 설명해주세요.", + "answer": "CPU가 명령어를 처리하는 과정으로 인출(fetch), 해석(decode), 실행(execute), 그리고 필요 시 저장(write back) 단계로 이루어집니다. 이 과정을 반복하며 프로그램을 수행합니다." + }, + { + "id": "ca-cpu-003", + "question": "레지스터란 무엇이고 어떤 종류가 있나요?", + "answer": "CPU 내부의 가장 빠른 임시 저장 공간입니다. 다음 명령어 주소를 담는 프로그램 카운터(PC), 현재 명령어를 담는 명령어 레지스터(IR), 연산 결과를 담는 누산기(accumulator) 등이 있습니다." + }, + { + "id": "ca-cpu-004", + "question": "프로그램 카운터(PC)의 역할은 무엇인가요?", + "answer": "다음에 실행할 명령어의 메모리 주소를 저장하는 레지스터입니다. 명령어를 인출할 때마다 자동으로 증가하며 분기나 점프가 일어나면 해당 주소로 값이 바뀝니다." + }, + { + "id": "ca-cpu-005", + "question": "클럭(clock)과 클럭 속도는 무엇을 의미하나요?", + "answer": "클럭은 CPU 내 동작의 타이밍을 맞추는 주기적 신호이고, 클럭 속도(Hz)는 1초에 발생하는 클럭 수를 의미합니다. 일반적으로 클럭이 높을수록 더 많은 명령을 처리하지만 발열과 전력 소모도 늘어납니다." + }, + { + "id": "ca-cpu-006", + "question": "CPI와 IPC는 무엇을 뜻하나요?", + "answer": "CPI는 명령어 하나를 처리하는 데 드는 평균 클럭 수, IPC는 한 클럭에 처리하는 평균 명령어 수로 서로 역수 관계입니다. CPU 성능은 클럭 속도, IPC, 명령어 수를 함께 고려해 평가합니다." + }, + { + "id": "ca-cpu-007", + "question": "누산기(accumulator)란 무엇인가요?", + "answer": "연산의 중간 결과나 최종 결과를 임시 저장하는 레지스터입니다. 많은 산술 연산이 이 레지스터를 거치며 ALU와 밀접하게 동작합니다." + }, + { + "id": "ca-cpu-008", + "question": "MAR과 MBR(MDR)은 무엇인가요?", + "answer": "MAR은 접근할 메모리 주소를 담는 레지스터, MBR은 그 주소에서 읽거나 쓸 데이터를 담는 레지스터입니다. 둘이 협력해 메모리 입출력을 수행합니다." + }, + { + "id": "ca-cpu-009", + "question": "제어장치(CU)의 역할은 무엇인가요?", + "answer": "명령어를 해석해 각 구성요소에 제어 신호를 보내 동작 순서를 지휘합니다. CPU의 지휘자 역할로 데이터 흐름과 연산 타이밍을 조정합니다." + }, + { + "id": "ca-cpu-010", + "question": "마이크로 연산(micro-operation)이란 무엇인가요?", + "answer": "하나의 명령어를 수행하기 위해 CPU 내부에서 일어나는 가장 작은 단위의 동작입니다. 레지스터 간 데이터 이동이나 ALU 연산 등이 이에 해당합니다." + }, + { + "id": "ca-cpu-011", + "question": "명령어 형식(instruction format)이란 무엇인가요?", + "answer": "명령어를 구성하는 비트들의 배치 규칙으로 연산 코드와 피연산자로 나뉩니다. 주소의 개수에 따라 0주소부터 3주소 명령어 형식까지 있습니다." + }, + { + "id": "ca-cpu-012", + "question": "싱글사이클과 멀티사이클 방식의 차이는 무엇인가요?", + "answer": "싱글사이클은 한 클럭에 명령어 하나를 처리해 단순하지만 가장 느린 명령에 클럭을 맞춰야 합니다. 멀티사이클은 명령어를 여러 단계로 나눠 단계마다 클럭을 써 효율적입니다." + }, + { + "id": "ca-cpu-013", + "question": "CPU 성능을 높이는 방법에는 무엇이 있나요?", + "answer": "클럭 향상, 파이프라이닝, 캐시 확대, 멀티코어, 명령어 수준 병렬성 활용 등이 있습니다. 클럭만 높이면 발열 한계가 있어 구조적 개선을 병행합니다." + } + ] + }, + { + "id": "ca-memory", + "name": "메모리 계층구조", + "questions": [ + { + "id": "ca-memory-001", + "question": "메모리 계층구조(memory hierarchy)란 무엇인가요?", + "answer": "속도, 용량, 비용이 다른 저장장치를 계층적으로 배치한 구조입니다. 위로 갈수록 빠르지만 비싸고 작으며(레지스터, 캐시), 아래로 갈수록 느리지만 싸고 큽니다(주기억장치, 보조기억장치)." + }, + { + "id": "ca-memory-002", + "question": "지역성(locality)의 원리란 무엇인가요?", + "answer": "프로그램이 메모리에 접근하는 패턴에 규칙성이 있다는 원리입니다. 최근 참조한 데이터를 다시 참조하는 시간 지역성과, 인접한 주소를 참조하는 공간 지역성이 있으며 캐시 효율의 근거가 됩니다." + }, + { + "id": "ca-memory-003", + "question": "SRAM과 DRAM의 차이는 무엇인가요?", + "answer": "SRAM은 플립플롭으로 구성되어 빠르고 재충전이 필요 없어 캐시에 쓰이며, DRAM은 커패시터 기반이라 느리고 주기적 재충전이 필요하지만 집적도가 높아 주기억장치에 사용됩니다." + }, + { + "id": "ca-memory-004", + "question": "폰 노이만 구조란 무엇이고 어떤 한계가 있나요?", + "answer": "프로그램과 데이터를 같은 메모리에 저장하고 하나의 버스로 접근하는 구조입니다. 구조가 단순하지만 명령어와 데이터가 같은 통로를 공유해 병목(폰 노이만 병목)이 생긴다는 한계가 있습니다." + }, + { + "id": "ca-memory-005", + "question": "하버드 구조와 폰 노이만 구조의 차이는 무엇인가요?", + "answer": "하버드 구조는 명령어 메모리와 데이터 메모리를 물리적으로 분리해 동시에 접근할 수 있어 병목이 적습니다. 폰 노이만은 하나의 메모리를 공유하며, 현대 CPU는 캐시 단계에서 두 방식을 절충해 사용합니다." + }, + { + "id": "ca-memory-006", + "question": "ROM과 RAM의 차이는 무엇인가요?", + "answer": "RAM은 읽고 쓸 수 있는 휘발성 메모리로 작업 공간에 쓰이고, ROM은 주로 읽기 전용이며 전원이 꺼져도 내용이 유지되어 펌웨어 저장에 쓰입니다." + }, + { + "id": "ca-memory-007", + "question": "휘발성 메모리와 비휘발성 메모리의 차이는 무엇인가요?", + "answer": "휘발성 메모리는 전원이 꺼지면 데이터가 사라지고(RAM), 비휘발성 메모리는 전원이 없어도 데이터를 유지합니다(ROM, SSD). 용도에 따라 구분해 사용합니다." + }, + { + "id": "ca-memory-008", + "question": "메모리 인터리빙(interleaving)이란 무엇인가요?", + "answer": "메모리를 여러 뱅크로 나누어 동시에 접근함으로써 대역폭을 높이는 기법입니다. 연속된 주소를 서로 다른 뱅크에 분산해 병렬 접근 효과를 냅니다." + }, + { + "id": "ca-memory-009", + "question": "가상 주소와 물리 주소의 차이는 무엇인가요?", + "answer": "가상 주소는 프로세스가 사용하는 논리적 주소이고, 물리 주소는 실제 메모리상의 주소입니다. MMU가 둘 사이를 변환해 프로세스 격리와 메모리 보호를 제공합니다." + }, + { + "id": "ca-memory-010", + "question": "MMU란 무엇인가요?", + "answer": "메모리 관리 장치로 가상 주소를 물리 주소로 변환하는 하드웨어입니다. 페이지 테이블을 참조해 주소를 변환하고 메모리 접근 권한을 검사합니다." + }, + { + "id": "ca-memory-011", + "question": "메모리 매핑 입출력(memory-mapped I/O)이란 무엇인가요?", + "answer": "입출력 장치의 레지스터를 메모리 주소 공간에 할당해 일반 메모리 접근 명령으로 장치를 제어하는 방식입니다. 별도 입출력 명령이 필요 없어 단순합니다." + } + ] + }, + { + "id": "ca-cache", + "name": "캐시 메모리", + "questions": [ + { + "id": "ca-cache-001", + "question": "캐시 메모리란 무엇이고 왜 사용하나요?", + "answer": "CPU와 주기억장치 사이의 속도 차이를 줄이기 위한 고속 임시 저장소입니다. 자주 쓰는 데이터를 미리 담아두어 느린 메모리 접근 횟수를 줄이고 전체 성능을 높입니다." + }, + { + "id": "ca-cache-002", + "question": "캐시 히트(hit)와 미스(miss)란 무엇인가요?", + "answer": "CPU가 찾는 데이터가 캐시에 있으면 히트, 없어서 하위 메모리에서 가져와야 하면 미스입니다. 히트율이 높을수록 평균 접근 시간이 짧아지므로 캐시 설계의 핵심 지표입니다." + }, + { + "id": "ca-cache-003", + "question": "캐시 매핑 방식에는 어떤 것들이 있나요?", + "answer": "메모리 블록을 캐시에 배치하는 규칙으로 직접 매핑, 완전 연관 매핑, 집합 연관 매핑이 있습니다. 직접 매핑은 빠르지만 충돌이 잦고, 연관 매핑은 유연하지만 비용이 높아 보통 집합 연관 방식을 절충해 씁니다." + }, + { + "id": "ca-cache-004", + "question": "캐시 교체 정책에는 어떤 것이 있나요?", + "answer": "캐시가 가득 찼을 때 어떤 블록을 내보낼지 정하는 정책입니다. 가장 오래 참조되지 않은 것을 교체하는 LRU, 들어온 순서대로 교체하는 FIFO, 무작위(Random) 방식 등이 있으며 LRU가 널리 쓰입니다." + }, + { + "id": "ca-cache-005", + "question": "Write-through와 Write-back의 차이는 무엇인가요?", + "answer": "쓰기 연산 시 Write-through는 캐시와 메모리에 동시에 기록해 일관성이 좋지만 느리고, Write-back은 캐시에만 먼저 쓰고 교체될 때 메모리에 반영해 빠르지만 일관성 관리가 필요합니다." + }, + { + "id": "ca-cache-006", + "question": "L1, L2, L3 캐시의 차이는 무엇인가요?", + "answer": "L1이 가장 작고 빠르며 코어에 가깝고, L3가 가장 크고 느리며 보통 여러 코어가 공유합니다. 계층을 둠으로써 속도와 용량의 균형을 맞춥니다." + }, + { + "id": "ca-cache-007", + "question": "캐시 라인(cache line)이란 무엇인가요?", + "answer": "캐시와 메모리 사이에 데이터를 옮기는 기본 단위입니다. 인접한 데이터를 한 번에 함께 가져와 공간 지역성을 활용해 효율을 높입니다." + }, + { + "id": "ca-cache-008", + "question": "캐시 일관성(cache coherence) 문제란 무엇인가요?", + "answer": "여러 코어가 각자 캐시에 같은 데이터의 복사본을 가질 때 한쪽이 값을 바꾸면 불일치가 생기는 문제입니다. MESI 같은 프로토콜로 일관성을 유지합니다." + }, + { + "id": "ca-cache-009", + "question": "콜드 미스, 충돌 미스, 용량 미스의 차이는 무엇인가요?", + "answer": "콜드 미스는 처음 접근 시, 충돌 미스는 같은 캐시 위치를 다투며, 용량 미스는 캐시 크기가 부족해 발생합니다. 원인별로 대응 방법이 다릅니다." + }, + { + "id": "ca-cache-010", + "question": "캐시 적중률을 높이는 방법은 무엇인가요?", + "answer": "지역성이 높은 코드를 작성하고, 캐시 크기와 연관도를 늘리며, 데이터를 캐시 라인에 맞게 배치하는 방법이 있습니다. 반복 접근 데이터를 가깝게 두는 것이 핵심입니다." + }, + { + "id": "ca-cache-011", + "question": "캐시가 성능에 미치는 영향은 무엇인가요?", + "answer": "캐시 적중 시 메모리 접근보다 수십 배 빠르므로 적중률이 전체 성능을 크게 좌우합니다. 캐시 미스가 잦으면 CPU가 메모리를 기다리며 성능이 급감합니다." + } + ] + }, + { + "id": "ca-pipeline", + "name": "파이프라이닝", + "questions": [ + { + "id": "ca-pipeline-001", + "question": "파이프라이닝(pipelining)이란 무엇인가요?", + "answer": "명령어 처리 과정을 여러 단계로 나누어 서로 다른 명령어를 동시에 겹쳐 처리하는 기법입니다. 한 명령이 끝나길 기다리지 않고 단계별로 병렬 처리해 처리량(throughput)을 높입니다." + }, + { + "id": "ca-pipeline-002", + "question": "파이프라인의 5단계를 설명해주세요.", + "answer": "명령어 인출(IF), 명령어 해석(ID), 실행(EX), 메모리 접근(MEM), 레지스터 쓰기(WB) 단계로 나뉩니다. 각 단계가 동시에 다른 명령어를 처리하면서 전체 속도가 향상됩니다." + }, + { + "id": "ca-pipeline-003", + "question": "파이프라인 해저드(hazard)에는 어떤 종류가 있나요?", + "answer": "데이터 의존성으로 생기는 데이터 해저드, 분기 때문에 생기는 제어 해저드, 자원 충돌로 생기는 구조적 해저드가 있습니다. 이들은 파이프라인을 멈추게 해 성능을 떨어뜨립니다." + }, + { + "id": "ca-pipeline-004", + "question": "데이터 해저드를 해결하는 방법은 무엇인가요?", + "answer": "연산 결과를 다음 단계로 바로 전달하는 포워딩(forwarding), 의존성이 해소될 때까지 멈추는 스톨(stall), 컴파일러가 명령 순서를 바꾸는 방법 등이 있습니다." + }, + { + "id": "ca-pipeline-005", + "question": "분기 예측(branch prediction)이란 무엇인가요?", + "answer": "조건 분기 결과를 미리 예측해 파이프라인을 멈추지 않고 다음 명령어를 가져오는 기법입니다. 예측이 맞으면 성능이 향상되고 틀리면 잘못 가져온 명령을 버리는 비용이 발생합니다." + }, + { + "id": "ca-pipeline-006", + "question": "구조적 해저드는 어떻게 해결하나요?", + "answer": "같은 자원을 동시에 쓰려는 충돌이므로 자원을 복제하거나(명령어와 데이터 캐시 분리), 접근 시점을 조정해 해결합니다." + }, + { + "id": "ca-pipeline-007", + "question": "제어 해저드는 어떻게 해결하나요?", + "answer": "분기 결과가 정해질 때까지 멈추거나, 분기 예측을 하거나, 분기 명령 뒤에 영향 없는 명령을 넣는 지연 분기 기법으로 완화합니다." + }, + { + "id": "ca-pipeline-008", + "question": "파이프라인 버블(bubble)이란 무엇인가요?", + "answer": "해저드로 인해 파이프라인에 끼워 넣는 빈 단계로 아무 일도 하지 않는 NOP 명령과 같습니다. 의존성이 해소될 때까지 흐름을 지연시킵니다." + }, + { + "id": "ca-pipeline-009", + "question": "슈퍼스칼라(superscalar)란 무엇인가요?", + "answer": "여러 개의 실행 유닛을 두어 한 클럭에 명령어를 여러 개 동시에 처리하는 구조입니다. 명령어 수준 병렬성을 활용해 IPC를 1 이상으로 끌어올립니다." + }, + { + "id": "ca-pipeline-010", + "question": "비순차 실행(out-of-order execution)이란 무엇인가요?", + "answer": "명령어를 프로그램 순서가 아니라 실행 가능한 순서대로 처리하는 기법입니다. 앞 명령이 대기 중일 때 뒤 명령을 먼저 실행해 유휴 시간을 줄입니다." + }, + { + "id": "ca-pipeline-011", + "question": "파이프라인 깊이가 깊으면 어떤 장단점이 있나요?", + "answer": "단계가 많을수록 클럭을 높일 수 있어 처리량이 늘지만, 분기 예측 실패 시 비우는 비용이 커지고 해저드 관리가 복잡해집니다." + } + ] + }, + { + "id": "ca-isa", + "name": "명령어 집합 구조(ISA)", + "questions": [ + { + "id": "ca-isa-001", + "question": "RISC와 CISC의 차이는 무엇인가요?", + "answer": "RISC는 단순하고 고정 길이의 명령어를 사용해 파이프라이닝에 유리하고, CISC는 복잡하고 가변 길이의 명령어로 한 명령이 많은 일을 처리합니다. ARM은 RISC, x86은 CISC 계열입니다." + }, + { + "id": "ca-isa-002", + "question": "명령어 집합 구조(ISA)란 무엇인가요?", + "answer": "하드웨어와 소프트웨어가 소통하는 인터페이스로, CPU가 이해하는 명령어의 종류와 형식, 레지스터, 주소 지정 방식 등을 정의합니다. 같은 ISA면 기계어 호환이 가능합니다." + }, + { + "id": "ca-isa-003", + "question": "어셈블리 언어와 기계어의 관계는 무엇인가요?", + "answer": "기계어는 0과 1로 된 CPU가 직접 실행하는 코드이고, 어셈블리는 이를 사람이 읽을 수 있게 기호로 표현한 언어입니다. 어셈블러가 어셈블리를 기계어로 1대1에 가깝게 번역합니다." + }, + { + "id": "ca-isa-004", + "question": "주소 지정 방식(addressing mode)이란 무엇인가요?", + "answer": "명령어에서 피연산자의 위치를 지정하는 방법입니다. 값을 직접 쓰는 즉시 주소, 주소를 직접 쓰는 직접 주소, 주소가 담긴 곳을 가리키는 간접 주소, 레지스터 기반 방식 등이 있습니다." + }, + { + "id": "ca-isa-005", + "question": "스택 기반 ISA와 레지스터 기반 ISA의 차이는 무엇인가요?", + "answer": "스택 기반은 피연산자를 스택에서 가져와 명령어가 짧지만 메모리 접근이 많고, 레지스터 기반은 레지스터를 직접 지정해 빠르지만 명령어가 깁니다." + }, + { + "id": "ca-isa-006", + "question": "마이크로아키텍처와 ISA의 차이는 무엇인가요?", + "answer": "ISA는 소프트웨어가 보는 명령어 집합 명세이고, 마이크로아키텍처는 그것을 실제로 구현한 하드웨어 설계입니다. 같은 ISA도 서로 다른 마이크로아키텍처로 구현됩니다." + }, + { + "id": "ca-isa-007", + "question": "명령어의 종류에는 무엇이 있나요?", + "answer": "데이터 전송 명령, 산술과 논리 연산 명령, 분기와 제어 명령, 입출력 명령 등이 있습니다. 이들을 조합해 프로그램의 모든 동작을 수행합니다." + }, + { + "id": "ca-isa-008", + "question": "워드(word)란 무엇인가요?", + "answer": "CPU가 한 번에 처리하는 데이터의 기본 단위입니다. 32비트 CPU는 4바이트, 64비트 CPU는 8바이트가 한 워드이며 레지스터와 버스 폭의 기준이 됩니다." + }, + { + "id": "ca-isa-009", + "question": "옵코드(opcode)와 오퍼랜드(operand)란 무엇인가요?", + "answer": "옵코드는 어떤 연산을 할지 지정하는 부분이고, 오퍼랜드는 그 연산의 대상이 되는 데이터나 주소입니다. 명령어는 이 둘의 조합으로 구성됩니다." + }, + { + "id": "ca-isa-010", + "question": "엔디안이 호환성 측면에서 중요한 이유는 무엇인가요?", + "answer": "엔디안이 다른 시스템 간에 데이터를 주고받을 때 바이트 순서를 맞추지 않으면 값이 잘못 해석되기 때문입니다. 네트워크 통신과 파일 호환에서 특히 중요합니다." + } + ] + }, + { + "id": "ca-io", + "name": "입출력과 인터럽트", + "questions": [ + { + "id": "ca-io-001", + "question": "인터럽트(interrupt)란 무엇이고 왜 필요한가요?", + "answer": "CPU가 작업 중일 때 외부 또는 내부에서 발생한 긴급 이벤트를 알리는 신호입니다. CPU가 입출력 완료 등을 계속 확인하지 않아도 되게 해 자원을 효율적으로 사용하게 합니다." + }, + { + "id": "ca-io-002", + "question": "폴링(polling)과 인터럽트의 차이는 무엇인가요?", + "answer": "폴링은 CPU가 주기적으로 장치 상태를 직접 확인하는 방식이라 자원 낭비가 크고, 인터럽트는 장치가 준비되면 CPU에 신호를 보내는 방식이라 효율적입니다." + }, + { + "id": "ca-io-003", + "question": "DMA(Direct Memory Access)란 무엇인가요?", + "answer": "CPU를 거치지 않고 입출력 장치가 메모리에 직접 접근해 데이터를 주고받는 방식입니다. 대량 데이터 전송 시 CPU 부담을 줄여 다른 작업을 동시에 수행할 수 있게 합니다." + }, + { + "id": "ca-io-004", + "question": "인터럽트 처리 과정을 설명해주세요.", + "answer": "인터럽트가 발생하면 현재 작업 상태를 저장하고, 인터럽트 벡터로 해당 처리 루틴(ISR)의 주소를 찾아 실행한 뒤, 저장했던 상태를 복원해 원래 작업으로 돌아갑니다." + }, + { + "id": "ca-io-005", + "question": "하드웨어 인터럽트와 소프트웨어 인터럽트의 차이는 무엇인가요?", + "answer": "하드웨어 인터럽트는 키보드 입력이나 타이머처럼 외부 장치가 발생시키고, 소프트웨어 인터럽트는 시스템 콜이나 0으로 나누기 같은 프로그램 내부 요인으로 발생합니다." + }, + { + "id": "ca-io-006", + "question": "프로그램 제어 입출력(programmed I/O)이란 무엇인가요?", + "answer": "CPU가 직접 입출력 장치의 상태를 확인하고 데이터를 옮기는 방식입니다. 구현은 단순하지만 CPU가 입출력 내내 묶여 있어 효율이 떨어집니다." + }, + { + "id": "ca-io-007", + "question": "인터럽트 우선순위는 어떻게 처리하나요?", + "answer": "여러 인터럽트가 동시에 발생하면 우선순위가 높은 것을 먼저 처리하고 낮은 것은 대기시킵니다. 데이지 체인이나 우선순위 인코더로 결정합니다." + }, + { + "id": "ca-io-008", + "question": "인터럽트 벡터 테이블이란 무엇인가요?", + "answer": "각 인터럽트에 대응하는 처리 루틴(ISR)의 주소를 모아둔 표입니다. 인터럽트가 발생하면 이 표를 참조해 해당 처리 코드로 빠르게 분기합니다." + }, + { + "id": "ca-io-009", + "question": "버스 중재(bus arbitration)란 무엇인가요?", + "answer": "여러 장치가 버스를 동시에 쓰려 할 때 충돌을 막기 위해 사용 권한을 조정하는 것입니다. 중앙 집중식과 분산식 방식이 있습니다." + }, + { + "id": "ca-io-010", + "question": "동기식 전송과 비동기식 전송의 차이는 무엇인가요?", + "answer": "동기식은 공통 클럭에 맞춰 전송해 빠르지만 거리에 제약이 있고, 비동기식은 시작과 정지 비트로 타이밍을 맞춰 유연하지만 오버헤드가 있습니다." + }, + { + "id": "ca-io-011", + "question": "입출력에서 버퍼(buffer)가 필요한 이유는 무엇인가요?", + "answer": "CPU와 느린 입출력 장치의 속도 차이를 완충하기 위해서입니다. 데이터를 임시 저장해 두면 양쪽이 자신의 속도로 동작할 수 있어 효율이 높아집니다." + } + ] + }, + { + "id": "ca-parallel", + "name": "병렬처리와 멀티코어", + "questions": [ + { + "id": "ca-parallel-001", + "question": "병렬처리(parallel processing)란 무엇인가요?", + "answer": "여러 처리 장치가 작업을 나누어 동시에 수행해 전체 속도를 높이는 방식입니다. 하나의 큰 문제를 작은 단위로 분할해 병렬로 계산함으로써 처리 시간을 단축합니다." + }, + { + "id": "ca-parallel-002", + "question": "멀티코어와 멀티프로세서의 차이는 무엇인가요?", + "answer": "멀티코어는 하나의 칩 안에 여러 코어를 넣은 것이고, 멀티프로세서는 여러 개의 물리적 CPU를 사용하는 것입니다. 멀티코어는 캐시 등 자원 공유가 쉽고 비용 효율이 높습니다." + }, + { + "id": "ca-parallel-003", + "question": "암달의 법칙(Amdahl's Law)이란 무엇인가요?", + "answer": "병렬화로 얻는 성능 향상은 프로그램에서 병렬화할 수 없는 부분에 의해 제한된다는 법칙입니다. 직렬 처리 비중이 크면 코어를 아무리 늘려도 속도 향상에 한계가 있습니다." + }, + { + "id": "ca-parallel-004", + "question": "하이퍼스레딩(hyper-threading)이란 무엇인가요?", + "answer": "하나의 물리 코어를 두 개의 논리 코어처럼 동작시켜 유휴 자원을 활용하는 기술입니다. 한 스레드가 대기하는 동안 다른 스레드가 자원을 쓰게 해 처리량을 높입니다." + }, + { + "id": "ca-parallel-005", + "question": "플린의 분류(Flynn's taxonomy)란 무엇인가요?", + "answer": "명령어 흐름과 데이터 흐름의 개수에 따라 SISD, SIMD, MISD, MIMD로 컴퓨터 구조를 분류한 것입니다. 일반 CPU는 SISD, GPU는 SIMD, 멀티코어는 MIMD에 해당합니다." + }, + { + "id": "ca-parallel-006", + "question": "SIMD란 무엇인가요?", + "answer": "하나의 명령으로 여러 데이터를 동시에 처리하는 방식입니다. 같은 연산을 대량 데이터에 적용하는 그래픽, 영상, 행렬 연산에 효율적입니다." + }, + { + "id": "ca-parallel-007", + "question": "GPU와 CPU의 구조적 차이는 무엇인가요?", + "answer": "CPU는 적은 수의 강력한 코어로 복잡한 순차 작업에 강하고, GPU는 수천 개의 단순한 코어로 대량의 병렬 연산에 강합니다. 용도에 따라 역할이 다릅니다." + }, + { + "id": "ca-parallel-008", + "question": "동시성(concurrency)과 병렬성(parallelism)의 차이는 무엇인가요?", + "answer": "동시성은 여러 작업을 번갈아 처리해 동시에 진행되는 것처럼 보이게 하는 것이고, 병렬성은 여러 작업을 물리적으로 같은 시점에 실제로 처리하는 것입니다." + }, + { + "id": "ca-parallel-009", + "question": "캐시 일관성 프로토콜(MESI)이란 무엇인가요?", + "answer": "멀티코어에서 각 캐시 라인을 수정, 배타, 공유, 무효 네 상태로 관리해 일관성을 유지하는 프로토콜입니다. 한 코어가 값을 바꾸면 다른 코어의 복사본을 무효화합니다." + }, + { + "id": "ca-parallel-010", + "question": "병렬처리에서 동기화 비용이 왜 중요한가요?", + "answer": "여러 처리 단위가 데이터를 공유할 때 동기화 오버헤드가 크면 병렬화 이득이 상쇄되기 때문입니다. 작업 분할과 의존성 최소화가 성능의 관건입니다." + } + ] + }, + { + "id": "ca-storage", + "name": "보조기억장치와 저장장치", + "questions": [ + { + "id": "ca-storage-001", + "question": "HDD와 SSD의 차이는 무엇인가요?", + "answer": "HDD는 회전하는 자기 디스크에 데이터를 저장해 느리고 충격에 약하지만 저렴하고, SSD는 반도체 플래시 메모리를 써서 빠르고 충격에 강하지만 상대적으로 비쌉니다." + }, + { + "id": "ca-storage-002", + "question": "HDD의 구조를 설명해주세요.", + "answer": "데이터를 저장하는 원형 플래터, 읽고 쓰는 헤드, 동심원 형태의 트랙, 트랙을 나눈 섹터로 구성됩니다. 헤드가 플래터 위를 이동하며 데이터를 읽고 씁니다." + }, + { + "id": "ca-storage-003", + "question": "SSD는 어떻게 동작하나요?", + "answer": "전기적으로 데이터를 저장하는 낸드 플래시 셀에 데이터를 기록합니다. 기계적 움직임이 없어 접근이 빠르지만 셀마다 쓰기 횟수에 수명 한계가 있습니다." + }, + { + "id": "ca-storage-004", + "question": "디스크 접근 시간을 구성하는 요소는 무엇인가요?", + "answer": "헤드를 원하는 트랙으로 옮기는 탐색 시간, 섹터가 헤드 아래로 오길 기다리는 회전 지연, 실제 데이터를 옮기는 전송 시간으로 이루어집니다." + }, + { + "id": "ca-storage-005", + "question": "RAID란 무엇인가요?", + "answer": "여러 디스크를 묶어 하나처럼 사용해 성능이나 안정성을 높이는 기술입니다. 데이터를 분산하거나 복제해 속도 향상 또는 장애 대비 효과를 얻습니다." + }, + { + "id": "ca-storage-006", + "question": "RAID 0, 1, 5의 차이는 무엇인가요?", + "answer": "RAID 0은 데이터를 분산해 속도를 높이지만 안정성이 없고, RAID 1은 그대로 복제해 안정성을 높이며, RAID 5는 패리티로 한 디스크 고장에 대비하면서 공간 효율도 챙깁니다." + }, + { + "id": "ca-storage-007", + "question": "플래시 메모리란 무엇인가요?", + "answer": "전기적으로 데이터를 지우고 다시 쓸 수 있는 비휘발성 메모리입니다. USB, SSD, 메모리 카드 등에 쓰이며 블록 단위로 지우는 특성이 있습니다." + }, + { + "id": "ca-storage-008", + "question": "버퍼와 캐시의 차이는 무엇인가요?", + "answer": "버퍼는 속도 차이를 완충하려 데이터를 임시 저장하는 공간이고, 캐시는 자주 쓰는 데이터를 미리 저장해 재접근 속도를 높이는 공간입니다. 목적이 다릅니다." + } + ] + }, + { + "id": "ca-bus", + "name": "시스템 버스와 데이터 전송", + "questions": [ + { + "id": "ca-bus-001", + "question": "시스템 버스란 무엇인가요?", + "answer": "CPU, 메모리, 입출력 장치가 데이터를 주고받는 공용 통로입니다. 데이터 버스, 주소 버스, 제어 버스로 구성됩니다." + }, + { + "id": "ca-bus-002", + "question": "데이터 버스, 주소 버스, 제어 버스의 차이는 무엇인가요?", + "answer": "데이터 버스는 실제 데이터를 전송하고, 주소 버스는 데이터의 위치 주소를 전달하며, 제어 버스는 읽기나 쓰기 같은 제어 신호를 전달합니다." + }, + { + "id": "ca-bus-003", + "question": "버스 폭(bus width)은 무엇에 영향을 주나요?", + "answer": "한 번에 전송할 수 있는 비트 수를 결정해 데이터 전송량에 영향을 줍니다. 주소 버스 폭은 접근 가능한 메모리의 최대 크기를 좌우합니다." + }, + { + "id": "ca-bus-004", + "question": "직렬 전송과 병렬 전송의 차이는 무엇인가요?", + "answer": "직렬은 한 선으로 한 비트씩 보내 거리에 강하고, 병렬은 여러 선으로 동시에 여러 비트를 보내 빠르지만 신호 간섭에 약합니다. 최근에는 고속 직렬이 주류입니다." + }, + { + "id": "ca-bus-005", + "question": "대역폭(bandwidth)이란 무엇인가요?", + "answer": "단위 시간당 전송할 수 있는 데이터 양입니다. 버스 폭과 전송 속도의 곱으로 결정되며 시스템 성능의 중요한 지표입니다." + }, + { + "id": "ca-bus-006", + "question": "폴링과 인터럽트 방식의 데이터 전송 차이는 무엇인가요?", + "answer": "폴링은 CPU가 장치를 주기적으로 확인하며 전송하고, 인터럽트는 장치가 준비되면 CPU에 알려 전송합니다. 인터럽트가 CPU 자원을 절약합니다." + }, + { + "id": "ca-bus-007", + "question": "PCI Express 같은 고속 버스가 등장한 이유는 무엇인가요?", + "answer": "기존 병렬 버스의 속도 한계와 신호 간섭 문제를 해결하기 위해서입니다. 고속 직렬 방식의 점대점 연결로 대역폭을 크게 높였습니다." + } + ] + }, + { + "id": "ca-software-interface", + "name": "하드웨어-소프트웨어 인터페이스", + "questions": [ + { + "id": "ca-software-interface-001", + "question": "컴파일러와 인터프리터의 차이는 무엇인가요?", + "answer": "컴파일러는 소스 코드 전체를 기계어로 번역한 뒤 실행하고, 인터프리터는 한 줄씩 해석하며 실행합니다. 컴파일은 실행이 빠르고 인터프리트는 개발이 유연합니다." + }, + { + "id": "ca-software-interface-002", + "question": "소스 코드가 실행되기까지의 과정은 무엇인가요?", + "answer": "전처리, 컴파일, 어셈블, 링크 과정을 거쳐 실행 파일이 만들어지고, 로더가 메모리에 올려 실행합니다. 각 단계가 코드를 점점 기계가 이해할 형태로 바꿉니다." + }, + { + "id": "ca-software-interface-003", + "question": "어셈블러, 링커, 로더의 역할은 무엇인가요?", + "answer": "어셈블러는 어셈블리를 기계어로 번역하고, 링커는 여러 목적 파일과 라이브러리를 합치며, 로더는 완성된 프로그램을 메모리에 적재합니다." + }, + { + "id": "ca-software-interface-004", + "question": "정적 링킹과 동적 링킹의 차이는 무엇인가요?", + "answer": "정적 링킹은 라이브러리를 실행 파일에 포함해 독립적이지만 크고, 동적 링킹은 실행 시 공유 라이브러리를 연결해 파일이 작고 메모리를 절약합니다." + }, + { + "id": "ca-software-interface-005", + "question": "시스템 소프트웨어와 응용 소프트웨어의 차이는 무엇인가요?", + "answer": "시스템 소프트웨어는 운영체제나 컴파일러처럼 하드웨어를 관리하고 다른 프로그램을 지원하며, 응용 소프트웨어는 사용자의 특정 작업을 위한 프로그램입니다." + }, + { + "id": "ca-software-interface-006", + "question": "가상 머신(virtual machine)이란 무엇인가요?", + "answer": "하드웨어를 소프트웨어로 모방해 그 위에서 독립된 운영체제나 프로그램을 실행하는 기술입니다. 자바의 JVM처럼 플랫폼 독립성을 제공하기도 합니다." + }, + { + "id": "ca-software-interface-007", + "question": "펌웨어(firmware)란 무엇인가요?", + "answer": "하드웨어를 제어하기 위해 기기에 내장된 소프트웨어입니다. ROM이나 플래시에 저장되어 하드웨어와 소프트웨어의 중간 역할을 합니다." + } + ] + }, + { + "id": "ca-perf", + "name": "성능 평가", + "questions": [ + { + "id": "ca-perf-001", + "question": "처리량(throughput)과 응답 시간(latency)의 차이는 무엇인가요?", + "answer": "처리량은 단위 시간당 처리한 작업량이고, 응답 시간은 작업 하나가 끝나기까지 걸린 시간입니다. 둘 다 성능 지표지만 최적화 방향이 다를 수 있습니다." + }, + { + "id": "ca-perf-002", + "question": "MIPS란 무엇인가요?", + "answer": "초당 처리하는 명령어 수를 백만 단위로 나타낸 성능 지표입니다. 직관적이지만 명령어 복잡도가 다른 CPU 간 비교에는 한계가 있습니다." + }, + { + "id": "ca-perf-003", + "question": "FLOPS란 무엇인가요?", + "answer": "초당 부동소수점 연산 횟수로 과학 계산이나 그래픽 성능을 평가하는 지표입니다. 슈퍼컴퓨터 성능 비교에 널리 쓰입니다." + }, + { + "id": "ca-perf-004", + "question": "벤치마크란 무엇인가요?", + "answer": "표준화된 작업을 실행해 시스템 성능을 측정하고 비교하는 방법입니다. 실제 사용 패턴을 반영한 벤치마크일수록 신뢰도가 높습니다." + }, + { + "id": "ca-perf-005", + "question": "무어의 법칙(Moore's Law)이란 무엇인가요?", + "answer": "반도체 집적회로의 트랜지스터 수가 약 2년마다 두 배로 증가한다는 경험적 법칙입니다. 최근에는 물리적 한계로 증가세가 둔화되고 있습니다." + }, + { + "id": "ca-perf-006", + "question": "성능 평가에 클럭 속도만으로 부족한 이유는 무엇인가요?", + "answer": "클럭이 높아도 IPC가 낮거나 메모리 병목이 있으면 실제 성능이 떨어질 수 있기 때문입니다. 클럭, IPC, 명령어 수를 함께 봐야 합니다." + }, + { + "id": "ca-perf-007", + "question": "병목(bottleneck) 현상이란 무엇인가요?", + "answer": "전체 성능이 가장 느린 구성요소에 의해 제한되는 현상입니다. CPU가 빨라도 메모리나 디스크가 느리면 그 부분이 전체 속도를 좌우합니다." + }, + { + "id": "ca-perf-008", + "question": "암달의 법칙이 시사하는 바는 무엇인가요?", + "answer": "병렬화로 얻는 성능 향상은 직렬 부분에 의해 제한되므로, 일부만 최적화해서는 전체 향상에 한계가 있다는 점입니다. 가장 큰 병목부터 개선해야 효과적입니다." + } + ] + }, + { + "id": "ca-extra", + "name": "핵심 보충 개념", + "questions": [ + { + "id": "ca-extra-001", + "question": "32비트와 64비트 시스템의 차이는 무엇인가요?", + "answer": "한 번에 처리하는 데이터 크기와 주소 공간이 다릅니다. 64비트는 4GB를 넘는 메모리를 다룰 수 있고 더 큰 정수를 한 번에 연산할 수 있습니다." + }, + { + "id": "ca-extra-002", + "question": "인터럽트와 예외(exception)의 차이는 무엇인가요?", + "answer": "인터럽트는 주로 외부 장치가 비동기적으로 발생시키고, 예외는 0으로 나누기처럼 명령어 실행 중 내부에서 동기적으로 발생합니다. 처리 방식은 비슷합니다." + }, + { + "id": "ca-extra-003", + "question": "트랩(trap)이란 무엇인가요?", + "answer": "프로그램이 의도적으로 발생시키는 소프트웨어 인터럽트입니다. 시스템 콜처럼 사용자 모드에서 커널 기능을 요청할 때 사용됩니다." + }, + { + "id": "ca-extra-004", + "question": "평균 메모리 접근 시간은 어떻게 결정되나요?", + "answer": "캐시 적중 시간과 미스 시 추가되는 페널티의 가중 평균으로 결정됩니다. 적중률이 높을수록 평균 접근 시간이 짧아져 성능이 좋아집니다." + }, + { + "id": "ca-extra-005", + "question": "파이프라이닝과 병렬처리의 차이는 무엇인가요?", + "answer": "파이프라이닝은 한 작업을 단계로 나눠 겹쳐 처리하는 것이고, 병렬처리는 여러 작업을 여러 장치로 동시에 처리하는 것입니다. 둘을 함께 쓰기도 합니다." + }, + { + "id": "ca-extra-006", + "question": "레지스터가 메모리보다 빠른 이유는 무엇인가요?", + "answer": "CPU 내부에 있어 접근 거리가 짧고 전용 회로로 만들어졌기 때문입니다. 용량은 매우 작지만 가장 빠른 저장 공간입니다." + }, + { + "id": "ca-extra-007", + "question": "폰 노이만 병목을 완화하는 방법은 무엇인가요?", + "answer": "캐시 도입, 명령어와 데이터 버스 분리, 파이프라이닝, 멀티코어 등으로 메모리 접근 부담을 줄입니다. 데이터를 CPU 가까이 두는 것이 핵심입니다." + } + ] + }, + { + "id": "ca-modern-cpu", + "name": "현대 CPU 기술", + "questions": [ + { + "id": "ca-modern-cpu-001", + "question": "분기 예측(branch prediction)이란 무엇인가요?", + "answer": "분기 명령의 결과를 미리 추측해 파이프라인을 멈추지 않고 진행하는 기법입니다. 예측이 맞으면 성능이 오르고 틀리면 작업을 되돌립니다." + }, + { + "id": "ca-modern-cpu-002", + "question": "추측 실행(speculative execution)이란 무엇인가요?", + "answer": "확실하지 않은 경로의 명령을 미리 실행해두고 맞으면 결과를 쓰는 기법입니다. 성능을 높이지만 보안 취약점의 원인이 되기도 합니다." + }, + { + "id": "ca-modern-cpu-003", + "question": "하이퍼스레딩(hyper-threading)이란 무엇인가요?", + "answer": "하나의 물리 코어를 논리적으로 둘처럼 보이게 해 동시에 여러 스레드를 처리하는 기술입니다. 유휴 자원을 활용해 처리량을 높입니다." + }, + { + "id": "ca-modern-cpu-004", + "question": "멀티코어가 등장한 배경은 무엇인가요?", + "answer": "클럭 속도를 무한정 높이기 어려운 발열과 전력 한계 때문입니다. 코어 수를 늘려 병렬로 성능을 높이는 방향으로 전환했습니다." + }, + { + "id": "ca-modern-cpu-005", + "question": "캐시 프리페칭(prefetching)이란 무엇인가요?", + "answer": "앞으로 쓸 것으로 예상되는 데이터를 미리 캐시에 가져오는 기법입니다. 캐시 미스를 줄여 성능을 높이지만 잘못 예측하면 낭비가 됩니다." + }, + { + "id": "ca-modern-cpu-006", + "question": "NUMA란 무엇인가요?", + "answer": "프로세서마다 가까운 메모리와 먼 메모리의 접근 속도가 다른 구조입니다. 멀티 프로세서에서 가까운 메모리를 쓰도록 배치하면 성능이 좋아집니다." + }, + { + "id": "ca-modern-cpu-007", + "question": "SIMD 명령어 확장(SSE, AVX 등)이란 무엇인가요?", + "answer": "하나의 명령으로 여러 데이터를 동시에 처리하도록 추가된 명령어 집합입니다. 멀티미디어와 과학 연산의 성능을 크게 높입니다." + }, + { + "id": "ca-modern-cpu-008", + "question": "클럭 속도를 높이기 어려운 이유는 무엇인가요?", + "answer": "클럭을 올릴수록 전력 소모와 발열이 급격히 늘어 냉각과 안정성에 한계가 오기 때문입니다. 그래서 병렬화로 방향을 바꿨습니다." + } + ] + }, + { + "id": "ca-digital-logic", + "name": "디지털 논리 기초", + "questions": [ + { + "id": "ca-digital-logic-001", + "question": "논리 게이트(logic gate)란 무엇인가요?", + "answer": "AND, OR, NOT 같은 기본 논리 연산을 수행하는 회로입니다. 이들을 조합해 모든 디지털 연산 회로를 구성합니다." + }, + { + "id": "ca-digital-logic-002", + "question": "조합 논리 회로와 순차 논리 회로의 차이는 무엇인가요?", + "answer": "조합 회로는 현재 입력만으로 출력이 정해지고, 순차 회로는 과거 상태도 반영합니다. 순차 회로는 플립플롭 등으로 상태를 저장합니다." + }, + { + "id": "ca-digital-logic-003", + "question": "플립플롭(flip-flop)이란 무엇인가요?", + "answer": "1비트의 정보를 저장하는 기본 기억 소자입니다. 클럭 신호에 맞춰 상태를 유지하거나 바꾸며 레지스터의 기본 단위가 됩니다." + }, + { + "id": "ca-digital-logic-004", + "question": "가산기(adder)란 무엇인가요?", + "answer": "이진수의 덧셈을 수행하는 회로입니다. 반가산기와 전가산기를 연결해 여러 비트의 덧셈을 처리하며 ALU의 핵심 요소입니다." + }, + { + "id": "ca-digital-logic-005", + "question": "멀티플렉서(MUX)란 무엇인가요?", + "answer": "여러 입력 중 하나를 선택 신호에 따라 골라 출력하는 회로입니다. 데이터 경로 선택에 쓰이며 디멀티플렉서는 그 반대 역할을 합니다." + }, + { + "id": "ca-digital-logic-006", + "question": "ALU란 무엇인가요?", + "answer": "산술 연산과 논리 연산을 수행하는 CPU의 핵심 회로입니다. 덧셈, 뺄셈, AND, OR 등 기본 연산을 담당합니다." + }, + { + "id": "ca-digital-logic-007", + "question": "클럭 신호의 역할은 무엇인가요?", + "answer": "디지털 회로의 동작 타이밍을 맞추는 주기적 신호입니다. 모든 구성요소가 클럭에 맞춰 동기화되어 일관되게 동작합니다." + }, + { + "id": "ca-digital-logic-008", + "question": "진리표(truth table)란 무엇인가요?", + "answer": "가능한 모든 입력 조합에 대한 출력을 정리한 표입니다. 논리 회로의 동작을 명확히 나타내고 설계와 검증에 사용됩니다." + } + ] + } + ] + }, + { + "id": "network", + "name": "네트워크", + "categories": [ + { + "id": "net-model", + "name": "네트워크 기초와 계층 모델", + "questions": [ + { + "id": "net-model-001", + "question": "OSI 7계층을 설명해주세요.", + "answer": "네트워크 통신을 7개 단계로 나눈 표준 모델로 물리, 데이터링크, 네트워크, 전송, 세션, 표현, 응용 계층으로 구성됩니다. 각 계층이 독립적 역할을 맡아 문제 분석과 표준화가 쉬워집니다." + }, + { + "id": "net-model-002", + "question": "TCP/IP 4계층 모델이란 무엇인가요?", + "answer": "실제 인터넷에서 쓰이는 모델로 네트워크 액세스, 인터넷, 전송, 응용 계층으로 구성됩니다. OSI보다 단순하며 현재 통신의 사실상 표준입니다." + }, + { + "id": "net-model-003", + "question": "OSI 모델과 TCP/IP 모델의 차이는 무엇인가요?", + "answer": "OSI는 7계층의 이론적 참조 모델이고 TCP/IP는 4계층의 실용적 구현 모델입니다. OSI는 교육과 표준화에 쓰이고 TCP/IP는 실제 네트워크 동작을 설명하는 데 쓰입니다." + }, + { + "id": "net-model-004", + "question": "캡슐화(encapsulation)란 무엇인가요?", + "answer": "데이터가 상위 계층에서 하위 계층으로 내려가며 각 계층의 헤더 정보를 덧붙이는 과정입니다. 수신 측에서는 역캡슐화로 헤더를 차례로 벗겨내며 원래 데이터를 복원합니다." + }, + { + "id": "net-model-005", + "question": "각 계층의 데이터 전송 단위(PDU)는 무엇인가요?", + "answer": "전송 계층은 세그먼트(TCP)나 데이터그램(UDP), 네트워크 계층은 패킷, 데이터링크 계층은 프레임, 물리 계층은 비트 단위로 데이터를 다룹니다." + }, + { + "id": "net-model-006", + "question": "프로토콜이란 무엇인가요?", + "answer": "통신하는 두 주체가 데이터를 주고받기 위해 따르는 약속이자 규칙입니다. 데이터 형식, 순서, 오류 처리 등을 정의해 서로 다른 기기도 통신할 수 있게 합니다." + }, + { + "id": "net-model-007", + "question": "물리 계층의 역할은 무엇인가요?", + "answer": "비트를 전기, 빛, 전파 같은 물리적 신호로 변환해 전송하는 계층입니다. 케이블, 커넥터, 전송 매체 등 하드웨어적 특성을 다룹니다." + }, + { + "id": "net-model-008", + "question": "데이터링크 계층의 역할은 무엇인가요?", + "answer": "같은 네트워크 내에서 MAC 주소로 프레임을 전달하고 오류를 검출하는 계층입니다. 인접한 장치 간 신뢰성 있는 전송을 담당합니다." + }, + { + "id": "net-model-009", + "question": "네트워크 계층의 역할은 무엇인가요?", + "answer": "IP 주소를 기반으로 서로 다른 네트워크 사이에서 패킷의 경로를 정하고 전달하는 계층입니다. 라우팅이 핵심 기능입니다." + }, + { + "id": "net-model-010", + "question": "전송 계층의 역할은 무엇인가요?", + "answer": "종단 간 신뢰성 있는 데이터 전달과 흐름 제어를 담당하는 계층입니다. TCP와 UDP가 대표적이며 포트 번호로 애플리케이션을 구분합니다." + }, + { + "id": "net-model-011", + "question": "응용 계층의 역할은 무엇인가요?", + "answer": "사용자와 가장 가까운 계층으로 HTTP, FTP, DNS 같은 서비스를 제공합니다. 실제 응용 프로그램이 네트워크를 사용하는 통로입니다." + } + ] + }, + { + "id": "net-transport", + "name": "TCP와 UDP", + "questions": [ + { + "id": "net-transport-001", + "question": "TCP와 UDP의 차이는 무엇인가요?", + "answer": "TCP는 연결을 설정하고 데이터 순서와 신뢰성을 보장하는 대신 느리고, UDP는 연결 없이 데이터를 빠르게 보내지만 신뢰성을 보장하지 않습니다. 용도에 따라 적절히 선택합니다." + }, + { + "id": "net-transport-002", + "question": "TCP 3-way handshake를 설명해주세요.", + "answer": "연결 설정 과정으로 클라이언트가 SYN을 보내고, 서버가 SYN+ACK로 응답하며, 클라이언트가 ACK를 보내 연결을 확립합니다. 양쪽이 서로 통신 준비가 되었음을 확인하는 절차입니다." + }, + { + "id": "net-transport-003", + "question": "TCP 4-way handshake(연결 종료)를 설명해주세요.", + "answer": "연결 종료 과정으로 한쪽이 FIN을 보내면 상대가 ACK로 응답하고, 상대도 FIN을 보낸 뒤 마지막 ACK로 종료됩니다. 양방향 연결을 각각 닫기 때문에 4단계가 필요합니다." + }, + { + "id": "net-transport-004", + "question": "TCP의 흐름 제어와 혼잡 제어의 차이는 무엇인가요?", + "answer": "흐름 제어는 수신자가 처리할 수 있는 만큼만 보내도록 송신 속도를 조절하는 것이고, 혼잡 제어는 네트워크 전체의 혼잡 상태를 고려해 전송량을 조절하는 것입니다." + }, + { + "id": "net-transport-005", + "question": "TCP가 신뢰성을 보장하는 방법은 무엇인가요?", + "answer": "데이터에 순서 번호를 매기고 수신 확인(ACK)을 받으며, 응답이 없으면 재전송합니다. 체크섬으로 오류를 검출하고 순서 번호로 중복과 순서 어긋남을 처리해 신뢰성을 확보합니다." + }, + { + "id": "net-transport-006", + "question": "UDP는 언제 사용하나요?", + "answer": "속도와 실시간성이 중요한 경우에 사용합니다. 약간의 데이터 손실이 허용되는 실시간 스트리밍, 온라인 게임, DNS 조회, VoIP 등에서 빠른 전송을 위해 쓰입니다." + }, + { + "id": "net-transport-007", + "question": "포트(port) 번호란 무엇인가요?", + "answer": "한 컴퓨터에서 실행 중인 여러 프로그램을 구분하기 위한 번호입니다. IP가 컴퓨터를 식별한다면 포트는 그 안의 특정 애플리케이션을 식별합니다." + }, + { + "id": "net-transport-008", + "question": "소켓(socket)이란 무엇인가요?", + "answer": "네트워크 통신의 끝점으로 IP 주소와 포트 번호의 조합입니다. 프로그램은 소켓을 통해 데이터를 주고받으며 통신 연결을 추상화합니다." + }, + { + "id": "net-transport-009", + "question": "TCP 헤더에는 어떤 정보가 들어 있나요?", + "answer": "출발지와 목적지 포트, 순서 번호, 확인 응답 번호, 플래그(SYN, ACK 등), 윈도우 크기, 체크섬 등이 담깁니다. 신뢰성 제어에 필요한 정보들입니다." + }, + { + "id": "net-transport-010", + "question": "슬라이딩 윈도우(sliding window)란 무엇인가요?", + "answer": "확인 응답을 기다리지 않고 여러 패킷을 연속 전송할 수 있게 하는 흐름 제어 기법입니다. 윈도우 크기만큼 미리 보내 전송 효율을 높입니다." + }, + { + "id": "net-transport-011", + "question": "TCP 혼잡 제어를 설명해주세요.", + "answer": "네트워크 혼잡을 피하기 위해 전송량을 조절합니다. 처음엔 천천히 늘리는 슬로우 스타트로 시작해, 혼잡이 감지되면 전송 윈도우를 줄여 대응합니다." + }, + { + "id": "net-transport-012", + "question": "TIME_WAIT 상태란 무엇인가요?", + "answer": "TCP 연결 종료 후 일정 시간 대기하는 상태입니다. 지연된 패킷이 다음 연결에 섞이는 것을 막고 마지막 응답이 확실히 전달되도록 보장합니다." + } + ] + }, + { + "id": "net-http", + "name": "HTTP와 HTTPS", + "questions": [ + { + "id": "net-http-001", + "question": "HTTP란 무엇인가요?", + "answer": "웹에서 클라이언트와 서버가 데이터를 주고받기 위한 요청-응답 기반 프로토콜입니다. 주로 HTML 등 웹 자원을 전송하며 상태를 저장하지 않는 무상태(stateless) 특성을 가집니다." + }, + { + "id": "net-http-002", + "question": "HTTP와 HTTPS의 차이는 무엇인가요?", + "answer": "HTTPS는 HTTP에 SSL/TLS 암호화를 적용한 것입니다. 데이터를 암호화해 도청과 변조를 막고 서버 신원을 인증하므로 보안이 필요한 통신에 사용됩니다." + }, + { + "id": "net-http-003", + "question": "주요 HTTP 메서드의 차이는 무엇인가요?", + "answer": "GET은 조회, POST는 생성, PUT은 전체 수정, PATCH는 부분 수정, DELETE는 삭제에 사용합니다. GET과 DELETE 등은 멱등성을 가지지만 POST는 호출할 때마다 결과가 달라질 수 있습니다." + }, + { + "id": "net-http-004", + "question": "HTTP 상태 코드를 설명해주세요.", + "answer": "응답 결과를 나타내는 숫자로 2xx는 성공, 3xx는 리다이렉션, 4xx는 클라이언트 오류, 5xx는 서버 오류를 의미합니다. 200(성공), 404(없음), 500(서버 에러)이 대표적입니다." + }, + { + "id": "net-http-005", + "question": "GET과 POST의 차이는 무엇인가요?", + "answer": "GET은 데이터를 URL 쿼리스트링에 담아 조회에 사용하고 캐싱이 가능하며, POST는 데이터를 본문(body)에 담아 생성이나 변경에 사용합니다. POST가 상대적으로 더 많은 데이터를 안전하게 전송할 수 있습니다." + }, + { + "id": "net-http-006", + "question": "HTTP는 무상태인데 어떻게 상태를 유지하나요?", + "answer": "쿠키와 세션을 사용합니다. 서버가 클라이언트에 쿠키를 저장하게 하거나 서버 측에 세션을 두어 사용자 식별 정보를 유지함으로써 로그인 상태 등을 이어갑니다." + }, + { + "id": "net-http-007", + "question": "HTTP/1.1, 2, 3의 차이는 무엇인가요?", + "answer": "HTTP/1.1은 연결당 순차 처리, HTTP/2는 멀티플렉싱으로 한 연결에서 여러 요청을 병렬 처리합니다. HTTP/3는 TCP 대신 UDP 기반 QUIC를 사용해 연결 지연과 패킷 손실 문제를 개선했습니다." + }, + { + "id": "net-http-008", + "question": "멱등성(idempotent)이란 무엇인가요?", + "answer": "같은 요청을 여러 번 보내도 결과가 달라지지 않는 성질입니다. GET, PUT, DELETE는 멱등하지만 POST는 호출할 때마다 새 자원이 생길 수 있어 멱등하지 않습니다." + }, + { + "id": "net-http-009", + "question": "주요 HTTP 헤더에는 무엇이 있나요?", + "answer": "콘텐츠 형식을 알리는 Content-Type, 인증 정보를 담는 Authorization, 클라이언트 정보를 담는 User-Agent, 캐시를 제어하는 Cache-Control 등이 있습니다." + }, + { + "id": "net-http-010", + "question": "쿠키의 보안 속성이란 무엇인가요?", + "answer": "HTTPS에서만 전송하는 Secure, 자바스크립트 접근을 막는 HttpOnly, 교차 사이트 전송을 제한하는 SameSite 속성이 있습니다. 쿠키 탈취와 CSRF 방어에 쓰입니다." + }, + { + "id": "net-http-011", + "question": "HTTP 상태 코드 301과 302의 차이는 무엇인가요?", + "answer": "301은 영구 이동으로 자원이 완전히 옮겨졌음을 의미하고, 302는 일시 이동으로 임시로 다른 위치를 가리킵니다. 검색엔진의 처리 방식이 다릅니다." + }, + { + "id": "net-http-012", + "question": "304 Not Modified는 언제 사용하나요?", + "answer": "클라이언트가 캐시한 자원이 서버에서 변경되지 않았을 때 반환합니다. 본문을 다시 보내지 않아 대역폭을 절약하고 응답 속도를 높입니다." + }, + { + "id": "net-http-013", + "question": "HTTP/2의 멀티플렉싱이란 무엇인가요?", + "answer": "하나의 연결에서 여러 요청과 응답을 동시에 주고받는 기능입니다. HTTP/1.1의 순차 처리로 인한 지연(HOL 블로킹)을 줄여 성능을 개선합니다." + } + ] + }, + { + "id": "net-ip", + "name": "IP와 라우팅", + "questions": [ + { + "id": "net-ip-001", + "question": "IP 주소란 무엇이고 IPv4와 IPv6의 차이는 무엇인가요?", + "answer": "네트워크상 장치를 식별하는 주소입니다. IPv4는 32비트로 약 43억 개를 표현하지만 고갈 문제가 있고, IPv6는 128비트로 사실상 무한에 가까운 주소를 제공합니다." + }, + { + "id": "net-ip-002", + "question": "공인 IP와 사설 IP의 차이는 무엇인가요?", + "answer": "공인 IP는 인터넷에서 전 세계적으로 유일하게 식별되는 주소이고, 사설 IP는 내부 네트워크에서만 사용되는 주소입니다. 사설 IP는 NAT를 통해 공인 IP로 변환되어 외부와 통신합니다." + }, + { + "id": "net-ip-003", + "question": "서브넷 마스크란 무엇인가요?", + "answer": "IP 주소에서 네트워크 부분과 호스트 부분을 구분하는 값입니다. 이를 통해 하나의 큰 네트워크를 여러 개의 작은 서브넷으로 나누어 관리 효율과 보안을 높입니다." + }, + { + "id": "net-ip-004", + "question": "라우터와 스위치의 차이는 무엇인가요?", + "answer": "스위치는 같은 네트워크 안에서 MAC 주소를 기반으로 프레임을 전달하고(2계층), 라우터는 서로 다른 네트워크 사이에서 IP 주소를 기반으로 패킷의 경로를 결정합니다(3계층)." + }, + { + "id": "net-ip-005", + "question": "NAT(Network Address Translation)란 무엇인가요?", + "answer": "사설 IP를 공인 IP로 변환해 여러 내부 기기가 하나의 공인 IP를 공유하게 하는 기술입니다. IP 주소 부족 문제를 완화하고 내부 네트워크를 외부로부터 숨기는 보안 효과도 있습니다." + }, + { + "id": "net-ip-006", + "question": "게이트웨이(gateway)란 무엇인가요?", + "answer": "서로 다른 네트워크를 연결하는 출입구 역할을 하는 장치입니다. 내부 네트워크의 기기가 외부 네트워크와 통신할 때 거치는 통로로, 보통 라우터가 그 역할을 합니다." + }, + { + "id": "net-ip-007", + "question": "라우팅 테이블이란 무엇인가요?", + "answer": "목적지 네트워크별로 다음에 보낼 경로 정보를 담은 표입니다. 라우터는 이 표를 참조해 패킷을 어느 인터페이스로 보낼지 결정합니다." + }, + { + "id": "net-ip-008", + "question": "정적 라우팅과 동적 라우팅의 차이는 무엇인가요?", + "answer": "정적은 관리자가 경로를 수동 설정해 단순하지만 변화에 약하고, 동적은 라우팅 프로토콜이 경로를 자동 갱신해 변화에 유연하지만 오버헤드가 있습니다." + }, + { + "id": "net-ip-009", + "question": "ICMP란 무엇인가요?", + "answer": "네트워크 상태나 오류를 알리는 데 쓰이는 프로토콜입니다. 목적지 도달 불가나 시간 초과 같은 메시지를 전달하며 ping과 traceroute의 기반이 됩니다." + }, + { + "id": "net-ip-010", + "question": "ping과 traceroute는 어떻게 동작하나요?", + "answer": "ping은 ICMP 요청과 응답으로 연결 여부와 지연을 확인하고, traceroute는 TTL을 늘려가며 패킷이 거치는 경로의 각 라우터를 추적합니다." + }, + { + "id": "net-ip-011", + "question": "CIDR이란 무엇인가요?", + "answer": "IP 주소를 클래스 단위가 아니라 임의의 비트 길이로 나누는 방식입니다. 주소를 유연하게 할당해 낭비를 줄이며 슬래시 표기로 나타냅니다." + }, + { + "id": "net-ip-012", + "question": "유니캐스트, 멀티캐스트, 브로드캐스트의 차이는 무엇인가요?", + "answer": "유니캐스트는 1대1, 멀티캐스트는 특정 그룹 대상, 브로드캐스트는 네트워크 내 모든 대상으로 전송하는 방식입니다. 전송 범위가 다릅니다." + } + ] + }, + { + "id": "net-dns", + "name": "DNS", + "questions": [ + { + "id": "net-dns-001", + "question": "DNS란 무엇인가요?", + "answer": "사람이 읽기 쉬운 도메인 이름을 컴퓨터가 사용하는 IP 주소로 변환해주는 시스템입니다. 인터넷의 전화번호부 역할을 하며 분산된 계층 구조로 운영됩니다." + }, + { + "id": "net-dns-002", + "question": "DNS 동작 과정을 설명해주세요.", + "answer": "도메인을 입력하면 먼저 로컬 캐시를 확인하고, 없으면 재귀 DNS 서버가 루트, TLD, 권한 있는 네임서버를 차례로 질의해 IP를 찾습니다. 결과는 캐시에 저장되어 다음 조회 속도를 높입니다." + }, + { + "id": "net-dns-003", + "question": "주요 DNS 레코드의 종류는 무엇인가요?", + "answer": "도메인을 IPv4에 연결하는 A 레코드, IPv6에 연결하는 AAAA, 다른 도메인 별칭을 지정하는 CNAME, 메일 서버를 지정하는 MX, 텍스트 정보를 담는 TXT 등이 있습니다." + }, + { + "id": "net-dns-004", + "question": "DNS는 주로 어떤 프로토콜을 사용하나요?", + "answer": "일반적인 질의는 빠른 응답을 위해 UDP 53번 포트를 사용하고, 응답 데이터가 크거나 영역 전송(zone transfer)이 필요할 때는 신뢰성을 위해 TCP를 사용합니다." + }, + { + "id": "net-dns-005", + "question": "재귀 질의와 반복 질의의 차이는 무엇인가요?", + "answer": "재귀 질의는 답을 얻을 때까지 DNS 서버가 대신 끝까지 찾아주고, 반복 질의는 다음에 물어볼 서버 정보만 알려줍니다. 리졸버는 보통 재귀, 서버 간은 반복으로 동작합니다." + }, + { + "id": "net-dns-006", + "question": "DNS의 TTL이란 무엇인가요?", + "answer": "조회 결과를 캐시에 보관하는 유효 시간입니다. TTL이 길면 캐시 효율이 좋지만 변경 반영이 느리고, 짧으면 최신성은 좋지만 조회가 잦아집니다." + }, + { + "id": "net-dns-007", + "question": "DNS 라운드 로빈이란 무엇인가요?", + "answer": "하나의 도메인에 여러 IP를 등록해 요청마다 다른 IP를 반환하는 방식입니다. 간단한 부하 분산 효과를 얻지만 서버 상태를 고려하지는 못합니다." + }, + { + "id": "net-dns-008", + "question": "정방향 조회와 역방향 조회의 차이는 무엇인가요?", + "answer": "정방향은 도메인 이름으로 IP를 찾는 것이고, 역방향은 IP로 도메인 이름을 찾는 것입니다. 역방향 조회는 메일 서버 검증 등에 쓰입니다." + }, + { + "id": "net-dns-009", + "question": "DNS가 분산 계층 구조인 이유는 무엇인가요?", + "answer": "전 세계 도메인을 한 서버가 관리하면 부하와 장애에 취약하기 때문입니다. 루트, TLD, 권한 서버로 책임을 나눠 확장성과 안정성을 확보합니다." + } + ] + }, + { + "id": "net-web", + "name": "웹 통신 흐름", + "questions": [ + { + "id": "net-web-001", + "question": "브라우저에 URL을 입력하면 어떤 일이 일어나나요?", + "answer": "DNS로 도메인을 IP로 변환하고, TCP 연결과 TLS 핸드셰이크를 거쳐 서버에 HTTP 요청을 보냅니다. 서버가 응답하면 브라우저가 HTML, CSS, JS를 받아 렌더링해 화면에 표시합니다." + }, + { + "id": "net-web-002", + "question": "쿠키와 세션의 차이는 무엇인가요?", + "answer": "쿠키는 클라이언트(브라우저)에 데이터를 저장하고, 세션은 서버에 데이터를 저장합니다. 쿠키는 탈취 위험이 있어 민감 정보에 부적합하고, 세션은 서버 자원을 사용하지만 더 안전합니다." + }, + { + "id": "net-web-003", + "question": "CORS란 무엇인가요?", + "answer": "다른 출처(도메인, 포트, 프로토콜)의 자원 요청을 제어하는 브라우저 보안 정책입니다. 기본적으로 교차 출처 요청을 막으며, 서버가 허용 헤더를 응답하면 접근을 허가합니다." + }, + { + "id": "net-web-004", + "question": "REST API란 무엇인가요?", + "answer": "자원을 URI로 표현하고 HTTP 메서드로 행위를 정의하는 API 설계 방식입니다. 무상태성과 일관된 인터페이스를 지향하며, 자원 중심의 직관적인 URL 설계가 특징입니다." + }, + { + "id": "net-web-005", + "question": "웹소켓(WebSocket)과 HTTP의 차이는 무엇인가요?", + "answer": "HTTP는 요청이 있어야 응답하는 단방향 요청-응답 방식이고, 웹소켓은 한 번 연결되면 서버와 클라이언트가 양방향으로 실시간 통신할 수 있습니다. 채팅이나 실시간 알림에 적합합니다." + }, + { + "id": "net-web-006", + "question": "동기와 비동기 통신의 차이는 무엇인가요?", + "answer": "동기는 요청 후 응답을 받을 때까지 기다리고, 비동기는 응답을 기다리지 않고 다른 작업을 진행하다 결과를 나중에 처리합니다. 비동기가 자원 활용에 유리합니다." + }, + { + "id": "net-web-007", + "question": "폴링, 롱 폴링, 웹소켓의 차이는 무엇인가요?", + "answer": "폴링은 주기적으로 요청해 확인하고, 롱 폴링은 응답을 보류했다가 변화 시 응답하며, 웹소켓은 연결을 유지해 양방향 실시간 통신을 합니다. 실시간성이 점점 높아집니다." + }, + { + "id": "net-web-008", + "question": "JWT란 무엇인가요?", + "answer": "사용자 정보를 담아 서명한 토큰으로 인증에 쓰입니다. 헤더, 페이로드, 서명으로 구성되며 서버가 상태를 저장하지 않아도 되어 확장성이 좋습니다." + }, + { + "id": "net-web-009", + "question": "세션 기반 인증과 토큰 기반 인증의 차이는 무엇인가요?", + "answer": "세션은 서버가 로그인 상태를 저장하고, 토큰은 클라이언트가 토큰을 보관해 매 요청에 보냅니다. 토큰 방식이 서버 부담이 적고 확장에 유리합니다." + }, + { + "id": "net-web-010", + "question": "CDN이란 무엇인가요?", + "answer": "콘텐츠를 사용자와 가까운 여러 서버에 분산 배치해 빠르게 전달하는 네트워크입니다. 지연을 줄이고 원본 서버 부하를 낮추며 대용량 트래픽에 유리합니다." + }, + { + "id": "net-web-011", + "question": "로드 밸런싱 알고리즘에는 어떤 것이 있나요?", + "answer": "순서대로 배분하는 라운드 로빈, 연결이 적은 서버에 보내는 최소 연결, 가중치를 둔 방식 등이 있습니다. 서버 상태와 용량에 맞게 선택합니다." + } + ] + }, + { + "id": "net-security", + "name": "네트워크 보안", + "questions": [ + { + "id": "net-security-001", + "question": "대칭키와 비대칭키 암호화의 차이는 무엇인가요?", + "answer": "대칭키는 암호화와 복호화에 같은 키를 써서 빠르지만 키 공유가 어렵고, 비대칭키는 공개키와 개인키 쌍을 써서 안전하지만 느립니다. 실제로는 두 방식을 함께 사용합니다." + }, + { + "id": "net-security-002", + "question": "HTTPS의 SSL/TLS 동작 과정을 설명해주세요.", + "answer": "핸드셰이크에서 서버 인증서로 신원을 확인하고 비대칭키로 대칭키를 안전하게 교환합니다. 이후 실제 데이터는 빠른 대칭키 방식으로 암호화해 주고받습니다." + }, + { + "id": "net-security-003", + "question": "공개키 기반구조(PKI)와 인증서란 무엇인가요?", + "answer": "공개키의 소유자를 신뢰할 수 있는 인증기관(CA)이 보증하는 체계입니다. CA가 서명한 디지털 인증서로 서버의 신원을 확인해 중간자 공격을 방지합니다." + }, + { + "id": "net-security-004", + "question": "방화벽(firewall)이란 무엇인가요?", + "answer": "정해진 규칙에 따라 들어오고 나가는 네트워크 트래픽을 허용하거나 차단하는 보안 시스템입니다. 신뢰할 수 없는 외부 네트워크로부터 내부를 보호하는 1차 방어선 역할을 합니다." + }, + { + "id": "net-security-005", + "question": "해싱과 암호화의 차이는 무엇인가요?", + "answer": "암호화는 키로 복호화해 원문을 복원할 수 있지만, 해싱은 단방향이라 원문을 복원할 수 없습니다. 비밀번호 저장에는 해싱이 적합합니다." + }, + { + "id": "net-security-006", + "question": "솔트(salt)란 무엇인가요?", + "answer": "비밀번호를 해싱하기 전에 덧붙이는 무작위 값입니다. 같은 비밀번호라도 다른 해시값이 나오게 해 미리 계산된 공격(레인보우 테이블)을 막습니다." + }, + { + "id": "net-security-007", + "question": "XSS란 무엇인가요?", + "answer": "악성 스크립트를 웹 페이지에 삽입해 다른 사용자의 브라우저에서 실행시키는 공격입니다. 입력값 검증과 출력 이스케이프로 방어합니다." + }, + { + "id": "net-security-008", + "question": "CSRF란 무엇인가요?", + "answer": "사용자가 로그인된 상태를 악용해 의도하지 않은 요청을 보내게 하는 공격입니다. CSRF 토큰이나 SameSite 쿠키로 방어합니다." + }, + { + "id": "net-security-009", + "question": "SQL 인젝션이란 무엇인가요?", + "answer": "입력값에 악성 SQL을 삽입해 데이터베이스를 조작하는 공격입니다. 매개변수화된 쿼리나 입력 검증으로 방어합니다." + }, + { + "id": "net-security-010", + "question": "DDoS 공격이란 무엇인가요?", + "answer": "다수의 기기로 대량의 트래픽을 보내 서비스를 마비시키는 공격입니다. 트래픽 필터링, CDN, 속도 제한 등으로 대응합니다." + } + ] + }, + { + "id": "net-etc", + "name": "기타 프로토콜과 장비", + "questions": [ + { + "id": "net-etc-001", + "question": "DHCP란 무엇인가요?", + "answer": "네트워크에 접속하는 기기에 IP 주소, 서브넷 마스크, 게이트웨이 등을 자동으로 할당해주는 프로토콜입니다. 수동 설정 없이 동적으로 주소를 배정해 관리 부담을 줄입니다." + }, + { + "id": "net-etc-002", + "question": "ARP란 무엇인가요?", + "answer": "IP 주소를 실제 통신에 필요한 MAC 주소로 변환하는 프로토콜입니다. 같은 네트워크에서 목적지 IP에 해당하는 하드웨어 주소를 알아내 프레임을 전달할 때 사용됩니다." + }, + { + "id": "net-etc-003", + "question": "MAC 주소란 무엇인가요?", + "answer": "네트워크 인터페이스 카드(NIC)에 부여된 고유한 물리적 주소입니다. 데이터링크 계층에서 같은 네트워크 내 기기를 식별하는 데 쓰이며 변하지 않는 하드웨어 식별자입니다." + }, + { + "id": "net-etc-004", + "question": "로드 밸런서(load balancer)란 무엇인가요?", + "answer": "들어오는 트래픽을 여러 서버에 분산시켜 부하를 고르게 나누는 장치 또는 소프트웨어입니다. 특정 서버 과부하를 막아 가용성과 응답 속도를 높이고 장애 대응력을 강화합니다." + }, + { + "id": "net-etc-005", + "question": "포워드 프록시와 리버스 프록시의 차이는 무엇인가요?", + "answer": "포워드 프록시는 클라이언트를 대신해 요청을 보내 클라이언트를 숨기고, 리버스 프록시는 서버 앞에 서서 요청을 받아 서버를 숨기고 부하를 분산합니다." + }, + { + "id": "net-etc-006", + "question": "VPN이란 무엇인가요?", + "answer": "공용 네트워크에 암호화된 가상의 사설 통로를 만들어 안전하게 통신하는 기술입니다. 원격 접속과 데이터 보호에 사용됩니다." + }, + { + "id": "net-etc-007", + "question": "패킷과 프레임의 차이는 무엇인가요?", + "answer": "패킷은 네트워크 계층의 데이터 단위로 IP 주소를 포함하고, 프레임은 데이터링크 계층의 단위로 MAC 주소를 포함합니다. 프레임이 패킷을 감싸 전송됩니다." + }, + { + "id": "net-etc-008", + "question": "허브와 스위치의 차이는 무엇인가요?", + "answer": "허브는 받은 데이터를 모든 포트로 단순 전달해 충돌이 많고, 스위치는 MAC 주소를 보고 해당 포트로만 전달해 효율적입니다. 스위치가 더 지능적입니다." + }, + { + "id": "net-etc-009", + "question": "OSI 1계층 장비란 무엇인가요?", + "answer": "신호를 단순 증폭하거나 중계하는 리피터와, 여러 기기를 물리적으로 연결하는 허브가 해당합니다. 데이터 내용은 해석하지 않습니다." + }, + { + "id": "net-etc-010", + "question": "게이트웨이와 라우터의 관계는 무엇인가요?", + "answer": "게이트웨이는 서로 다른 네트워크를 잇는 출입구의 개념이고, 라우터가 그 역할을 수행하는 대표적 장비입니다. 종종 같은 의미로 쓰이기도 합니다." + } + ] + }, + { + "id": "net-arch", + "name": "네트워크 구조와 통신 방식", + "questions": [ + { + "id": "net-arch-001", + "question": "클라이언트-서버 모델과 P2P 모델의 차이는 무엇인가요?", + "answer": "클라이언트-서버는 중앙 서버가 자원을 제공하고 클라이언트가 요청하는 구조이고, P2P는 모든 노드가 대등하게 자원을 주고받는 구조입니다." + }, + { + "id": "net-arch-002", + "question": "회선 교환과 패킷 교환의 차이는 무엇인가요?", + "answer": "회선 교환은 통신 전 전용 경로를 미리 확보하고, 패킷 교환은 데이터를 패킷으로 쪼개 각자 경로로 전송합니다. 인터넷은 패킷 교환을 사용합니다." + }, + { + "id": "net-arch-003", + "question": "대역폭과 지연 시간의 차이는 무엇인가요?", + "answer": "대역폭은 단위 시간당 보낼 수 있는 데이터 양이고, 지연 시간은 데이터가 도착하기까지 걸리는 시간입니다. 둘 다 네트워크 성능에 영향을 줍니다." + }, + { + "id": "net-arch-004", + "question": "LAN, WAN, MAN의 차이는 무엇인가요?", + "answer": "LAN은 건물 등 좁은 지역, WAN은 국가나 대륙을 잇는 넓은 지역, MAN은 도시 규모의 네트워크입니다. 범위와 속도, 관리 주체가 다릅니다." + }, + { + "id": "net-arch-005", + "question": "이더넷(Ethernet)이란 무엇인가요?", + "answer": "유선 LAN에서 가장 널리 쓰이는 통신 기술 표준입니다. CSMA/CD 방식으로 충돌을 관리하며 프레임 단위로 데이터를 전송합니다." + }, + { + "id": "net-arch-006", + "question": "3계층 아키텍처란 무엇인가요?", + "answer": "시스템을 프레젠테이션, 애플리케이션(비즈니스 로직), 데이터 계층으로 나눈 구조입니다. 계층 분리로 유지보수성과 확장성이 좋아집니다." + }, + { + "id": "net-arch-007", + "question": "처리량(throughput)이란 무엇인가요?", + "answer": "실제로 단위 시간당 전송에 성공한 데이터 양입니다. 대역폭은 이론적 최대치이고 처리량은 혼잡 등을 고려한 실측치라는 점이 다릅니다." + }, + { + "id": "net-arch-008", + "question": "네트워크 토폴로지란 무엇인가요?", + "answer": "네트워크 기기들이 연결된 물리적이거나 논리적인 구조입니다. 버스, 스타, 링, 메시 등이 있으며 각각 비용, 확장성, 장애 대응력이 다릅니다." + } + ] + }, + { + "id": "net-rest-api", + "name": "API와 웹 서비스", + "questions": [ + { + "id": "net-rest-api-001", + "question": "RESTful API의 설계 원칙은 무엇인가요?", + "answer": "자원을 URI로 표현하고, HTTP 메서드로 행위를 나타내며, 무상태성을 유지하고, 일관된 인터페이스를 제공하는 것입니다. 자원 중심의 직관적 설계를 지향합니다." + }, + { + "id": "net-rest-api-002", + "question": "REST와 SOAP의 차이는 무엇인가요?", + "answer": "REST는 가볍고 HTTP 기반으로 유연하며, SOAP는 XML 기반의 엄격한 표준 프로토콜로 보안과 트랜잭션이 강합니다. 웹에서는 주로 REST가 쓰입니다." + }, + { + "id": "net-rest-api-003", + "question": "GraphQL과 REST의 차이는 무엇인가요?", + "answer": "REST는 엔드포인트마다 정해진 데이터를 반환하고, GraphQL은 클라이언트가 필요한 데이터만 골라 요청합니다. GraphQL은 과다 조회와 과소 조회 문제를 줄입니다." + }, + { + "id": "net-rest-api-004", + "question": "인증(authentication)과 인가(authorization)의 차이는 무엇인가요?", + "answer": "인증은 사용자가 누구인지 신원을 확인하는 것이고, 인가는 그 사용자가 무엇을 할 수 있는지 권한을 확인하는 것입니다. 인증 후 인가가 이루어집니다." + }, + { + "id": "net-rest-api-005", + "question": "OAuth란 무엇인가요?", + "answer": "비밀번호를 공유하지 않고 제3자 앱에 제한된 접근 권한을 위임하는 표준입니다. 토큰을 발급해 사용자를 대신해 자원에 접근하게 합니다." + }, + { + "id": "net-rest-api-006", + "question": "API 버전 관리는 왜 필요한가요?", + "answer": "기존 사용자에게 영향을 주지 않으면서 API를 변경하기 위해서입니다. URL이나 헤더에 버전을 명시해 하위 호환성을 유지합니다." + }, + { + "id": "net-rest-api-007", + "question": "안전한 메서드와 멱등한 메서드의 차이는 무엇인가요?", + "answer": "안전한 메서드는 서버 상태를 변경하지 않고(GET), 멱등한 메서드는 여러 번 호출해도 결과가 같습니다(PUT, DELETE). GET은 둘 다에 해당합니다." + }, + { + "id": "net-rest-api-008", + "question": "HTTP 상태 코드를 API 설계에서 어떻게 활용하나요?", + "answer": "요청 결과를 명확히 알리기 위해 상황에 맞는 코드를 반환합니다. 생성은 201, 권한 문제는 401과 403, 잘못된 요청은 400 등으로 의미를 전달합니다." + } + ] + }, + { + "id": "net-perf-reliability", + "name": "네트워크 성능과 신뢰성", + "questions": [ + { + "id": "net-perf-reliability-001", + "question": "패킷 손실은 왜 발생하나요?", + "answer": "네트워크 혼잡, 신호 간섭, 장비 오류 등으로 패킷이 목적지에 도달하지 못할 때 발생합니다. TCP는 재전송으로 이를 복구합니다." + }, + { + "id": "net-perf-reliability-002", + "question": "지터(jitter)란 무엇인가요?", + "answer": "패킷이 도착하는 시간 간격이 일정하지 않고 흔들리는 현상입니다. 실시간 음성이나 영상 통신의 품질을 떨어뜨려 버퍼로 완화합니다." + }, + { + "id": "net-perf-reliability-003", + "question": "RTT란 무엇인가요?", + "answer": "패킷이 목적지에 갔다가 응답이 돌아오기까지 걸리는 왕복 시간입니다. 네트워크 지연을 측정하는 기본 지표로 ping으로 확인할 수 있습니다." + }, + { + "id": "net-perf-reliability-004", + "question": "흐름 제어와 혼잡 제어를 비교하면 어떻게 다른가요?", + "answer": "흐름 제어는 수신자의 처리 능력에 맞추는 것이고, 혼잡 제어는 네트워크 전체 상태에 맞추는 것입니다. 둘 다 전송 속도를 조절하지만 대상이 다릅니다." + }, + { + "id": "net-perf-reliability-005", + "question": "QoS란 무엇인가요?", + "answer": "중요한 트래픽에 우선순위를 부여해 일정 수준의 품질을 보장하는 기술입니다. 음성이나 영상처럼 지연에 민감한 서비스에 활용됩니다." + }, + { + "id": "net-perf-reliability-006", + "question": "캐싱이 네트워크 성능을 높이는 원리는 무엇인가요?", + "answer": "자주 쓰는 데이터를 가까운 곳에 저장해 원본까지 가지 않아도 되게 하기 때문입니다. 응답 속도가 빨라지고 서버와 네트워크 부하가 줄어듭니다." + }, + { + "id": "net-perf-reliability-007", + "question": "고가용성(HA)이란 무엇인가요?", + "answer": "장애가 발생해도 서비스가 중단되지 않도록 이중화와 장애 조치를 갖춘 구성입니다. 로드 밸런서와 다중 서버로 단일 장애점을 제거합니다." + }, + { + "id": "net-perf-reliability-008", + "question": "단일 장애점(SPOF)이란 무엇인가요?", + "answer": "한 부분이 고장 나면 전체 시스템이 멈추는 지점입니다. 이를 없애기 위해 핵심 구성요소를 이중화하고 부하를 분산합니다." + } + ] + }, + { + "id": "net-modern", + "name": "현대 웹과 보안 심화", + "questions": [ + { + "id": "net-modern-001", + "question": "HTTPS와 SSL/TLS의 관계는 무엇인가요?", + "answer": "TLS는 SSL의 후속 보안 프로토콜이고, HTTPS는 HTTP에 TLS를 적용한 것입니다. 현재는 보안상 SSL 대신 TLS를 사용합니다." + }, + { + "id": "net-modern-002", + "question": "대칭키와 비대칭키를 함께 쓰는 이유는 무엇인가요?", + "answer": "비대칭키로 안전하게 대칭키를 교환한 뒤, 빠른 대칭키로 실제 데이터를 암호화하기 위해서입니다. 보안과 속도를 모두 얻습니다." + }, + { + "id": "net-modern-003", + "question": "디지털 서명이란 무엇인가요?", + "answer": "개인키로 데이터의 해시를 암호화해 발신자 인증과 위변조 방지를 제공하는 기술입니다. 공개키로 검증해 무결성과 부인 방지를 보장합니다." + }, + { + "id": "net-modern-004", + "question": "무결성(integrity)이란 무엇인가요?", + "answer": "데이터가 전송 중 변조되지 않았음을 보장하는 성질입니다. 해시나 체크섬으로 검증하며 보안의 핵심 요소 중 하나입니다." + }, + { + "id": "net-modern-005", + "question": "중간자 공격(MITM)이란 무엇인가요?", + "answer": "통신하는 두 주체 사이에 끼어들어 데이터를 가로채거나 변조하는 공격입니다. HTTPS의 인증서 검증으로 방어합니다." + }, + { + "id": "net-modern-006", + "question": "방화벽과 IDS/IPS의 차이는 무엇인가요?", + "answer": "방화벽은 규칙에 따라 트래픽을 차단하고, IDS는 침입을 탐지해 알리며, IPS는 탐지와 동시에 차단합니다. 역할이 단계적으로 다릅니다." + }, + { + "id": "net-modern-007", + "question": "쿠키, 세션, 토큰의 보안 특성을 비교하면 어떤가요?", + "answer": "쿠키는 탈취에 취약하고, 세션은 서버 부담이 있으며, 토큰은 탈취 시 만료 전까지 위험합니다. 각각 HttpOnly와 만료 시간 등으로 보완합니다." + }, + { + "id": "net-modern-008", + "question": "HTTPS 적용이 주는 이점은 무엇인가요?", + "answer": "데이터 보호로 사용자 신뢰를 높이고, 검색엔진이 보안 사이트를 우대하며, 최신 브라우저가 비보안 경고를 띄우지 않게 됩니다." + } + ] + }, + { + "id": "net-app-protocols", + "name": "응용 계층 프로토콜", + "questions": [ + { + "id": "net-app-protocols-001", + "question": "FTP란 무엇인가요?", + "answer": "파일을 전송하기 위한 프로토콜입니다. 제어 연결과 데이터 연결을 따로 사용하며 업로드와 다운로드를 지원합니다." + }, + { + "id": "net-app-protocols-002", + "question": "SMTP, POP3, IMAP의 차이는 무엇인가요?", + "answer": "SMTP는 메일 발송, POP3는 메일을 받아 로컬로 내려받고, IMAP은 서버에 두고 동기화하며 봅니다. 용도에 따라 구분됩니다." + }, + { + "id": "net-app-protocols-003", + "question": "DHCP란 무엇인가요?", + "answer": "네트워크에 접속한 기기에 IP 주소 등 설정을 자동으로 할당하는 프로토콜입니다. 수동 설정 없이 네트워크를 쉽게 사용하게 합니다." + }, + { + "id": "net-app-protocols-004", + "question": "SSH란 무엇인가요?", + "answer": "원격 시스템에 암호화된 안전한 연결로 접속하는 프로토콜입니다. 명령 실행과 파일 전송을 보안성 있게 수행합니다." + }, + { + "id": "net-app-protocols-005", + "question": "웹소켓(WebSocket)이란 무엇인가요?", + "answer": "하나의 연결을 유지하며 서버와 클라이언트가 양방향으로 실시간 통신하는 프로토콜입니다. 채팅이나 실시간 알림에 적합합니다." + }, + { + "id": "net-app-protocols-006", + "question": "HTTP와 HTTPS의 기본 포트는 무엇인가요?", + "answer": "HTTP는 80번, HTTPS는 443번 포트를 기본으로 사용합니다. 포트로 서비스 종류를 구분합니다." + }, + { + "id": "net-app-protocols-007", + "question": "MIME 타입이란 무엇인가요?", + "answer": "전송되는 데이터의 형식을 나타내는 식별자입니다. 브라우저가 콘텐츠를 어떻게 처리할지 결정하는 데 사용됩니다." + }, + { + "id": "net-app-protocols-008", + "question": "텔넷과 SSH의 차이는 무엇인가요?", + "answer": "텔넷은 데이터를 암호화 없이 평문으로 전송해 보안에 취약하고, SSH는 암호화해 안전합니다. 현재는 SSH가 표준입니다." + } + ] + }, + { + "id": "net-wireless-mobile", + "name": "무선과 이동 통신", + "questions": [ + { + "id": "net-wireless-mobile-001", + "question": "Wi-Fi와 유선랜의 차이는 무엇인가요?", + "answer": "Wi-Fi는 전파로 연결해 이동이 자유롭지만 간섭과 보안에 약하고, 유선랜은 케이블로 연결해 안정적이고 빠릅니다. 환경에 따라 선택합니다." + }, + { + "id": "net-wireless-mobile-002", + "question": "무선 통신에서 충돌을 어떻게 다루나요?", + "answer": "전송 전 채널이 비었는지 확인하고 충돌을 피하는 CSMA/CA 방식을 씁니다. 유선의 CSMA/CD와 달리 회피에 중점을 둡니다." + }, + { + "id": "net-wireless-mobile-003", + "question": "셀룰러 네트워크의 셀(cell) 개념이란 무엇인가요?", + "answer": "지역을 작은 구역으로 나누고 각 구역에 기지국을 두는 구조입니다. 주파수를 재사용해 많은 사용자를 수용합니다." + }, + { + "id": "net-wireless-mobile-004", + "question": "4G와 5G의 차이는 무엇인가요?", + "answer": "5G는 4G보다 훨씬 빠른 속도와 낮은 지연, 더 많은 동시 연결을 제공합니다. 자율주행이나 IoT 같은 새로운 응용을 가능하게 합니다." + }, + { + "id": "net-wireless-mobile-005", + "question": "핸드오버(handover)란 무엇인가요?", + "answer": "이동 중인 기기가 한 기지국에서 다른 기지국으로 연결을 끊김 없이 넘기는 과정입니다. 통화나 데이터가 유지되게 합니다." + }, + { + "id": "net-wireless-mobile-006", + "question": "블루투스와 Wi-Fi의 차이는 무엇인가요?", + "answer": "블루투스는 짧은 거리의 기기 간 연결에, Wi-Fi는 더 넓은 범위의 네트워크 접속에 쓰입니다. 전력 소모와 속도, 범위가 다릅니다." + }, + { + "id": "net-wireless-mobile-007", + "question": "무선 네트워크의 보안 방식은 무엇인가요?", + "answer": "WPA2나 WPA3 같은 암호화 표준으로 데이터를 보호합니다. 비밀번호 인증과 암호화로 무단 접속과 도청을 막습니다." + }, + { + "id": "net-wireless-mobile-008", + "question": "신호 세기와 통신 품질의 관계는 무엇인가요?", + "answer": "신호가 약하면 오류와 재전송이 늘어 속도가 떨어집니다. 거리, 장애물, 간섭이 신호 세기에 영향을 줍니다." + } + ] + } + ] + }, + { + "id": "operating-system", + "name": "운영체제", + "categories": [ + { + "id": "os-intro", + "name": "운영체제 개요", + "questions": [ + { + "id": "os-intro-001", + "question": "운영체제란 무엇이고 어떤 역할을 하나요?", + "answer": "하드웨어와 응용 프로그램 사이에서 자원을 관리하고 중개하는 시스템 소프트웨어입니다. 프로세스, 메모리, 파일, 입출력 장치를 관리하며 사용자에게 편리한 인터페이스를 제공합니다." + }, + { + "id": "os-intro-002", + "question": "커널(kernel)이란 무엇인가요?", + "answer": "운영체제의 핵심으로 메모리에 상주하며 CPU, 메모리, 장치 등 핵심 자원을 직접 관리합니다. 응용 프로그램이 하드웨어에 접근할 때 반드시 커널을 거치도록 해 시스템을 보호합니다." + }, + { + "id": "os-intro-003", + "question": "시스템 콜(system call)이란 무엇인가요?", + "answer": "응용 프로그램이 커널의 기능을 사용하기 위해 요청하는 인터페이스입니다. 파일 입출력이나 프로세스 생성처럼 권한이 필요한 작업을 사용자 모드에서 커널 모드로 전환해 수행합니다." + }, + { + "id": "os-intro-004", + "question": "사용자 모드와 커널 모드의 차이는 무엇인가요?", + "answer": "사용자 모드는 일반 응용 프로그램이 제한된 권한으로 실행되는 모드이고, 커널 모드는 하드웨어에 직접 접근할 수 있는 모든 권한을 가진 모드입니다. 이 구분으로 시스템 안정성을 지킵니다." + }, + { + "id": "os-intro-005", + "question": "운영체제에서 듀얼 모드가 필요한 이유는 무엇인가요?", + "answer": "일반 프로그램이 하드웨어나 핵심 자원에 무분별하게 접근하지 못하게 하기 위해서입니다. 위험한 작업은 커널 모드에서만 수행하도록 분리해 시스템 보호와 안정성을 확보합니다." + }, + { + "id": "os-intro-006", + "question": "시분할 시스템이란 무엇인가요?", + "answer": "CPU 시간을 짧게 나누어 여러 사용자나 프로세스가 번갈아 사용하게 하는 방식입니다. 동시에 쓰는 것처럼 보이게 해 자원을 효율적으로 공유합니다." + }, + { + "id": "os-intro-007", + "question": "배치 처리와 실시간 시스템의 차이는 무엇인가요?", + "answer": "배치 처리는 작업을 모아 한꺼번에 처리하고, 실시간 시스템은 정해진 시간 안에 반드시 응답해야 합니다. 실시간은 마감 시간 준수가 핵심입니다." + }, + { + "id": "os-intro-008", + "question": "운영체제의 주요 기능은 무엇인가요?", + "answer": "프로세스 관리, 메모리 관리, 파일 관리, 입출력 관리, 자원 보호 등을 수행합니다. 하드웨어를 추상화해 사용자와 프로그램에 편의를 제공합니다." + }, + { + "id": "os-intro-009", + "question": "모놀리식 커널과 마이크로 커널의 차이는 무엇인가요?", + "answer": "모놀리식은 커널에 대부분 기능을 넣어 빠르지만 크고, 마이크로 커널은 핵심만 커널에 두고 나머지를 분리해 안정적이지만 통신 비용이 있습니다." + }, + { + "id": "os-intro-010", + "question": "부팅(booting) 과정이란 무엇인가요?", + "answer": "전원이 켜지면 펌웨어가 하드웨어를 점검하고, 부트로더가 커널을 메모리에 올려 운영체제를 시작하는 과정입니다." + }, + { + "id": "os-intro-011", + "question": "API와 시스템 콜의 관계는 무엇인가요?", + "answer": "API는 프로그래머가 쓰는 함수 인터페이스이고, 그 내부에서 필요 시 시스템 콜을 호출해 커널 기능을 사용합니다. API가 시스템 콜을 감싸는 경우가 많습니다." + } + ] + }, + { + "id": "os-process", + "name": "프로세스와 스레드", + "questions": [ + { + "id": "os-process-001", + "question": "프로세스와 스레드의 차이는 무엇인가요?", + "answer": "프로세스는 실행 중인 프로그램으로 독립된 메모리 공간을 가지며, 스레드는 프로세스 내 실행 흐름의 단위로 같은 프로세스의 메모리를 공유합니다. 스레드는 생성과 전환 비용이 더 적습니다." + }, + { + "id": "os-process-002", + "question": "프로세스의 상태(state)에는 어떤 것이 있나요?", + "answer": "생성(new), 실행 준비가 된 준비(ready), CPU를 점유한 실행(running), 입출력 등을 기다리는 대기(waiting), 종료(terminated) 상태가 있습니다. 스케줄러에 의해 상태가 전이됩니다." + }, + { + "id": "os-process-003", + "question": "PCB(Process Control Block)란 무엇인가요?", + "answer": "운영체제가 프로세스를 관리하기 위해 저장하는 정보 블록입니다. 프로세스 식별자(PID), 상태, 프로그램 카운터, 레지스터 값, 메모리 정보 등이 담겨 컨텍스트 스위칭 시 사용됩니다." + }, + { + "id": "os-process-004", + "question": "컨텍스트 스위칭(context switching)이란 무엇인가요?", + "answer": "CPU가 실행 중인 프로세스를 바꿀 때 기존 프로세스의 상태를 PCB에 저장하고 새 프로세스의 상태를 불러오는 작업입니다. 멀티태스킹을 가능하게 하지만 잦으면 오버헤드가 됩니다." + }, + { + "id": "os-process-005", + "question": "멀티프로세스와 멀티스레드의 장단점은 무엇인가요?", + "answer": "멀티프로세스는 한 프로세스가 죽어도 다른 프로세스에 영향이 없어 안정적이지만 자원 소모와 통신 비용이 큽니다. 멀티스레드는 자원 공유로 효율적이지만 하나의 오류가 전체에 영향을 줄 수 있습니다." + }, + { + "id": "os-process-006", + "question": "IPC(프로세스 간 통신)란 무엇인가요?", + "answer": "독립된 메모리를 가진 프로세스들이 데이터를 주고받는 방법입니다. 공유 메모리, 파이프, 메시지 큐, 소켓, 시그널 등의 방식이 있으며 상황에 맞게 선택합니다." + }, + { + "id": "os-process-007", + "question": "좀비 프로세스와 고아 프로세스란 무엇인가요?", + "answer": "좀비 프로세스는 종료됐지만 부모가 종료 상태를 회수하지 않아 남아 있는 프로세스이고, 고아 프로세스는 부모가 먼저 종료된 자식 프로세스입니다. 고아는 보통 init 프로세스가 입양해 정리합니다." + }, + { + "id": "os-process-008", + "question": "fork()와 exec()의 차이는 무엇인가요?", + "answer": "fork는 현재 프로세스를 복제해 자식 프로세스를 만들고, exec는 현재 프로세스를 새 프로그램으로 교체합니다. 보통 fork 후 exec로 새 프로그램을 실행합니다." + }, + { + "id": "os-process-009", + "question": "프로세스 주소 공간은 어떻게 구성되나요?", + "answer": "코드, 데이터, 힙, 스택 영역으로 나뉩니다. 힙은 동적 할당으로 위로, 스택은 함수 호출로 아래로 자라며 서로 반대 방향으로 확장됩니다." + }, + { + "id": "os-process-010", + "question": "스레드의 장점은 무엇인가요?", + "answer": "생성과 전환 비용이 적고, 같은 프로세스의 메모리를 공유해 통신이 빠릅니다. 응답성을 높이고 멀티코어를 효율적으로 활용할 수 있습니다." + }, + { + "id": "os-process-011", + "question": "사용자 스레드와 커널 스레드의 차이는 무엇인가요?", + "answer": "사용자 스레드는 라이브러리가 관리해 빠르지만 하나가 블로킹되면 전체가 멈추고, 커널 스레드는 운영체제가 관리해 병렬성이 좋지만 전환 비용이 큽니다." + }, + { + "id": "os-process-012", + "question": "컨텍스트 스위칭 비용을 줄이는 방법은 무엇인가요?", + "answer": "스레드를 활용하거나, 불필요한 전환을 줄이고, 적절한 타임 퀀텀을 설정하는 방법이 있습니다. 전환이 잦을수록 오버헤드가 커집니다." + }, + { + "id": "os-process-013", + "question": "데몬(daemon) 프로세스란 무엇인가요?", + "answer": "사용자와 직접 상호작용 없이 백그라운드에서 동작하는 프로세스입니다. 서버나 예약 작업처럼 시스템 서비스를 담당합니다." + } + ] + }, + { + "id": "os-scheduling", + "name": "CPU 스케줄링", + "questions": [ + { + "id": "os-scheduling-001", + "question": "CPU 스케줄링이란 무엇인가요?", + "answer": "준비 상태의 여러 프로세스 중 어떤 프로세스에 CPU를 할당할지 결정하는 작업입니다. CPU 활용률과 처리량을 높이고 대기 시간과 응답 시간을 줄이는 것을 목표로 합니다." + }, + { + "id": "os-scheduling-002", + "question": "선점형과 비선점형 스케줄링의 차이는 무엇인가요?", + "answer": "선점형은 실행 중인 프로세스의 CPU를 운영체제가 강제로 빼앗을 수 있는 방식이고, 비선점형은 프로세스가 스스로 CPU를 반납할 때까지 기다리는 방식입니다. 선점형이 응답성이 좋습니다." + }, + { + "id": "os-scheduling-003", + "question": "FCFS, SJF, RR 스케줄링을 설명해주세요.", + "answer": "FCFS는 도착 순서대로 처리하고, SJF는 실행 시간이 짧은 작업을 먼저 처리하며, RR은 정해진 시간 단위(타임 퀀텀)만큼 돌아가며 처리합니다. RR은 응답성이 좋아 시분할 시스템에 적합합니다." + }, + { + "id": "os-scheduling-004", + "question": "라운드 로빈에서 타임 퀀텀의 크기는 어떤 영향을 주나요?", + "answer": "타임 퀀텀이 너무 크면 FCFS처럼 동작해 응답성이 떨어지고, 너무 작으면 컨텍스트 스위칭이 잦아져 오버헤드가 커집니다. 적절한 크기를 정하는 것이 성능의 관건입니다." + }, + { + "id": "os-scheduling-005", + "question": "기아(starvation) 현상과 에이징(aging)이란 무엇인가요?", + "answer": "기아는 우선순위가 낮은 프로세스가 계속 밀려 CPU를 받지 못하는 현상입니다. 에이징은 대기 시간이 길어질수록 우선순위를 점점 높여주어 기아를 방지하는 기법입니다." + }, + { + "id": "os-scheduling-006", + "question": "다단계 큐 스케줄링이란 무엇인가요?", + "answer": "프로세스를 우선순위나 특성별로 여러 큐에 나누어 각 큐마다 다른 정책을 적용하는 방식입니다. 대화형과 배치 작업을 구분해 처리합니다." + }, + { + "id": "os-scheduling-007", + "question": "다단계 피드백 큐란 무엇인가요?", + "answer": "프로세스가 큐 사이를 이동할 수 있는 다단계 큐입니다. CPU를 오래 쓰면 낮은 우선순위 큐로 내려보내 짧은 작업에 유리하게 합니다." + }, + { + "id": "os-scheduling-008", + "question": "선점이 발생하는 시점은 언제인가요?", + "answer": "더 높은 우선순위 프로세스가 도착하거나, 타임 퀀텀이 끝나거나, 입출력 완료로 대기 프로세스가 준비 상태가 될 때 발생합니다." + }, + { + "id": "os-scheduling-009", + "question": "응답 시간과 대기 시간의 차이는 무엇인가요?", + "answer": "응답 시간은 요청 후 첫 반응까지의 시간이고, 대기 시간은 준비 큐에서 기다린 총 시간입니다. 대화형 시스템은 응답 시간이 중요합니다." + }, + { + "id": "os-scheduling-010", + "question": "SJF의 단점은 무엇인가요?", + "answer": "실행 시간을 미리 알기 어렵고, 긴 작업이 계속 밀려 기아가 발생할 수 있습니다. 이를 보완하기 위해 예측 기법이나 에이징을 함께 씁니다." + }, + { + "id": "os-scheduling-011", + "question": "CPU 바운드와 I/O 바운드 작업의 차이는 무엇인가요?", + "answer": "CPU 바운드는 계산이 많아 CPU를 오래 쓰고, I/O 바운드는 입출력 대기가 많아 CPU를 짧게 씁니다. 둘을 섞어 스케줄링하면 자원 활용이 좋아집니다." + } + ] + }, + { + "id": "os-sync", + "name": "프로세스 동기화", + "questions": [ + { + "id": "os-sync-001", + "question": "임계 영역(critical section)이란 무엇인가요?", + "answer": "여러 프로세스나 스레드가 공유 자원에 접근하는 코드 영역으로, 동시에 실행되면 문제가 생기는 부분입니다. 한 번에 하나만 진입하도록 상호 배제를 보장해야 합니다." + }, + { + "id": "os-sync-002", + "question": "경쟁 상태(race condition)란 무엇인가요?", + "answer": "여러 프로세스가 공유 데이터에 동시 접근할 때 실행 순서에 따라 결과가 달라지는 상황입니다. 동기화가 없으면 데이터 일관성이 깨져 예측 불가능한 버그가 발생합니다." + }, + { + "id": "os-sync-003", + "question": "뮤텍스(mutex)와 세마포어(semaphore)의 차이는 무엇인가요?", + "answer": "뮤텍스는 한 번에 하나만 접근 가능한 잠금으로 소유 개념이 있고, 세마포어는 정해진 개수만큼 동시 접근을 허용하는 카운터 기반 방식입니다. 뮤텍스는 세마포어의 특수한 경우로 볼 수 있습니다." + }, + { + "id": "os-sync-004", + "question": "동기화가 필요한 이유는 무엇인가요?", + "answer": "여러 실행 흐름이 공유 자원에 동시에 접근하면 경쟁 상태로 데이터가 손상될 수 있기 때문입니다. 동기화로 접근 순서를 제어해 데이터 일관성과 정확성을 보장합니다." + }, + { + "id": "os-sync-005", + "question": "모니터(monitor)란 무엇인가요?", + "answer": "공유 자원과 그 접근 연산을 하나로 묶어 자동으로 상호 배제를 보장하는 고수준 동기화 도구입니다. 프로그래머가 직접 락을 다루지 않아도 되어 세마포어보다 사용이 안전하고 편리합니다." + }, + { + "id": "os-sync-006", + "question": "교착 상태와 경쟁 상태의 차이는 무엇인가요?", + "answer": "경쟁 상태는 실행 순서에 따라 결과가 달라지는 문제이고, 교착 상태는 서로 자원을 기다리며 멈춘 상태입니다. 둘 다 동기화 문제지만 양상이 다릅니다." + }, + { + "id": "os-sync-007", + "question": "스핀락(spinlock)이란 무엇인가요?", + "answer": "락을 얻을 때까지 계속 확인하며 대기하는 방식의 락입니다. 대기 시간이 짧을 때 문맥 전환 없이 효율적이지만 길면 CPU를 낭비합니다." + }, + { + "id": "os-sync-008", + "question": "생산자-소비자 문제란 무엇인가요?", + "answer": "데이터를 만드는 생산자와 소비하는 소비자가 공유 버퍼를 함께 쓸 때 발생하는 동기화 문제입니다. 세마포어로 버퍼 상태를 관리해 해결합니다." + }, + { + "id": "os-sync-009", + "question": "식사하는 철학자 문제란 무엇인가요?", + "answer": "여러 철학자가 공유 젓가락을 두고 식사하려다 교착에 빠지는 고전 문제입니다. 자원 할당 순서나 제한으로 데드락을 예방하는 예시로 쓰입니다." + }, + { + "id": "os-sync-010", + "question": "데드락과 라이브락의 차이는 무엇인가요?", + "answer": "데드락은 프로세스들이 멈춰 아무 진전이 없는 상태이고, 라이브락은 상태는 계속 바뀌지만 실제로는 진행되지 않는 상태입니다." + }, + { + "id": "os-sync-011", + "question": "원자적 연산(atomic operation)이란 무엇인가요?", + "answer": "중간에 끼어들 수 없이 한 번에 완료되는 연산입니다. 경쟁 상태를 막는 동기화의 기본 단위로 하드웨어가 지원하기도 합니다." + } + ] + }, + { + "id": "os-deadlock", + "name": "데드락", + "questions": [ + { + "id": "os-deadlock-001", + "question": "데드락(교착 상태)이란 무엇인가요?", + "answer": "두 개 이상의 프로세스가 서로 상대가 가진 자원을 기다리며 무한정 멈춰 있는 상태입니다. 어느 쪽도 자원을 내놓지 않아 모두 진행하지 못하는 상황을 말합니다." + }, + { + "id": "os-deadlock-002", + "question": "데드락 발생의 4가지 조건은 무엇인가요?", + "answer": "상호 배제, 점유와 대기, 비선점, 순환 대기 네 가지가 모두 충족될 때 발생합니다. 이 중 하나라도 깨면 데드락을 예방할 수 있습니다." + }, + { + "id": "os-deadlock-003", + "question": "데드락을 해결하는 방법은 무엇인가요?", + "answer": "발생 조건을 원천 차단하는 예방, 안전 상태를 유지하는 회피, 발생을 허용하고 탐지 후 처리하는 탐지와 복구가 있습니다. 비용과 상황에 따라 적절한 방식을 선택합니다." + }, + { + "id": "os-deadlock-004", + "question": "은행원 알고리즘(banker's algorithm)이란 무엇인가요?", + "answer": "자원을 할당하기 전에 그 할당이 시스템을 안전 상태로 유지하는지 미리 검사하는 데드락 회피 기법입니다. 안전한 경우에만 자원을 내주어 교착 상태를 사전에 막습니다." + }, + { + "id": "os-deadlock-005", + "question": "상호 배제 조건을 깨서 데드락을 예방하려면 어떻게 하나요?", + "answer": "자원을 공유 가능하게 만들면 됩니다. 다만 본질적으로 한 번에 하나만 써야 하는 자원에는 적용하기 어렵습니다." + }, + { + "id": "os-deadlock-006", + "question": "점유와 대기 조건을 깨려면 어떻게 하나요?", + "answer": "프로세스가 필요한 자원을 한꺼번에 모두 요청하게 하거나, 자원을 가진 상태에서 추가 요청을 못하게 합니다. 자원 활용률이 떨어질 수 있습니다." + }, + { + "id": "os-deadlock-007", + "question": "비선점 조건을 깨려면 어떻게 하나요?", + "answer": "다른 자원을 기다리는 프로세스의 자원을 빼앗을 수 있게 합니다. 상태 저장과 복원이 가능한 자원에만 적용할 수 있습니다." + }, + { + "id": "os-deadlock-008", + "question": "순환 대기 조건을 깨려면 어떻게 하나요?", + "answer": "모든 자원에 순서를 매겨 정해진 순서대로만 요청하게 합니다. 순환 형태의 대기가 생기지 않아 데드락을 예방합니다." + }, + { + "id": "os-deadlock-009", + "question": "데드락 탐지는 어떻게 하나요?", + "answer": "자원 할당 그래프에서 순환(사이클)이 있는지 검사합니다. 주기적으로 검사해 교착을 발견하면 복구 절차를 진행합니다." + }, + { + "id": "os-deadlock-010", + "question": "데드락 복구 방법은 무엇인가요?", + "answer": "교착에 빠진 프로세스를 강제 종료하거나, 자원을 선점해 회수하는 방법이 있습니다. 어떤 프로세스를 희생할지 비용을 고려해 결정합니다." + } + ] + }, + { + "id": "os-memory", + "name": "메모리 관리", + "questions": [ + { + "id": "os-memory-001", + "question": "메모리 관리란 무엇인가요?", + "answer": "한정된 물리 메모리를 여러 프로세스에 효율적으로 할당하고 회수하는 운영체제의 기능입니다. 프로세스 간 메모리 보호와 공간 활용 극대화를 목표로 합니다." + }, + { + "id": "os-memory-002", + "question": "단편화(fragmentation)란 무엇인가요?", + "answer": "메모리 할당과 해제가 반복되면서 사용하지 못하는 빈 공간이 생기는 현상입니다. 전체 여유 공간은 충분해도 연속된 공간이 부족해 할당에 실패할 수 있습니다." + }, + { + "id": "os-memory-003", + "question": "내부 단편화와 외부 단편화의 차이는 무엇인가요?", + "answer": "내부 단편화는 할당된 공간 안에 남는 자투리 공간이고, 외부 단편화는 할당 가능한 공간들이 잘게 흩어져 연속 공간을 못 만드는 것입니다. 페이징은 외부 단편화를 해결합니다." + }, + { + "id": "os-memory-004", + "question": "페이징(paging)이란 무엇인가요?", + "answer": "메모리를 고정 크기의 페이지로 나누어 관리하는 기법입니다. 프로세스를 페이지 단위로 비연속적으로 적재할 수 있어 외부 단편화가 사라지지만 약간의 내부 단편화가 생깁니다." + }, + { + "id": "os-memory-005", + "question": "세그멘테이션(segmentation)이란 무엇인가요?", + "answer": "프로세스를 코드, 데이터, 스택처럼 논리적 단위(세그먼트)로 나누어 관리하는 기법입니다. 크기가 가변적이라 논리 구조를 반영하기 좋지만 외부 단편화가 발생할 수 있습니다." + }, + { + "id": "os-memory-006", + "question": "페이징과 세그멘테이션의 차이는 무엇인가요?", + "answer": "페이징은 고정 크기의 물리적 단위로 나누어 외부 단편화가 없고, 세그멘테이션은 가변 크기의 논리적 단위로 나누어 의미 단위 관리에 유리합니다. 둘을 결합한 방식도 사용됩니다." + }, + { + "id": "os-memory-007", + "question": "스왑(swap)이란 무엇인가요?", + "answer": "메모리가 부족할 때 사용하지 않는 프로세스나 페이지를 디스크로 옮기고, 필요할 때 다시 불러오는 기법입니다. 메모리 공간을 확보하지만 속도는 느려집니다." + }, + { + "id": "os-memory-008", + "question": "페이지 테이블이란 무엇인가요?", + "answer": "가상 페이지 번호를 물리 프레임 번호로 변환하는 정보를 담은 표입니다. 프로세스마다 존재하며 주소 변환의 기준이 됩니다." + }, + { + "id": "os-memory-009", + "question": "페이지 크기는 성능에 어떤 영향을 주나요?", + "answer": "페이지가 크면 테이블 크기가 줄지만 내부 단편화가 늘고, 작으면 단편화는 줄지만 테이블이 커집니다. 적절한 크기 선택이 중요합니다." + }, + { + "id": "os-memory-010", + "question": "압축(compaction)이란 무엇인가요?", + "answer": "흩어진 메모리 공간을 한쪽으로 모아 연속된 빈 공간을 만드는 작업입니다. 외부 단편화를 해소하지만 이동 비용이 큽니다." + }, + { + "id": "os-memory-011", + "question": "최초 적합, 최적 적합, 최악 적합의 차이는 무엇인가요?", + "answer": "최초 적합은 처음 맞는 공간에, 최적 적합은 가장 작게 맞는 공간에, 최악 적합은 가장 큰 공간에 할당합니다. 속도와 단편화에서 장단점이 다릅니다." + }, + { + "id": "os-memory-012", + "question": "메모리 보호는 어떻게 이루어지나요?", + "answer": "각 프로세스의 주소 범위를 한정하고, 권한을 검사해 다른 프로세스 영역 접근을 막습니다. 베이스와 리미트 레지스터나 페이지 권한 비트로 구현합니다." + } + ] + }, + { + "id": "os-vm", + "name": "가상 메모리", + "questions": [ + { + "id": "os-vm-001", + "question": "가상 메모리란 무엇인가요?", + "answer": "물리 메모리보다 큰 주소 공간을 프로세스에 제공하는 기법입니다. 당장 필요한 부분만 메모리에 올리고 나머지는 디스크에 두어, 실제 메모리보다 큰 프로그램도 실행할 수 있게 합니다." + }, + { + "id": "os-vm-002", + "question": "페이지 폴트(page fault)란 무엇인가요?", + "answer": "접근하려는 페이지가 물리 메모리에 없어 디스크에서 가져와야 하는 상황입니다. 운영체제가 해당 페이지를 메모리에 적재한 뒤 중단된 작업을 재개하며, 잦으면 성능이 저하됩니다." + }, + { + "id": "os-vm-003", + "question": "페이지 교체 알고리즘을 설명해주세요.", + "answer": "메모리가 꽉 찼을 때 내보낼 페이지를 고르는 방법입니다. 가장 오래된 것을 교체하는 FIFO, 가장 오래 안 쓰인 것을 교체하는 LRU, 앞으로 가장 늦게 쓰일 것을 교체하는 이론적 최적(Optimal) 등이 있습니다." + }, + { + "id": "os-vm-004", + "question": "스래싱(thrashing)이란 무엇인가요?", + "answer": "페이지 폴트가 너무 자주 발생해 CPU가 실제 작업보다 페이지 교체에만 시간을 쓰는 현상입니다. 프로세스 수가 과도하게 많을 때 발생하며 시스템 성능이 급격히 떨어집니다." + }, + { + "id": "os-vm-005", + "question": "요구 페이징(demand paging)이란 무엇인가요?", + "answer": "프로세스 실행에 실제로 필요한 페이지만 그때그때 메모리에 적재하는 방식입니다. 미리 전부 올리지 않으므로 메모리를 절약하고 프로그램 시작 시간을 단축합니다." + }, + { + "id": "os-vm-006", + "question": "TLB란 무엇인가요?", + "answer": "가상 주소를 물리 주소로 변환하는 페이지 테이블 정보를 캐싱하는 고속 하드웨어입니다. 주소 변환 시 매번 메모리의 페이지 테이블을 참조하지 않아도 되어 변환 속도를 크게 높입니다." + }, + { + "id": "os-vm-007", + "question": "지역성이 가상 메모리에서 왜 중요한가요?", + "answer": "프로그램이 일부 페이지에 집중 접근하는 지역성 덕분에 적은 메모리로도 효율적으로 동작할 수 있기 때문입니다. 지역성이 낮으면 페이지 폴트가 늘어납니다." + }, + { + "id": "os-vm-008", + "question": "워킹 셋(working set)이란 무엇인가요?", + "answer": "프로세스가 일정 시간 동안 실제로 참조하는 페이지들의 집합입니다. 이 집합을 메모리에 유지하면 페이지 폴트를 줄이고 스래싱을 방지할 수 있습니다." + }, + { + "id": "os-vm-009", + "question": "LRU를 실제로 구현하기 어려운 이유는 무엇인가요?", + "answer": "모든 페이지의 마지막 사용 시점을 추적해야 해 비용이 크기 때문입니다. 그래서 참조 비트를 쓰는 클럭 알고리즘 같은 근사 방식을 사용합니다." + }, + { + "id": "os-vm-010", + "question": "페이지 폴트 처리 비용이 큰 이유는 무엇인가요?", + "answer": "디스크에서 페이지를 읽어와야 하는데 디스크 접근이 메모리보다 수만 배 느리기 때문입니다. 그래서 폴트를 줄이는 것이 성능에 중요합니다." + }, + { + "id": "os-vm-011", + "question": "스래싱을 해결하는 방법은 무엇인가요?", + "answer": "워킹 셋 모델로 필요한 페이지를 확보하거나, 다중 프로그래밍 정도를 낮춰 메모리 경쟁을 줄입니다. 메모리를 늘리는 것도 방법입니다." + }, + { + "id": "os-vm-012", + "question": "메모리 매핑 파일(memory-mapped file)이란 무엇인가요?", + "answer": "파일을 가상 메모리 주소에 연결해 메모리처럼 읽고 쓰는 기법입니다. 입출력 호출 없이 접근할 수 있어 편리하고 빠릅니다." + } + ] + }, + { + "id": "os-file", + "name": "파일 시스템", + "questions": [ + { + "id": "os-file-001", + "question": "파일 시스템이란 무엇인가요?", + "answer": "보조기억장치에 데이터를 파일 단위로 저장하고 관리하는 체계입니다. 파일의 이름, 위치, 권한 등을 관리하며 사용자가 데이터를 쉽게 저장하고 검색할 수 있게 합니다." + }, + { + "id": "os-file-002", + "question": "아이노드(inode)란 무엇인가요?", + "answer": "유닉스 계열 파일 시스템에서 파일의 메타데이터를 저장하는 자료구조입니다. 파일 크기, 권한, 소유자, 데이터 블록 위치 등을 담지만 파일 이름은 디렉터리가 따로 관리합니다." + }, + { + "id": "os-file-003", + "question": "파일 접근 방법에는 어떤 것이 있나요?", + "answer": "처음부터 차례로 읽는 순차 접근, 임의의 위치에 바로 접근하는 직접 접근, 색인을 이용해 빠르게 찾는 색인 접근이 있습니다. 데이터 특성과 용도에 따라 선택합니다." + }, + { + "id": "os-file-004", + "question": "파일 디스크립터(file descriptor)란 무엇인가요?", + "answer": "열린 파일을 가리키는 정수 식별자입니다. 프로세스가 파일을 다룰 때 이 번호로 접근하며 0, 1, 2는 표준 입출력에 예약되어 있습니다." + }, + { + "id": "os-file-005", + "question": "절대 경로와 상대 경로의 차이는 무엇인가요?", + "answer": "절대 경로는 루트부터 전체 경로를 명시하고, 상대 경로는 현재 위치를 기준으로 나타냅니다. 절대는 위치가 고정적이고 상대는 유연합니다." + }, + { + "id": "os-file-006", + "question": "하드 링크와 소프트 링크의 차이는 무엇인가요?", + "answer": "하드 링크는 같은 아이노드를 가리키는 또 다른 이름이고, 소프트 링크는 경로를 가리키는 바로가기입니다. 소프트 링크는 원본이 사라지면 깨집니다." + }, + { + "id": "os-file-007", + "question": "디렉터리란 무엇인가요?", + "answer": "파일과 다른 디렉터리의 이름 및 위치 정보를 담는 특수한 파일입니다. 계층적 구조로 파일을 체계적으로 조직합니다." + }, + { + "id": "os-file-008", + "question": "저널링 파일 시스템이란 무엇인가요?", + "answer": "변경 사항을 먼저 로그(저널)에 기록한 뒤 실제로 반영하는 파일 시스템입니다. 갑작스러운 중단 시에도 복구가 쉬워 안정성이 높습니다." + }, + { + "id": "os-file-009", + "question": "파일 시스템의 블록(block)이란 무엇인가요?", + "answer": "데이터를 저장하고 관리하는 기본 단위입니다. 디스크 공간을 블록 단위로 할당하며 크기에 따라 효율과 단편화가 달라집니다." + } + ] + }, + { + "id": "os-disk", + "name": "디스크와 입출력 관리", + "questions": [ + { + "id": "os-disk-001", + "question": "디스크 스케줄링이란 무엇인가요?", + "answer": "디스크 접근 요청들을 어떤 순서로 처리할지 정해 헤드 이동을 줄이는 기법입니다. 탐색 시간을 최소화해 디스크 성능을 높입니다." + }, + { + "id": "os-disk-002", + "question": "FCFS와 SSTF 디스크 스케줄링의 차이는 무엇인가요?", + "answer": "FCFS는 요청 순서대로 처리해 공정하지만 비효율적이고, SSTF는 현재 헤드에서 가장 가까운 요청을 먼저 처리해 빠르지만 기아가 생길 수 있습니다." + }, + { + "id": "os-disk-003", + "question": "SCAN과 C-SCAN의 차이는 무엇인가요?", + "answer": "SCAN은 한쪽 끝까지 갔다가 방향을 바꿔 처리하고, C-SCAN은 끝에 도달하면 처음으로 돌아가 한 방향으로만 처리합니다. C-SCAN이 대기 시간이 더 균등합니다." + }, + { + "id": "os-disk-004", + "question": "버퍼링과 스풀링의 차이는 무엇인가요?", + "answer": "버퍼링은 속도 차이를 완충하려 데이터를 임시 저장하는 것이고, 스풀링은 느린 장치 작업을 디스크에 모아두고 순차 처리하는 것입니다. 프린터가 대표적 예입니다." + }, + { + "id": "os-disk-005", + "question": "블로킹 입출력과 논블로킹 입출력의 차이는 무엇인가요?", + "answer": "블로킹은 입출력이 끝날 때까지 프로세스가 기다리고, 논블로킹은 즉시 반환해 다른 일을 할 수 있습니다. 논블로킹이 자원 활용에 유리합니다." + }, + { + "id": "os-disk-006", + "question": "동기 입출력과 비동기 입출력의 차이는 무엇인가요?", + "answer": "동기는 입출력 완료를 기다려 결과를 받고, 비동기는 요청만 하고 완료 시 알림을 받습니다. 비동기가 동시 처리에 유리합니다." + }, + { + "id": "os-disk-007", + "question": "디바이스 드라이버란 무엇인가요?", + "answer": "운영체제가 특정 하드웨어 장치를 제어할 수 있게 해주는 소프트웨어입니다. 장치마다 다른 세부 동작을 추상화해 일관된 인터페이스를 제공합니다." + }, + { + "id": "os-disk-008", + "question": "인터럽트 기반 입출력이 효율적인 이유는 무엇인가요?", + "answer": "CPU가 입출력 완료를 계속 확인하지 않고 다른 작업을 하다가 신호를 받으면 처리하기 때문입니다. 폴링보다 CPU 자원을 아낍니다." + } + ] + }, + { + "id": "os-concurrency", + "name": "동시성과 멀티스레딩 심화", + "questions": [ + { + "id": "os-concurrency-001", + "question": "임계 영역 문제의 세 가지 요구 조건은 무엇인가요?", + "answer": "한 번에 하나만 진입하는 상호 배제, 진입 기회를 보장하는 진행, 무한 대기를 막는 한정 대기입니다. 올바른 동기화는 이 셋을 만족해야 합니다." + }, + { + "id": "os-concurrency-002", + "question": "바쁜 대기(busy waiting)란 무엇인가요?", + "answer": "조건이 충족될 때까지 CPU가 계속 반복 확인하며 기다리는 것입니다. 응답은 빠르지만 CPU를 낭비하므로 짧은 대기에만 적합합니다." + }, + { + "id": "os-concurrency-003", + "question": "세마포어의 wait와 signal 연산이란 무엇인가요?", + "answer": "wait는 자원을 사용하려 카운터를 줄이고, signal은 자원을 반납하며 카운터를 늘립니다. 카운터가 0이면 wait한 프로세스는 대기합니다." + }, + { + "id": "os-concurrency-004", + "question": "이진 세마포어와 계수 세마포어의 차이는 무엇인가요?", + "answer": "이진 세마포어는 0과 1만 가져 상호 배제에 쓰이고, 계수 세마포어는 여러 개의 자원 개수를 관리합니다. 이진 세마포어는 뮤텍스와 유사합니다." + }, + { + "id": "os-concurrency-005", + "question": "교착, 기아, 우선순위 역전의 차이는 무엇인가요?", + "answer": "교착은 서로 기다려 멈춤, 기아는 계속 밀려 못 받음, 우선순위 역전은 낮은 우선순위가 자원을 쥐어 높은 쪽이 막히는 현상입니다." + }, + { + "id": "os-concurrency-006", + "question": "스레드 안전(thread-safe)하다는 것은 무엇인가요?", + "answer": "여러 스레드가 동시에 접근해도 올바르게 동작하도록 설계된 것을 의미합니다. 공유 자원에 적절한 동기화가 적용되어 있어야 합니다." + }, + { + "id": "os-concurrency-007", + "question": "락 없는(lock-free) 프로그래밍이란 무엇인가요?", + "answer": "락 대신 원자적 연산으로 동기화해 교착 없이 동시성을 확보하는 기법입니다. 성능은 좋지만 구현이 어렵습니다." + }, + { + "id": "os-concurrency-008", + "question": "컨디션 변수(condition variable)란 무엇인가요?", + "answer": "특정 조건이 만족될 때까지 스레드를 대기시키고, 조건이 되면 깨우는 동기화 도구입니다. 모니터와 함께 자주 사용됩니다." + } + ] + }, + { + "id": "os-virtualization", + "name": "가상화와 현대 운영체제", + "questions": [ + { + "id": "os-virtualization-001", + "question": "가상화(virtualization)란 무엇인가요?", + "answer": "물리 자원을 논리적으로 분할하거나 추상화해 여러 환경을 독립적으로 실행하는 기술입니다. 자원 활용률을 높이고 격리를 제공합니다." + }, + { + "id": "os-virtualization-002", + "question": "하이퍼바이저(hypervisor)란 무엇인가요?", + "answer": "여러 가상 머신을 생성하고 관리하며 하드웨어 자원을 분배하는 소프트웨어입니다. 하드웨어 위에서 직접 도는 타입1과 OS 위에서 도는 타입2가 있습니다." + }, + { + "id": "os-virtualization-003", + "question": "가상 머신과 컨테이너의 차이는 무엇인가요?", + "answer": "가상 머신은 운영체제 전체를 포함해 무겁고 격리가 강하며, 컨테이너는 호스트 커널을 공유해 가볍고 빠릅니다. 용도에 따라 선택합니다." + }, + { + "id": "os-virtualization-004", + "question": "컨테이너가 가벼운 이유는 무엇인가요?", + "answer": "게스트 운영체제 없이 호스트 커널을 공유하고 애플리케이션과 의존성만 패키징하기 때문입니다. 시작이 빠르고 자원 소모가 적습니다." + }, + { + "id": "os-virtualization-005", + "question": "프로세스 격리는 왜 중요한가요?", + "answer": "한 프로세스의 오류나 침해가 다른 프로세스와 시스템에 번지지 않게 하기 때문입니다. 메모리 보호와 권한 분리로 안정성과 보안을 지킵니다." + }, + { + "id": "os-virtualization-006", + "question": "운영체제 전반에서 캐싱이 쓰이는 예는 무엇인가요?", + "answer": "페이지 캐시, 디스크 버퍼 캐시, TLB 등 여러 곳에서 자주 쓰는 데이터를 가까이 두어 성능을 높입니다. 운영체제 성능의 핵심 기법입니다." + }, + { + "id": "os-virtualization-007", + "question": "사용자 공간과 커널 공간의 분리는 왜 필요한가요?", + "answer": "응용 프로그램이 커널 메모리에 함부로 접근해 시스템을 손상시키는 것을 막기 위해서입니다. 안정성과 보안의 기반이 됩니다." + } + ] + }, + { + "id": "os-security", + "name": "운영체제 보안과 보호", + "questions": [ + { + "id": "os-security-001", + "question": "사용자 모드와 커널 모드의 차이는 무엇인가요?", + "answer": "사용자 모드는 권한이 제한되어 직접 하드웨어에 접근할 수 없고, 커널 모드는 모든 권한을 가집니다. 둘을 나눠 시스템을 보호합니다." + }, + { + "id": "os-security-002", + "question": "시스템 콜이 모드 전환을 일으키는 이유는 무엇인가요?", + "answer": "사용자 프로그램이 커널의 보호된 기능을 안전하게 요청해야 하기 때문입니다. 트랩으로 커널 모드로 전환해 처리 후 돌아옵니다." + }, + { + "id": "os-security-003", + "question": "접근 제어(access control)란 무엇인가요?", + "answer": "누가 어떤 자원에 어떤 권한으로 접근할 수 있는지 통제하는 것입니다. 권한 비트나 접근 제어 목록(ACL)으로 구현합니다." + }, + { + "id": "os-security-004", + "question": "권한 상승(privilege escalation)이란 무엇인가요?", + "answer": "낮은 권한 사용자가 허용되지 않은 높은 권한을 얻는 공격입니다. 취약점을 막고 최소 권한 원칙을 지켜 방어합니다." + }, + { + "id": "os-security-005", + "question": "샌드박스(sandbox)란 무엇인가요?", + "answer": "프로그램을 격리된 제한 환경에서 실행해 시스템에 피해를 주지 못하게 하는 기법입니다. 신뢰할 수 없는 코드 실행에 쓰입니다." + }, + { + "id": "os-security-006", + "question": "버퍼 오버플로우란 무엇인가요?", + "answer": "할당된 버퍼를 넘어 데이터를 써 인접 메모리를 침범하는 취약점입니다. 악성 코드 실행에 악용될 수 있어 경계 검사로 방어합니다." + }, + { + "id": "os-security-007", + "question": "최소 권한 원칙이란 무엇인가요?", + "answer": "각 주체에게 작업에 필요한 최소한의 권한만 부여하는 보안 원칙입니다. 피해 범위를 줄이고 침해 가능성을 낮춥니다." + }, + { + "id": "os-security-008", + "question": "운영체제가 자원을 보호하는 방법은 무엇인가요?", + "answer": "모드 분리, 메모리 보호, 접근 제어, 권한 검사 등을 사용합니다. 프로그램 간 간섭과 무단 접근을 막아 안정성을 지킵니다." + } + ] + }, + { + "id": "os-boot-init", + "name": "시스템 관리와 부팅", + "questions": [ + { + "id": "os-boot-init-001", + "question": "POST란 무엇인가요?", + "answer": "전원이 켜질 때 하드웨어가 정상인지 검사하는 자가 진단 과정입니다. 문제가 있으면 부팅을 멈추고 신호로 알립니다." + }, + { + "id": "os-boot-init-002", + "question": "부트로더(bootloader)란 무엇인가요?", + "answer": "운영체제 커널을 메모리에 올려 실행을 시작하게 하는 프로그램입니다. 부팅 과정에서 펌웨어와 운영체제를 잇는 다리 역할을 합니다." + }, + { + "id": "os-boot-init-003", + "question": "BIOS와 UEFI의 차이는 무엇인가요?", + "answer": "UEFI는 BIOS의 후속 펌웨어로 더 빠른 부팅, 큰 디스크 지원, 보안 부팅 등을 제공합니다. 현대 시스템은 대부분 UEFI를 씁니다." + }, + { + "id": "os-boot-init-004", + "question": "커널과 셸(shell)의 차이는 무엇인가요?", + "answer": "커널은 하드웨어를 관리하는 운영체제 핵심이고, 셸은 사용자 명령을 받아 커널에 전달하는 인터페이스입니다. 셸은 사용자와 커널을 잇습니다." + }, + { + "id": "os-boot-init-005", + "question": "init(또는 systemd) 프로세스의 역할은 무엇인가요?", + "answer": "부팅 후 가장 먼저 실행되어 다른 시스템 프로세스와 서비스를 시작하는 최초의 프로세스입니다. 모든 프로세스의 조상이 됩니다." + }, + { + "id": "os-boot-init-006", + "question": "런레벨이나 타깃이란 무엇인가요?", + "answer": "시스템이 동작하는 상태나 모드를 정의한 것입니다. 어떤 서비스를 띄울지 결정하며 다중 사용자 모드나 그래픽 모드 등이 있습니다." + }, + { + "id": "os-boot-init-007", + "question": "시스템 로그(log)는 왜 중요한가요?", + "answer": "시스템과 프로그램의 동작 기록을 남겨 문제 진단과 보안 분석에 쓰이기 때문입니다. 장애 원인을 추적하는 핵심 단서가 됩니다." + } + ] + } + ] + }, + { + "id": "algorithms-datastructures", + "name": "알고리즘과 자료구조", + "categories": [ + { + "id": "algo-complexity", + "name": "복잡도 분석", + "questions": [ + { + "id": "algo-complexity-001", + "question": "시간 복잡도와 공간 복잡도란 무엇인가요?", + "answer": "시간 복잡도는 입력 크기에 따라 알고리즘 실행에 필요한 연산 횟수의 증가율이고, 공간 복잡도는 필요한 메모리 양의 증가율입니다. 둘 다 알고리즘 효율을 평가하는 기준입니다." + }, + { + "id": "algo-complexity-002", + "question": "빅오(Big-O) 표기법이란 무엇인가요?", + "answer": "입력이 커질 때 알고리즘의 최악 성능을 점근적으로 표현하는 표기법입니다. 상수와 낮은 차수 항을 무시하고 가장 지배적인 항만 남겨 증가율을 나타냅니다." + }, + { + "id": "algo-complexity-003", + "question": "O(1), O(log n), O(n), O(n^2)의 차이는 무엇인가요?", + "answer": "O(1)은 입력과 무관한 상수 시간, O(log n)은 입력이 늘어도 천천히 증가, O(n)은 입력에 비례, O(n^2)은 입력의 제곱에 비례합니다. 뒤로 갈수록 입력이 커질 때 급격히 느려집니다." + }, + { + "id": "algo-complexity-004", + "question": "최선, 평균, 최악의 경우란 무엇인가요?", + "answer": "입력 상황에 따른 알고리즘의 성능을 나타냅니다. 최선은 가장 빠른 경우, 최악은 가장 느린 경우, 평균은 일반적인 경우의 성능이며 보통 최악의 경우를 기준으로 평가합니다." + }, + { + "id": "algo-complexity-005", + "question": "점근적 표기법에는 어떤 것이 있나요?", + "answer": "상한을 나타내는 빅오, 하한을 나타내는 빅오메가, 상한과 하한이 같은 빅세타가 있습니다. 보통 최악을 보는 빅오를 가장 많이 씁니다." + }, + { + "id": "algo-complexity-006", + "question": "분할 상환 분석(amortized analysis)이란 무엇인가요?", + "answer": "비용이 큰 연산이 드물게 일어날 때 전체 연산의 평균 비용을 분석하는 방법입니다. 동적 배열의 삽입이 평균 O(1)인 것이 대표 예입니다." + }, + { + "id": "algo-complexity-007", + "question": "O(n log n)이 비교 기반 정렬의 한계로 불리는 이유는 무엇인가요?", + "answer": "비교 기반 정렬은 최선의 경우에도 O(n log n)보다 빠를 수 없다는 이론적 하한이 있기 때문입니다. 계수 정렬 등은 비교를 안 해 예외입니다." + }, + { + "id": "algo-complexity-008", + "question": "시간 복잡도와 실제 실행 시간의 관계는 무엇인가요?", + "answer": "시간 복잡도는 증가 추세를 나타낼 뿐 상수 계수나 하드웨어를 반영하지 않습니다. 같은 복잡도라도 실제 속도는 다를 수 있습니다." + }, + { + "id": "algo-complexity-009", + "question": "공간 복잡도를 고려해야 하는 경우는 언제인가요?", + "answer": "메모리가 제한된 환경이나 대용량 데이터를 다룰 때입니다. 시간을 줄이려 메모리를 더 쓰는 트레이드오프를 판단해야 합니다." + }, + { + "id": "algo-complexity-010", + "question": "재귀 알고리즘의 복잡도는 어떻게 분석하나요?", + "answer": "점화식을 세우고 마스터 정리나 전개를 통해 계산합니다. 예를 들어 병합 정렬은 점화식이 2T(n/2)+O(n)이라 O(n log n)이 됩니다." + } + ] + }, + { + "id": "algo-array", + "name": "배열과 연결 리스트", + "questions": [ + { + "id": "algo-array-001", + "question": "배열과 연결 리스트의 차이는 무엇인가요?", + "answer": "배열은 연속된 메모리에 저장되어 인덱스로 빠르게 접근(O(1))하지만 삽입과 삭제가 느립니다. 연결 리스트는 노드가 포인터로 연결되어 삽입과 삭제가 빠르지만 임의 접근이 느립니다(O(n))." + }, + { + "id": "algo-array-002", + "question": "배열의 장단점은 무엇인가요?", + "answer": "장점은 인덱스를 통한 O(1) 임의 접근과 캐시 효율이 좋다는 점이고, 단점은 크기가 고정적이며 중간 삽입과 삭제 시 원소 이동이 필요해 O(n)이 든다는 점입니다." + }, + { + "id": "algo-array-003", + "question": "연결 리스트의 종류는 무엇인가요?", + "answer": "다음 노드만 가리키는 단일 연결 리스트, 양방향을 가리키는 이중 연결 리스트, 마지막 노드가 처음을 가리키는 원형 연결 리스트가 있습니다. 용도에 따라 적절한 형태를 선택합니다." + }, + { + "id": "algo-array-004", + "question": "배열에서 삽입과 삭제의 시간 복잡도는 어떻게 되나요?", + "answer": "맨 뒤 삽입과 삭제는 O(1)이지만, 중간이나 앞에 삽입하거나 삭제하면 뒤 원소들을 모두 이동해야 하므로 O(n)입니다. 임의 위치 접근 자체는 O(1)입니다." + }, + { + "id": "algo-array-005", + "question": "동적 배열(ArrayList)은 어떻게 동작하나요?", + "answer": "내부적으로 고정 크기 배열을 쓰다가 가득 차면 보통 두 배 크기의 새 배열을 만들어 복사합니다. 이 재할당 덕분에 평균적으로는 삽입이 O(1)에 가깝게 동작합니다(분할 상환)." + }, + { + "id": "algo-array-006", + "question": "배열의 캐시 효율이 좋은 이유는 무엇인가요?", + "answer": "데이터가 연속된 메모리에 저장되어 공간 지역성을 잘 활용하기 때문입니다. 인접 원소가 함께 캐시에 올라와 순회가 빠릅니다." + }, + { + "id": "algo-array-007", + "question": "연결 리스트가 배열보다 유리한 경우는 언제인가요?", + "answer": "중간 삽입과 삭제가 빈번하거나 크기가 자주 변할 때입니다. 노드의 연결만 바꾸면 되어 원소 이동이 필요 없습니다." + }, + { + "id": "algo-array-008", + "question": "이중 연결 리스트의 장점은 무엇인가요?", + "answer": "양방향 탐색이 가능하고 특정 노드의 삭제가 쉽습니다. 이전 노드를 따로 찾지 않아도 되지만 포인터를 하나 더 관리해야 합니다." + }, + { + "id": "algo-array-009", + "question": "원형 연결 리스트는 언제 쓰나요?", + "answer": "끝과 처음이 이어져 순환이 필요한 경우에 씁니다. 라운드 로빈 스케줄링이나 반복 재생 목록 등에 적합합니다." + }, + { + "id": "algo-array-010", + "question": "동적 배열의 확장 비용은 어떻게 분석하나요?", + "answer": "확장 시 복사 비용이 들지만 두 배씩 늘리면 분할 상환상 삽입이 평균 O(1)이 됩니다. 가끔의 큰 비용이 여러 삽입에 분산됩니다." + }, + { + "id": "algo-array-011", + "question": "배열 대신 해시맵을 쓰는 경우는 언제인가요?", + "answer": "인덱스가 아니라 키로 빠르게 찾아야 할 때입니다. 데이터가 희소하거나 키가 정수가 아닐 때 해시맵이 효율적입니다." + } + ] + }, + { + "id": "algo-stack", + "name": "스택과 큐", + "questions": [ + { + "id": "algo-stack-001", + "question": "스택과 큐의 차이는 무엇인가요?", + "answer": "스택은 마지막에 넣은 것을 먼저 꺼내는 후입선출(LIFO) 구조이고, 큐는 먼저 넣은 것을 먼저 꺼내는 선입선출(FIFO) 구조입니다. 데이터 처리 순서가 정반대입니다." + }, + { + "id": "algo-stack-002", + "question": "스택의 활용 사례는 무엇인가요?", + "answer": "함수 호출 스택, 수식의 괄호 검사, 실행 취소(undo) 기능, 웹 브라우저의 뒤로 가기, 깊이 우선 탐색(DFS) 등에 활용됩니다. 되돌아가는 동작에 적합합니다." + }, + { + "id": "algo-stack-003", + "question": "큐의 활용 사례는 무엇인가요?", + "answer": "작업 대기열, 프린터 인쇄 순서, CPU 스케줄링, 너비 우선 탐색(BFS), 메시지 큐 등에 활용됩니다. 들어온 순서대로 처리해야 하는 상황에 적합합니다." + }, + { + "id": "algo-stack-004", + "question": "원형 큐(circular queue)란 무엇인가요?", + "answer": "배열의 끝과 처음을 논리적으로 연결해 원형으로 사용하는 큐입니다. 일반 배열 큐에서 앞쪽 빈 공간을 재활용하지 못하는 문제를 해결해 공간 효율을 높입니다." + }, + { + "id": "algo-stack-005", + "question": "덱(deque)이란 무엇인가요?", + "answer": "양쪽 끝에서 모두 삽입과 삭제가 가능한 자료구조입니다. 스택과 큐의 기능을 모두 가지며 슬라이딩 윈도우 문제 등 양방향 처리가 필요한 곳에 유용합니다." + }, + { + "id": "algo-stack-006", + "question": "스택 두 개로 큐를 구현하는 방법은 무엇인가요?", + "answer": "입력용 스택과 출력용 스택을 둡니다. 넣을 때는 입력 스택에 쌓고, 뺄 때 출력 스택이 비어 있으면 입력 스택의 내용을 모두 옮긴 뒤 꺼내면 선입선출이 구현됩니다." + }, + { + "id": "algo-stack-007", + "question": "후위 표기법(postfix)이란 무엇인가요?", + "answer": "연산자를 피연산자 뒤에 두는 수식 표기법입니다. 괄호 없이 계산 순서를 명확히 하며 스택으로 쉽게 계산할 수 있습니다." + }, + { + "id": "algo-stack-008", + "question": "괄호 검사는 스택으로 어떻게 하나요?", + "answer": "여는 괄호는 스택에 넣고 닫는 괄호가 나오면 짝을 꺼내 맞춰봅니다. 끝까지 짝이 맞고 스택이 비면 올바른 괄호입니다." + }, + { + "id": "algo-stack-009", + "question": "함수 호출 스택이란 무엇인가요?", + "answer": "함수가 호출되면 지역 변수와 복귀 주소를 스택 프레임으로 쌓고, 반환되면 꺼내는 구조입니다. 재귀가 깊으면 스택 오버플로우가 날 수 있습니다." + }, + { + "id": "algo-stack-010", + "question": "우선순위 큐(priority queue)란 무엇인가요?", + "answer": "들어온 순서가 아니라 우선순위가 높은 원소가 먼저 나오는 자료구조입니다. 보통 힙으로 구현하며 작업 스케줄링 등에 쓰입니다." + }, + { + "id": "algo-stack-011", + "question": "큐 두 개로 스택을 구현하는 방법은 무엇인가요?", + "answer": "새 원소를 넣을 때마다 기존 원소들을 뒤로 돌려 항상 마지막에 넣은 것이 앞에 오게 합니다. 그러면 후입선출처럼 동작합니다." + }, + { + "id": "algo-stack-012", + "question": "모노토닉 스택(monotonic stack)이란 무엇인가요?", + "answer": "원소가 항상 증가하거나 감소하도록 유지하는 스택입니다. 다음 큰 원소 찾기 같은 문제를 효율적으로 풀 때 사용합니다." + } + ] + }, + { + "id": "algo-tree", + "name": "트리", + "questions": [ + { + "id": "algo-tree-001", + "question": "트리(tree)란 무엇인가요?", + "answer": "노드들이 부모-자식 관계로 연결된 계층적 자료구조로, 사이클이 없는 그래프입니다. 최상위에 루트 노드가 있고 아래로 가지를 뻗으며 파일 시스템, 조직도 등에 쓰입니다." + }, + { + "id": "algo-tree-002", + "question": "이진 트리와 이진 탐색 트리(BST)의 차이는 무엇인가요?", + "answer": "이진 트리는 각 노드가 최대 두 개의 자식을 가지는 트리이고, 이진 탐색 트리는 왼쪽은 작은 값, 오른쪽은 큰 값으로 정렬된 이진 트리입니다. BST는 탐색이 평균 O(log n)으로 빠릅니다." + }, + { + "id": "algo-tree-003", + "question": "트리 순회 방법을 설명해주세요.", + "answer": "전위 순회는 루트를 먼저 방문하고, 중위 순회는 루트를 가운데에, 후위 순회는 루트를 마지막에 방문합니다. 이진 탐색 트리를 중위 순회하면 오름차순으로 정렬된 값을 얻습니다." + }, + { + "id": "algo-tree-004", + "question": "균형 이진 트리(AVL, Red-Black Tree)란 무엇인가요?", + "answer": "삽입과 삭제 시 트리의 높이가 한쪽으로 치우치지 않게 유지하는 트리입니다. 한쪽으로 쏠려 O(n)이 되는 것을 막아 탐색, 삽입, 삭제를 항상 O(log n)으로 보장합니다." + }, + { + "id": "algo-tree-005", + "question": "힙(heap)이란 무엇인가요?", + "answer": "부모가 자식보다 항상 크거나(최대 힙) 작은(최소 힙) 완전 이진 트리입니다. 루트에서 최댓값이나 최솟값을 O(1)에 얻을 수 있어 우선순위 큐 구현에 사용됩니다." + }, + { + "id": "algo-tree-006", + "question": "B-트리란 무엇인가요?", + "answer": "하나의 노드가 여러 개의 키와 자식을 가질 수 있는 균형 트리입니다. 트리 높이가 낮아 디스크 접근 횟수를 줄여주므로 데이터베이스와 파일 시스템의 인덱스에 널리 쓰입니다." + }, + { + "id": "algo-tree-007", + "question": "완전 이진 트리와 포화 이진 트리의 차이는 무엇인가요?", + "answer": "포화 이진 트리는 모든 레벨이 꽉 차 있고, 완전 이진 트리는 마지막 레벨을 제외하고 꽉 차 있으며 마지막 레벨은 왼쪽부터 채워진 트리입니다. 힙은 완전 이진 트리 구조를 사용합니다." + }, + { + "id": "algo-tree-008", + "question": "레벨 순회(level order traversal)란 무엇인가요?", + "answer": "트리를 위에서 아래로, 같은 깊이끼리 왼쪽부터 방문하는 방식입니다. 너비 우선 탐색과 같으며 큐를 이용해 구현합니다." + }, + { + "id": "algo-tree-009", + "question": "이진 탐색 트리가 한쪽으로 치우치면 어떻게 되나요?", + "answer": "사실상 연결 리스트가 되어 탐색이 O(n)으로 느려집니다. 이를 막기 위해 AVL이나 레드블랙 트리 같은 균형 트리를 씁니다." + }, + { + "id": "algo-tree-010", + "question": "힙과 이진 탐색 트리의 차이는 무엇인가요?", + "answer": "힙은 부모와 자식 간 크기 관계만 보장하는 완전 이진 트리이고, BST는 좌우 정렬을 보장합니다. 힙은 최댓값이나 최솟값 추출, BST는 검색에 유리합니다." + }, + { + "id": "algo-tree-011", + "question": "트라이(trie)란 무엇인가요?", + "answer": "문자열을 문자 단위로 저장하는 트리입니다. 접두사 검색이 빠르고 자동완성이나 사전 구현에 효율적이지만 메모리를 많이 씁니다." + }, + { + "id": "algo-tree-012", + "question": "세그먼트 트리란 무엇인가요?", + "answer": "구간의 합이나 최솟값 같은 질의를 빠르게 처리하기 위한 트리입니다. 구간 질의와 갱신을 O(log n)에 수행할 수 있습니다." + }, + { + "id": "algo-tree-013", + "question": "균형 트리가 중요한 이유는 무엇인가요?", + "answer": "트리의 높이를 낮게 유지해 탐색, 삽입, 삭제를 항상 O(log n)으로 보장하기 때문입니다. 한쪽으로 쏠리면 성능이 급격히 나빠집니다." + } + ] + }, + { + "id": "algo-hash", + "name": "해시", + "questions": [ + { + "id": "algo-hash-001", + "question": "해시 테이블이란 무엇인가요?", + "answer": "키를 해시 함수로 변환한 값을 인덱스로 사용해 데이터를 저장하는 자료구조입니다. 평균적으로 삽입, 삭제, 탐색을 O(1)에 수행할 수 있어 빠른 검색에 유리합니다." + }, + { + "id": "algo-hash-002", + "question": "해시 충돌(collision)이란 무엇이고 어떻게 해결하나요?", + "answer": "서로 다른 키가 같은 해시 값을 가지는 현상입니다. 같은 위치에 연결 리스트로 묶는 체이닝, 비어 있는 다른 칸을 찾아 저장하는 개방 주소법으로 해결합니다." + }, + { + "id": "algo-hash-003", + "question": "체이닝과 개방 주소법의 차이는 무엇인가요?", + "answer": "체이닝은 충돌한 데이터를 연결 리스트로 같은 버킷에 저장해 구현이 단순하고, 개방 주소법은 다른 빈 버킷을 찾아 저장해 메모리는 절약하지만 군집화 문제가 있습니다." + }, + { + "id": "algo-hash-004", + "question": "좋은 해시 함수의 조건은 무엇인가요?", + "answer": "키들을 테이블 전체에 고르게 분산시켜 충돌을 최소화하고, 계산이 빠르며, 같은 키에 항상 같은 값을 반환해야 합니다. 분포가 균등할수록 성능이 좋습니다." + }, + { + "id": "algo-hash-005", + "question": "해시 테이블의 시간 복잡도는 어떻게 되나요?", + "answer": "충돌이 적으면 평균적으로 삽입, 삭제, 탐색 모두 O(1)입니다. 다만 충돌이 심해 한 버킷에 데이터가 몰리면 최악의 경우 O(n)까지 떨어질 수 있습니다." + }, + { + "id": "algo-hash-006", + "question": "로드 팩터(load factor)란 무엇인가요?", + "answer": "해시 테이블에서 저장된 원소 수를 전체 버킷 수로 나눈 값입니다. 너무 높으면 충돌이 늘어 성능이 떨어지므로 일정 수준을 넘으면 테이블을 키웁니다." + }, + { + "id": "algo-hash-007", + "question": "리해싱(rehashing)이란 무엇인가요?", + "answer": "로드 팩터가 높아지면 더 큰 테이블을 만들어 모든 원소를 다시 배치하는 과정입니다. 비용은 크지만 충돌을 줄여 성능을 회복합니다." + }, + { + "id": "algo-hash-008", + "question": "선형 탐사와 이차 탐사의 차이는 무엇인가요?", + "answer": "선형 탐사는 충돌 시 바로 옆 칸을 차례로 찾고, 이차 탐사는 제곱 간격으로 떨어진 칸을 찾습니다. 이차 탐사가 군집화를 줄입니다." + }, + { + "id": "algo-hash-009", + "question": "해시맵과 해시셋의 차이는 무엇인가요?", + "answer": "해시맵은 키와 값 쌍을 저장하고, 해시셋은 키만 저장해 중복 없는 집합을 표현합니다. 둘 다 해시 기반으로 빠른 조회를 제공합니다." + }, + { + "id": "algo-hash-010", + "question": "좋은 해시 함수가 충돌에 미치는 영향은 무엇인가요?", + "answer": "값을 고르게 분산할수록 충돌이 줄어 평균 O(1) 성능을 유지합니다. 분포가 치우치면 특정 버킷에 몰려 성능이 떨어집니다." + }, + { + "id": "algo-hash-011", + "question": "해시 테이블의 단점은 무엇인가요?", + "answer": "순서가 보장되지 않고, 최악의 경우 충돌로 O(n)이 될 수 있으며, 메모리 오버헤드가 있습니다. 범위 검색에도 부적합합니다." + } + ] + }, + { + "id": "algo-graph", + "name": "그래프", + "questions": [ + { + "id": "algo-graph-001", + "question": "그래프(graph)란 무엇인가요?", + "answer": "정점(vertex)과 그것을 잇는 간선(edge)으로 이루어진 자료구조입니다. 노드 간의 다양한 연결 관계를 표현하며 지도, 소셜 네트워크, 네트워크 경로 등을 모델링하는 데 쓰입니다." + }, + { + "id": "algo-graph-002", + "question": "그래프의 표현 방법은 무엇인가요?", + "answer": "정점 간 연결을 2차원 배열로 나타내는 인접 행렬과, 각 정점의 인접 정점을 리스트로 나타내는 인접 리스트가 있습니다. 간선이 적은 희소 그래프는 인접 리스트가 메모리 효율이 좋습니다." + }, + { + "id": "algo-graph-003", + "question": "DFS와 BFS의 차이는 무엇인가요?", + "answer": "DFS는 한 방향으로 깊게 끝까지 탐색한 뒤 되돌아오는 방식으로 스택(재귀)을 쓰고, BFS는 가까운 노드부터 너비 우선으로 탐색하며 큐를 씁니다. 최단 경로 탐색에는 BFS가 적합합니다." + }, + { + "id": "algo-graph-004", + "question": "다익스트라 알고리즘이란 무엇인가요?", + "answer": "가중치가 있는 그래프에서 한 정점으로부터 다른 모든 정점까지의 최단 경로를 구하는 알고리즘입니다. 음의 가중치가 없을 때 사용하며 우선순위 큐로 효율을 높입니다." + }, + { + "id": "algo-graph-005", + "question": "최소 신장 트리(MST)란 무엇인가요?", + "answer": "그래프의 모든 정점을 사이클 없이 연결하면서 간선 가중치의 합이 최소가 되는 트리입니다. 크루스칼과 프림 알고리즘으로 구하며 네트워크 최소 비용 연결 설계에 쓰입니다." + }, + { + "id": "algo-graph-006", + "question": "방향 그래프와 무방향 그래프의 차이는 무엇인가요?", + "answer": "방향 그래프는 간선에 방향이 있어 한쪽으로만 이동할 수 있고, 무방향 그래프는 방향이 없어 양쪽으로 이동할 수 있습니다. 일방통행 도로와 양방향 도로에 비유할 수 있습니다." + }, + { + "id": "algo-graph-007", + "question": "위상 정렬(topological sort)이란 무엇인가요?", + "answer": "방향 그래프에서 선후 관계를 어기지 않도록 정점을 일렬로 나열하는 것입니다. 작업 순서나 의존성 해결에 쓰이며 사이클이 없어야 합니다." + }, + { + "id": "algo-graph-008", + "question": "인접 행렬과 인접 리스트의 장단점은 무엇인가요?", + "answer": "인접 행렬은 간선 확인이 O(1)이지만 메모리를 많이 쓰고, 인접 리스트는 메모리 효율이 좋지만 간선 확인이 느립니다. 그래프 밀도에 따라 선택합니다." + }, + { + "id": "algo-graph-009", + "question": "벨만-포드 알고리즘이란 무엇인가요?", + "answer": "음의 가중치가 있어도 최단 경로를 구할 수 있는 알고리즘입니다. 다익스트라보다 느리지만 음의 사이클도 탐지할 수 있습니다." + }, + { + "id": "algo-graph-010", + "question": "플로이드-워셜 알고리즘이란 무엇인가요?", + "answer": "모든 정점 쌍 사이의 최단 경로를 구하는 알고리즘입니다. 점화식 기반의 동적 프로그래밍으로 정점 수의 세제곱에 비례하는 시간에 동작합니다." + }, + { + "id": "algo-graph-011", + "question": "크루스칼과 프림 알고리즘의 차이는 무엇인가요?", + "answer": "둘 다 최소 신장 트리를 구하지만, 크루스칼은 간선을 가중치 순으로 선택하고, 프림은 정점을 하나씩 확장합니다. 그래프 형태에 따라 효율이 다릅니다." + }, + { + "id": "algo-graph-012", + "question": "그래프에서 사이클 탐지는 어떻게 하나요?", + "answer": "무방향 그래프는 방문 중 이미 방문한 노드를 만나면, 방향 그래프는 재귀 스택에 있는 노드를 다시 만나면 사이클이 있습니다. DFS로 검사합니다." + } + ] + }, + { + "id": "algo-sort", + "name": "정렬 알고리즘", + "questions": [ + { + "id": "algo-sort-001", + "question": "버블, 선택, 삽입 정렬을 설명해주세요.", + "answer": "버블 정렬은 인접한 두 원소를 비교 교환하고, 선택 정렬은 최솟값을 찾아 앞에 배치하며, 삽입 정렬은 정렬된 부분에 원소를 끼워 넣습니다. 셋 다 평균 O(n^2)의 간단한 정렬입니다." + }, + { + "id": "algo-sort-002", + "question": "퀵 정렬의 동작 원리와 시간 복잡도는 어떻게 되나요?", + "answer": "피벗을 기준으로 작은 값과 큰 값으로 분할한 뒤 각 부분을 재귀적으로 정렬합니다. 평균 O(n log n)으로 빠르지만 피벗이 한쪽으로 치우치면 최악 O(n^2)이 됩니다." + }, + { + "id": "algo-sort-003", + "question": "병합 정렬(merge sort)이란 무엇인가요?", + "answer": "배열을 절반씩 분할해 각각 정렬한 뒤 합치며 정렬하는 분할 정복 알고리즘입니다. 항상 O(n log n)을 보장하고 안정 정렬이지만 추가 메모리 공간이 필요합니다." + }, + { + "id": "algo-sort-004", + "question": "힙 정렬이란 무엇인가요?", + "answer": "데이터를 힙으로 구성한 뒤 루트의 최댓값(또는 최솟값)을 차례로 꺼내며 정렬하는 방식입니다. 시간 복잡도는 항상 O(n log n)이며 추가 메모리가 거의 필요 없습니다." + }, + { + "id": "algo-sort-005", + "question": "안정 정렬(stable sort)이란 무엇인가요?", + "answer": "값이 같은 원소들의 상대적 순서가 정렬 후에도 유지되는 정렬입니다. 병합 정렬과 삽입 정렬은 안정적이고, 퀵 정렬과 힙 정렬은 일반적으로 불안정합니다." + }, + { + "id": "algo-sort-006", + "question": "퀵 정렬과 병합 정렬의 차이는 무엇인가요?", + "answer": "퀵 정렬은 추가 메모리가 거의 없고 평균적으로 빠르지만 최악 O(n^2)이 될 수 있고, 병합 정렬은 추가 메모리가 필요하지만 항상 O(n log n)을 보장하며 안정 정렬입니다." + }, + { + "id": "algo-sort-007", + "question": "계수 정렬(counting sort)이란 무엇인가요?", + "answer": "값의 등장 횟수를 세어 정렬하는, 비교하지 않는 정렬입니다. 값의 범위가 작을 때 O(n)으로 매우 빠르지만 범위가 크면 비효율적입니다." + }, + { + "id": "algo-sort-008", + "question": "기수 정렬(radix sort)이란 무엇인가요?", + "answer": "자릿수별로 나누어 정렬을 반복하는 방식입니다. 비교를 하지 않아 특정 조건에서 빠르며 계수 정렬을 자릿수마다 적용하기도 합니다." + }, + { + "id": "algo-sort-009", + "question": "정렬 알고리즘 선택 기준은 무엇인가요?", + "answer": "데이터 크기, 메모리 제약, 안정성 필요 여부, 데이터의 정렬 상태 등을 고려합니다. 대부분 평균이 빠른 퀵 정렬이나 안정적인 병합 정렬을 씁니다." + }, + { + "id": "algo-sort-010", + "question": "거의 정렬된 데이터에 적합한 정렬은 무엇인가요?", + "answer": "삽입 정렬입니다. 이미 정렬된 부분이 많으면 비교와 이동이 적어 거의 O(n)에 가깝게 동작합니다." + }, + { + "id": "algo-sort-011", + "question": "제자리 정렬(in-place sort)이란 무엇인가요?", + "answer": "추가 메모리를 거의 쓰지 않고 입력 배열 안에서 정렬하는 방식입니다. 퀵 정렬과 힙 정렬이 대표적이며 메모리 효율이 좋습니다." + }, + { + "id": "algo-sort-012", + "question": "정렬이 알고리즘 문제에서 중요한 이유는 무엇인가요?", + "answer": "데이터를 정렬해두면 이진 탐색, 투 포인터, 그리디 등 여러 기법을 적용하기 쉬워지기 때문입니다. 많은 문제의 전처리 단계로 쓰입니다." + } + ] + }, + { + "id": "algo-search", + "name": "탐색 알고리즘", + "questions": [ + { + "id": "algo-search-001", + "question": "선형 탐색과 이진 탐색의 차이는 무엇인가요?", + "answer": "선형 탐색은 처음부터 하나씩 순서대로 찾아 O(n)이고, 이진 탐색은 정렬된 데이터에서 절반씩 범위를 좁혀가며 찾아 O(log n)입니다. 이진 탐색이 훨씬 빠르지만 정렬이 전제됩니다." + }, + { + "id": "algo-search-002", + "question": "이진 탐색의 조건과 시간 복잡도는 어떻게 되나요?", + "answer": "데이터가 반드시 정렬되어 있어야 사용할 수 있습니다. 매 단계마다 탐색 범위를 절반으로 줄이므로 시간 복잡도는 O(log n)으로 매우 효율적입니다." + }, + { + "id": "algo-search-003", + "question": "해시 탐색과 이진 탐색의 차이는 무엇인가요?", + "answer": "해시 탐색은 해시 함수로 위치를 바로 계산해 평균 O(1)이고, 이진 탐색은 정렬된 데이터를 절반씩 줄여 O(log n)입니다. 범위 검색에는 이진 탐색이, 단일 키 검색에는 해시가 유리합니다." + }, + { + "id": "algo-search-004", + "question": "이진 탐색에서 무한 루프를 피하려면 어떻게 하나요?", + "answer": "탐색 범위를 줄일 때 중간값을 포함하거나 제외하는 경계 처리를 명확히 해야 합니다. left와 right 갱신 조건을 정확히 설정하는 것이 중요합니다." + }, + { + "id": "algo-search-005", + "question": "매개 변수 탐색(parametric search)이란 무엇인가요?", + "answer": "최적화 문제를 결정 문제로 바꿔 이진 탐색으로 답을 찾는 기법입니다. 정답이 단조성을 가질 때 사용하며 범위를 좁혀갑니다." + }, + { + "id": "algo-search-006", + "question": "투 포인터(two pointer)란 무엇인가요?", + "answer": "두 개의 인덱스를 움직이며 조건을 만족하는 구간이나 쌍을 찾는 기법입니다. 정렬된 배열에서 O(n)에 문제를 푸는 데 자주 쓰입니다." + }, + { + "id": "algo-search-007", + "question": "슬라이딩 윈도우(sliding window)란 무엇인가요?", + "answer": "고정되거나 가변적인 구간을 이동시키며 부분 배열 문제를 효율적으로 푸는 기법입니다. 매번 다시 계산하지 않아 시간을 절약합니다." + }, + { + "id": "algo-search-008", + "question": "선형 탐색이 더 나은 경우는 언제인가요?", + "answer": "데이터가 정렬되어 있지 않거나, 데이터 양이 적거나, 한 번만 탐색할 때입니다. 정렬 비용이 탐색 이득보다 클 수 있습니다." + } + ] + }, + { + "id": "algo-design", + "name": "알고리즘 설계 기법", + "questions": [ + { + "id": "algo-design-001", + "question": "동적 프로그래밍(DP)이란 무엇인가요?", + "answer": "큰 문제를 작은 부분 문제로 나누고, 그 결과를 저장해 재사용함으로써 중복 계산을 피하는 기법입니다. 부분 문제가 겹치고 최적 부분 구조를 가질 때 효과적입니다." + }, + { + "id": "algo-design-002", + "question": "분할 정복(divide and conquer)이란 무엇인가요?", + "answer": "문제를 독립적인 작은 부분으로 나누어 각각 해결한 뒤 결과를 합치는 기법입니다. 병합 정렬과 퀵 정렬이 대표적이며 부분 문제들이 서로 겹치지 않는다는 점이 DP와 다릅니다." + }, + { + "id": "algo-design-003", + "question": "그리디(greedy) 알고리즘이란 무엇인가요?", + "answer": "매 단계에서 그 순간 가장 좋아 보이는 선택을 하는 기법입니다. 구현이 단순하고 빠르지만 항상 전체 최적해를 보장하지는 않으며, 최적 부분 구조와 탐욕 선택 속성이 있어야 정답이 됩니다." + }, + { + "id": "algo-design-004", + "question": "DP와 분할 정복의 차이는 무엇인가요?", + "answer": "둘 다 문제를 나누지만, 분할 정복은 부분 문제가 서로 겹치지 않고, DP는 부분 문제가 겹쳐서 결과를 저장해 재사용합니다. 겹치는 부분 문제의 존재 여부가 핵심 차이입니다." + }, + { + "id": "algo-design-005", + "question": "재귀와 반복의 차이는 무엇인가요?", + "answer": "재귀는 함수가 자기 자신을 호출해 문제를 푸는 방식으로 코드가 간결하지만 호출 스택 비용이 있고, 반복은 루프로 푸는 방식으로 메모리 효율이 좋습니다. 깊은 재귀는 스택 오버플로우를 유발할 수 있습니다." + }, + { + "id": "algo-design-006", + "question": "백트래킹(backtracking)이란 무엇인가요?", + "answer": "해를 찾아가다가 조건에 맞지 않으면 되돌아가 다른 경로를 탐색하는 기법입니다. 가능성이 없는 경로를 미리 가지치기해 모든 경우를 탐색하는 완전 탐색보다 효율적입니다." + }, + { + "id": "algo-design-007", + "question": "메모이제이션과 타뷸레이션의 차이는 무엇인가요?", + "answer": "메모이제이션은 재귀로 풀며 결과를 저장하는 하향식이고, 타뷸레이션은 작은 문제부터 표를 채우는 상향식입니다. 둘 다 중복 계산을 피합니다." + }, + { + "id": "algo-design-008", + "question": "DP로 풀 수 있는 문제의 조건은 무엇인가요?", + "answer": "큰 문제가 작은 문제로 나뉘는 최적 부분 구조와, 같은 부분 문제가 반복되는 중복 부분 문제를 가질 때입니다. 둘 다 만족해야 효과적입니다." + }, + { + "id": "algo-design-009", + "question": "그리디가 항상 최적해를 보장하지 않는 예는 무엇인가요?", + "answer": "거스름돈 문제에서 동전 단위가 일반적이지 않으면 그리디가 최소 개수를 못 찾을 수 있습니다. 이럴 땐 DP가 필요합니다." + }, + { + "id": "algo-design-010", + "question": "완전 탐색(brute force)이란 무엇인가요?", + "answer": "가능한 모든 경우를 다 확인해 답을 찾는 방법입니다. 정확하지만 느리며, 경우의 수가 적거나 다른 방법이 없을 때 사용합니다." + }, + { + "id": "algo-design-011", + "question": "분할 정복의 대표 알고리즘은 무엇인가요?", + "answer": "병합 정렬, 퀵 정렬, 이진 탐색, 거듭제곱 빠른 계산 등이 있습니다. 문제를 절반씩 나누어 푸는 구조가 공통점입니다." + }, + { + "id": "algo-design-012", + "question": "비트마스킹(bitmasking)이란 무엇인가요?", + "answer": "집합의 상태를 비트로 표현해 빠르게 처리하는 기법입니다. 부분집합 순회나 상태 기반 DP에서 메모리와 시간을 절약합니다." + } + ] + }, + { + "id": "algo-string", + "name": "문자열 알고리즘", + "questions": [ + { + "id": "algo-string-001", + "question": "문자열 매칭이란 무엇인가요?", + "answer": "한 문자열 안에서 특정 패턴이 나타나는 위치를 찾는 문제입니다. 단순 비교는 O(nm)이지만 KMP 등으로 더 빠르게 할 수 있습니다." + }, + { + "id": "algo-string-002", + "question": "KMP 알고리즘이란 무엇인가요?", + "answer": "패턴의 접두사 정보를 미리 계산해 불일치 시 불필요한 비교를 건너뛰는 문자열 매칭 알고리즘입니다. 선형 시간에 동작합니다." + }, + { + "id": "algo-string-003", + "question": "라빈-카프 알고리즘이란 무엇인가요?", + "answer": "문자열을 해시값으로 바꿔 비교해 빠르게 매칭하는 기법입니다. 해시 충돌만 주의하면 평균적으로 효율적입니다." + }, + { + "id": "algo-string-004", + "question": "회문(palindrome) 판별은 어떻게 하나요?", + "answer": "양 끝에서 안쪽으로 두 포인터를 좁히며 문자를 비교합니다. 모두 같으면 회문이며 O(n)에 확인할 수 있습니다." + }, + { + "id": "algo-string-005", + "question": "접미사 배열(suffix array)이란 무엇인가요?", + "answer": "문자열의 모든 접미사를 정렬한 배열입니다. 문자열 검색이나 가장 긴 공통 부분 문자열 같은 문제를 효율적으로 풀 때 쓰입니다." + }, + { + "id": "algo-string-006", + "question": "문자열을 다룰 때 주의할 점은 무엇인가요?", + "answer": "불변성 여부, 인코딩, 길이 계산 비용 등을 고려해야 합니다. 잦은 연결은 비효율적이라 빌더나 배열을 쓰는 것이 좋습니다." + }, + { + "id": "algo-string-007", + "question": "아나그램 판별은 어떻게 하나요?", + "answer": "두 문자열의 글자 개수가 같은지 비교하면 됩니다. 정렬해서 비교하거나 글자 빈도수를 세어 확인할 수 있습니다." + } + ] + }, + { + "id": "algo-recursion-dp", + "name": "재귀와 DP 실전", + "questions": [ + { + "id": "algo-recursion-dp-001", + "question": "피보나치를 DP로 풀면 왜 빨라지나요?", + "answer": "단순 재귀는 같은 값을 중복 계산해 지수 시간이지만, 이전 결과를 저장하면 O(n)으로 줄기 때문입니다. 중복 부분 문제를 제거한 결과입니다." + }, + { + "id": "algo-recursion-dp-002", + "question": "배낭 문제(knapsack)란 무엇인가요?", + "answer": "무게 한도 안에서 가치를 최대로 담는 문제입니다. 0/1 배낭은 DP로 풀며, 분할 가능한 버전은 그리디로 풀 수 있습니다." + }, + { + "id": "algo-recursion-dp-003", + "question": "최장 공통 부분 수열(LCS)이란 무엇인가요?", + "answer": "두 수열에 공통으로 순서대로 나타나는 가장 긴 부분 수열을 찾는 문제입니다. DP 표를 채워 O(nm)에 해결합니다." + }, + { + "id": "algo-recursion-dp-004", + "question": "최장 증가 부분 수열(LIS)이란 무엇인가요?", + "answer": "수열에서 증가하는 가장 긴 부분 수열을 찾는 문제입니다. DP로 O(n^2), 이진 탐색을 더하면 O(n log n)에 풉니다." + }, + { + "id": "algo-recursion-dp-005", + "question": "동전 교환 문제는 어떻게 푸나요?", + "answer": "금액을 만드는 최소 동전 수를 DP로 구합니다. 각 금액을 만들 수 있는 최소 개수를 작은 금액부터 채워 나갑니다." + }, + { + "id": "algo-recursion-dp-006", + "question": "재귀를 반복으로 바꾸는 이유는 무엇인가요?", + "answer": "깊은 재귀의 스택 오버플로우를 막고 함수 호출 오버헤드를 줄이기 위해서입니다. 명시적 스택을 쓰거나 반복문으로 변환합니다." + }, + { + "id": "algo-recursion-dp-007", + "question": "DP의 점화식을 세우는 요령은 무엇인가요?", + "answer": "현재 상태를 이전 상태들로 어떻게 표현할지 정의하는 것이 핵심입니다. 상태와 전이를 명확히 하고 초기 조건을 정하면 됩니다." + } + ] + }, + { + "id": "algo-misc", + "name": "자료구조 심화와 기타", + "questions": [ + { + "id": "algo-misc-001", + "question": "우선순위 큐와 힙의 관계는 무엇인가요?", + "answer": "우선순위 큐는 추상 자료형이고, 힙은 그것을 효율적으로 구현하는 대표적 자료구조입니다. 삽입과 최댓값 추출을 O(log n)에 처리합니다." + }, + { + "id": "algo-misc-002", + "question": "유니온 파인드(disjoint set)란 무엇인가요?", + "answer": "원소들을 집합으로 묶고 같은 집합인지 빠르게 확인하는 자료구조입니다. 그래프의 사이클 판별이나 크루스칼 알고리즘에 쓰입니다." + }, + { + "id": "algo-misc-003", + "question": "그래프와 트리의 차이는 무엇인가요?", + "answer": "트리는 사이클이 없고 노드가 N개면 간선이 N-1개인 연결 그래프입니다. 그래프는 사이클과 다양한 연결을 허용하는 더 일반적인 구조입니다." + }, + { + "id": "algo-misc-004", + "question": "배열과 해시의 시간 복잡도를 비교하면 어떤가요?", + "answer": "배열은 인덱스 접근이 O(1)이지만 값 검색은 O(n)이고, 해시는 키 기반 검색이 평균 O(1)입니다. 접근 방식에 따라 선택합니다." + }, + { + "id": "algo-misc-005", + "question": "캐시 친화적 자료구조란 무엇인가요?", + "answer": "데이터가 메모리에 연속해 지역성을 잘 활용하는 자료구조입니다. 배열이 대표적이며 포인터를 많이 쓰는 구조보다 실제 성능이 좋을 수 있습니다." + }, + { + "id": "algo-misc-006", + "question": "자료구조를 선택하는 기준은 무엇인가요?", + "answer": "주로 어떤 연산이 많은지, 데이터 크기, 메모리 제약, 순서 필요 여부 등을 고려합니다. 검색이 많으면 해시, 정렬이 필요하면 트리가 유리합니다." + }, + { + "id": "algo-misc-007", + "question": "추상 자료형(ADT)이란 무엇인가요?", + "answer": "데이터와 그에 대한 연산을 구현과 분리해 정의한 개념입니다. 스택, 큐, 리스트처럼 무엇을 하는지만 정의하고 구현은 자유롭게 합니다." + } + ] + }, + { + "id": "algo-greedy-backtrack", + "name": "그리디와 백트래킹", + "questions": [ + { + "id": "algo-greedy-backtrack-001", + "question": "그리디 알고리즘이란 무엇인가요?", + "answer": "매 순간 가장 좋아 보이는 선택을 하는 방식입니다. 빠르지만 항상 최적해를 보장하지는 않아 적용 조건을 확인해야 합니다." + }, + { + "id": "algo-greedy-backtrack-002", + "question": "그리디가 최적해를 보장하는 조건은 무엇인가요?", + "answer": "부분 문제의 최적 선택이 전체 최적으로 이어지는 탐욕 선택 속성과 최적 부분 구조를 만족할 때입니다. 이 경우 빠르고 정확합니다." + }, + { + "id": "algo-greedy-backtrack-003", + "question": "백트래킹(backtracking)이란 무엇인가요?", + "answer": "해를 찾아가다 가능성이 없으면 이전 단계로 되돌아가 다른 경로를 시도하는 기법입니다. 가지치기로 탐색량을 줄입니다." + }, + { + "id": "algo-greedy-backtrack-004", + "question": "가지치기(pruning)란 무엇인가요?", + "answer": "탐색 중 답이 될 수 없는 경우를 미리 배제해 불필요한 탐색을 줄이는 것입니다. 백트래킹의 효율을 크게 높입니다." + }, + { + "id": "algo-greedy-backtrack-005", + "question": "N-퀸 문제는 어떻게 푸나요?", + "answer": "퀸을 한 줄씩 놓으며 서로 공격하지 못하는 위치를 백트래킹으로 탐색합니다. 충돌이 생기면 되돌아가 다른 자리를 시도합니다." + }, + { + "id": "algo-greedy-backtrack-006", + "question": "활동 선택 문제란 무엇인가요?", + "answer": "시간이 겹치지 않게 최대한 많은 활동을 고르는 문제입니다. 끝나는 시간이 빠른 것부터 그리디로 선택하면 최적해를 얻습니다." + }, + { + "id": "algo-greedy-backtrack-007", + "question": "동적 프로그래밍과 그리디의 차이는 무엇인가요?", + "answer": "DP는 모든 부분 문제를 검토해 최적을 보장하고, 그리디는 매 순간 최선만 골라 빠르지만 보장이 없습니다. 문제 특성에 따라 선택합니다." + }, + { + "id": "algo-greedy-backtrack-008", + "question": "완전 탐색과 백트래킹의 차이는 무엇인가요?", + "answer": "완전 탐색은 모든 경우를 다 보고, 백트래킹은 가능성 없는 경로를 중간에 잘라냅니다. 백트래킹이 같은 문제를 더 효율적으로 풉니다." + } + ] + }, + { + "id": "algo-number-theory", + "name": "수학과 정수론 알고리즘", + "questions": [ + { + "id": "algo-number-theory-001", + "question": "최대공약수는 어떻게 구하나요?", + "answer": "유클리드 호제법으로 구합니다. 두 수를 나눈 나머지로 반복해 나머지가 0이 될 때의 수가 최대공약수입니다." + }, + { + "id": "algo-number-theory-002", + "question": "에라토스테네스의 체란 무엇인가요?", + "answer": "일정 범위의 소수를 빠르게 찾는 방법입니다. 작은 수의 배수를 차례로 지워 남은 수가 소수가 됩니다." + }, + { + "id": "algo-number-theory-003", + "question": "소수 판별은 어떻게 하나요?", + "answer": "2부터 그 수의 제곱근까지 나누어떨어지는지 확인합니다. 제곱근까지만 봐도 충분해 효율적입니다." + }, + { + "id": "algo-number-theory-004", + "question": "모듈러 연산(modular arithmetic)이란 무엇인가요?", + "answer": "어떤 수로 나눈 나머지로 계산하는 연산입니다. 큰 수를 다룰 때 오버플로우를 막고 암호와 해시에 널리 쓰입니다." + }, + { + "id": "algo-number-theory-005", + "question": "빠른 거듭제곱(분할 정복)이란 무엇인가요?", + "answer": "지수를 절반씩 나누어 곱셈 횟수를 줄이는 기법입니다. 거듭제곱을 O(log n)에 계산할 수 있습니다." + }, + { + "id": "algo-number-theory-006", + "question": "순열과 조합의 차이는 무엇인가요?", + "answer": "순열은 순서를 고려한 나열이고, 조합은 순서를 무시한 선택입니다. 경우의 수 계산에서 구분해 사용합니다." + }, + { + "id": "algo-number-theory-007", + "question": "진법 변환 알고리즘은 어떻게 동작하나요?", + "answer": "나눗셈의 나머지를 모아 역순으로 읽어 다른 진법으로 바꿉니다. 반대로는 자릿값을 곱해 더해 10진수로 만듭니다." + }, + { + "id": "algo-number-theory-008", + "question": "정수론 알고리즘이 코딩 테스트에 자주 나오는 이유는 무엇인가요?", + "answer": "수학적 원리로 큰 문제를 효율적으로 줄일 수 있어 사고력과 최적화 능력을 평가하기 좋기 때문입니다. 소수, 최대공약수 등이 단골로 출제됩니다." + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/frontend/public/data/frontend-interview-questions.json b/frontend/public/data/frontend-interview-questions.json new file mode 100644 index 00000000..d5afa9ff --- /dev/null +++ b/frontend/public/data/frontend-interview-questions.json @@ -0,0 +1,3265 @@ +{ + "version": "1.0", + "title": "프론트엔드 면접 대비 질문 모음", + "description": "프론트엔드 개발자 기술 면접에 자주 나오는 핵심 질문과 답변 모음입니다. HTML/CSS/JavaScript/TypeScript/React부터 브라우저 동작 원리, 네트워크, 성능 최적화, 보안, 접근성, 개발 도구까지 분야별로 정리했습니다.", + "subjects": [ + { + "id": "html", + "name": "HTML", + "categories": [ + { + "id": "html-semantic", + "name": "시맨틱 마크업", + "questions": [ + { + "id": "html-semantic-001", + "question": "시맨틱 마크업(Semantic Markup)이란 무엇인가요?", + "answer": "태그 자체가 의미를 가지도록 작성하는 마크업 방식입니다. div, span처럼 의미가 없는 태그 대신 header, nav, main, article 등 내용의 역할을 나타내는 태그를 사용합니다. 코드 가독성, 유지보수성, 검색엔진 최적화(SEO), 웹 접근성 측면에서 이점이 있습니다." + }, + { + "id": "html-semantic-002", + "question": "div와 시맨틱 태그의 차이는 무엇인가요?", + "answer": "div는 아무런 의미가 없는 범용 블록 컨테이너로 스타일링이나 구조 분리 용도로만 쓰입니다. 반면 시맨틱 태그(header, footer, article 등)는 콘텐츠의 의미와 역할을 브라우저, 검색엔진, 스크린리더에 전달합니다. 기능은 같아 보여도 기계가 해석할 수 있는 정보량이 다릅니다." + }, + { + "id": "html-semantic-003", + "question": "header, footer, main, nav 태그의 용도를 설명해 주세요.", + "answer": "header는 페이지나 섹션의 머리말(로고, 제목, 네비게이션)을, footer는 바닥글(저작권, 연락처, 링크)을 나타냅니다. main은 문서의 핵심 콘텐츠로 페이지당 하나만 존재해야 하며, nav는 주요 네비게이션 링크 그룹을 의미합니다." + }, + { + "id": "html-semantic-004", + "question": "section과 article의 차이는 무엇인가요?", + "answer": "article은 그 자체로 독립적으로 배포/재사용 가능한 완결된 콘텐츠(블로그 글, 뉴스 기사, 댓글)에 사용합니다. section은 주제별로 콘텐츠를 묶는 일반적인 구획으로, 보통 제목(heading)을 동반합니다. '떼어내도 말이 되는가'가 article 여부를 판단하는 기준입니다." + }, + { + "id": "html-semantic-005", + "question": "aside 태그는 언제 사용하나요?", + "answer": "본문과 간접적으로만 관련된 부가 콘텐츠를 나타낼 때 사용합니다. 사이드바, 광고, 관련 링크 모음, 용어 설명 박스 등이 해당합니다. 제거해도 본문 이해에 큰 지장이 없는 보조적 정보에 적합합니다." + }, + { + "id": "html-semantic-006", + "question": "figure와 figcaption은 무엇인가요?", + "answer": "figure는 이미지, 다이어그램, 코드 조각 등 본문에서 참조되는 독립적인 콘텐츠를 감싸는 태그이고, figcaption은 그에 대한 설명(캡션)입니다. 본문 흐름에서 분리해도 의미가 유지되는 그림이나 예시를 의미적으로 묶을 때 사용합니다." + }, + { + "id": "html-semantic-007", + "question": "h1부터 h6 제목 태그 사용 시 주의할 점은?", + "answer": "제목 레벨은 시각적 크기가 아니라 문서의 논리적 계층을 나타내므로 건너뛰지 않고 순서대로 사용해야 합니다. 크기 조절은 CSS로 하고, 페이지의 주제를 나타내는 h1은 보통 하나만 두는 것이 접근성과 SEO에 좋습니다." + }, + { + "id": "html-semantic-008", + "question": "시맨틱 마크업의 장점은 무엇인가요?", + "answer": "검색엔진이 콘텐츠 구조를 잘 파악해 SEO에 유리하고, 스크린리더 사용자가 페이지를 효율적으로 탐색할 수 있어 접근성이 향상됩니다. 또한 코드만 봐도 구조가 명확해 개발자 간 협업과 유지보수가 쉬워집니다." + }, + { + "id": "html-semantic-009", + "question": "time 태그는 어떤 역할을 하나요?", + "answer": "날짜나 시간을 기계가 읽을 수 있는 형식으로 표현하는 태그입니다. datetime 속성에 ISO 8601 형식 값을 넣으면 사람이 보는 표시와 별개로 검색엔진과 캘린더 앱이 정확한 시각을 인식할 수 있습니다." + }, + { + "id": "html-semantic-010", + "question": "address 태그는 어디에 사용하나요?", + "answer": "가장 가까운 article 또는 body의 작성자나 소유자에 대한 연락처 정보를 나타낼 때 사용합니다. 이메일, 주소, 전화번호 등이 들어가며, 일반적인 우편 주소 표기 용도로 쓰는 태그는 아닙니다." + } + ] + }, + { + "id": "html-form", + "name": "폼과 입력", + "questions": [ + { + "id": "html-form-001", + "question": "label과 input을 연결하는 방법과 이유는?", + "answer": "label의 for 속성과 input의 id를 같은 값으로 맞추거나, label로 input을 감싸서 연결합니다. 연결하면 라벨 클릭 시 입력 요소가 포커스되고, 스크린리더가 입력 필드의 용도를 읽어줘 접근성이 좋아집니다." + }, + { + "id": "html-form-002", + "question": "input의 type 속성에는 어떤 종류가 있나요?", + "answer": "text, password, email, number, tel, url, date, time, checkbox, radio, file, range, color, search 등이 있습니다. 타입에 따라 모바일 키보드 형태, 기본 검증, 전용 UI(날짜 선택기 등)가 자동으로 제공됩니다." + }, + { + "id": "html-form-003", + "question": "form의 GET과 POST 방식의 차이는?", + "answer": "GET은 데이터를 URL 쿼리스트링에 담아 전송하므로 길이 제한이 있고 노출되며 캐싱/북마크가 가능해 조회에 적합합니다. POST는 데이터를 본문(body)에 담아 보내 길이 제한이 사실상 없고 노출이 적어 생성/수정 등 상태를 바꾸는 요청에 적합합니다." + }, + { + "id": "html-form-004", + "question": "HTML 기본 폼 검증 속성에는 무엇이 있나요?", + "answer": "required(필수 입력), pattern(정규식 검증), min/max(범위), minlength/maxlength(길이), type=email/url(형식) 등이 있습니다. 자바스크립트 없이도 기본적인 클라이언트 검증을 제공하지만, 서버 검증은 별도로 반드시 필요합니다." + }, + { + "id": "html-form-005", + "question": "placeholder를 label 대용으로 쓰면 안 되는 이유는?", + "answer": "placeholder는 입력을 시작하면 사라져 사용자가 어떤 필드인지 잊을 수 있고, 스크린리더가 라벨로 안정적으로 인식하지 못하며, 대비가 낮아 가독성과 접근성이 떨어집니다. 힌트는 placeholder로, 필드명은 항상 label로 제공해야 합니다." + }, + { + "id": "html-form-006", + "question": "fieldset과 legend는 어떤 용도인가요?", + "answer": "fieldset은 연관된 폼 요소들을 그룹으로 묶고, legend는 그 그룹의 제목을 나타냅니다. 라디오 버튼 묶음처럼 함께 이해해야 하는 입력들을 의미적으로 그룹화해 접근성을 높일 때 사용합니다." + }, + { + "id": "html-form-007", + "question": "button 태그의 type 속성 종류와 차이는?", + "answer": "submit(폼 제출, 기본값), reset(폼 초기화), button(기본 동작 없음)이 있습니다. 폼 안에서 type을 지정하지 않으면 submit으로 동작해 의도치 않은 제출이 일어날 수 있으므로 일반 버튼은 type=button을 명시하는 것이 안전합니다." + }, + { + "id": "html-form-008", + "question": "input의 name 속성은 왜 중요한가요?", + "answer": "폼 전송 시 서버로 보내지는 키(key) 역할을 하기 때문입니다. name이 없는 입력값은 전송되지 않으며, 라디오 버튼은 같은 name으로 묶어야 하나만 선택되는 그룹으로 동작합니다." + }, + { + "id": "html-form-009", + "question": "autocomplete 속성은 어떤 역할을 하나요?", + "answer": "브라우저가 이전 입력값이나 저장된 개인정보를 자동완성할지 제어하는 속성입니다. name, email 등 표준 토큰을 지정하면 자동완성 정확도가 올라가고, 비밀번호 같은 민감한 필드는 off나 new-password로 제어합니다." + }, + { + "id": "html-form-010", + "question": "disabled와 readonly의 차이는?", + "answer": "disabled는 입력을 비활성화하며 폼 전송 시 값이 서버로 전송되지 않고 포커스도 불가능합니다. readonly는 수정만 막을 뿐 값은 전송되고 포커스/복사도 가능합니다. '값을 보내야 하는가'가 둘을 가르는 핵심 차이입니다." + } + ] + }, + { + "id": "html-meta", + "name": "메타데이터와 SEO", + "questions": [ + { + "id": "html-meta-001", + "question": "meta viewport 태그는 왜 필요한가요?", + "answer": "모바일 브라우저가 페이지의 뷰포트 크기와 배율을 어떻게 설정할지 알려주는 태그입니다. width=device-width, initial-scale=1로 설정하면 기기 너비에 맞춰 렌더링되어 반응형 디자인이 의도대로 동작합니다. 없으면 모바일에서 데스크톱 화면을 축소해 보여줍니다." + }, + { + "id": "html-meta-002", + "question": "meta charset의 역할은 무엇인가요?", + "answer": "문서의 문자 인코딩을 지정하는 태그로, 보통 UTF-8을 사용합니다. 브라우저가 바이트를 어떤 문자로 해석할지 알려주며, 지정하지 않거나 잘못되면 한글 등이 깨져 보입니다. 인코딩이 빨리 결정되도록 head 최상단에 두는 것이 권장됩니다." + }, + { + "id": "html-meta-003", + "question": "Open Graph 태그란 무엇인가요?", + "answer": "페이스북, 카카오톡 등에서 링크를 공유할 때 표시되는 제목, 설명, 이미지를 제어하는 메타데이터입니다. og:title, og:description, og:image 등을 지정하면 공유 시 미리보기 카드가 의도한 대로 노출됩니다." + }, + { + "id": "html-meta-004", + "question": "title 태그가 SEO에서 중요한 이유는?", + "answer": "검색 결과 페이지에 파란 제목으로 표시되고 검색엔진이 페이지 주제를 판단하는 핵심 신호이기 때문입니다. 페이지마다 고유하고 핵심 키워드를 포함한 간결한 제목을 작성하는 것이 클릭률과 순위에 영향을 줍니다." + }, + { + "id": "html-meta-005", + "question": "meta description은 어떤 역할을 하나요?", + "answer": "검색 결과에서 제목 아래 표시되는 페이지 요약문입니다. 순위에 직접적인 영향은 작지만, 사용자가 클릭할지 결정하는 데 영향을 주므로 클릭률(CTR) 관점에서 중요합니다. 페이지 내용을 잘 요약해 작성합니다." + }, + { + "id": "html-meta-006", + "question": "canonical 링크는 왜 사용하나요?", + "answer": "동일하거나 유사한 콘텐츠가 여러 URL로 접근될 때 검색엔진에 대표 URL을 알려주는 태그입니다. 중복 콘텐츠로 인한 SEO 평가 분산을 막고, 검색 색인이 원하는 URL로 모이도록 합니다." + }, + { + "id": "html-meta-007", + "question": "robots 메타 태그의 역할은?", + "answer": "검색엔진 크롤러에게 해당 페이지의 색인(index)과 링크 추적(follow) 여부를 지시하는 태그입니다. noindex는 검색 결과에 노출하지 않도록, nofollow는 페이지의 링크를 따라가지 않도록 지시합니다." + }, + { + "id": "html-meta-008", + "question": "구조화 데이터(JSON-LD)는 무엇이고 왜 쓰나요?", + "answer": "Schema.org 어휘로 페이지 내용을 기계가 이해하도록 기술하는 데이터입니다. 보통 script 태그 안에 JSON-LD 형식으로 넣으며, 검색 결과에 별점, 가격, FAQ 같은 리치 스니펫이 노출되도록 도와 클릭률을 높입니다." + }, + { + "id": "html-meta-009", + "question": "alt 속성과 SEO/접근성의 관계는?", + "answer": "alt는 이미지를 설명하는 대체 텍스트로, 스크린리더가 읽어주고 이미지 로딩 실패 시 표시됩니다. 검색엔진은 alt로 이미지 내용을 파악하므로 이미지 검색 노출에 도움이 됩니다. 장식용 이미지는 alt를 빈 값으로 두어 무시되게 합니다." + }, + { + "id": "html-meta-010", + "question": "시맨틱 마크업이 SEO에 어떻게 기여하나요?", + "answer": "검색엔진 크롤러가 header, main, article 등으로 페이지의 구조와 핵심 콘텐츠 영역을 정확히 파악할 수 있게 해줍니다. 콘텐츠의 맥락과 중요도를 더 잘 전달하므로 색인 품질과 검색 노출에 긍정적으로 작용합니다." + } + ] + }, + { + "id": "html-media", + "name": "멀티미디어와 그래픽", + "questions": [ + { + "id": "html-media-001", + "question": "picture 태그는 언제 사용하나요?", + "answer": "화면 크기, 해상도, 포맷 지원 여부에 따라 서로 다른 이미지를 제공하는 아트 디렉션이 필요할 때 사용합니다. 내부의 여러 source 중 조건에 맞는 첫 번째 이미지가 선택되고, 매칭이 없으면 img가 폴백으로 표시됩니다." + }, + { + "id": "html-media-002", + "question": "srcset과 sizes 속성은 무엇인가요?", + "answer": "srcset은 같은 이미지의 여러 해상도 버전을 나열하고, sizes는 뷰포트 조건별로 이미지가 차지할 너비를 알려줍니다. 브라우저가 기기 화면과 픽셀 밀도에 맞는 최적 이미지를 선택해 다운로드하므로 데이터와 성능을 절약합니다." + }, + { + "id": "html-media-003", + "question": "Canvas와 SVG의 차이는 무엇인가요?", + "answer": "Canvas는 픽셀 기반(래스터)으로 자바스크립트로 직접 그리며, 게임이나 복잡한 실시간 렌더링에 강하지만 확대 시 깨지고 개별 요소 제어가 어렵습니다. SVG는 벡터 기반으로 DOM 요소이므로 확대해도 선명하고 CSS/이벤트로 제어가 쉽지만 요소가 많아지면 성능이 떨어집니다." + }, + { + "id": "html-media-004", + "question": "이미지 lazy loading은 어떻게 적용하나요?", + "answer": "img나 iframe에 loading=\"lazy\" 속성을 추가하면 됩니다. 뷰포트에 가까워질 때 비로소 리소스를 로드해 초기 페이지 로딩 속도와 데이터 사용량을 줄여줍니다. 화면 상단의 중요한 이미지에는 eager나 기본값을 사용하는 것이 좋습니다." + }, + { + "id": "html-media-005", + "question": "WebP, AVIF 같은 최신 이미지 포맷의 장점은?", + "answer": "기존 JPEG/PNG보다 같은 화질에서 파일 크기가 작아 로딩 성능과 데이터 절감에 유리합니다. 투명도와 애니메이션도 지원합니다. 다만 구형 브라우저 호환을 위해 picture 태그로 폴백 이미지를 함께 제공하는 것이 안전합니다." + }, + { + "id": "html-media-006", + "question": "video와 audio 태그의 주요 속성은?", + "answer": "controls(재생 UI 표시), autoplay(자동 재생), loop(반복), muted(음소거), preload(사전 로드 정도), poster(영상 썸네일) 등이 있습니다. 모바일 자동재생은 보통 muted가 함께 있어야 허용됩니다." + }, + { + "id": "html-media-007", + "question": "iframe의 보안 관련 속성에는 무엇이 있나요?", + "answer": "sandbox는 iframe 내부 콘텐츠의 권한(스크립트 실행, 폼 제출 등)을 제한하고, allow는 카메라/마이크 같은 기능 권한을 제어합니다. 외부 콘텐츠를 임베드할 때 sandbox로 권한을 최소화하면 보안 위험을 줄일 수 있습니다." + }, + { + "id": "html-media-008", + "question": "반응형 이미지에서 width/height 속성을 지정하는 이유는?", + "answer": "브라우저가 이미지의 가로세로 비율을 미리 알 수 있어 로딩 전에 공간을 확보하기 때문입니다. 이미지가 늦게 로드되며 레이아웃이 밀리는 누적 레이아웃 이동(CLS)을 방지해 사용자 경험과 Core Web Vitals 점수를 개선합니다." + }, + { + "id": "html-media-009", + "question": "data 속성(data-*)은 무엇인가요?", + "answer": "표준 속성으로 표현할 수 없는 커스텀 데이터를 HTML 요소에 저장하는 속성입니다. data-id처럼 자유롭게 이름 짓고, 자바스크립트에서 dataset으로 접근합니다. 마크업과 스크립트 사이에 부가 정보를 주고받을 때 유용합니다." + }, + { + "id": "html-media-010", + "question": "프리로드(preload)와 프리페치(prefetch)의 차이는?", + "answer": "preload는 현재 페이지에서 곧 필요한 핵심 리소스를 우선순위 높게 미리 받아두는 것이고, prefetch는 사용자가 다음에 방문할 가능성이 있는 리소스를 한가할 때 낮은 우선순위로 받아두는 것입니다. 둘 다 link 태그의 rel 속성으로 지정합니다." + } + ] + } + ] + }, + { + "id": "css", + "name": "CSS", + "categories": [ + { + "id": "css-box", + "name": "박스 모델과 레이아웃", + "questions": [ + { + "id": "css-box-001", + "question": "CSS 박스 모델(Box Model)을 설명해 주세요.", + "answer": "모든 요소를 content, padding, border, margin 네 영역의 사각형으로 보는 모델입니다. 안쪽부터 콘텐츠, 안쪽 여백(padding), 테두리(border), 바깥 여백(margin) 순으로 감싸지며, 이 영역들의 합이 요소가 차지하는 전체 공간을 결정합니다." + }, + { + "id": "css-box-002", + "question": "box-sizing의 content-box와 border-box 차이는?", + "answer": "content-box(기본값)는 width가 콘텐츠 영역만 의미해 padding과 border가 더해지면 실제 크기가 커집니다. border-box는 width에 padding과 border까지 포함되어 지정한 너비가 곧 최종 너비가 됩니다. 레이아웃 계산이 직관적이라 border-box를 많이 사용합니다." + }, + { + "id": "css-box-003", + "question": "margin collapsing(마진 병합)이란 무엇인가요?", + "answer": "수직 방향으로 인접한 블록 요소들의 margin이 서로 합쳐지지 않고 더 큰 값 하나로 합쳐지는 현상입니다. 예를 들어 위 요소 margin-bottom 20px, 아래 요소 margin-top 30px이면 간격은 50px이 아닌 30px이 됩니다. flex/grid 컨테이너 안이나 padding/border가 있으면 발생하지 않습니다." + }, + { + "id": "css-box-004", + "question": "display의 block, inline, inline-block 차이는?", + "answer": "block은 한 줄을 차지하고 width/height 지정이 가능합니다. inline은 콘텐츠만큼만 차지하고 width/height와 수직 margin이 적용되지 않습니다. inline-block은 inline처럼 한 줄에 배치되면서도 block처럼 크기 지정이 가능합니다." + }, + { + "id": "css-box-005", + "question": "position 속성의 값들을 설명해 주세요.", + "answer": "static(기본, 일반 흐름), relative(자기 원래 위치 기준 이동), absolute(가장 가까운 위치 지정 조상 기준, 흐름에서 제거), fixed(뷰포트 기준 고정), sticky(스크롤 임계점까지는 relative, 이후 fixed처럼 고정)가 있습니다." + }, + { + "id": "css-box-006", + "question": "position: absolute는 무엇을 기준으로 배치되나요?", + "answer": "가장 가까운 position이 static이 아닌 조상 요소를 기준으로 배치됩니다. 그런 조상이 없으면 초기 컨테이닝 블록(보통 뷰포트/문서)을 기준으로 합니다. 그래서 부모에 position: relative를 주어 기준점을 만드는 패턴을 자주 사용합니다." + }, + { + "id": "css-box-007", + "question": "z-index가 동작하지 않는 경우는 언제인가요?", + "answer": "position이 static인 요소에는 z-index가 적용되지 않습니다. 또한 z-index는 같은 쌓임 맥락(stacking context) 안에서만 비교되므로, 부모가 별도의 쌓임 맥락을 형성하면 자식의 큰 z-index도 다른 맥락의 요소를 넘어설 수 없습니다." + }, + { + "id": "css-box-008", + "question": "쌓임 맥락(stacking context)은 무엇인가요?", + "answer": "요소들이 z축으로 쌓이는 독립적인 계층 공간입니다. position과 z-index, opacity 1 미만, transform, filter 등이 적용되면 새 쌓임 맥락이 생깁니다. 한 맥락 내부의 z-index 비교는 외부 요소와 직접 경쟁하지 않습니다." + }, + { + "id": "css-box-009", + "question": "overflow 속성의 값과 용도는?", + "answer": "visible(기본, 넘침 그대로 표시), hidden(넘친 부분 잘림), scroll(항상 스크롤바), auto(필요할 때만 스크롤바)가 있습니다. 또한 overflow를 visible이 아닌 값으로 주면 내부 float을 포함하는 BFC가 생성되는 부수 효과도 있습니다." + }, + { + "id": "css-box-010", + "question": "BFC(Block Formatting Context)란 무엇인가요?", + "answer": "블록 박스들이 배치되는 독립된 렌더링 영역입니다. overflow: hidden, display: flow-root, float, position absolute 등으로 생성되며, 내부 float을 포함시켜 높이 붕괴를 막거나 margin 병합을 차단하는 데 활용됩니다." + } + ] + }, + { + "id": "css-layout", + "name": "Flexbox와 Grid", + "questions": [ + { + "id": "css-layout-001", + "question": "Flexbox와 Grid의 차이와 사용 시점은?", + "answer": "Flexbox는 한 방향(행 또는 열)의 1차원 레이아웃에, Grid는 행과 열을 동시에 다루는 2차원 레이아웃에 적합합니다. 메뉴, 버튼 정렬처럼 한 줄 배치는 Flex, 전체 페이지 구조나 카드 격자처럼 행렬 배치는 Grid가 편리합니다." + }, + { + "id": "css-layout-002", + "question": "justify-content와 align-items의 차이는?", + "answer": "Flexbox에서 justify-content는 주축(main axis) 방향 정렬을, align-items는 교차축(cross axis) 방향 정렬을 담당합니다. flex-direction이 row면 주축은 가로, 교차축은 세로가 되므로 방향에 따라 두 속성의 작동 축이 바뀝니다." + }, + { + "id": "css-layout-003", + "question": "flex-grow, flex-shrink, flex-basis는 각각 무엇인가요?", + "answer": "flex-basis는 아이템의 기본 크기, flex-grow는 남는 공간을 나눠 가지는 비율, flex-shrink는 공간이 부족할 때 줄어드는 비율입니다. 보통 flex 단축 속성으로 'flex: 1 1 0' 처럼 한 번에 지정합니다." + }, + { + "id": "css-layout-004", + "question": "flex 컨테이너에서 가운데 정렬은 어떻게 하나요?", + "answer": "display: flex 후 justify-content: center와 align-items: center를 함께 지정하면 자식이 가로세로 중앙에 옵니다. 두 줄로 완벽한 중앙 정렬이 가능해 과거의 복잡한 정렬 기법을 대체하는 가장 흔한 패턴입니다." + }, + { + "id": "css-layout-005", + "question": "Grid의 fr 단위는 무엇인가요?", + "answer": "그리드 컨테이너의 남은 공간을 비율로 나누는 유연한 단위입니다. grid-template-columns: 1fr 2fr이면 남은 공간을 1:2로 나눠 두 번째 열이 두 배 넓어집니다. 고정 픽셀과 달리 컨테이너 크기에 따라 자동으로 비례 조정됩니다." + }, + { + "id": "css-layout-006", + "question": "Grid의 repeat과 minmax는 어떻게 활용하나요?", + "answer": "repeat은 반복되는 트랙 정의를 줄여주고, minmax는 트랙의 최소/최대 크기를 지정합니다. 'repeat(auto-fill, minmax(200px, 1fr))' 패턴은 화면 너비에 따라 200px 이상을 유지하며 열 개수가 자동으로 늘고 줄어드는 반응형 카드 그리드를 만듭니다." + }, + { + "id": "css-layout-007", + "question": "gap 속성은 무엇이고 어디에 쓰나요?", + "answer": "Flex/Grid 아이템 사이의 간격을 지정하는 속성입니다. margin으로 간격을 줄 때 생기는 양 끝 여백 문제 없이 아이템 사이에만 일정한 간격을 만들 수 있어 간격 관리가 훨씬 간결해집니다." + }, + { + "id": "css-layout-008", + "question": "Grid에서 영역 이름으로 배치하는 방법은?", + "answer": "grid-template-areas로 영역에 이름을 부여하고, 각 아이템에 grid-area로 해당 이름을 지정합니다. 헤더, 사이드바, 본문, 푸터 같은 레이아웃을 시각적으로 직관적인 코드로 구성할 수 있고, 반응형에서 영역 재배치도 쉽습니다." + }, + { + "id": "css-layout-009", + "question": "flex-wrap은 어떤 역할을 하나요?", + "answer": "Flex 아이템이 한 줄에 다 들어가지 않을 때 다음 줄로 넘길지를 제어합니다. 기본값 nowrap은 한 줄에 욱여넣어 아이템을 축소시키고, wrap은 공간이 부족하면 여러 줄로 자연스럽게 줄바꿈합니다." + }, + { + "id": "css-layout-010", + "question": "align-items와 align-content의 차이는?", + "answer": "align-items는 각 줄 내부에서 아이템들의 교차축 정렬을 다루고, align-content는 여러 줄이 있을 때 줄들 전체를 교차축 방향으로 정렬합니다. align-content는 wrap으로 줄이 여러 개일 때만 의미가 있습니다." + } + ] + }, + { + "id": "css-selector", + "name": "선택자와 우선순위", + "questions": [ + { + "id": "css-selector-001", + "question": "CSS 명시도(Specificity)는 어떻게 계산되나요?", + "answer": "선택자를 인라인 스타일, id, class/속성/가상클래스, 태그/가상요소의 가중치로 비교합니다. 보통 (인라인, id 개수, class 개수, 태그 개수) 순서로 큰 쪽이 우선합니다. 같은 명시도라면 나중에 선언된 규칙이 적용됩니다." + }, + { + "id": "css-selector-002", + "question": "!important는 무엇이고 왜 신중히 써야 하나요?", + "answer": "명시도를 무시하고 해당 선언을 강제로 적용하는 키워드입니다. 우선순위 체계를 깨뜨려 이후 스타일을 또 다른 !important로만 덮을 수 있게 만들어 유지보수를 어렵게 합니다. 꼭 필요한 예외 상황에만 제한적으로 사용해야 합니다." + }, + { + "id": "css-selector-003", + "question": "자손 선택자와 자식 선택자의 차이는?", + "answer": "자손 선택자(공백, A B)는 A 안의 모든 깊이의 B를 선택하고, 자식 선택자(A > B)는 A의 바로 아래 단계 B만 선택합니다. 자식 선택자가 더 좁고 명확하게 범위를 한정합니다." + }, + { + "id": "css-selector-004", + "question": "가상 클래스와 가상 요소의 차이는?", + "answer": "가상 클래스(:hover, :focus, :nth-child)는 요소의 특정 상태나 위치를 선택하고, 가상 요소(::before, ::after, ::first-line)는 실제로 존재하지 않는 가상의 부분을 만들거나 선택합니다. 표기상 콜론 개수(: vs ::)로 구분합니다." + }, + { + "id": "css-selector-005", + "question": ":nth-child와 :nth-of-type의 차이는?", + "answer": ":nth-child(n)은 부모의 전체 자식 중 n번째가 해당 요소인지 따지고, :nth-of-type(n)은 같은 태그 종류 중에서 n번째를 선택합니다. 형제 중 태그가 섞여 있을 때 의도와 다르게 동작할 수 있어 주의해야 합니다." + }, + { + "id": "css-selector-006", + "question": "::before와 ::after는 어떻게 활용하나요?", + "answer": "요소의 콘텐츠 앞뒤에 가상 콘텐츠를 삽입하는 가상 요소입니다. content 속성이 필수이며, 아이콘, 장식, 말풍선 꼬리, 클리어픽스 등 마크업을 늘리지 않고 시각적 요소를 추가할 때 사용합니다." + }, + { + "id": "css-selector-007", + "question": "인접 형제 선택자(+)와 일반 형제 선택자(~)의 차이는?", + "answer": "A + B는 A 바로 다음에 오는 형제 B 하나만, A ~ B는 A 이후의 모든 형제 B를 선택합니다. 둘 다 같은 부모 아래 형제 관계에서만 동작하며 이전 형제는 선택할 수 없습니다." + }, + { + "id": "css-selector-008", + "question": "속성 선택자에는 어떤 형태가 있나요?", + "answer": "[attr](속성 존재), [attr=value](정확히 일치), [attr^=value](시작), [attr$=value](끝), [attr*=value](포함) 등이 있습니다. 특정 확장자 링크나 data 속성 값에 따라 스타일을 다르게 적용할 때 유용합니다." + }, + { + "id": "css-selector-009", + "question": ":root 선택자는 무엇이고 왜 쓰나요?", + "answer": "문서의 최상위 요소(HTML에서는 html)를 선택하는 가상 클래스로 html보다 명시도가 높습니다. 주로 전역 CSS 변수(커스텀 프로퍼티)를 선언하는 위치로 사용해 색상, 간격 등 디자인 토큰을 한곳에서 관리합니다." + }, + { + "id": "css-selector-010", + "question": "CSS 우선순위 적용 순서를 전체적으로 설명해 주세요.", + "answer": "먼저 출처와 !important 여부(사용자 에이전트 < 일반 < !important)를 따지고, 다음으로 명시도를 비교하며, 명시도가 같으면 소스 코드상 나중에 선언된 규칙이 이깁니다. 상속된 값은 직접 지정된 값보다 약합니다." + } + ] + }, + { + "id": "css-responsive", + "name": "반응형과 미디어쿼리", + "questions": [ + { + "id": "css-responsive-001", + "question": "반응형 웹 디자인이란 무엇인가요?", + "answer": "하나의 코드베이스로 다양한 화면 크기와 기기에 맞춰 레이아웃이 유연하게 적응하는 설계 방식입니다. 유동적 그리드, 유연한 이미지, 미디어쿼리를 핵심 기술로 사용해 데스크톱부터 모바일까지 최적의 사용자 경험을 제공합니다." + }, + { + "id": "css-responsive-002", + "question": "미디어쿼리(media query)는 어떻게 동작하나요?", + "answer": "@media 규칙으로 뷰포트 너비, 방향, 해상도 등 조건을 검사해 조건이 맞을 때만 특정 CSS를 적용합니다. 예를 들어 @media (max-width: 768px)는 화면 너비가 768px 이하일 때의 스타일을 정의해 화면별 레이아웃 분기를 가능하게 합니다." + }, + { + "id": "css-responsive-003", + "question": "모바일 퍼스트(Mobile First) 전략이란?", + "answer": "작은 화면용 기본 스타일을 먼저 작성하고 min-width 미디어쿼리로 큰 화면용 스타일을 점진적으로 더해가는 방식입니다. 모바일에 불필요한 무거운 스타일을 줄이고, 성능과 우선순위 관리 측면에서 유리합니다." + }, + { + "id": "css-responsive-004", + "question": "px, em, rem 단위의 차이는?", + "answer": "px는 고정 절대 단위, em은 부모(글꼴) 크기에 상대적이라 중첩 시 누적되며, rem은 항상 루트(html) 글꼴 크기를 기준으로 합니다. 접근성과 일관성 측면에서 글꼴·간격에는 rem을 많이 사용합니다." + }, + { + "id": "css-responsive-005", + "question": "vw, vh 단위는 무엇인가요?", + "answer": "뷰포트 기준 상대 단위로 1vw는 뷰포트 너비의 1%, 1vh는 높이의 1%입니다. 화면 크기에 비례하는 풀스크린 섹션이나 유동 타이포그래피에 쓰이며, 모바일 주소창 변화로 인한 vh 문제는 dvh/svh로 보완합니다." + }, + { + "id": "css-responsive-006", + "question": "clamp() 함수는 어떻게 활용하나요?", + "answer": "clamp(최솟값, 선호값, 최댓값) 형태로 값을 범위 안에서 유동적으로 조절합니다. 예를 들어 글꼴 크기에 clamp(1rem, 2.5vw, 2rem)을 주면 화면에 따라 커지되 최소/최대 한도를 넘지 않아 미디어쿼리 없이 반응형 타이포그래피를 구현합니다." + }, + { + "id": "css-responsive-007", + "question": "브레이크포인트(breakpoint)는 어떻게 정하나요?", + "answer": "특정 기기 해상도에 맞추기보다 콘텐츠가 보기 불편해지는 지점을 기준으로 정하는 것이 좋습니다. 일반적으로 모바일/태블릿/데스크톱 정도의 주요 구간을 두고, 디자인이 깨지는 곳에서 추가 브레이크포인트를 둡니다." + }, + { + "id": "css-responsive-008", + "question": "컨테이너 쿼리(container query)란 무엇인가요?", + "answer": "뷰포트가 아니라 부모 컨테이너의 크기에 따라 스타일을 적용하는 기능입니다. 같은 컴포넌트가 사이드바에 있을 때와 본문에 있을 때 다르게 보이도록 컴포넌트 단위 반응형을 구현할 수 있어 재사용성이 높습니다." + }, + { + "id": "css-responsive-009", + "question": "이미지를 반응형으로 만드는 기본 방법은?", + "answer": "max-width: 100%와 height: auto를 주면 이미지가 부모 너비를 넘지 않으면서 비율을 유지합니다. 더 나아가 srcset/sizes나 picture로 화면별 최적 이미지를 제공하면 성능까지 함께 개선됩니다." + }, + { + "id": "css-responsive-010", + "question": "prefers-color-scheme 미디어쿼리는 무엇인가요?", + "answer": "사용자가 운영체제에서 설정한 라이트/다크 모드 선호를 감지하는 미디어쿼리입니다. @media (prefers-color-scheme: dark)로 다크 모드용 색상을 정의하면 시스템 설정에 맞춰 자동으로 테마가 전환됩니다." + } + ] + }, + { + "id": "css-animation", + "name": "애니메이션과 트랜지션", + "questions": [ + { + "id": "css-animation-001", + "question": "transition과 animation의 차이는?", + "answer": "transition은 상태 변화(hover 등) 사이를 자동으로 부드럽게 보간하는 단순한 효과이고, animation은 keyframes로 여러 단계를 정의해 반복, 지연, 방향 등을 세밀하게 제어하는 복잡한 효과입니다. 시작 트리거 없이 자동 재생이 필요하면 animation을 사용합니다." + }, + { + "id": "css-animation-002", + "question": "@keyframes는 어떻게 작성하나요?", + "answer": "@keyframes 이름 {} 안에 from/to 또는 0%~100% 구간별 스타일을 정의합니다. 이후 animation 속성으로 이름, 시간, 타이밍 함수, 반복 등을 요소에 적용하면 정의한 단계대로 애니메이션이 실행됩니다." + }, + { + "id": "css-animation-003", + "question": "GPU 가속을 받는 애니메이션 속성은 무엇인가요?", + "answer": "transform과 opacity는 레이아웃과 페인트를 다시 하지 않고 합성(composite) 단계에서 처리되어 GPU 가속을 받아 부드럽습니다. 반면 width, top, margin 같은 속성 애니메이션은 리플로우를 유발해 성능이 떨어지므로 가급적 피합니다." + }, + { + "id": "css-animation-004", + "question": "transition의 4가지 값은 무엇을 의미하나요?", + "answer": "transition: property duration timing-function delay 순으로, 어떤 속성을, 얼마 동안, 어떤 가속 곡선으로, 얼마 지연 후에 전환할지를 지정합니다. all 대신 특정 속성만 지정하면 불필요한 전환을 막아 성능에 유리합니다." + }, + { + "id": "css-animation-005", + "question": "타이밍 함수(easing)에는 어떤 것이 있나요?", + "answer": "linear(일정 속도), ease(기본, 느림-빠름-느림), ease-in(점점 빨라짐), ease-out(점점 느려짐), ease-in-out, 그리고 직접 곡선을 정의하는 cubic-bezier와 단계적 변화를 주는 steps가 있습니다." + }, + { + "id": "css-animation-006", + "question": "will-change 속성은 언제 사용하나요?", + "answer": "곧 변경될 속성을 브라우저에 미리 알려 최적화 레이어를 준비시키는 힌트입니다. 애니메이션 성능을 개선할 수 있지만 남용하면 메모리를 과도하게 사용하므로, 실제로 자주 변하는 요소에만 제한적으로 적용해야 합니다." + }, + { + "id": "css-animation-007", + "question": "transform의 주요 함수에는 무엇이 있나요?", + "answer": "translate(이동), scale(확대/축소), rotate(회전), skew(기울이기)가 있습니다. 레이아웃에 영향을 주지 않고 시각적 변형만 하므로 성능이 좋고, 여러 함수를 공백으로 이어 한 번에 적용할 수 있습니다." + }, + { + "id": "css-animation-008", + "question": "animation-fill-mode는 무엇을 제어하나요?", + "answer": "애니메이션 실행 전후에 요소가 어떤 스타일을 유지할지 정합니다. forwards는 마지막 키프레임 상태를 유지, backwards는 시작 전 첫 키프레임 상태를 적용, both는 둘 다 적용합니다. 애니메이션 종료 후 원래 상태로 돌아가는 깜빡임을 방지할 때 유용합니다." + }, + { + "id": "css-animation-009", + "question": "prefers-reduced-motion은 왜 고려해야 하나요?", + "answer": "어지럼증 등으로 움직임을 최소화하도록 설정한 사용자를 위한 미디어쿼리입니다. 접근성 차원에서 이 설정이 켜진 경우 큰 애니메이션을 줄이거나 제거해 멀미나 불편을 유발하지 않도록 배려해야 합니다." + }, + { + "id": "css-animation-010", + "question": "리페인트와 리플로우를 줄이는 애니메이션 방법은?", + "answer": "위치나 크기를 바꿀 때 left/top/width 대신 transform: translate/scale을, 표시 전환에는 display 대신 opacity를 사용합니다. 이들은 합성 단계에서 처리되어 레이아웃 재계산과 다시 그리기를 피할 수 있어 부드러운 60fps를 유지하기 쉽습니다." + } + ] + }, + { + "id": "css-misc", + "name": "단위·색상·기타", + "questions": [ + { + "id": "css-misc-001", + "question": "CSS 변수(커스텀 프로퍼티)는 무엇이고 장점은?", + "answer": "--main-color처럼 -- 로 정의하고 var()로 사용하는 변수입니다. 전처리기 변수와 달리 런타임에 동작해 자바스크립트로 변경할 수 있고 상속/캐스케이드를 따릅니다. 테마 전환과 디자인 토큰 관리에 유용합니다." + }, + { + "id": "css-misc-002", + "question": "rgba와 hsl, hsla 색상 표기의 차이는?", + "answer": "rgb(a)는 빨강/초록/파랑과 투명도로 색을 지정하고, hsl(a)는 색상(hue), 채도(saturation), 명도(lightness), 투명도로 지정합니다. hsl은 명도/채도만 조절해 색의 밝기 변형을 만들기 쉬워 직관적인 색 조정에 유리합니다." + }, + { + "id": "css-misc-003", + "question": "em 기반 누적 문제를 피하는 방법은?", + "answer": "em은 부모 글꼴 크기를 기준으로 하여 중첩될수록 값이 곱해지며 예측이 어려워집니다. 글꼴이나 전역 간격은 루트 기준인 rem을 사용하고, 컴포넌트 내부의 상대적 비례에만 em을 제한적으로 쓰면 누적 문제를 피할 수 있습니다." + }, + { + "id": "css-misc-004", + "question": "CSS에서 중앙 정렬 방법을 여러 가지 설명해 주세요.", + "answer": "블록 요소는 margin: 0 auto, 텍스트는 text-align: center, Flexbox는 justify-content/align-items: center, Grid는 place-items: center, 절대 위치는 top/left 50%에 transform: translate(-50%,-50%)를 사용합니다. 상황에 맞는 방법을 선택합니다." + }, + { + "id": "css-misc-005", + "question": "object-fit 속성은 무엇인가요?", + "answer": "img나 video가 지정된 박스를 채우는 방식을 제어합니다. cover는 비율 유지하며 박스를 꽉 채우고 넘치는 부분을 자르며, contain은 비율 유지하며 박스 안에 모두 보이게 맞춥니다. 썸네일을 일정 크기로 깔끔하게 맞출 때 유용합니다." + }, + { + "id": "css-misc-006", + "question": "visibility: hidden, display: none, opacity: 0의 차이는?", + "answer": "display: none은 요소를 렌더링에서 완전히 제거해 공간도 차지하지 않습니다. visibility: hidden은 보이지 않지만 공간은 차지합니다. opacity: 0은 투명하지만 공간을 차지하고 클릭 등 이벤트도 받습니다. 접근성과 이벤트 처리 측면에서 동작이 다릅니다." + }, + { + "id": "css-misc-007", + "question": "텍스트 말줄임(...) 처리는 어떻게 하나요?", + "answer": "한 줄은 white-space: nowrap, overflow: hidden, text-overflow: ellipsis를 함께 적용합니다. 여러 줄은 display: -webkit-box와 -webkit-line-clamp, -webkit-box-orient: vertical, overflow: hidden 조합으로 지정한 줄 수에서 말줄임 처리합니다." + }, + { + "id": "css-misc-008", + "question": "CSS 전처리기(Sass/Less)의 장점은?", + "answer": "변수, 중첩, 믹스인, 함수, 모듈 분리 등 프로그래밍적 기능으로 CSS를 더 구조적이고 재사용 가능하게 작성하게 해줍니다. 빌드 시 일반 CSS로 컴파일되며, 대규모 스타일을 유지보수하기 쉽게 만듭니다." + }, + { + "id": "css-misc-009", + "question": "CSS 방법론(BEM 등)을 쓰는 이유는?", + "answer": "클래스 네이밍 규칙을 정해 스타일 충돌과 명시도 전쟁을 줄이고 구조를 예측 가능하게 만들기 위함입니다. BEM은 Block__Element--Modifier 형태로 역할을 명확히 드러내 대규모 프로젝트에서 협업과 유지보수를 돕습니다." + }, + { + "id": "css-misc-010", + "question": "유틸리티 퍼스트 CSS(Tailwind 등)의 장단점은?", + "answer": "장점은 미리 정의된 작은 클래스를 조합해 빠르게 일관된 UI를 만들고 사용하지 않는 CSS를 제거하기 쉽다는 점입니다. 단점은 마크업에 클래스가 길게 붙어 가독성이 떨어지고 학습 곡선이 있다는 점입니다. 프로젝트 규모와 팀 선호에 따라 선택합니다." + } + ] + } + ] + }, + { + "id": "javascript", + "name": "JavaScript", + "categories": [ + { + "id": "js-type", + "name": "데이터 타입과 변수", + "questions": [ + { + "id": "js-type-001", + "question": "JavaScript의 원시 타입(primitive type)에는 무엇이 있나요?", + "answer": "string, number, boolean, undefined, null, symbol, bigint 7가지가 있습니다. 원시 타입은 변경 불가능(immutable)하며 값 자체로 복사되어 전달됩니다. 그 외의 객체, 배열, 함수는 모두 참조 타입(object)입니다." + }, + { + "id": "js-type-002", + "question": "let, const, var의 차이는 무엇인가요?", + "answer": "var는 함수 스코프이며 호이스팅 시 undefined로 초기화되고 재선언이 가능합니다. let과 const는 블록 스코프이며 TDZ로 인해 선언 전 접근 시 에러가 납니다. const는 재할당이 불가능합니다. 현대 코드에서는 const를 기본으로 쓰고 재할당이 필요할 때만 let을 씁니다." + }, + { + "id": "js-type-003", + "question": "== 와 === 의 차이는?", + "answer": "==는 타입이 다르면 강제 형변환 후 값을 비교하고, ===는 형변환 없이 타입과 값을 모두 비교합니다. ==는 예측하기 어려운 변환으로 버그를 만들 수 있어 일반적으로 ===(엄격한 동등) 사용이 권장됩니다." + }, + { + "id": "js-type-004", + "question": "null과 undefined의 차이는?", + "answer": "undefined는 값이 할당되지 않은 상태로 시스템이 부여하는 기본값이고, null은 값이 없음을 개발자가 의도적으로 명시한 값입니다. typeof는 undefined는 'undefined', null은 'object'를 반환하는 점도 차이입니다." + }, + { + "id": "js-type-005", + "question": "원시 타입과 참조 타입의 복사 동작 차이는?", + "answer": "원시 타입은 변수에 값 자체가 저장되어 복사 시 독립적인 값이 만들어집니다. 참조 타입은 변수에 메모리 주소(참조)가 저장되어 복사하면 같은 객체를 가리키므로, 한쪽을 수정하면 다른 쪽에도 영향을 줍니다." + }, + { + "id": "js-type-006", + "question": "얕은 복사와 깊은 복사의 차이는?", + "answer": "얕은 복사는 한 단계 속성만 복사해 중첩된 객체는 참조를 공유합니다(스프레드, Object.assign). 깊은 복사는 모든 중첩 구조까지 완전히 새로 복제해 원본과 완전히 분리됩니다(structuredClone, 재귀 복사 등)." + }, + { + "id": "js-type-007", + "question": "typeof 연산자의 주의할 점은?", + "answer": "typeof null이 'object'를 반환하는 오래된 버그가 있고, 함수는 'function', 배열은 'object'를 반환합니다. 배열 판별에는 Array.isArray를, 정확한 타입 구분에는 Object.prototype.toString.call을 보조적으로 사용합니다." + }, + { + "id": "js-type-008", + "question": "형변환(Type Coercion)이란 무엇인가요?", + "answer": "다른 타입의 값이 연산에서 자동 또는 명시적으로 변환되는 것입니다. 예를 들어 '5' - 2는 숫자 3, '5' + 2는 문자열 '52'가 됩니다. + 연산자가 문자열을 만나면 연결로 동작하는 등 규칙이 까다로워 의도적 변환을 권장합니다." + }, + { + "id": "js-type-009", + "question": "JavaScript에서 falsy 값에는 무엇이 있나요?", + "answer": "false, 0, -0, 0n(BigInt), 빈 문자열, null, undefined, NaN이 falsy입니다. 그 외의 모든 값(빈 배열 [], 빈 객체 {}, '0' 문자열 포함)은 truthy로 평가됩니다. 조건문 동작을 정확히 이해하는 데 중요합니다." + }, + { + "id": "js-type-010", + "question": "Symbol은 무엇이고 어디에 쓰나요?", + "answer": "고유하고 변경 불가능한 원시 값으로, 같은 설명을 가져도 항상 서로 다릅니다. 객체 프로퍼티 키로 사용해 이름 충돌 없는 고유 키를 만들거나, Symbol.iterator처럼 객체의 내부 동작을 정의하는 데 활용됩니다." + } + ] + }, + { + "id": "js-scope", + "name": "스코프와 클로저", + "questions": [ + { + "id": "js-scope-001", + "question": "스코프(scope)란 무엇인가요?", + "answer": "변수와 함수에 접근할 수 있는 유효 범위입니다. 전역 스코프, 함수 스코프, 블록 스코프가 있으며, 안쪽 스코프에서는 바깥 변수에 접근할 수 있지만 그 반대는 불가능합니다. 변수 검색은 안쪽에서 바깥으로 이루어집니다." + }, + { + "id": "js-scope-002", + "question": "호이스팅(Hoisting)이란 무엇인가요?", + "answer": "변수와 함수 선언이 코드 실행 전에 스코프 최상단으로 끌어올려진 것처럼 동작하는 현상입니다. var와 함수 선언문은 호이스팅되어 선언 전 참조가 가능하지만, let/const는 TDZ로 인해 선언 전 접근 시 에러가 발생합니다." + }, + { + "id": "js-scope-003", + "question": "클로저(Closure)란 무엇인가요?", + "answer": "함수가 선언될 당시의 외부 변수(렉시컬 환경)를 기억해, 외부 함수가 종료된 뒤에도 그 변수에 계속 접근할 수 있는 함수입니다. 상태를 함수 내부에 은닉하고 유지하는 강력한 메커니즘입니다." + }, + { + "id": "js-scope-004", + "question": "클로저는 실무에서 어떻게 활용되나요?", + "answer": "데이터 은닉과 캡슐화(모듈 패턴), 상태 유지(카운터, 한 번만 실행되는 함수), 콜백에서 변수 보존, 커링과 부분 적용 등에 사용됩니다. private 변수를 흉내 내거나 팩토리 함수를 만들 때 유용합니다." + }, + { + "id": "js-scope-005", + "question": "TDZ(Temporal Dead Zone)란 무엇인가요?", + "answer": "let/const로 선언한 변수가 스코프 시작부터 선언문에 도달하기 전까지 접근할 수 없는 구간입니다. 이 구간에서 변수를 참조하면 ReferenceError가 발생해, 선언 전 사용을 막아 더 안전한 코드를 유도합니다." + }, + { + "id": "js-scope-006", + "question": "렉시컬 스코프(Lexical Scope)란?", + "answer": "함수의 스코프가 호출 위치가 아니라 코드가 작성된(선언된) 위치에 따라 결정되는 방식입니다. JavaScript는 렉시컬 스코프를 따르므로, 함수가 어디서 호출되든 자신이 정의된 곳의 외부 변수를 참조합니다." + }, + { + "id": "js-scope-007", + "question": "반복문에서 var와 let의 클로저 동작 차이는?", + "answer": "var는 함수 스코프라 반복이 끝난 뒤의 마지막 값을 모든 콜백이 공유하지만, let은 매 반복마다 새로운 블록 스코프 바인딩을 만들어 각 콜백이 해당 시점의 값을 기억합니다. setTimeout 루프 예제에서 흔히 차이가 드러납니다." + }, + { + "id": "js-scope-008", + "question": "IIFE(즉시 실행 함수)는 무엇이고 왜 쓰였나요?", + "answer": "정의와 동시에 즉시 호출되는 함수 표현식입니다. 모듈 시스템이 없던 시절 전역 오염을 막고 변수를 캡슐화하기 위해 사용했습니다. 지금은 블록 스코프(let/const)와 모듈로 상당 부분 대체되었습니다." + }, + { + "id": "js-scope-009", + "question": "전역 변수 사용을 피해야 하는 이유는?", + "answer": "어디서나 접근/수정이 가능해 이름 충돌과 의도치 않은 부수 효과를 일으키고, 코드 추적과 테스트를 어렵게 만듭니다. 모듈 스코프나 함수 스코프로 범위를 좁혀 의존성을 명확히 하는 것이 안전합니다." + }, + { + "id": "js-scope-010", + "question": "스코프 체인(Scope Chain)이란 무엇인가요?", + "answer": "변수를 찾을 때 현재 스코프에서 시작해 상위 스코프로 거슬러 올라가며 검색하는 연결 구조입니다. 가장 가까운 스코프에서 변수를 찾으면 멈추고, 전역까지 못 찾으면 ReferenceError가 발생합니다." + } + ] + }, + { + "id": "js-this", + "name": "this와 실행 컨텍스트", + "questions": [ + { + "id": "js-this-001", + "question": "this는 어떻게 결정되나요?", + "answer": "this는 함수가 호출되는 방식에 따라 동적으로 결정됩니다. 일반 함수는 전역(또는 strict 모드에서 undefined), 메서드 호출은 호출한 객체, 생성자는 새 인스턴스, call/apply/bind는 지정한 객체를 가리킵니다. 화살표 함수는 예외적으로 상위 스코프의 this를 따릅니다." + }, + { + "id": "js-this-002", + "question": "화살표 함수와 일반 함수의 this 차이는?", + "answer": "일반 함수의 this는 호출 방식에 따라 동적으로 바뀌지만, 화살표 함수는 자신만의 this가 없어 선언된 위치의 상위 스코프 this를 그대로 사용합니다. 그래서 콜백에서 this를 유지해야 할 때 화살표 함수가 유용합니다." + }, + { + "id": "js-this-003", + "question": "call, apply, bind의 차이는?", + "answer": "셋 다 this를 명시적으로 지정합니다. call은 인자를 쉼표로 나열해 즉시 호출, apply는 인자를 배열로 받아 즉시 호출하며, bind는 this가 고정된 새 함수를 반환할 뿐 즉시 실행하지 않습니다." + }, + { + "id": "js-this-004", + "question": "실행 컨텍스트(Execution Context)란 무엇인가요?", + "answer": "코드가 실행되는 환경 정보를 담은 객체로, 변수 환경, 렉시컬 환경, this 바인딩 등을 포함합니다. 전역 컨텍스트와 함수 컨텍스트가 있으며, 함수 호출 시 새 컨텍스트가 콜 스택에 쌓이고 종료되면 제거됩니다." + }, + { + "id": "js-this-005", + "question": "콜 스택(Call Stack)은 무엇인가요?", + "answer": "실행 컨텍스트가 쌓이고 제거되는 LIFO(후입선출) 구조의 자료구조입니다. 함수가 호출되면 스택에 쌓이고 반환되면 빠집니다. 재귀가 너무 깊으면 스택 크기를 초과해 스택 오버플로 에러가 발생합니다." + }, + { + "id": "js-this-006", + "question": "이벤트 핸들러에서 this는 무엇을 가리키나요?", + "answer": "addEventListener에 일반 함수를 전달하면 this는 이벤트가 바인딩된 요소(currentTarget)를 가리킵니다. 화살표 함수를 쓰면 상위 스코프의 this를 따르므로 요소 대신 외부 컨텍스트를 가리키게 됩니다." + }, + { + "id": "js-this-007", + "question": "메서드를 변수에 할당해 호출하면 this는 어떻게 되나요?", + "answer": "객체의 메서드를 분리해 일반 함수처럼 호출하면 호출 객체가 사라져 this가 전역(또는 strict에서 undefined)이 됩니다. 이를 방지하려면 bind로 this를 고정하거나 화살표 함수로 감싸 호출합니다." + }, + { + "id": "js-this-008", + "question": "strict mode는 this에 어떤 영향을 주나요?", + "answer": "비엄격 모드에서 일반 함수의 this는 undefined일 때 전역 객체로 대체되지만, strict mode에서는 그대로 undefined가 됩니다. 의도치 않은 전역 객체 참조를 막아 버그를 빨리 드러나게 합니다." + }, + { + "id": "js-this-009", + "question": "new 연산자로 함수를 호출하면 어떤 일이 일어나나요?", + "answer": "빈 객체를 만들고, 그 객체를 함수의 prototype에 연결하고, this를 그 객체에 바인딩해 함수 본문을 실행한 뒤, 명시적 객체 반환이 없으면 만든 객체를 반환합니다. 이 과정으로 인스턴스가 생성됩니다." + }, + { + "id": "js-this-010", + "question": "this 바인딩의 우선순위는 어떻게 되나요?", + "answer": "new 바인딩이 가장 높고, 다음으로 명시적 바인딩(call/apply/bind), 그다음 메서드 호출의 암시적 바인딩, 마지막으로 기본 바인딩(전역/undefined) 순입니다. 화살표 함수는 이 규칙을 따르지 않고 상위 this를 사용합니다." + } + ] + }, + { + "id": "js-prototype", + "name": "프로토타입과 객체", + "questions": [ + { + "id": "js-prototype-001", + "question": "프로토타입(Prototype)이란 무엇인가요?", + "answer": "JavaScript 객체가 다른 객체로부터 속성과 메서드를 상속받기 위해 연결되는 원본 객체입니다. 모든 객체는 [[Prototype]] 내부 링크로 자신의 프로토타입을 가리키며, 이를 통해 상속이 구현됩니다." + }, + { + "id": "js-prototype-002", + "question": "프로토타입 체인(Prototype Chain)을 설명해 주세요.", + "answer": "객체에서 속성을 찾을 때 자신에게 없으면 프로토타입을 따라 위로 올라가며 검색하는 연결 구조입니다. 최상위 Object.prototype까지 가도 없으면 undefined를 반환합니다. 상속과 메서드 공유가 이 체인을 통해 이루어집니다." + }, + { + "id": "js-prototype-003", + "question": "__proto__와 prototype의 차이는?", + "answer": "prototype은 함수(생성자)가 가진 속성으로, 그 함수로 만든 인스턴스의 프로토타입이 될 객체입니다. __proto__는 모든 객체가 가진 접근자로 자신의 실제 프로토타입을 가리킵니다. 즉 instance.__proto__ === Constructor.prototype 관계입니다." + }, + { + "id": "js-prototype-004", + "question": "클래스(class)는 프로토타입과 어떤 관계인가요?", + "answer": "ES6 class는 프로토타입 기반 상속을 더 익숙한 문법으로 감싼 문법적 설탕(syntactic sugar)입니다. 내부적으로는 여전히 프로토타입과 생성자 함수로 동작하며, 메서드는 prototype에 정의됩니다." + }, + { + "id": "js-prototype-005", + "question": "프로토타입 메서드와 인스턴스 메서드의 차이는?", + "answer": "프로토타입에 정의한 메서드는 모든 인스턴스가 하나를 공유해 메모리에 효율적입니다. 생성자 내부에서 this에 할당한 메서드는 인스턴스마다 별도로 생성되어 메모리를 더 쓰지만 각 인스턴스에 종속됩니다." + }, + { + "id": "js-prototype-006", + "question": "Object.create는 무엇을 하나요?", + "answer": "지정한 객체를 프로토타입으로 삼는 새 객체를 생성합니다. 생성자 함수 없이 프로토타입을 직접 연결할 수 있어 상속 구조를 명시적으로 만들거나, 프로토타입이 없는 순수 객체(Object.create(null))를 만들 때 사용합니다." + }, + { + "id": "js-prototype-007", + "question": "hasOwnProperty는 왜 필요한가요?", + "answer": "객체가 해당 속성을 프로토타입 체인이 아닌 자기 자신에 직접 가지고 있는지 확인하기 위해서입니다. for...in이 상속된 속성까지 순회하므로, 자기 속성만 다루고 싶을 때 hasOwnProperty로 걸러냅니다." + }, + { + "id": "js-prototype-008", + "question": "프로토타입 상속과 클래스 상속(extends)의 동작은?", + "answer": "extends는 자식 클래스의 prototype을 부모 클래스의 prototype에 연결해 프로토타입 체인을 구성합니다. super로 부모 생성자와 메서드를 호출하며, 결국 메서드 탐색은 프로토타입 체인을 따라 이루어집니다." + }, + { + "id": "js-prototype-009", + "question": "객체 속성을 순회하는 방법들의 차이는?", + "answer": "for...in은 상속된 열거 가능 속성까지, Object.keys/values/entries는 자기 자신의 열거 가능 속성만 다룹니다. 일반적으로 자기 속성만 안전하게 다루려면 Object.keys 계열을 사용하는 것이 권장됩니다." + }, + { + "id": "js-prototype-010", + "question": "getter와 setter는 무엇인가요?", + "answer": "속성을 읽거나 쓸 때 함수를 실행하도록 정의하는 접근자 프로퍼티입니다. get은 값을 계산해 반환하고 set은 할당 시 검증이나 부수 작업을 수행합니다. 외부에는 일반 속성처럼 보이면서 내부 로직을 캡슐화할 수 있습니다." + } + ] + }, + { + "id": "js-async", + "name": "비동기 처리", + "questions": [ + { + "id": "js-async-001", + "question": "동기와 비동기의 차이는 무엇인가요?", + "answer": "동기는 한 작업이 끝날 때까지 다음 작업이 대기하며 순서대로 실행됩니다. 비동기는 오래 걸리는 작업을 기다리지 않고 다음 코드를 실행한 뒤, 완료되면 결과를 처리합니다. 네트워크 요청처럼 시간이 걸리는 작업에 비동기가 사용됩니다." + }, + { + "id": "js-async-002", + "question": "Promise란 무엇인가요?", + "answer": "비동기 작업의 최종 완료 또는 실패를 나타내는 객체입니다. pending, fulfilled, rejected 세 상태를 가지며, then으로 성공 결과를, catch로 에러를 처리합니다. 콜백 중첩(콜백 지옥)을 체이닝으로 풀어 가독성을 높입니다." + }, + { + "id": "js-async-003", + "question": "async/await는 어떻게 동작하나요?", + "answer": "Promise를 동기 코드처럼 작성하게 해주는 문법입니다. async 함수는 항상 Promise를 반환하고, await는 Promise가 처리될 때까지 함수 실행을 잠시 멈춥니다. 에러는 try/catch로 처리해 흐름이 직관적입니다." + }, + { + "id": "js-async-004", + "question": "콜백 지옥(Callback Hell)이란 무엇이고 어떻게 해결하나요?", + "answer": "비동기 콜백이 중첩되며 코드가 오른쪽으로 깊어져 가독성과 에러 처리가 어려워지는 현상입니다. Promise 체이닝이나 async/await로 평탄하게 펼쳐 해결하며, 현대 코드에서는 async/await가 가장 선호됩니다." + }, + { + "id": "js-async-005", + "question": "Promise.all, allSettled, race, any의 차이는?", + "answer": "all은 모두 성공해야 하며 하나라도 실패하면 즉시 reject됩니다. allSettled는 성공/실패와 무관하게 모든 결과를 기다립니다. race는 가장 먼저 처리된 하나의 결과를, any는 가장 먼저 성공한 하나의 결과를 반환합니다." + }, + { + "id": "js-async-006", + "question": "Promise 체이닝에서 에러는 어떻게 전파되나요?", + "answer": "체인 중간에서 발생한 에러는 가장 가까운 다음 catch로 건너뛰어 전달됩니다. 그래서 체인 끝에 catch 하나를 두면 앞선 모든 단계의 에러를 한곳에서 처리할 수 있습니다. then의 두 번째 인자로도 개별 처리가 가능합니다." + }, + { + "id": "js-async-007", + "question": "async 함수에서 여러 비동기를 병렬로 처리하려면?", + "answer": "각각 await를 순차로 쓰면 직렬 실행되어 느립니다. 먼저 Promise들을 동시에 시작한 뒤 Promise.all로 함께 기다리면 병렬로 처리되어 전체 소요 시간이 가장 오래 걸리는 작업 수준으로 단축됩니다." + }, + { + "id": "js-async-008", + "question": "fetch와 XMLHttpRequest의 차이는?", + "answer": "fetch는 Promise 기반의 현대적 API로 문법이 간결하고 스트림을 지원합니다. XHR은 이벤트/콜백 기반의 옛 방식입니다. 단 fetch는 HTTP 에러 상태(404 등)에서도 reject되지 않으므로 response.ok로 직접 확인해야 합니다." + }, + { + "id": "js-async-009", + "question": "Promise를 반환하는 함수에서 에러를 처리하지 않으면?", + "answer": "처리되지 않은 거부(unhandled rejection)가 발생해 경고가 뜨고 환경에 따라 프로세스가 종료될 수 있습니다. 모든 Promise 체인 끝에 catch를, async 함수에는 try/catch를 두어 에러를 반드시 처리해야 합니다." + }, + { + "id": "js-async-010", + "question": "디바운스(debounce)와 스로틀(throttle)의 차이는?", + "answer": "디바운스는 연속된 호출 중 마지막 호출 후 일정 시간이 지나야 실행해 검색 입력 같은 곳에 적합합니다. 스로틀은 일정 시간 간격마다 최대 한 번만 실행해 스크롤/리사이즈처럼 빈번한 이벤트의 호출 빈도를 제한할 때 적합합니다." + } + ] + }, + { + "id": "js-event", + "name": "이벤트와 이벤트 루프", + "questions": [ + { + "id": "js-event-001", + "question": "이벤트 루프(Event Loop)를 설명해 주세요.", + "answer": "싱글 스레드인 JavaScript가 비동기를 처리하는 메커니즘입니다. 콜 스택이 비면 이벤트 루프가 태스크 큐의 콜백을 꺼내 스택에 넣어 실행합니다. 이 반복으로 블로킹 없이 비동기 작업의 결과를 순차 처리합니다." + }, + { + "id": "js-event-002", + "question": "마이크로태스크와 매크로태스크의 차이는?", + "answer": "Promise 콜백, queueMicrotask 등은 마이크로태스크 큐에, setTimeout, setInterval, 이벤트 콜백 등은 매크로태스크 큐에 들어갑니다. 매 작업 후 마이크로태스크 큐를 모두 비운 뒤 다음 매크로태스크로 넘어가므로 마이크로태스크가 더 먼저 처리됩니다." + }, + { + "id": "js-event-003", + "question": "이벤트 버블링과 캡처링의 차이는?", + "answer": "이벤트가 발생하면 캡처링 단계에서 최상위에서 대상까지 내려갔다가, 버블링 단계에서 대상에서 최상위로 다시 올라갑니다. addEventListener는 기본적으로 버블링 단계에서 동작하며, 세 번째 인자 capture를 true로 주면 캡처링 단계에서 처리합니다." + }, + { + "id": "js-event-004", + "question": "이벤트 위임(Event Delegation)이란 무엇인가요?", + "answer": "자식 요소 각각에 핸들러를 붙이는 대신, 공통 부모에 하나의 핸들러를 두고 버블링을 이용해 이벤트를 처리하는 기법입니다. 동적으로 추가되는 요소도 자동 처리되고 메모리도 절약되어 리스트나 테이블에 유용합니다." + }, + { + "id": "js-event-005", + "question": "preventDefault와 stopPropagation의 차이는?", + "answer": "preventDefault는 링크 이동이나 폼 제출 같은 브라우저 기본 동작을 막습니다. stopPropagation은 이벤트가 더 이상 버블링/캡처링으로 전파되지 않게 막습니다. 둘은 목적이 다르며 필요에 따라 함께 또는 따로 사용합니다." + }, + { + "id": "js-event-006", + "question": "setTimeout(fn, 0)은 즉시 실행되나요?", + "answer": "아니요. 콜백은 즉시 실행되지 않고 매크로태스크 큐에 들어가 현재 실행 중인 동기 코드와 마이크로태스크가 모두 끝난 뒤에 실행됩니다. 또한 최소 지연(보통 4ms)이 적용될 수 있어 정확히 0ms 후가 아닙니다." + }, + { + "id": "js-event-007", + "question": "JavaScript가 싱글 스레드인데 어떻게 비동기가 가능한가요?", + "answer": "JavaScript 엔진은 싱글 스레드지만, 브라우저/Node 런타임이 타이머, 네트워크, 파일 I/O 같은 작업을 별도로 처리합니다. 완료된 작업의 콜백을 큐에 넣고 이벤트 루프가 콜 스택이 빌 때 실행하므로 동시성처럼 동작합니다." + }, + { + "id": "js-event-008", + "question": "requestAnimationFrame은 무엇이고 언제 쓰나요?", + "answer": "브라우저의 다음 리페인트 직전에 콜백을 실행하도록 예약하는 API입니다. 보통 화면 주사율에 맞춰 호출되어 setTimeout보다 부드럽고 효율적인 애니메이션을 만들며, 탭이 비활성화되면 자동으로 멈춰 자원을 아낍니다." + }, + { + "id": "js-event-009", + "question": "이벤트 객체의 target과 currentTarget의 차이는?", + "answer": "target은 이벤트가 실제로 발생한 요소이고, currentTarget은 현재 핸들러가 바인딩된 요소입니다. 이벤트 위임에서 target은 클릭된 자식, currentTarget은 핸들러가 붙은 부모를 가리켜 구분이 중요합니다." + }, + { + "id": "js-event-010", + "question": "passive 이벤트 리스너는 무엇인가요?", + "answer": "{ passive: true } 옵션으로 등록한 리스너로, 핸들러가 preventDefault를 호출하지 않겠다고 브라우저에 약속하는 것입니다. 스크롤 이벤트에서 브라우저가 스크롤을 기다리지 않고 즉시 처리할 수 있어 스크롤 성능이 향상됩니다." + } + ] + }, + { + "id": "js-es6", + "name": "ES6+ 문법", + "questions": [ + { + "id": "js-es6-001", + "question": "구조 분해 할당(Destructuring)이란?", + "answer": "배열이나 객체의 값을 개별 변수로 손쉽게 추출하는 문법입니다. const {name, age} = user처럼 필요한 속성만 꺼내거나, 기본값과 별칭을 지정할 수 있어 코드가 간결해집니다. 함수 매개변수에도 자주 활용됩니다." + }, + { + "id": "js-es6-002", + "question": "스프레드 연산자와 rest 파라미터의 차이는?", + "answer": "둘 다 ... 기호를 쓰지만 역할이 반대입니다. 스프레드는 배열/객체를 개별 요소로 펼치고(복사, 병합), rest는 여러 인자를 하나의 배열로 모읍니다. 위치(우변에서 펼치기 vs 매개변수에서 모으기)로 구분합니다." + }, + { + "id": "js-es6-003", + "question": "템플릿 리터럴(Template Literal)의 장점은?", + "answer": "백틱(`)으로 문자열을 감싸 ${} 안에 표현식을 삽입하고 여러 줄 문자열을 그대로 작성할 수 있습니다. 문자열 연결(+)보다 가독성이 좋고, 태그드 템플릿으로 문자열을 가공하는 고급 활용도 가능합니다." + }, + { + "id": "js-es6-004", + "question": "기본 매개변수(Default Parameter)는 무엇인가요?", + "answer": "함수 인자가 전달되지 않거나 undefined일 때 사용할 기본값을 매개변수에 직접 지정하는 기능입니다. function f(x = 10)처럼 작성하며, 함수 내부에서 값 존재 여부를 검사하는 코드를 줄여줍니다." + }, + { + "id": "js-es6-005", + "question": "단축 평가(short-circuit)와 ||, &&, ?? 의 차이는?", + "answer": "||는 왼쪽이 falsy면 오른쪽을, &&는 왼쪽이 truthy면 오른쪽을 반환합니다. ??(널 병합)는 왼쪽이 null이나 undefined일 때만 오른쪽을 반환해, 0이나 빈 문자열을 유효값으로 다뤄야 할 때 ||보다 안전합니다." + }, + { + "id": "js-es6-006", + "question": "옵셔널 체이닝(?.)은 무엇인가요?", + "answer": "중첩된 객체 속성에 접근할 때 중간 값이 null이나 undefined면 에러 없이 undefined를 반환하는 문법입니다. a?.b?.c처럼 사용해 깊은 속성 접근 시 일일이 존재 여부를 검사하는 코드를 크게 줄여줍니다." + }, + { + "id": "js-es6-007", + "question": "Map과 일반 객체(Object)의 차이는?", + "answer": "Map은 키로 모든 타입(객체 포함)을 쓸 수 있고 삽입 순서를 보장하며 size로 크기를 바로 알 수 있고 순회가 쉽습니다. Object는 키가 문자열/심볼로 제한됩니다. 빈번한 추가/삭제와 임의 키에는 Map이 유리합니다." + }, + { + "id": "js-es6-008", + "question": "Set은 무엇이고 어디에 쓰나요?", + "answer": "중복을 허용하지 않는 값들의 집합입니다. 배열의 중복 제거([...new Set(arr)]), 존재 여부 빠른 확인, 합집합/교집합 연산 등에 사용합니다. has로 포함 여부를 O(1)에 가깝게 확인할 수 있습니다." + }, + { + "id": "js-es6-009", + "question": "제너레이터(Generator) 함수란 무엇인가요?", + "answer": "function*로 정의하고 yield로 실행을 중간에 멈췄다 재개할 수 있는 함수입니다. 호출 시 이터레이터를 반환하며, 값을 필요할 때마다 하나씩 생산(지연 평가)하거나 무한 수열, 커스텀 이터레이션을 구현할 때 사용합니다." + }, + { + "id": "js-es6-010", + "question": "모듈의 named export와 default export 차이는?", + "answer": "named export는 이름을 그대로 가져와야 하며 한 파일에서 여러 개 내보낼 수 있습니다. default export는 모듈당 하나만 가능하고 import 시 원하는 이름을 붙일 수 있습니다. 함께 사용할 수도 있습니다." + } + ] + }, + { + "id": "js-functional", + "name": "배열과 함수형", + "questions": [ + { + "id": "js-functional-001", + "question": "map, filter, reduce의 차이는?", + "answer": "map은 각 요소를 변환해 같은 길이의 새 배열을, filter는 조건을 만족하는 요소만 골라 새 배열을 반환합니다. reduce는 요소들을 하나의 누적 값으로 줄입니다. 모두 원본을 바꾸지 않고 새 결과를 만드는 비파괴적 메서드입니다." + }, + { + "id": "js-functional-002", + "question": "forEach와 map의 차이는?", + "answer": "forEach는 각 요소에 대해 동작만 수행하고 반환값이 없어 부수 효과 용도이며 체이닝이 불가능합니다. map은 변환 결과를 담은 새 배열을 반환해 체이닝과 함수형 흐름에 적합합니다. 새 배열이 필요하면 map을 씁니다." + }, + { + "id": "js-functional-003", + "question": "순수 함수(Pure Function)란 무엇인가요?", + "answer": "같은 입력에 항상 같은 출력을 반환하고 외부 상태를 변경하는 부수 효과가 없는 함수입니다. 예측 가능하고 테스트와 디버깅이 쉬우며 병렬 처리에 안전해 함수형 프로그래밍의 핵심 개념입니다." + }, + { + "id": "js-functional-004", + "question": "부수 효과(Side Effect)란 무엇인가요?", + "answer": "함수가 자신의 반환값 외에 외부 상태를 변경하는 것입니다. 전역 변수 수정, DOM 조작, 네트워크 요청, 콘솔 출력 등이 해당합니다. 부수 효과를 최소화하고 격리하면 코드의 예측 가능성과 유지보수성이 높아집니다." + }, + { + "id": "js-functional-005", + "question": "고차 함수(Higher-Order Function)란?", + "answer": "함수를 인자로 받거나 함수를 반환하는 함수입니다. map, filter처럼 콜백을 받는 함수나, 설정을 받아 새 함수를 만들어 주는 함수가 예입니다. 로직의 재사용과 추상화를 가능하게 해줍니다." + }, + { + "id": "js-functional-006", + "question": "커링(Currying)이란 무엇인가요?", + "answer": "여러 인자를 받는 함수를 인자 하나씩 받는 함수들의 연쇄로 변환하는 기법입니다. f(a)(b)(c) 형태로 호출하며, 일부 인자를 미리 고정한 특화 함수를 만들거나 함수 합성에 활용합니다." + }, + { + "id": "js-functional-007", + "question": "find와 filter의 차이는?", + "answer": "find는 조건을 만족하는 첫 번째 요소 하나를 반환하고 없으면 undefined를, filter는 조건을 만족하는 모든 요소를 배열로 반환합니다. 하나만 찾으면 되는 경우 find가 더 효율적입니다." + }, + { + "id": "js-functional-008", + "question": "some과 every의 차이는?", + "answer": "some은 하나라도 조건을 만족하면 true, every는 모든 요소가 조건을 만족해야 true를 반환합니다. 둘 다 조건이 확정되는 순간 순회를 멈추는 단축 평가를 하므로 효율적입니다." + }, + { + "id": "js-functional-009", + "question": "불변성(Immutability)을 지키는 이유와 방법은?", + "answer": "데이터를 직접 수정하지 않으면 예기치 않은 변경을 막고 변화 추적과 비교가 쉬워져 특히 React 등 상태 관리에서 중요합니다. 스프레드, map/filter, structuredClone 등으로 원본 대신 새 객체/배열을 만들어 갱신합니다." + }, + { + "id": "js-functional-010", + "question": "sort 메서드 사용 시 주의할 점은?", + "answer": "sort는 원본 배열을 직접 변경(in-place)하고, 비교 함수를 주지 않으면 요소를 문자열로 변환해 정렬해 숫자가 의도와 다르게 정렬됩니다. 숫자는 (a, b) => a - b 같은 비교 함수를 반드시 넘겨야 합니다." + } + ] + } + ] + }, + { + "id": "typescript", + "name": "TypeScript", + "categories": [ + { + "id": "ts-basic", + "name": "기본 개념과 타입", + "questions": [ + { + "id": "ts-basic-001", + "question": "TypeScript를 사용하는 이유는 무엇인가요?", + "answer": "정적 타입을 통해 컴파일 시점에 타입 오류를 잡아 런타임 버그를 줄여줍니다. 자동완성과 리팩터링 지원으로 개발 생산성이 높아지고, 타입이 곧 문서 역할을 해 대규모 협업과 유지보수에 유리합니다." + }, + { + "id": "ts-basic-002", + "question": "any, unknown, never의 차이는?", + "answer": "any는 타입 검사를 사실상 끄는 타입이라 위험합니다. unknown은 모든 값을 받지만 사용 전에 타입을 좁혀야 해 안전합니다. never는 절대 발생하지 않는 값(항상 예외를 던지거나 무한 루프인 함수의 반환)을 나타냅니다." + }, + { + "id": "ts-basic-003", + "question": "type과 interface의 차이는?", + "answer": "interface는 선언 병합이 가능하고 객체 구조 정의에 특화되어 확장에 유리합니다. type은 유니온, 인터섹션, 기본 타입 별칭 등 더 폭넓은 표현이 가능합니다. 객체 모양 정의는 interface, 복합 타입 표현은 type을 선호하는 편입니다." + }, + { + "id": "ts-basic-004", + "question": "타입 추론(Type Inference)이란?", + "answer": "명시적으로 타입을 적지 않아도 TypeScript가 값으로부터 타입을 자동으로 유추하는 기능입니다. let x = 3이면 x는 number로 추론됩니다. 추론이 충분히 정확한 경우 불필요한 타입 주석을 생략해 코드를 간결하게 유지합니다." + }, + { + "id": "ts-basic-005", + "question": "유니온 타입과 인터섹션 타입의 차이는?", + "answer": "유니온(A | B)은 여러 타입 중 하나일 수 있음을 의미하고, 인터섹션(A & B)은 여러 타입을 모두 만족(속성을 합침)해야 함을 의미합니다. 유니온은 선택, 인터섹션은 결합이라고 이해하면 쉽습니다." + }, + { + "id": "ts-basic-006", + "question": "리터럴 타입(Literal Type)은 무엇인가요?", + "answer": "특정 값 자체를 타입으로 사용하는 것입니다. type Dir = 'left' | 'right'처럼 정해진 값만 허용해, 잘못된 문자열 전달을 컴파일 단계에서 막고 자동완성도 제공합니다. 상수 집합을 표현할 때 유용합니다." + }, + { + "id": "ts-basic-007", + "question": "enum과 union 리터럴 중 무엇을 선호하나요?", + "answer": "상황에 따라 다릅니다. enum은 명명된 상수 집합과 역방향 매핑을 제공하지만 컴파일 결과 코드가 생기고 트리 쉐이킹이 어려울 수 있습니다. 유니온 리터럴이나 const 객체는 더 가볍고 타입 안전해 최근에는 후자를 선호하기도 합니다." + }, + { + "id": "ts-basic-008", + "question": "타입 단언(Type Assertion)은 무엇이고 주의점은?", + "answer": "as 키워드로 컴파일러에게 값의 타입을 개발자가 단언하는 것입니다. 실제 검사를 우회하므로 잘못 단언하면 런타임 오류로 이어질 수 있습니다. 정말 확신할 때만 사용하고 가능하면 타입 가드로 안전하게 좁히는 것이 좋습니다." + }, + { + "id": "ts-basic-009", + "question": "tuple 타입은 무엇인가요?", + "answer": "고정된 길이와 각 위치별 타입이 정해진 배열입니다. [string, number]는 첫 요소가 문자열, 둘째가 숫자여야 함을 의미합니다. React의 useState 반환값처럼 위치마다 의미가 다른 값을 표현할 때 사용합니다." + }, + { + "id": "ts-basic-010", + "question": "strict 모드는 어떤 검사를 강화하나요?", + "answer": "strictNullChecks, noImplicitAny 등 엄격한 검사들을 한꺼번에 켭니다. null/undefined를 명시적으로 다루게 하고 암시적 any를 금지해, 더 안전한 코드를 작성하도록 강제합니다. 새 프로젝트에서는 켜는 것이 권장됩니다." + } + ] + }, + { + "id": "ts-interface", + "name": "인터페이스와 객체 타입", + "questions": [ + { + "id": "ts-interface-001", + "question": "선택적 속성(optional)과 readonly는 어떻게 표현하나요?", + "answer": "속성 이름 뒤에 ?를 붙이면 선택적 속성으로 없어도 되고, 앞에 readonly를 붙이면 초기화 후 재할당이 불가능합니다. 예를 들어 { readonly id: number; name?: string }은 id는 불변, name은 선택적임을 나타냅니다." + }, + { + "id": "ts-interface-002", + "question": "인터페이스 확장(extends)은 어떻게 하나요?", + "answer": "interface B extends A 형태로 기존 인터페이스의 속성을 물려받아 확장합니다. 여러 인터페이스를 동시에 상속할 수도 있어 공통 속성을 재사용하고 계층적인 타입 구조를 만들기에 좋습니다." + }, + { + "id": "ts-interface-003", + "question": "인덱스 시그니처(Index Signature)란?", + "answer": "키의 이름을 미리 알 수 없을 때 키와 값의 타입을 정의하는 방법입니다. { [key: string]: number }는 문자열 키에 숫자 값을 갖는 객체를 의미합니다. 동적인 키를 가진 사전형 객체를 표현할 때 사용합니다." + }, + { + "id": "ts-interface-004", + "question": "함수 타입은 어떻게 정의하나요?", + "answer": "(a: number, b: number) => number처럼 매개변수와 반환 타입을 화살표로 표현합니다. 인터페이스 안에서 메서드 시그니처로 정의하거나 type 별칭으로 만들 수 있어, 콜백 타입이나 함수 형태를 재사용할 때 유용합니다." + }, + { + "id": "ts-interface-005", + "question": "선언 병합(Declaration Merging)이란 무엇인가요?", + "answer": "같은 이름의 interface를 여러 번 선언하면 자동으로 하나로 합쳐지는 기능입니다. 외부 라이브러리의 타입을 확장하거나 전역 타입을 보강할 때 활용됩니다. type 별칭에는 적용되지 않는 interface만의 특징입니다." + }, + { + "id": "ts-interface-006", + "question": "구조적 타이핑(Structural Typing)이란?", + "answer": "타입의 이름이 아니라 구조(속성과 형태)가 호환되면 같은 타입으로 취급하는 방식입니다. TypeScript는 구조적 타이핑을 따르므로, 명시적으로 상속하지 않아도 필요한 속성을 모두 갖추면 할당이 가능합니다." + }, + { + "id": "ts-interface-007", + "question": "객체 타입에서 과잉 속성 검사(Excess Property Check)란?", + "answer": "객체 리터럴을 직접 할당할 때 타입에 없는 속성이 있으면 오류를 내는 검사입니다. 오타나 의도치 않은 속성을 잡아줍니다. 변수에 먼저 담아 전달하면 이 검사를 우회할 수 있습니다." + }, + { + "id": "ts-interface-008", + "question": "메서드 시그니처와 속성 함수 정의의 차이는?", + "answer": "foo(): void는 메서드 단축 표기, foo: () => void는 함수 타입 속성입니다. 동작은 거의 같지만 strictFunctionTypes 하에서 매개변수 변형 검사가 다르게 적용되는 미묘한 차이가 있습니다." + }, + { + "id": "ts-interface-009", + "question": "인터페이스로 클래스의 구현을 강제할 수 있나요?", + "answer": "네, class C implements I 형태로 클래스가 인터페이스의 모든 멤버를 구현하도록 강제할 수 있습니다. 인터페이스는 공개 형태(계약)만 정의하므로 private 멤버나 구현 세부는 클래스가 책임집니다." + }, + { + "id": "ts-interface-010", + "question": "Record 타입은 무엇인가요?", + "answer": "Record는 키 타입 K와 값 타입 V를 갖는 객체 타입을 만드는 유틸리티입니다. Record처럼 키-값 매핑을 간결하게 표현하며, 인덱스 시그니처보다 의도가 명확하게 드러납니다." + } + ] + }, + { + "id": "ts-generic", + "name": "제네릭", + "questions": [ + { + "id": "ts-generic-001", + "question": "제네릭(Generic)이란 무엇이고 왜 쓰나요?", + "answer": "타입을 매개변수처럼 받아 사용하는 시점에 구체화하는 기능입니다. 어떤 타입이든 받아 처리하면서도 타입 정보를 잃지 않아, any 없이 재사용 가능하고 타입 안전한 함수/클래스를 만들 수 있습니다." + }, + { + "id": "ts-generic-002", + "question": "제네릭 제약(extends)은 어떻게 사용하나요?", + "answer": " 형태로 타입 매개변수가 특정 조건을 만족하도록 제한합니다. 예를 들어 는 length 속성이 있는 타입만 허용해, 함수 내부에서 안전하게 그 속성을 사용할 수 있게 합니다." + }, + { + "id": "ts-generic-003", + "question": "제네릭 함수의 기본 타입은 어떻게 지정하나요?", + "answer": " 형태로 타입 매개변수에 기본값을 줄 수 있습니다. 호출 시 타입을 명시하지 않으면 기본 타입이 사용되어, 자주 쓰는 타입을 기본으로 두고 필요할 때만 다른 타입을 지정하게 합니다." + }, + { + "id": "ts-generic-004", + "question": "여러 타입 매개변수를 가진 제네릭의 예는?", + "answer": "Map처럼 키와 값 두 타입이 필요한 경우 를 사용합니다. 예를 들어 function pair(k: K, v: V)는 서로 다른 두 타입을 각각 받아 그 관계를 유지하는 결과를 만들 수 있게 합니다." + }, + { + "id": "ts-generic-005", + "question": "제네릭과 any의 차이는?", + "answer": "any는 타입 정보를 잃어 무엇이든 허용하고 검사를 포기합니다. 제네릭은 호출 시점의 실제 타입을 보존해 입력과 출력의 타입 관계를 유지합니다. 따라서 제네릭이 타입 안전성과 자동완성 측면에서 훨씬 우월합니다." + }, + { + "id": "ts-generic-006", + "question": "제네릭 인터페이스와 제네릭 클래스의 예는?", + "answer": "interface Box { value: T }처럼 인터페이스에, class Container {}처럼 클래스에 타입 매개변수를 둘 수 있습니다. 사용 시점에 Box으로 구체화해 컨테이너형 자료구조를 타입 안전하게 표현합니다." + }, + { + "id": "ts-generic-007", + "question": "keyof와 제네릭을 함께 쓰는 패턴은?", + "answer": "function get(obj: T, key: K): T[K] 패턴이 대표적입니다. 객체의 실제 키만 인자로 받게 제한하고 해당 키의 값 타입을 정확히 반환해, 객체 접근을 타입 안전하게 만듭니다." + }, + { + "id": "ts-generic-008", + "question": "조건부 타입(Conditional Type)이란?", + "answer": "T extends U ? X : Y 형태로 타입을 조건에 따라 분기하는 기능입니다. 입력 타입에 따라 다른 타입을 반환하는 유연한 타입을 만들 수 있어, 유틸리티 타입 구현의 기반이 됩니다." + }, + { + "id": "ts-generic-009", + "question": "infer 키워드는 무엇인가요?", + "answer": "조건부 타입 안에서 타입의 일부를 추론해 변수처럼 캡처하는 키워드입니다. 예를 들어 함수의 반환 타입을 추출하는 ReturnType이 infer로 구현됩니다. 복잡한 타입에서 원하는 부분만 뽑아낼 때 사용합니다." + }, + { + "id": "ts-generic-010", + "question": "제네릭을 남용하면 안 되는 이유는?", + "answer": "필요 이상으로 제네릭을 쓰면 타입이 추상화되어 가독성이 떨어지고 추론이 어려워질 수 있습니다. 한 번만 쓰이거나 타입 관계가 단순한 경우 구체 타입이 더 명확합니다. 타입 간 관계가 실제로 있을 때만 사용하는 것이 좋습니다." + } + ] + }, + { + "id": "ts-utility", + "name": "유틸리티 타입", + "questions": [ + { + "id": "ts-utility-001", + "question": "Partial과 Required는 무엇인가요?", + "answer": "Partial는 T의 모든 속성을 선택적으로, Required는 모든 속성을 필수로 만듭니다. 일부만 업데이트하는 함수의 인자나, 선택적 속성을 모두 채워야 하는 상황을 타입으로 표현할 때 유용합니다." + }, + { + "id": "ts-utility-002", + "question": "Pick과 Omit의 차이는?", + "answer": "Pick는 T에서 K에 명시한 속성만 골라 새 타입을 만들고, Omit는 K에 명시한 속성을 제외한 나머지로 타입을 만듭니다. 큰 타입에서 필요한 부분만 추리거나 특정 속성을 빼낼 때 사용합니다." + }, + { + "id": "ts-utility-003", + "question": "Readonly 유틸리티 타입은 무엇인가요?", + "answer": "Readonly는 T의 모든 속성을 읽기 전용으로 만들어 초기화 후 변경을 막습니다. 불변 데이터를 다루거나 함수가 인자를 수정하지 못하도록 보장하고 싶을 때 사용합니다. 얕은 수준에만 적용된다는 점에 주의합니다." + }, + { + "id": "ts-utility-004", + "question": "ReturnType과 Parameters는 무엇인가요?", + "answer": "ReturnType는 함수 타입 F의 반환 타입을, Parameters는 매개변수들을 튜플로 추출합니다. 기존 함수의 시그니처를 재사용해 타입 중복을 줄이고, 함수 변경 시 타입이 자동으로 따라오게 합니다." + }, + { + "id": "ts-utility-005", + "question": "Record 유틸리티 타입의 활용 예는?", + "answer": "Record는 키 집합 K마다 값 타입 V를 갖는 객체를 만듭니다. 예를 들어 Record<'a' | 'b', number>는 a, b 키에 숫자를 갖는 객체를 강제합니다. 정해진 키들에 대한 매핑을 표현할 때 깔끔합니다." + }, + { + "id": "ts-utility-006", + "question": "Exclude와 Extract의 차이는?", + "answer": "Exclude는 유니온 T에서 U에 해당하는 멤버를 제거하고, Extract는 반대로 U에 해당하는 멤버만 추출합니다. 유니온 타입을 필터링해 원하는 부분만 남기거나 제외할 때 사용합니다." + }, + { + "id": "ts-utility-007", + "question": "NonNullable 타입은 무엇인가요?", + "answer": "NonNullable는 타입 T에서 null과 undefined를 제거한 타입을 만듭니다. 값이 반드시 존재한다고 좁힌 뒤 다룰 때나, 옵셔널 값을 검증 후 안전한 타입으로 변환할 때 유용합니다." + }, + { + "id": "ts-utility-008", + "question": "매핑된 타입(Mapped Type)이란?", + "answer": "기존 타입의 각 속성을 순회하며 새 타입을 생성하는 문법입니다. { [K in keyof T]: ... } 형태로 작성하며, Partial이나 Readonly 같은 유틸리티 타입이 이 매핑된 타입으로 구현됩니다." + }, + { + "id": "ts-utility-009", + "question": "Awaited 타입은 어떤 경우에 쓰나요?", + "answer": "Awaited는 Promise를 풀어(unwrap) 실제 해소 값의 타입을 얻습니다. 비동기 함수의 결과 타입을 추출하거나 중첩 Promise를 평탄화한 타입이 필요할 때 사용해, async 코드의 타입을 정확히 다룹니다." + }, + { + "id": "ts-utility-010", + "question": "유틸리티 타입을 조합한 예를 들어 주세요.", + "answer": "Partial>처럼 조합하면 User에서 name, email만 고른 뒤 모두 선택적으로 만든 타입이 됩니다. 이렇게 유틸리티 타입을 중첩하면 복잡한 요구사항도 간결하고 안전하게 표현할 수 있습니다." + } + ] + }, + { + "id": "ts-advanced", + "name": "고급 타입과 실전", + "questions": [ + { + "id": "ts-advanced-001", + "question": "타입 가드(Type Guard)란 무엇인가요?", + "answer": "런타임 검사를 통해 특정 블록 안에서 값의 타입을 좁혀주는 기법입니다. typeof, instanceof, in 연산자나 사용자 정의 타입 가드(value is Type)를 사용해, 유니온 타입을 안전하게 분기 처리합니다." + }, + { + "id": "ts-advanced-002", + "question": "사용자 정의 타입 가드는 어떻게 만드나요?", + "answer": "반환 타입을 value is Type 형태로 선언한 함수를 만듭니다. 예를 들어 function isDog(a: Animal): a is Dog { return 'bark' in a } 처럼 작성하면, 이 함수가 true를 반환한 블록에서 a가 Dog로 좁혀집니다." + }, + { + "id": "ts-advanced-003", + "question": "판별 유니온(Discriminated Union)이란?", + "answer": "공통의 리터럴 식별 속성(예: type 필드)을 가진 유니온 타입입니다. 그 속성 값으로 switch 분기하면 각 분기에서 정확한 타입으로 자동 좁혀집니다. 상태나 액션을 안전하게 모델링하는 강력한 패턴입니다." + }, + { + "id": "ts-advanced-004", + "question": "as const는 어떤 역할을 하나요?", + "answer": "값을 읽기 전용이며 가장 좁은 리터럴 타입으로 고정합니다. 배열은 readonly 튜플로, 객체 속성은 리터럴 타입으로 추론됩니다. 상수 객체나 설정 값에서 타입을 정확하게 좁히고 싶을 때 사용합니다." + }, + { + "id": "ts-advanced-005", + "question": "keyof 연산자는 무엇을 반환하나요?", + "answer": "객체 타입의 모든 키를 유니온 타입으로 반환합니다. keyof { a: 1; b: 2 }는 'a' | 'b'가 됩니다. 객체의 키만 인자로 받도록 제한하거나, 키 기반 매핑 타입을 만들 때 핵심적으로 쓰입니다." + }, + { + "id": "ts-advanced-006", + "question": "템플릿 리터럴 타입(Template Literal Type)이란?", + "answer": "백틱 문자열 타입 안에 다른 타입을 끼워 문자열 패턴을 타입으로 만드는 기능입니다. 예를 들어 `on${Capitalize}` 같은 식으로 이벤트 핸들러 이름 타입을 생성하는 등 문자열 조합을 타입 수준에서 다룹니다." + }, + { + "id": "ts-advanced-007", + "question": "타입 좁히기(Narrowing)의 흐름 분석이란?", + "answer": "TypeScript가 조건문, typeof, null 체크 등 코드 흐름을 분석해 변수의 타입을 자동으로 좁히는 것입니다. 예를 들어 if (x) 블록 안에서는 x의 falsy 가능성이 제거됩니다. 명시적 단언 없이 안전하게 다루게 해줍니다." + }, + { + "id": "ts-advanced-008", + "question": "satisfies 연산자는 무엇인가요?", + "answer": "값이 특정 타입을 만족하는지 검사하되, 추론된 더 좁은 타입은 그대로 유지하는 연산자입니다. as와 달리 타입 안전성을 해치지 않으면서 리터럴의 정확한 타입 추론을 보존할 수 있어, 설정 객체 검증에 유용합니다." + }, + { + "id": "ts-advanced-009", + "question": "declare 키워드는 언제 사용하나요?", + "answer": "실제 구현 없이 타입 정보만 선언할 때 사용합니다. 외부 자바스크립트 라이브러리나 전역 변수의 타입을 알려주는 선언 파일(.d.ts)에서 주로 쓰여, 타입 검사기가 존재를 인식하도록 합니다." + }, + { + "id": "ts-advanced-010", + "question": "제네릭과 조건부 타입으로 유틸리티 타입을 만드는 예는?", + "answer": "type ElementType = T extends (infer U)[] ? U : T처럼 작성하면 배열이면 요소 타입을, 아니면 그대로 반환하는 유틸리티가 됩니다. 제네릭, extends, infer를 조합해 입력에 따라 동적으로 타입을 계산할 수 있습니다." + } + ] + } + ] + }, + { + "id": "react", + "name": "React", + "categories": [ + { + "id": "react-component", + "name": "컴포넌트와 JSX", + "questions": [ + { + "id": "react-component-001", + "question": "JSX란 무엇인가요?", + "answer": "JavaScript 안에서 HTML과 유사한 문법으로 UI를 작성할 수 있게 해주는 확장 문법입니다. 브라우저는 JSX를 직접 이해하지 못하므로 Babel 등이 React.createElement 호출로 변환합니다. 마크업과 로직을 한곳에서 표현해 가독성을 높입니다." + }, + { + "id": "react-component-002", + "question": "함수형 컴포넌트와 클래스형 컴포넌트의 차이는?", + "answer": "클래스형은 this와 라이프사이클 메서드를 사용하고 코드가 장황합니다. 함수형은 훅으로 상태와 생명주기를 다루며 간결하고 테스트가 쉽습니다. 현재 React는 훅 기반의 함수형 컴포넌트를 권장합니다." + }, + { + "id": "react-component-003", + "question": "React에서 key를 사용하는 이유는?", + "answer": "리스트 렌더링 시 어떤 항목이 변경, 추가, 제거되었는지 식별하기 위해서입니다. 안정적인 고유 key가 있으면 React가 DOM을 효율적으로 재사용하고 정확히 갱신합니다. 인덱스를 key로 쓰면 순서 변경 시 버그가 생길 수 있습니다." + }, + { + "id": "react-component-004", + "question": "컴포넌트를 합성(Composition)하는 패턴은?", + "answer": "children prop으로 컴포넌트 안에 다른 컴포넌트를 끼워 넣거나, prop으로 컴포넌트를 전달하는 방식입니다. 상속 대신 합성을 사용하면 재사용성과 유연성이 높아져, React는 합성을 권장합니다." + }, + { + "id": "react-component-005", + "question": "Fragment는 무엇이고 왜 쓰나요?", + "answer": "불필요한 DOM 노드를 추가하지 않고 여러 요소를 그룹화하는 래퍼입니다. 컴포넌트는 단일 루트를 반환해야 하는데, 의미 없는 div로 감싸는 대신 Fragment(<>...)를 쓰면 DOM 구조를 깔끔하게 유지할 수 있습니다." + }, + { + "id": "react-component-006", + "question": "조건부 렌더링은 어떻게 구현하나요?", + "answer": "삼항 연산자, && 단축 평가, 변수에 JSX를 담아 분기하는 방식 등을 사용합니다. && 사용 시 왼쪽이 0 같은 falsy 숫자면 0이 화면에 노출될 수 있어, Boolean 변환이나 삼항으로 처리하는 것이 안전합니다." + }, + { + "id": "react-component-007", + "question": "controlled와 uncontrolled 컴포넌트의 차이는?", + "answer": "controlled는 입력값을 React state로 관리해 value와 onChange로 제어하고, uncontrolled는 DOM이 값을 직접 관리하며 ref로 읽습니다. 검증과 동적 제어가 필요하면 controlled, 단순 입력엔 uncontrolled가 간편합니다." + }, + { + "id": "react-component-008", + "question": "JSX에서 사용할 수 없는 HTML 속성명이 있나요?", + "answer": "class는 예약어라 className으로, for는 htmlFor로 써야 합니다. 또한 속성명은 camelCase(onClick, tabIndex)를 사용합니다. 이는 JSX가 결국 JavaScript 객체로 변환되기 때문에 생기는 규칙입니다." + }, + { + "id": "react-component-009", + "question": "컴포넌트가 순수해야 한다는 것은 무슨 의미인가요?", + "answer": "같은 props와 state면 항상 같은 JSX를 반환하고, 렌더링 중에 외부 값을 변경하지 않아야 한다는 의미입니다. 렌더링은 부수 효과 없이 순수하게 유지하고, 부수 효과는 useEffect나 이벤트 핸들러로 분리해야 예측 가능한 동작을 보장합니다." + }, + { + "id": "react-component-010", + "question": "props.children은 무엇인가요?", + "answer": "컴포넌트 태그 사이에 작성한 내용이 자동으로 전달되는 특별한 prop입니다. 레이아웃, 카드, 모달처럼 내부 콘텐츠가 바뀌는 래퍼 컴포넌트를 만들 때 사용해 유연한 합성을 가능하게 합니다." + } + ] + }, + { + "id": "react-state", + "name": "State와 Props", + "questions": [ + { + "id": "react-state-001", + "question": "state와 props의 차이는?", + "answer": "props는 부모가 자식에게 전달하는 읽기 전용 값이고, state는 컴포넌트가 내부에서 관리하며 변할 수 있는 값입니다. props는 외부에서 주입되어 자식이 직접 바꿀 수 없고, state는 자신이 소유하고 갱신합니다." + }, + { + "id": "react-state-002", + "question": "setState(또는 setter)가 비동기처럼 동작하는 이유는?", + "answer": "React가 성능을 위해 여러 상태 업데이트를 모아 일괄 처리(batching)하기 때문입니다. 그래서 set 직후 state를 읽으면 갱신 전 값일 수 있습니다. 이전 값에 의존하는 갱신은 함수형 업데이트(prev => prev + 1)를 사용해야 안전합니다." + }, + { + "id": "react-state-003", + "question": "상태를 직접 변경하면 안 되는 이유는?", + "answer": "React는 이전 state와 새 state의 참조를 비교해 리렌더링 여부를 결정하기 때문입니다. 객체나 배열을 직접 변경하면 참조가 그대로라 변경을 감지하지 못합니다. 항상 새 객체/배열을 만들어 불변하게 업데이트해야 합니다." + }, + { + "id": "react-state-004", + "question": "상태 끌어올리기(Lifting State Up)란?", + "answer": "여러 컴포넌트가 같은 상태를 공유해야 할 때, 그 상태를 가장 가까운 공통 부모로 옮기는 패턴입니다. 부모가 상태를 소유하고 props로 내려주면 자식들이 동일한 데이터를 일관되게 사용할 수 있습니다." + }, + { + "id": "react-state-005", + "question": "props drilling이란 무엇이고 어떻게 해결하나요?", + "answer": "중간에 필요 없는 컴포넌트들을 거쳐 props를 깊이 전달해야 하는 문제입니다. Context API로 전역적으로 값을 공유하거나, 상태 관리 라이브러리, 컴포넌트 합성으로 중간 전달을 줄여 해결합니다." + }, + { + "id": "react-state-006", + "question": "함수형 업데이트는 언제 사용하나요?", + "answer": "새 상태가 이전 상태에 의존할 때 사용합니다. setCount(prev => prev + 1)처럼 작성하면 batching이나 클로저로 인한 오래된 값 문제 없이 항상 최신 상태를 기준으로 갱신해 정확한 결과를 보장합니다." + }, + { + "id": "react-state-007", + "question": "객체나 배열 상태를 올바르게 업데이트하는 방법은?", + "answer": "원본을 변경하지 않고 스프레드 연산자나 map/filter로 새 복사본을 만들어 set 합니다. 예를 들어 setUser({...user, name: 'new'})처럼 갱신합니다. 중첩 구조는 각 단계마다 새 객체를 만들어야 참조가 바뀝니다." + }, + { + "id": "react-state-008", + "question": "파생 상태(derived state)는 어떻게 다루는 게 좋나요?", + "answer": "기존 state나 props로 계산할 수 있는 값은 별도 state로 저장하지 않고 렌더링 중 계산하는 것이 좋습니다. 불필요한 상태 중복과 동기화 버그를 막을 수 있으며, 계산이 무거우면 useMemo로 캐시합니다." + }, + { + "id": "react-state-009", + "question": "상태를 어디에 둘지 결정하는 기준은?", + "answer": "그 상태를 사용하는 컴포넌트들의 가장 가까운 공통 부모에 두는 것이 기본입니다. 한 컴포넌트만 쓰면 그 안에, 여러 곳에서 쓰면 공통 부모나 전역 상태로 올립니다. 가능한 한 사용 지점에 가깝게 두어 관리 범위를 좁힙니다." + }, + { + "id": "react-state-010", + "question": "key를 바꿔 컴포넌트를 리셋하는 기법은 무엇인가요?", + "answer": "컴포넌트에 부여한 key가 바뀌면 React는 기존 인스턴스를 버리고 새로 마운트하여 내부 state가 초기화됩니다. 폼을 특정 항목 전환 시 완전히 초기화하고 싶을 때 등 명시적 리셋 수단으로 활용할 수 있습니다." + } + ] + }, + { + "id": "react-hook", + "name": "훅(Hooks)", + "questions": [ + { + "id": "react-hook-001", + "question": "Hook의 규칙(Rules of Hooks)은 무엇인가요?", + "answer": "훅은 컴포넌트나 커스텀 훅의 최상위에서만 호출해야 하고, 조건문, 반복문, 중첩 함수 안에서 호출하면 안 됩니다. 이는 React가 렌더링마다 훅 호출 순서로 상태를 추적하기 때문이며, 순서가 어긋나면 버그가 발생합니다." + }, + { + "id": "react-hook-002", + "question": "useState는 어떻게 동작하나요?", + "answer": "컴포넌트에 상태 변수와 그 변수를 갱신하는 함수를 제공합니다. setter를 호출하면 상태가 업데이트되고 컴포넌트가 리렌더링됩니다. 초기값은 첫 렌더링에만 사용되며, 무거운 초기값은 함수 형태로 넘겨 지연 초기화할 수 있습니다." + }, + { + "id": "react-hook-003", + "question": "useEffect는 언제 실행되나요?", + "answer": "기본적으로 렌더링이 화면에 반영된 후 실행됩니다. 의존성 배열이 없으면 매 렌더링마다, 빈 배열이면 마운트 시 한 번, 값이 들어 있으면 그 값이 바뀔 때마다 실행됩니다. 반환한 정리 함수는 다음 실행 전과 언마운트 시 호출됩니다." + }, + { + "id": "react-hook-004", + "question": "useEffect의 의존성 배열을 잘못 다루면 어떤 문제가 생기나요?", + "answer": "필요한 값을 누락하면 오래된 값을 참조하는 stale closure 버그가, 불필요한 값을 넣거나 매번 새 객체를 넣으면 무한 실행이 발생할 수 있습니다. 사용하는 모든 외부 값을 정확히 넣고, 필요시 useCallback/useMemo로 안정화합니다." + }, + { + "id": "react-hook-005", + "question": "useMemo와 useCallback의 차이는?", + "answer": "useMemo는 계산 결과 값을, useCallback은 함수 자체를 메모이제이션합니다. useCallback(fn, deps)는 useMemo(() => fn, deps)와 같습니다. 둘 다 의존성이 바뀔 때만 다시 만들어 불필요한 재계산이나 자식 리렌더링을 막습니다." + }, + { + "id": "react-hook-006", + "question": "useRef의 두 가지 용도는?", + "answer": "첫째는 DOM 요소에 직접 접근하는 것이고, 둘째는 리렌더링을 유발하지 않고 값을 유지하는 가변 컨테이너로 쓰는 것입니다. 타이머 ID, 이전 값 저장 등 렌더링과 무관한 데이터를 담을 때 유용합니다." + }, + { + "id": "react-hook-007", + "question": "useReducer는 언제 useState 대신 쓰나요?", + "answer": "상태 로직이 복잡하거나 여러 하위 값이 함께 변하거나, 다음 상태가 이전 상태에 크게 의존할 때 적합합니다. 상태 변경 로직을 reducer 함수로 모아 예측 가능하게 관리할 수 있어 복잡한 폼이나 상태 머신에 유용합니다." + }, + { + "id": "react-hook-008", + "question": "커스텀 훅(Custom Hook)은 무엇이고 왜 만드나요?", + "answer": "use로 시작하는 함수로 여러 훅을 조합해 재사용 가능한 로직을 추출한 것입니다. 데이터 패칭, 폼 처리, 미디어쿼리 감지 등 공통 로직을 여러 컴포넌트에서 재사용하고 관심사를 분리할 수 있습니다." + }, + { + "id": "react-hook-009", + "question": "useContext는 어떻게 사용하나요?", + "answer": "createContext로 만든 Context를 useContext로 구독해 Provider가 제공하는 값을 직접 읽습니다. props drilling 없이 테마, 인증 정보 등을 전역적으로 공유할 수 있지만, 값이 바뀌면 구독한 모든 컴포넌트가 리렌더링되는 점을 유의합니다." + }, + { + "id": "react-hook-010", + "question": "useLayoutEffect와 useEffect의 차이는?", + "answer": "useEffect는 화면 페인트 후 비동기로, useLayoutEffect는 DOM 변경 직후 페인트 전 동기로 실행됩니다. 레이아웃 측정이나 깜빡임 방지가 필요할 때 useLayoutEffect를 쓰지만, 렌더링을 막으므로 대부분의 경우 useEffect가 권장됩니다." + } + ] + }, + { + "id": "react-render", + "name": "렌더링과 최적화", + "questions": [ + { + "id": "react-render-001", + "question": "Virtual DOM이란 무엇이고 왜 쓰나요?", + "answer": "실제 DOM을 본뜬 가벼운 JavaScript 객체 트리입니다. 상태 변화 시 새 가상 DOM을 만들어 이전 것과 비교(diffing)하고 변경된 부분만 실제 DOM에 반영합니다. 직접 DOM 조작보다 효율적이고 선언적으로 UI를 다룰 수 있게 해줍니다." + }, + { + "id": "react-render-002", + "question": "재조정(Reconciliation)이란 무엇인가요?", + "answer": "새 가상 DOM과 이전 가상 DOM을 비교해 실제 DOM에 적용할 최소한의 변경을 찾아내는 과정입니다. 타입이 같으면 속성만 갱신하고 다르면 교체하며, 리스트는 key로 항목을 식별해 효율을 높입니다." + }, + { + "id": "react-render-003", + "question": "컴포넌트는 언제 리렌더링되나요?", + "answer": "자신의 state가 바뀌거나, 전달받은 props가 바뀌거나, 부모가 리렌더링되거나, 구독한 Context 값이 바뀔 때 리렌더링됩니다. 부모가 렌더링되면 기본적으로 자식도 함께 렌더링되므로 최적화가 필요할 수 있습니다." + }, + { + "id": "react-render-004", + "question": "React.memo는 무엇을 하나요?", + "answer": "컴포넌트를 메모이제이션해 props가 바뀌지 않으면 리렌더링을 건너뛰게 합니다. 부모 리렌더링으로 인한 불필요한 자식 렌더링을 막을 때 유용하지만, props로 매번 새 객체/함수가 내려오면 효과가 없으므로 함께 최적화해야 합니다." + }, + { + "id": "react-render-005", + "question": "불필요한 리렌더링을 줄이는 방법들은?", + "answer": "React.memo로 컴포넌트를, useMemo로 값을, useCallback으로 함수를 메모이제이션하고, 상태를 필요한 범위로 분리하며, 자식에 새 객체/배열을 매번 넘기지 않도록 합니다. 다만 과도한 최적화는 오히려 복잡성을 높일 수 있습니다." + }, + { + "id": "react-render-006", + "question": "key로 인덱스를 쓰면 안 되는 이유는?", + "answer": "리스트의 순서가 바뀌거나 항목이 추가/삭제되면 인덱스가 다른 항목을 가리키게 되어, React가 잘못된 요소를 재사용해 입력값이 섞이거나 상태가 어긋나는 버그가 생깁니다. 항목 고유의 안정적인 id를 key로 써야 합니다." + }, + { + "id": "react-render-007", + "question": "큰 리스트를 효율적으로 렌더링하는 방법은?", + "answer": "화면에 보이는 항목만 렌더링하는 가상화(windowing) 기법을 사용합니다. react-window 같은 라이브러리로 보이는 영역의 요소만 DOM에 두어, 수천 개 항목도 적은 노드로 부드럽게 스크롤할 수 있게 합니다." + }, + { + "id": "react-render-008", + "question": "코드 분할(Code Splitting)과 lazy 로딩은 어떻게 하나요?", + "answer": "React.lazy와 Suspense로 컴포넌트를 필요할 때 비동기로 불러옵니다. 초기 번들 크기를 줄여 첫 로딩 속도를 개선하고, 라우트 단위나 무거운 컴포넌트 단위로 분할하면 효과가 큽니다." + }, + { + "id": "react-render-009", + "question": "useMemo를 남용하면 안 되는 이유는?", + "answer": "메모이제이션 자체에도 비교와 캐싱 비용이 들고 코드가 복잡해지기 때문입니다. 가벼운 계산까지 모두 감싸면 오히려 손해일 수 있습니다. 실제로 비용이 큰 계산이나 참조 안정성이 필요한 경우에만 선택적으로 사용합니다." + }, + { + "id": "react-render-010", + "question": "상태 구조 설계가 성능에 미치는 영향은?", + "answer": "자주 바뀌는 상태와 그렇지 않은 상태를 분리하면 리렌더링 범위를 좁힐 수 있습니다. 너무 큰 단일 상태 객체는 일부만 바뀌어도 전체를 갱신하게 하므로, 관심사별로 상태를 나누고 사용 지점 가까이 두는 것이 유리합니다." + } + ] + }, + { + "id": "react-lifecycle", + "name": "라이프사이클과 사이드 이펙트", + "questions": [ + { + "id": "react-lifecycle-001", + "question": "함수형 컴포넌트의 생명주기는 어떻게 표현되나요?", + "answer": "마운트, 업데이트, 언마운트를 useEffect로 표현합니다. 빈 의존성 배열은 마운트 시점, 의존성이 있는 경우는 해당 값 변경 시점, 반환된 정리 함수는 업데이트 직전과 언마운트 시점에 대응합니다." + }, + { + "id": "react-lifecycle-002", + "question": "useEffect의 cleanup 함수는 무엇을 하나요?", + "answer": "이펙트가 만든 구독, 타이머, 이벤트 리스너 등을 정리합니다. 다음 이펙트 실행 전과 컴포넌트 언마운트 시 호출되어, 메모리 누수와 중복 등록을 방지합니다. 정리하지 않으면 누적되어 버그와 성능 문제로 이어집니다." + }, + { + "id": "react-lifecycle-003", + "question": "데이터 패칭을 useEffect에서 할 때 주의점은?", + "answer": "비동기 응답이 도착하기 전에 컴포넌트가 언마운트되거나 의존성이 바뀌면 경쟁 상태(race condition)가 생길 수 있습니다. 정리 함수에서 무시 플래그를 두거나 AbortController로 요청을 취소해 오래된 응답이 상태를 덮어쓰지 않게 합니다." + }, + { + "id": "react-lifecycle-004", + "question": "마운트 시 한 번만 실행하려면 어떻게 하나요?", + "answer": "useEffect에 빈 의존성 배열([])을 전달하면 됩니다. 초기 데이터 로드, 외부 라이브러리 초기화 등 한 번만 필요한 작업에 적합합니다. 다만 내부에서 참조하는 외부 값이 있다면 누락되지 않도록 주의해야 합니다." + }, + { + "id": "react-lifecycle-005", + "question": "useEffect 안에서 async/await를 직접 쓸 수 없는 이유는?", + "answer": "useEffect 콜백은 정리 함수 또는 undefined를 반환해야 하는데, async 함수는 Promise를 반환하기 때문입니다. 내부에 async 함수를 따로 정의해 호출하거나 즉시 실행 함수로 감싸는 방식으로 처리합니다." + }, + { + "id": "react-lifecycle-006", + "question": "StrictMode에서 이펙트가 두 번 실행되는 이유는?", + "answer": "개발 모드에서 React가 정리 로직이 올바른지 검증하기 위해 의도적으로 마운트-언마운트-재마운트를 한 번 더 시뮬레이션하기 때문입니다. 프로덕션에서는 한 번만 실행되며, 이펙트를 멱등하고 정리 가능하게 작성하도록 유도합니다." + }, + { + "id": "react-lifecycle-007", + "question": "이벤트 리스너를 useEffect에서 등록할 때 패턴은?", + "answer": "이펙트 안에서 addEventListener로 등록하고, 정리 함수에서 같은 핸들러로 removeEventListener를 호출합니다. 핸들러가 매 렌더마다 새로 만들어지면 제거가 어긋날 수 있으므로 안정적인 참조를 유지하는 것이 중요합니다." + }, + { + "id": "react-lifecycle-008", + "question": "값이 바뀔 때만 특정 로직을 실행하려면?", + "answer": "의존성 배열에 감시할 값을 넣으면 그 값이 변경될 때만 이펙트가 실행됩니다. 이전 값과 비교가 필요하면 useRef에 이전 값을 저장해 두고 현재 값과 비교하는 패턴을 함께 사용할 수 있습니다." + }, + { + "id": "react-lifecycle-009", + "question": "구독(subscribe) 패턴을 React에서 안전하게 다루려면?", + "answer": "useEffect에서 구독을 시작하고 정리 함수에서 구독을 해제하는 것이 기본입니다. 외부 스토어 구독은 useSyncExternalStore 훅을 사용하면 동시성 환경에서도 일관된 값을 안전하게 읽을 수 있습니다." + }, + { + "id": "react-lifecycle-010", + "question": "렌더링과 사이드 이펙트를 분리해야 하는 이유는?", + "answer": "렌더링은 순수해야 예측 가능하고 React가 자유롭게 재실행할 수 있기 때문입니다. 네트워크 요청, DOM 조작, 구독 같은 부수 효과는 useEffect나 이벤트 핸들러로 분리해야 중복 실행이나 예기치 않은 동작을 피할 수 있습니다." + } + ] + }, + { + "id": "react-state-mgmt", + "name": "상태 관리와 데이터", + "questions": [ + { + "id": "react-state-mgmt-001", + "question": "Context API와 상태 관리 라이브러리의 차이는?", + "answer": "Context는 props drilling을 피하는 의존성 주입 도구에 가깝고 값이 바뀌면 구독자 전체가 리렌더링됩니다. Redux/Zustand 같은 라이브러리는 선택적 구독, 미들웨어, 개발 도구 등 대규모 상태 관리를 위한 기능을 제공합니다." + }, + { + "id": "react-state-mgmt-002", + "question": "전역 상태와 서버 상태는 어떻게 구분하나요?", + "answer": "전역 상태는 클라이언트가 소유하는 UI 상태(테마, 모달 열림 등)이고, 서버 상태는 서버가 진짜 출처인 데이터(목록, 사용자 정보)입니다. 서버 상태는 캐싱, 동기화, 무효화가 필요해 React Query 같은 전용 도구가 적합합니다." + }, + { + "id": "react-state-mgmt-003", + "question": "Redux의 핵심 원칙은 무엇인가요?", + "answer": "단일 스토어에 상태를 두고, 상태는 읽기 전용이며 액션으로만 변경하고, 변경은 순수 함수인 리듀서로 처리한다는 원칙입니다. 예측 가능한 단방향 데이터 흐름을 만들어 디버깅과 추적을 쉽게 합니다." + }, + { + "id": "react-state-mgmt-004", + "question": "React Query(TanStack Query)는 어떤 문제를 해결하나요?", + "answer": "서버 데이터의 캐싱, 백그라운드 갱신, 로딩/에러 상태 관리, 중복 요청 제거, 무효화 등을 자동으로 처리합니다. useEffect로 직접 패칭할 때 생기는 반복 코드와 경쟁 상태, 캐시 관리 문제를 크게 줄여줍니다." + }, + { + "id": "react-state-mgmt-005", + "question": "Context 사용 시 성능 문제를 줄이는 방법은?", + "answer": "자주 바뀌는 값과 거의 안 바뀌는 값을 별도 Context로 분리하고, Provider value를 useMemo로 안정화하며, 소비 컴포넌트를 memo로 감쌉니다. 값 변경 시 불필요한 구독자 리렌더링을 줄일 수 있습니다." + }, + { + "id": "react-state-mgmt-006", + "question": "낙관적 업데이트(Optimistic Update)란?", + "answer": "서버 응답을 기다리지 않고 UI를 먼저 변경한 뒤, 실패하면 되돌리는 기법입니다. 좋아요나 삭제처럼 성공 가능성이 높은 작업에서 즉각적인 반응성을 제공해 사용자 경험을 크게 개선합니다." + }, + { + "id": "react-state-mgmt-007", + "question": "상태 관리 라이브러리를 도입할지 판단하는 기준은?", + "answer": "여러 컴포넌트가 공유하는 상태가 많고 복잡하거나, props drilling이 심하거나, 비동기 흐름이 얽혀 추적이 어려울 때입니다. 단순한 앱은 useState와 Context로 충분하므로 필요가 명확할 때 도입하는 것이 좋습니다." + }, + { + "id": "react-state-mgmt-008", + "question": "Zustand 같은 경량 상태 관리의 특징은?", + "answer": "보일러플레이트가 적고 Provider 없이 훅으로 스토어를 바로 사용하며, 선택자로 필요한 상태만 구독해 리렌더링을 최소화합니다. Redux보다 가볍게 전역 상태를 다루고 싶을 때 인기 있는 선택지입니다." + }, + { + "id": "react-state-mgmt-009", + "question": "상태 정규화(normalization)란 무엇인가요?", + "answer": "중첩되고 중복된 데이터를 id를 키로 하는 평탄한 구조로 저장하는 방식입니다. 같은 데이터의 중복을 없애 갱신 시 한 곳만 바꾸면 되고, 조회와 일관성 유지가 쉬워집니다. 관계형 데이터를 다룰 때 유용합니다." + }, + { + "id": "react-state-mgmt-010", + "question": "캐시 무효화(invalidation)는 왜 중요한가요?", + "answer": "서버 데이터가 변경되면 클라이언트 캐시가 오래된(stale) 상태가 되기 때문입니다. 변경 작업 후 관련 쿼리를 무효화해 최신 데이터를 다시 가져오게 하면, 화면과 실제 데이터의 불일치를 방지할 수 있습니다." + } + ] + } + ] + }, + { + "id": "browser", + "name": "브라우저 동작 원리", + "categories": [ + { + "id": "browser-rendering", + "name": "렌더링 과정", + "questions": [ + { + "id": "browser-rendering-001", + "question": "브라우저가 화면을 그리는 과정을 설명해 주세요.", + "answer": "HTML을 파싱해 DOM 트리를, CSS를 파싱해 CSSOM 트리를 만들고, 둘을 합쳐 렌더 트리를 구성합니다. 이후 각 요소의 위치와 크기를 계산하는 레이아웃(리플로우), 픽셀을 채우는 페인트, 레이어를 합치는 합성(composite) 단계를 거쳐 화면에 표시됩니다." + }, + { + "id": "browser-rendering-002", + "question": "Critical Rendering Path(주요 렌더링 경로)란 무엇인가요?", + "answer": "HTML, CSS, JS를 받아 픽셀로 그려내기까지 브라우저가 반드시 거치는 단계들의 묶음입니다. DOM/CSSOM 생성, 렌더 트리, 레이아웃, 페인트로 이어지며, 이 경로를 최적화하면 첫 화면 표시 속도를 높일 수 있습니다." + }, + { + "id": "browser-rendering-003", + "question": "DOM과 렌더 트리의 차이는 무엇인가요?", + "answer": "DOM은 HTML 구조를 그대로 표현한 트리로 display:none 요소도 포함합니다. 렌더 트리는 실제 화면에 그려질 요소만 담으며 CSSOM의 스타일 정보가 결합되어 있습니다. 따라서 보이지 않는 요소는 렌더 트리에서 제외됩니다." + }, + { + "id": "browser-rendering-004", + "question": "CSS가 렌더링을 막는(render-blocking) 이유는 무엇인가요?", + "answer": "렌더 트리를 만들려면 CSSOM이 완성되어야 하기 때문입니다. CSS를 모두 받아 파싱하기 전에는 화면을 그릴 수 없으므로, CSS는 기본적으로 렌더링 차단 리소스로 취급됩니다. 그래서 CSS는 가능한 한 빨리, 작게 전달하는 것이 중요합니다." + }, + { + "id": "browser-rendering-005", + "question": "script 태그의 위치가 렌더링에 미치는 영향은?", + "answer": "기본 script는 만나는 즉시 다운로드와 실행을 위해 파싱을 멈춥니다. head에 두면 본문 렌더링이 지연되므로, 보통 body 끝에 두거나 async/defer를 사용합니다. 그래야 콘텐츠가 먼저 보이고 사용자 체감 속도가 빨라집니다." + }, + { + "id": "browser-rendering-006", + "question": "async와 defer의 차이는 무엇인가요?", + "answer": "둘 다 스크립트를 비동기로 내려받아 파싱을 막지 않습니다. async는 다운로드가 끝나는 즉시 실행되어 순서가 보장되지 않고, defer는 HTML 파싱이 끝난 뒤 선언된 순서대로 실행됩니다. 의존성이 있으면 defer가 안전합니다." + }, + { + "id": "browser-rendering-007", + "question": "합성(Composite) 단계는 무엇을 하나요?", + "answer": "페인트된 여러 레이어를 GPU를 활용해 하나의 최종 화면으로 합치는 과정입니다. transform이나 opacity처럼 합성만으로 처리되는 속성은 레이아웃과 페인트를 건너뛰므로 애니메이션 성능이 좋습니다." + }, + { + "id": "browser-rendering-008", + "question": "레이어(Layer)는 언제 분리되나요?", + "answer": "transform, opacity 애니메이션, will-change, position:fixed, video/canvas 등 특정 조건에서 브라우저가 별도 합성 레이어를 만듭니다. 레이어를 분리하면 해당 부분만 다시 합성할 수 있지만, 과도하면 메모리를 많이 쓰므로 주의해야 합니다." + }, + { + "id": "browser-rendering-009", + "question": "브라우저의 주요 구성 요소(엔진)는 무엇인가요?", + "answer": "사용자 인터페이스, 브라우저 엔진, 화면을 그리는 렌더링 엔진(Blink, WebKit 등), JS를 실행하는 자바스크립트 엔진(V8 등), 네트워크, UI 백엔드, 데이터 저장소 등으로 구성됩니다. 렌더링 엔진과 JS 엔진이 화면 표현의 핵심입니다." + }, + { + "id": "browser-rendering-010", + "question": "파싱 중 만난 외부 CSS는 JS 실행과 어떤 관계가 있나요?", + "answer": "JS는 스타일 정보를 읽을 수 있으므로, 앞선 CSS가 로드/파싱될 때까지 스크립트 실행이 지연될 수 있습니다. 즉 CSS가 JS 실행을 막고, JS가 DOM 파싱을 막는 의존 관계가 생겨 전체 렌더링이 늦어질 수 있습니다." + } + ] + }, + { + "id": "browser-dom", + "name": "DOM과 CSSOM", + "questions": [ + { + "id": "browser-dom-001", + "question": "DOM이란 무엇인가요?", + "answer": "Document Object Model의 약자로, HTML 문서를 객체 트리 구조로 표현한 것입니다. 각 태그가 노드가 되며, JS로 이 노드들에 접근해 내용, 구조, 스타일을 동적으로 읽고 변경할 수 있습니다." + }, + { + "id": "browser-dom-002", + "question": "DOM 조작이 비용이 큰 이유는 무엇인가요?", + "answer": "DOM 변경이 레이아웃과 페인트 같은 렌더링 작업을 유발할 수 있기 때문입니다. 특히 반복적으로 DOM을 읽고 쓰면 리플로우가 여러 번 발생해 성능이 저하됩니다. 그래서 변경을 모아서 처리하는 것이 좋습니다." + }, + { + "id": "browser-dom-003", + "question": "DocumentFragment는 왜 사용하나요?", + "answer": "메모리상에만 존재하는 가벼운 DOM 컨테이너로, 여러 노드를 먼저 fragment에 모은 뒤 한 번에 실제 DOM에 추가합니다. 중간 과정에서 리플로우가 발생하지 않아 다수의 요소를 삽입할 때 성능에 유리합니다." + }, + { + "id": "browser-dom-004", + "question": "Virtual DOM과 실제 DOM의 차이는 무엇인가요?", + "answer": "Virtual DOM은 실제 DOM을 본뜬 자바스크립트 객체입니다. 변경 시 가상 트리를 먼저 갱신하고 이전 트리와 비교(diffing)해 바뀐 부분만 실제 DOM에 반영합니다. 직접 DOM을 여러 번 만지는 것보다 효율적인 갱신이 가능합니다." + }, + { + "id": "browser-dom-005", + "question": "CSSOM이란 무엇인가요?", + "answer": "CSS Object Model로, CSS 규칙을 객체 트리로 표현한 것입니다. DOM이 구조를 담는다면 CSSOM은 각 요소에 적용될 스타일 정보를 담으며, 둘이 결합되어 렌더 트리가 만들어집니다." + }, + { + "id": "browser-dom-006", + "question": "노드(Node)와 요소(Element)의 차이는?", + "answer": "노드는 DOM 트리를 이루는 모든 것을 가리키는 상위 개념으로 텍스트, 주석, 요소 등을 포함합니다. 요소는 그중 HTML 태그에 해당하는 노드입니다. 즉 모든 요소는 노드지만 모든 노드가 요소는 아닙니다." + }, + { + "id": "browser-dom-007", + "question": "innerHTML과 textContent의 차이는?", + "answer": "innerHTML은 문자열을 HTML로 파싱해 태그를 해석하므로 XSS 위험이 있습니다. textContent는 순수 텍스트로만 다뤄 태그를 문자 그대로 표시하고 더 빠르며 안전합니다. 사용자 입력을 넣을 때는 textContent가 권장됩니다." + }, + { + "id": "browser-dom-008", + "question": "이벤트 위임(Event Delegation)이란 무엇인가요?", + "answer": "자식 각각에 핸들러를 붙이는 대신 공통 부모에 하나의 핸들러를 등록하고, 이벤트 버블링을 이용해 어떤 자식에서 발생했는지 판별하는 기법입니다. 동적으로 추가되는 요소에도 대응할 수 있고 메모리 사용이 효율적입니다." + }, + { + "id": "browser-dom-009", + "question": "querySelector와 getElementById의 차이는?", + "answer": "getElementById는 id로만 검색하며 매우 빠릅니다. querySelector는 CSS 선택자 문법을 사용해 더 유연하게 첫 번째 일치 요소를 찾지만 상대적으로 느립니다. 단순 id 조회는 getElementById가 효율적입니다." + }, + { + "id": "browser-dom-010", + "question": "라이브(live) 컬렉션과 정적(static) 컬렉션의 차이는?", + "answer": "getElementsByTagName 등이 반환하는 HTMLCollection은 DOM 변경을 실시간 반영하는 라이브 컬렉션입니다. querySelectorAll의 NodeList는 호출 시점의 상태를 담는 정적 컬렉션입니다. 반복 중 DOM을 바꿀 때 동작이 달라 주의해야 합니다." + } + ] + }, + { + "id": "browser-event", + "name": "이벤트 처리", + "questions": [ + { + "id": "browser-event-001", + "question": "이벤트 버블링과 캡처링이란 무엇인가요?", + "answer": "이벤트가 발생하면 최상위에서 대상까지 내려오는 캡처링 단계, 대상에서 최상위로 올라가는 버블링 단계를 거칩니다. 기본적으로 핸들러는 버블링 단계에서 실행되며, addEventListener의 세 번째 인자로 캡처링 단계 처리를 지정할 수 있습니다." + }, + { + "id": "browser-event-002", + "question": "event.preventDefault와 stopPropagation의 차이는?", + "answer": "preventDefault는 링크 이동이나 폼 제출 같은 브라우저 기본 동작을 막습니다. stopPropagation은 이벤트가 상위로 전파되는 것을 멈춥니다. 둘은 목적이 다르며 필요에 따라 함께 또는 따로 사용합니다." + }, + { + "id": "browser-event-003", + "question": "이벤트 루프(Event Loop)란 무엇인가요?", + "answer": "콜 스택이 비었을 때 태스크 큐의 콜백을 꺼내 실행하는 자바스크립트의 동시성 처리 메커니즘입니다. 싱글 스레드인 JS가 비동기 작업을 논블로킹으로 처리할 수 있게 해줍니다." + }, + { + "id": "browser-event-004", + "question": "매크로태스크와 마이크로태스크의 차이는?", + "answer": "setTimeout, 이벤트 콜백 등은 매크로태스크 큐에, Promise.then, queueMicrotask 등은 마이크로태스크 큐에 들어갑니다. 각 매크로태스크 실행 후 마이크로태스크 큐를 모두 비우므로 마이크로태스크가 먼저 처리됩니다." + }, + { + "id": "browser-event-005", + "question": "디바운스(debounce)와 스로틀(throttle)의 차이는?", + "answer": "디바운스는 마지막 호출 후 일정 시간이 지나야 한 번 실행해 입력 자동완성 등에 적합합니다. 스로틀은 일정 주기마다 최대 한 번만 실행해 스크롤이나 리사이즈처럼 빈번한 이벤트의 빈도를 제한할 때 씁니다." + }, + { + "id": "browser-event-006", + "question": "passive 이벤트 리스너는 무엇인가요?", + "answer": "preventDefault를 호출하지 않겠다고 미리 알려주는 리스너 옵션입니다. 브라우저가 스크롤을 막지 않을 것을 보장받아 즉시 스크롤할 수 있어, 터치/휠 이벤트의 스크롤 성능이 향상됩니다." + }, + { + "id": "browser-event-007", + "question": "커스텀 이벤트는 어떻게 만들고 사용하나요?", + "answer": "CustomEvent 생성자로 이벤트를 만들고 detail에 데이터를 담아 dispatchEvent로 발생시킵니다. addEventListener로 구독하면 컴포넌트 간 느슨하게 결합된 통신을 구현할 수 있습니다." + }, + { + "id": "browser-event-008", + "question": "마우스 이벤트와 포인터 이벤트의 차이는?", + "answer": "마우스 이벤트는 마우스 전용이고, 포인터 이벤트(Pointer Events)는 마우스, 터치, 펜 입력을 하나의 통합 API로 다룹니다. 다양한 입력 장치를 일관되게 처리하고 싶을 때 포인터 이벤트가 유리합니다." + }, + { + "id": "browser-event-009", + "question": "이벤트 핸들러를 제거하지 않으면 어떤 문제가 생기나요?", + "answer": "참조가 남아 가비지 컬렉션이 되지 않으므로 메모리 누수가 발생할 수 있습니다. 특히 SPA에서 컴포넌트가 사라질 때 removeEventListener로 정리하지 않으면 핸들러가 쌓여 성능이 점점 저하됩니다." + }, + { + "id": "browser-event-010", + "question": "requestAnimationFrame은 언제 사용하나요?", + "answer": "다음 화면 갱신 직전에 콜백을 실행하도록 예약하는 API로, 보통 초당 60회 주기에 맞춰집니다. setTimeout 기반 애니메이션보다 부드럽고, 탭이 비활성일 때 자동으로 멈춰 자원도 절약합니다." + } + ] + }, + { + "id": "browser-storage", + "name": "브라우저 저장소", + "questions": [ + { + "id": "browser-storage-001", + "question": "localStorage와 sessionStorage의 차이는?", + "answer": "둘 다 키-값을 문자열로 저장하지만, localStorage는 명시적으로 지우기 전까지 영구 보관되고 sessionStorage는 탭이 닫히면 사라집니다. 또한 sessionStorage는 같은 탭 내에서만 공유됩니다." + }, + { + "id": "browser-storage-002", + "question": "쿠키와 localStorage의 차이는?", + "answer": "쿠키는 매 요청마다 서버로 자동 전송되며 용량이 약 4KB로 작고 만료 설정이 가능합니다. localStorage는 서버로 전송되지 않고 약 5~10MB까지 저장하며 클라이언트 전용입니다. 인증 정보는 보통 쿠키, 단순 클라이언트 데이터는 localStorage가 적합합니다." + }, + { + "id": "browser-storage-003", + "question": "IndexedDB는 언제 사용하나요?", + "answer": "대용량 구조화 데이터를 클라이언트에 저장해야 할 때 사용하는 비동기 트랜잭션 기반 데이터베이스입니다. 객체 저장, 인덱싱, 검색을 지원해 오프라인 앱이나 대량 캐시에 적합합니다." + }, + { + "id": "browser-storage-004", + "question": "쿠키의 HttpOnly 속성은 무엇인가요?", + "answer": "자바스크립트의 document.cookie로 접근하지 못하게 막는 속성입니다. XSS 공격으로 토큰이 탈취되는 것을 방지하므로, 세션 식별자 같은 민감한 쿠키에 반드시 설정하는 것이 좋습니다." + }, + { + "id": "browser-storage-005", + "question": "쿠키의 Secure와 SameSite 속성은?", + "answer": "Secure는 HTTPS 연결에서만 쿠키를 전송하게 합니다. SameSite는 교차 사이트 요청에 쿠키를 보낼지 제어하며 Strict/Lax/None 값을 가집니다. CSRF 공격을 완화하는 데 SameSite가 중요한 역할을 합니다." + }, + { + "id": "browser-storage-006", + "question": "Web Storage의 한계는 무엇인가요?", + "answer": "문자열만 저장되어 객체는 직렬화가 필요하고, 동기 API라 대량 처리 시 메인 스레드를 막을 수 있습니다. 또 도메인당 용량 제한이 있고 보안 저장소가 아니므로 민감 정보 저장에는 부적합합니다." + }, + { + "id": "browser-storage-007", + "question": "Cache Storage와 HTTP 캐시는 어떻게 다른가요?", + "answer": "HTTP 캐시는 브라우저가 헤더에 따라 자동 관리하는 캐시입니다. Cache Storage는 서비스 워커에서 코드로 요청/응답을 직접 저장하고 제어하는 API로, 오프라인 지원과 세밀한 캐싱 전략 구현에 사용됩니다." + }, + { + "id": "browser-storage-008", + "question": "서비스 워커(Service Worker)란 무엇인가요?", + "answer": "브라우저와 네트워크 사이에서 동작하는 백그라운드 스크립트로, 네트워크 요청을 가로채 캐시로 응답하거나 푸시 알림을 처리합니다. PWA의 오프라인 기능과 백그라운드 동기화의 핵심입니다." + }, + { + "id": "browser-storage-009", + "question": "저장소 데이터를 안전하게 다루려면 어떻게 해야 하나요?", + "answer": "민감 정보(비밀번호, 토큰)는 localStorage에 평문 저장하지 않고, 필요한 경우 HttpOnly 쿠키를 사용합니다. 저장 전 검증과 인코딩으로 XSS를 방지하고, 만료와 삭제 정책을 명확히 둡니다." + }, + { + "id": "browser-storage-010", + "question": "storage 이벤트는 언제 발생하나요?", + "answer": "같은 출처의 다른 탭이나 창에서 localStorage가 변경될 때 발생합니다. 이를 활용하면 여러 탭 간 상태 동기화(예: 로그아웃 전파)를 구현할 수 있습니다. 변경을 일으킨 탭 자신에서는 발생하지 않습니다." + } + ] + }, + { + "id": "browser-reflow", + "name": "리플로우와 리페인트", + "questions": [ + { + "id": "browser-reflow-001", + "question": "리플로우(Reflow)란 무엇인가요?", + "answer": "요소의 크기나 위치가 바뀌어 레이아웃을 다시 계산하는 과정입니다. 한 요소의 변경이 주변과 전체 트리에 영향을 줄 수 있어 비용이 크며, 너비/높이/위치/폰트 크기 변경 등이 이를 유발합니다." + }, + { + "id": "browser-reflow-002", + "question": "리페인트(Repaint)란 무엇인가요?", + "answer": "레이아웃은 그대로지만 색상, 배경, 가시성 등 시각적 속성이 바뀌어 픽셀을 다시 칠하는 과정입니다. 리플로우보다는 가볍지만 여전히 비용이 있으며, 리플로우가 일어나면 리페인트도 함께 발생합니다." + }, + { + "id": "browser-reflow-003", + "question": "리플로우를 유발하는 작업에는 어떤 것이 있나요?", + "answer": "요소 추가/삭제, 크기·위치·폰트 변경, 윈도우 리사이즈 등이 있습니다. 또한 offsetHeight, getComputedStyle처럼 레이아웃 정보를 읽는 것도 강제 동기 리플로우를 유발할 수 있습니다." + }, + { + "id": "browser-reflow-004", + "question": "강제 동기 레이아웃(Forced Synchronous Layout)이란?", + "answer": "스타일을 변경한 직후 레이아웃 값을 읽어 브라우저가 즉시 레이아웃을 다시 계산하게 만드는 현상입니다. 반복문 안에서 읽기와 쓰기를 번갈아 하면 레이아웃 스래싱이 발생해 성능이 크게 떨어집니다." + }, + { + "id": "browser-reflow-005", + "question": "레이아웃 스래싱(Layout Thrashing)을 어떻게 피하나요?", + "answer": "DOM 읽기와 쓰기를 분리해 읽기를 먼저 모아서 하고 쓰기를 나중에 일괄 처리합니다. 또는 requestAnimationFrame으로 변경을 묶고, 배치 측정 라이브러리를 활용하면 반복적 리플로우를 줄일 수 있습니다." + }, + { + "id": "browser-reflow-006", + "question": "transform이 left/top보다 애니메이션에 유리한 이유는?", + "answer": "left/top 변경은 레이아웃과 페인트를 유발하지만, transform과 opacity는 합성 단계에서만 처리되어 레이아웃·페인트를 건너뜁니다. 그래서 GPU 가속을 받아 더 부드럽고 효율적인 애니메이션이 가능합니다." + }, + { + "id": "browser-reflow-007", + "question": "will-change 속성은 어떤 역할을 하나요?", + "answer": "특정 속성이 곧 변경될 것임을 브라우저에 미리 알려, 해당 요소를 별도 레이어로 준비시켜 변화를 부드럽게 합니다. 다만 남용하면 메모리를 과도하게 사용하므로 꼭 필요한 곳에만 적용해야 합니다." + }, + { + "id": "browser-reflow-008", + "question": "DOM 변경을 모아서 처리하면 왜 좋은가요?", + "answer": "변경마다 리플로우가 일어나는 대신 한 번에 처리하면 레이아웃 계산 횟수가 줄어들기 때문입니다. DocumentFragment 사용이나 클래스 토글로 여러 스타일을 한 번에 바꾸는 방식이 대표적입니다." + }, + { + "id": "browser-reflow-009", + "question": "display:none과 visibility:hidden의 렌더링 차이는?", + "answer": "display:none은 렌더 트리에서 제외되어 공간을 차지하지 않고 리플로우를 유발합니다. visibility:hidden은 공간은 유지한 채 보이지만 않으므로 리페인트만 발생합니다. 토글 빈도와 레이아웃 영향에 따라 선택이 달라집니다." + }, + { + "id": "browser-reflow-010", + "question": "contain 속성은 성능에 어떻게 도움이 되나요?", + "answer": "요소의 레이아웃, 스타일, 페인트 영향 범위를 해당 서브트리로 격리하도록 브라우저에 알리는 속성입니다. 변경 시 영향 범위가 제한되어 리플로우/리페인트 계산이 줄어들어 렌더링 성능이 향상됩니다." + } + ] + } + ] + }, + { + "id": "network", + "name": "네트워크", + "categories": [ + { + "id": "network-http", + "name": "HTTP 기초", + "questions": [ + { + "id": "network-http-001", + "question": "HTTP란 무엇인가요?", + "answer": "웹에서 클라이언트와 서버가 데이터를 주고받기 위한 요청-응답 기반의 통신 프로토콜입니다. 상태를 저장하지 않는(stateless) 특성을 가지며, 텍스트 기반 메시지로 동작합니다." + }, + { + "id": "network-http-002", + "question": "HTTP가 무상태(stateless)라는 것은 무슨 의미인가요?", + "answer": "각 요청이 독립적이며 서버가 이전 요청의 정보를 기억하지 않는다는 뜻입니다. 그래서 로그인 상태 유지 같은 기능은 쿠키, 세션, 토큰 등 별도 수단으로 상태를 관리해야 합니다." + }, + { + "id": "network-http-003", + "question": "HTTP/1.1과 HTTP/2의 차이는 무엇인가요?", + "answer": "HTTP/1.1은 연결당 요청을 순차 처리해 HOL 블로킹이 있습니다. HTTP/2는 하나의 연결에서 여러 요청을 동시에 보내는 멀티플렉싱, 헤더 압축, 서버 푸시를 지원해 성능이 크게 향상됩니다." + }, + { + "id": "network-http-004", + "question": "HTTP/3는 무엇이 다른가요?", + "answer": "전송 계층으로 TCP 대신 UDP 기반의 QUIC을 사용합니다. 연결 수립이 빠르고, TCP의 HOL 블로킹 문제를 해소하며, 네트워크가 바뀌어도 연결을 유지하는 등 모바일 환경에서 특히 유리합니다." + }, + { + "id": "network-http-005", + "question": "HTTP 요청 메시지의 구조는 어떻게 되나요?", + "answer": "메서드와 경로, 버전이 담긴 시작 줄(start line), 메타데이터를 담은 헤더, 빈 줄, 그리고 선택적인 본문(body)으로 구성됩니다. 응답 메시지도 상태 줄, 헤더, 본문 구조를 가집니다." + }, + { + "id": "network-http-006", + "question": "Keep-Alive(지속 연결)란 무엇인가요?", + "answer": "하나의 TCP 연결을 여러 요청에 재사용하는 기능입니다. 매 요청마다 연결을 새로 맺는 비용을 줄여 지연을 감소시키며, HTTP/1.1에서는 기본으로 활성화되어 있습니다." + }, + { + "id": "network-http-007", + "question": "TCP와 UDP의 차이는 무엇인가요?", + "answer": "TCP는 연결을 맺고 순서와 도착을 보장하는 신뢰성 있는 프로토콜로 웹/파일 전송에 쓰입니다. UDP는 연결 없이 빠르게 보내지만 손실·순서를 보장하지 않아 실시간 스트리밍이나 게임에 적합합니다." + }, + { + "id": "network-http-008", + "question": "TCP 3-way handshake란 무엇인가요?", + "answer": "연결을 맺기 위해 클라이언트와 서버가 SYN, SYN-ACK, ACK 세 단계로 패킷을 주고받는 과정입니다. 양쪽이 서로 통신할 준비가 되었음을 확인한 뒤 데이터 전송을 시작합니다." + }, + { + "id": "network-http-009", + "question": "URL을 입력하면 화면이 뜨기까지 과정을 설명해 주세요.", + "answer": "DNS로 도메인을 IP로 변환하고, TCP(및 HTTPS면 TLS) 연결을 맺은 뒤 HTTP 요청을 보냅니다. 서버 응답으로 받은 HTML을 파싱해 추가 리소스를 받고, 렌더링 과정을 거쳐 화면에 표시합니다." + }, + { + "id": "network-http-010", + "question": "DNS는 어떤 역할을 하나요?", + "answer": "사람이 읽는 도메인 이름을 컴퓨터가 사용하는 IP 주소로 변환해 주는 시스템입니다. 브라우저는 캐시, 로컬, 재귀 DNS 서버를 거쳐 IP를 조회하며, 이 과정의 지연도 초기 로딩 속도에 영향을 줍니다." + } + ] + }, + { + "id": "network-method", + "name": "메서드와 상태 코드", + "questions": [ + { + "id": "network-method-001", + "question": "주요 HTTP 메서드와 용도를 설명해 주세요.", + "answer": "GET은 조회, POST는 생성, PUT은 전체 수정/교체, PATCH는 부분 수정, DELETE는 삭제에 사용합니다. 각 메서드는 리소스에 대한 의도를 나타내며 RESTful 설계의 기본이 됩니다." + }, + { + "id": "network-method-002", + "question": "GET과 POST의 차이는 무엇인가요?", + "answer": "GET은 데이터를 URL 쿼리로 보내며 조회용이고 캐시·북마크가 가능합니다. POST는 본문에 데이터를 담아 서버 상태를 변경하는 데 쓰이며, 캐시되지 않고 길이 제한이 사실상 없습니다." + }, + { + "id": "network-method-003", + "question": "멱등성(Idempotency)이란 무엇인가요?", + "answer": "같은 요청을 여러 번 보내도 결과가 동일한 성질입니다. GET, PUT, DELETE는 멱등하지만 POST는 호출할 때마다 새 리소스를 만들 수 있어 멱등하지 않습니다. 재시도 안전성과 관련이 깊습니다." + }, + { + "id": "network-method-004", + "question": "PUT과 PATCH의 차이는?", + "answer": "PUT은 리소스 전체를 보낸 값으로 교체하므로 누락된 필드는 사라질 수 있습니다. PATCH는 변경할 일부 필드만 보내 부분 수정합니다. 전체 갱신은 PUT, 부분 갱신은 PATCH가 적절합니다." + }, + { + "id": "network-method-005", + "question": "HTTP 상태 코드 분류를 설명해 주세요.", + "answer": "1xx는 정보, 2xx는 성공, 3xx는 리다이렉션, 4xx는 클라이언트 오류, 5xx는 서버 오류를 나타냅니다. 앞자리만 봐도 응답의 대략적인 성격을 파악할 수 있습니다." + }, + { + "id": "network-method-006", + "question": "200, 201, 204의 차이는?", + "answer": "200은 요청 성공과 본문 반환, 201은 리소스 생성 성공(주로 POST 후), 204는 성공했지만 반환할 본문이 없음을 의미합니다. 상황에 맞는 코드를 쓰면 API 의도가 명확해집니다." + }, + { + "id": "network-method-007", + "question": "301과 302의 차이는 무엇인가요?", + "answer": "301은 영구 이동으로 브라우저와 검색엔진이 새 URL로 갱신하고 캐시합니다. 302는 일시적 이동으로 원래 URL을 유지합니다. SEO에 영향을 주므로 영구 변경에는 301을 사용합니다." + }, + { + "id": "network-method-008", + "question": "401과 403의 차이는?", + "answer": "401 Unauthorized는 인증이 필요하거나 실패한 경우(누구인지 모름)이고, 403 Forbidden은 인증은 됐지만 권한이 없는 경우(누구인지 알지만 금지)입니다. 인증과 인가의 차이를 반영합니다." + }, + { + "id": "network-method-009", + "question": "404와 410의 차이는?", + "answer": "404 Not Found는 리소스를 찾을 수 없음을 의미하며 일시적일 수 있습니다. 410 Gone은 리소스가 영구히 삭제되어 다시 제공되지 않음을 명시합니다. 410은 검색엔진에 더 강한 신호를 줍니다." + }, + { + "id": "network-method-010", + "question": "500과 503의 차이는?", + "answer": "500 Internal Server Error는 서버 내부의 예기치 못한 오류를 의미합니다. 503 Service Unavailable은 과부하나 점검 등으로 일시적으로 처리 불가한 상태로, Retry-After 헤더로 재시도 시점을 안내할 수 있습니다." + } + ] + }, + { + "id": "network-https", + "name": "HTTPS와 보안", + "questions": [ + { + "id": "network-https-001", + "question": "HTTPS란 무엇인가요?", + "answer": "HTTP에 TLS 암호화를 더한 프로토콜입니다. 데이터를 암호화해 도청과 변조를 막고, 인증서로 서버의 신원을 확인합니다. 현대 웹에서는 보안과 신뢰를 위해 사실상 필수입니다." + }, + { + "id": "network-https-002", + "question": "HTTPS는 어떻게 보안을 제공하나요?", + "answer": "기밀성(암호화로 도청 방지), 무결성(변조 감지), 인증(인증서로 서버 신원 확인)을 제공합니다. 대칭키로 데이터를 암호화하고, 그 대칭키 교환은 공개키 방식으로 안전하게 처리합니다." + }, + { + "id": "network-https-003", + "question": "TLS 핸드셰이크는 어떻게 동작하나요?", + "answer": "클라이언트와 서버가 사용할 암호 방식을 협상하고, 서버 인증서를 검증한 뒤, 안전하게 세션용 대칭키를 교환합니다. 이후 통신은 빠른 대칭키 암호화로 이루어집니다." + }, + { + "id": "network-https-004", + "question": "대칭키와 비대칭키 암호화의 차이는?", + "answer": "대칭키는 같은 키로 암복호화해 빠르지만 키 공유가 어렵습니다. 비대칭키는 공개키와 개인키 쌍을 사용해 키 교환과 서명에 유리하지만 느립니다. HTTPS는 둘을 결합해 장점을 취합니다." + }, + { + "id": "network-https-005", + "question": "SSL 인증서(디지털 인증서)는 무엇을 보장하나요?", + "answer": "인증기관(CA)이 서명한 문서로, 해당 도메인의 공개키와 소유자 신원을 보증합니다. 브라우저는 이를 검증해 접속한 서버가 사칭이 아닌지 확인하고, 신뢰할 수 없으면 경고를 표시합니다." + }, + { + "id": "network-https-006", + "question": "HTTPS여도 안전하지 않은 경우가 있나요?", + "answer": "전송 구간은 안전하지만 서버 자체의 취약점, XSS, 피싱 사이트의 유효 인증서 등은 막지 못합니다. 즉 HTTPS는 통신 보안을 보장할 뿐, 애플리케이션 수준의 보안은 별도로 챙겨야 합니다." + }, + { + "id": "network-https-007", + "question": "HSTS란 무엇인가요?", + "answer": "HTTP Strict Transport Security로, 브라우저가 해당 사이트에 항상 HTTPS로만 접속하도록 강제하는 응답 헤더입니다. HTTP로의 다운그레이드 공격과 중간자 공격 위험을 줄여줍니다." + }, + { + "id": "network-https-008", + "question": "혼합 콘텐츠(Mixed Content)란 무엇인가요?", + "answer": "HTTPS 페이지에서 이미지·스크립트 등 일부 리소스를 HTTP로 불러오는 상황입니다. 보안이 약해지고 브라우저가 차단하거나 경고하므로, 모든 리소스를 HTTPS로 제공해야 합니다." + }, + { + "id": "network-https-009", + "question": "중간자 공격(MITM)이란 무엇인가요?", + "answer": "공격자가 통신 양측 사이에 끼어들어 데이터를 가로채거나 변조하는 공격입니다. HTTPS의 암호화와 인증서 검증은 이런 공격을 어렵게 만들며, 신뢰할 수 없는 인증서 경고를 무시하면 위험에 노출됩니다." + }, + { + "id": "network-https-010", + "question": "TLS 1.3은 이전 버전보다 무엇이 개선되었나요?", + "answer": "핸드셰이크 왕복 횟수를 줄여 연결이 더 빠르고, 취약한 옛 암호 알고리즘을 제거해 보안이 강화되었습니다. 0-RTT 재개 기능으로 재접속 지연도 줄일 수 있습니다." + } + ] + }, + { + "id": "network-rest", + "name": "REST와 API", + "questions": [ + { + "id": "network-rest-001", + "question": "REST란 무엇인가요?", + "answer": "자원을 URI로 식별하고 HTTP 메서드로 행위를 표현하는 아키텍처 스타일입니다. 무상태성, 일관된 인터페이스, 자원 중심 설계를 원칙으로 하며 웹 API 설계에 널리 쓰입니다." + }, + { + "id": "network-rest-002", + "question": "RESTful API 설계의 좋은 관례는?", + "answer": "자원은 명사 복수형 URI(/users/1)로 표현하고, 행위는 HTTP 메서드로 구분하며, 적절한 상태 코드를 반환합니다. 동사를 URI에 넣지 않고 일관된 명명과 버전 관리를 유지하는 것이 좋습니다." + }, + { + "id": "network-rest-003", + "question": "REST와 GraphQL의 차이는 무엇인가요?", + "answer": "REST는 엔드포인트마다 정해진 응답을 주어 오버페칭/언더페칭이 생길 수 있습니다. GraphQL은 클라이언트가 필요한 필드만 단일 엔드포인트로 질의해 받아옵니다. 유연성은 GraphQL, 단순함과 캐싱은 REST가 강점입니다." + }, + { + "id": "network-rest-004", + "question": "오버페칭과 언더페칭이란 무엇인가요?", + "answer": "오버페칭은 필요 이상으로 많은 데이터를 받는 것이고, 언더페칭은 한 번 요청으로 부족해 여러 번 호출해야 하는 상황입니다. 고정된 REST 응답에서 흔히 발생하며 GraphQL이 이를 완화합니다." + }, + { + "id": "network-rest-005", + "question": "API 버전 관리는 왜, 어떻게 하나요?", + "answer": "기존 클라이언트를 깨뜨리지 않고 API를 발전시키기 위해서입니다. URI 경로(/v1/), 쿼리 파라미터, 헤더 방식 등이 있으며, 호환성을 유지하면서 점진적으로 마이그레이션하도록 돕습니다." + }, + { + "id": "network-rest-006", + "question": "페이지네이션 방식에는 어떤 것이 있나요?", + "answer": "offset/limit 방식은 구현이 쉽지만 데이터가 바뀌면 누락·중복이 생길 수 있습니다. 커서(cursor) 기반은 마지막 항목 기준으로 다음을 가져와 대용량과 실시간 데이터에 더 안정적입니다." + }, + { + "id": "network-rest-007", + "question": "REST에서 무상태성이 중요한 이유는?", + "answer": "각 요청이 독립적이라 서버가 세션을 보관하지 않아도 되고, 어떤 서버 인스턴스든 요청을 처리할 수 있어 수평 확장과 부하 분산이 쉬워지기 때문입니다." + }, + { + "id": "network-rest-008", + "question": "멱등성과 안전성(Safe) 메서드 개념을 API 관점에서 설명해 주세요.", + "answer": "안전한 메서드(GET 등)는 서버 상태를 바꾸지 않습니다. 멱등한 메서드(GET, PUT, DELETE)는 반복해도 결과가 같습니다. 이를 지키면 캐싱, 재시도, 프리페치를 안전하게 적용할 수 있습니다." + }, + { + "id": "network-rest-009", + "question": "API 에러 응답은 어떻게 설계하는 것이 좋나요?", + "answer": "적절한 HTTP 상태 코드와 함께 일관된 본문 구조(에러 코드, 메시지, 상세)를 제공합니다. 클라이언트가 프로그래밍적으로 처리할 수 있도록 사람이 읽는 메시지와 기계용 코드를 함께 주는 것이 좋습니다." + }, + { + "id": "network-rest-010", + "question": "Polling, Long Polling, WebSocket의 차이는?", + "answer": "Polling은 주기적으로 요청해 확인하고, Long Polling은 응답을 보류했다가 데이터가 생기면 반환합니다. WebSocket은 양방향 지속 연결로 실시간 통신에 가장 적합합니다. 실시간성 요구와 서버 부하에 따라 선택합니다." + } + ] + }, + { + "id": "network-cache", + "name": "캐싱", + "questions": [ + { + "id": "network-cache-001", + "question": "HTTP 캐싱이란 무엇인가요?", + "answer": "이전에 받은 응답을 재사용해 불필요한 요청과 전송을 줄이는 기법입니다. 로딩 속도를 높이고 서버 부하와 대역폭을 줄이며, 응답 헤더로 캐시 동작을 제어합니다." + }, + { + "id": "network-cache-002", + "question": "Cache-Control의 주요 지시어를 설명해 주세요.", + "answer": "max-age는 캐시 유효 기간, no-cache는 사용 전 재검증, no-store는 저장 금지, public/private은 공유 캐시 허용 여부를 지정합니다. 이를 조합해 리소스별 캐싱 전략을 세웁니다." + }, + { + "id": "network-cache-003", + "question": "강한 캐시와 약한 캐시(재검증)의 차이는?", + "answer": "강한 캐시는 max-age/Expires 동안 서버에 묻지 않고 바로 캐시를 사용합니다. 약한 캐시는 ETag/Last-Modified로 변경 여부를 서버에 확인한 뒤 사용합니다. 전자는 빠르고 후자는 최신성을 보장합니다." + }, + { + "id": "network-cache-004", + "question": "ETag는 어떻게 동작하나요?", + "answer": "리소스의 버전을 식별하는 해시 값입니다. 클라이언트가 If-None-Match로 ETag를 보내면, 서버는 변경이 없을 때 304 Not Modified를 반환해 본문 전송 없이 캐시를 재사용하게 합니다." + }, + { + "id": "network-cache-005", + "question": "304 Not Modified 응답의 의미는?", + "answer": "캐시된 리소스가 여전히 유효해 재사용해도 된다는 의미입니다. 본문 없이 헤더만 반환되어 전송량이 적고, 재검증 기반 캐싱에서 대역폭 절약의 핵심 역할을 합니다." + }, + { + "id": "network-cache-006", + "question": "정적 자원에 캐시 버스팅(cache busting)을 하는 이유는?", + "answer": "파일을 오래 캐시하면서도 변경 시 즉시 반영하기 위해서입니다. 파일명에 해시를 붙여(app.a1b2.js) 내용이 바뀌면 URL이 달라지므로, 긴 max-age를 두고도 갱신을 안전하게 보장할 수 있습니다." + }, + { + "id": "network-cache-007", + "question": "CDN은 어떻게 성능을 향상시키나요?", + "answer": "콘텐츠를 사용자와 지리적으로 가까운 엣지 서버에 캐시해 전송 거리를 줄입니다. 지연이 감소하고 원본 서버 부하가 줄며, 트래픽 급증과 분산 공격에도 더 잘 견딥니다." + }, + { + "id": "network-cache-008", + "question": "no-cache와 no-store의 차이는?", + "answer": "no-cache는 캐시에 저장은 하되 사용 전 반드시 서버에 재검증하라는 의미입니다. no-store는 아예 저장하지 말라는 의미로 민감한 데이터에 사용합니다. 이름과 달리 no-cache는 캐싱을 완전히 막지 않습니다." + }, + { + "id": "network-cache-009", + "question": "캐시 적중률(hit ratio)을 높이려면 어떻게 하나요?", + "answer": "자주 바뀌지 않는 정적 자원에 긴 캐시 기간을 두고, 콘텐츠 해시로 버전을 관리하며, CDN과 적절한 Vary 헤더 설정을 활용합니다. 사용자별로 달라지지 않는 응답을 공유 캐시 대상으로 만드는 것이 중요합니다." + }, + { + "id": "network-cache-010", + "question": "Vary 헤더는 어떤 역할을 하나요?", + "answer": "같은 URL이라도 특정 요청 헤더(예: Accept-Encoding, User-Agent)에 따라 응답이 달라질 수 있음을 캐시에 알립니다. 이를 통해 잘못된 캐시 응답이 다른 조건의 클라이언트에게 제공되는 것을 방지합니다." + } + ] + }, + { + "id": "network-cors", + "name": "CORS", + "questions": [ + { + "id": "network-cors-001", + "question": "CORS란 무엇인가요?", + "answer": "Cross-Origin Resource Sharing의 약자로, 다른 출처의 리소스 요청을 허용할지 브라우저가 제어하는 보안 메커니즘입니다. 서버가 응답 헤더로 허용 출처를 명시하면 브라우저가 교차 출처 접근을 허가합니다." + }, + { + "id": "network-cors-002", + "question": "동일 출처 정책(Same-Origin Policy)이란?", + "answer": "프로토콜, 호스트, 포트가 모두 같아야 같은 출처로 보고 자원 접근을 허용하는 브라우저의 기본 보안 정책입니다. 악성 사이트가 다른 사이트의 데이터에 무단 접근하는 것을 막습니다." + }, + { + "id": "network-cors-003", + "question": "프리플라이트(Preflight) 요청은 무엇인가요?", + "answer": "본 요청 전에 OPTIONS 메서드로 서버에 해당 교차 출처 요청이 허용되는지 미리 확인하는 요청입니다. 커스텀 헤더나 PUT/DELETE 같은 비단순 요청에서 발생하며, 서버가 허용하면 본 요청이 진행됩니다." + }, + { + "id": "network-cors-004", + "question": "단순 요청(Simple Request)의 조건은?", + "answer": "GET/POST/HEAD 메서드에 허용된 기본 헤더만 사용하고, Content-Type이 form 계열인 경우 프리플라이트 없이 바로 전송됩니다. 이 조건을 벗어나면 프리플라이트가 선행됩니다." + }, + { + "id": "network-cors-005", + "question": "Access-Control-Allow-Origin 헤더의 역할은?", + "answer": "서버가 어떤 출처의 접근을 허용하는지 명시하는 응답 헤더입니다. 특정 도메인이나 와일드카드(*)를 지정할 수 있으며, 인증 정보를 포함하는 요청에는 와일드카드를 쓸 수 없습니다." + }, + { + "id": "network-cors-006", + "question": "CORS 에러는 왜 발생하고 어떻게 해결하나요?", + "answer": "서버가 요청 출처를 허용하는 CORS 헤더를 보내지 않아 브라우저가 응답을 차단할 때 발생합니다. 해결은 서버에서 적절한 Access-Control-Allow-* 헤더를 설정하는 것이며, 프런트엔드만으로는 우회할 수 없습니다." + }, + { + "id": "network-cors-007", + "question": "credentials(쿠키 포함) 요청에서 주의할 점은?", + "answer": "fetch에 credentials를 설정하면 쿠키가 전송되며, 서버는 Access-Control-Allow-Credentials를 true로 하고 Allow-Origin에 와일드카드 대신 정확한 출처를 명시해야 합니다. 그렇지 않으면 요청이 차단됩니다." + }, + { + "id": "network-cors-008", + "question": "CORS는 서버 간 통신도 막나요?", + "answer": "아닙니다. CORS는 브라우저에서 동작하는 정책이므로 서버 대 서버 통신이나 프록시 요청에는 적용되지 않습니다. 그래서 백엔드 프록시를 두면 CORS 제약을 받지 않고 데이터를 중계할 수 있습니다." + }, + { + "id": "network-cors-009", + "question": "프록시(proxy)로 CORS 문제를 우회하는 원리는?", + "answer": "브라우저가 같은 출처의 자체 서버로 요청하고, 그 서버가 대신 외부 API를 호출해 응답을 전달하는 방식입니다. 브라우저 입장에서는 동일 출처 통신이므로 CORS 검사를 받지 않습니다." + }, + { + "id": "network-cors-010", + "question": "CORS와 CSRF는 어떤 관계인가요?", + "answer": "CORS는 교차 출처 응답 읽기를 제어하는 정책이고, CSRF는 사용자의 인증 상태를 악용해 원치 않는 요청을 보내는 공격입니다. CORS만으로 CSRF를 막을 수 없으며, SameSite 쿠키나 토큰 같은 별도 방어가 필요합니다." + } + ] + } + ] + }, + { + "id": "performance", + "name": "성능 최적화", + "categories": [ + { + "id": "perf-loading", + "name": "로딩 최적화", + "questions": [ + { + "id": "perf-loading-001", + "question": "초기 로딩 속도를 개선하는 대표적인 방법은?", + "answer": "리소스를 압축·최소화하고, 코드 스플리팅과 지연 로딩으로 초기 번들을 줄이며, 캐싱과 CDN을 활용합니다. 또 중요 리소스를 우선 로딩하고 불필요한 요청을 제거해 첫 화면 표시 시간을 단축합니다." + }, + { + "id": "perf-loading-002", + "question": "코드 스플리팅(Code Splitting)이란?", + "answer": "번들을 여러 청크로 나눠 필요한 시점에 필요한 코드만 불러오는 기법입니다. 초기 다운로드 크기를 줄여 첫 로딩을 빠르게 하며, 라우트 단위나 컴포넌트 단위로 분할하는 것이 일반적입니다." + }, + { + "id": "perf-loading-003", + "question": "지연 로딩(Lazy Loading)은 무엇인가요?", + "answer": "당장 필요하지 않은 리소스를 실제로 필요할 때까지 미루어 불러오는 기법입니다. 화면 밖 이미지나 라우트 컴포넌트를 나중에 로드해 초기 부담을 줄이고 체감 속도를 높입니다." + }, + { + "id": "perf-loading-004", + "question": "preload와 prefetch의 차이는?", + "answer": "preload는 현재 페이지에 곧 필요한 리소스를 우선순위 높게 미리 가져옵니다. prefetch는 다음에 필요할 가능성이 있는 리소스를 한가할 때 낮은 우선순위로 미리 받아둡니다. 시점과 우선순위가 다릅니다." + }, + { + "id": "perf-loading-005", + "question": "트리 셰이킹(Tree Shaking)이란?", + "answer": "사용되지 않는 코드(dead code)를 번들에서 제거하는 최적화입니다. ES 모듈의 정적 구조를 분석해 import되지 않은 export를 빼내며, 최종 번들 크기를 줄여 로딩을 빠르게 합니다." + }, + { + "id": "perf-loading-006", + "question": "리소스 힌트(resource hints)에는 어떤 것이 있나요?", + "answer": "dns-prefetch는 DNS를 미리 조회하고, preconnect는 연결을 미리 맺으며, preload/prefetch는 리소스를 미리 가져옵니다. 외부 도메인이나 중요 자원에 적용하면 연결·로딩 지연을 줄일 수 있습니다." + }, + { + "id": "perf-loading-007", + "question": "압축(gzip, brotli)은 어떻게 성능에 도움이 되나요?", + "answer": "텍스트 리소스를 서버에서 압축해 전송량을 크게 줄입니다. brotli는 보통 gzip보다 압축률이 높아 더 작은 전송 크기를 제공하며, 네트워크 지연이 큰 환경에서 특히 효과적입니다." + }, + { + "id": "perf-loading-008", + "question": "Critical CSS란 무엇인가요?", + "answer": "첫 화면(above-the-fold)에 필요한 최소한의 CSS를 인라인으로 먼저 제공하고 나머지는 비동기로 불러오는 기법입니다. 렌더링 차단을 줄여 사용자에게 콘텐츠를 더 빨리 보여줄 수 있습니다." + }, + { + "id": "perf-loading-009", + "question": "폰트 로딩을 최적화하는 방법은?", + "answer": "font-display: swap으로 폰트 로딩 중 대체 폰트를 먼저 보여주고, 필요한 글자만 추리는 서브셋, preload, WOFF2 포맷을 활용합니다. FOIT(보이지 않는 텍스트)를 줄여 텍스트가 빨리 표시됩니다." + }, + { + "id": "perf-loading-010", + "question": "HTTP 요청 수를 줄이는 것이 왜 중요한가요?", + "answer": "각 요청마다 연결·왕복 비용이 들기 때문입니다. 다만 HTTP/2 멀티플렉싱 환경에서는 영향이 줄어, 무조건 합치기보다 캐싱 효율과 병렬 로딩을 함께 고려해 균형을 맞추는 것이 좋습니다." + } + ] + }, + { + "id": "perf-rendering", + "name": "렌더링 최적화", + "questions": [ + { + "id": "perf-rendering-001", + "question": "렌더링 성능을 높이는 핵심 원칙은?", + "answer": "리플로우와 리페인트를 최소화하고, 합성만으로 처리되는 transform/opacity를 활용하며, 메인 스레드의 긴 작업을 줄이는 것입니다. 또 보이는 부분만 그리고 불필요한 리렌더링을 막습니다." + }, + { + "id": "perf-rendering-002", + "question": "가상 스크롤(virtualization)이란?", + "answer": "긴 목록에서 화면에 보이는 항목만 DOM에 렌더링하고 나머지는 그리지 않는 기법입니다. 수천 개 항목도 적은 DOM 노드로 처리해 메모리와 렌더링 비용을 크게 절약합니다." + }, + { + "id": "perf-rendering-003", + "question": "메인 스레드 블로킹을 줄이려면 어떻게 하나요?", + "answer": "긴 작업을 작은 단위로 쪼개고, 무거운 연산은 Web Worker로 옮기며, requestIdleCallback으로 한가할 때 처리합니다. 이렇게 하면 입력 응답성이 유지되어 끊김이 줄어듭니다." + }, + { + "id": "perf-rendering-004", + "question": "Web Worker는 언제 사용하나요?", + "answer": "이미지 처리, 대량 데이터 파싱·정렬 같은 CPU 집약적 작업을 메인 스레드와 분리된 별도 스레드에서 처리할 때 사용합니다. UI 응답성을 유지하면서 무거운 연산을 수행할 수 있습니다." + }, + { + "id": "perf-rendering-005", + "question": "60fps를 유지하려면 프레임당 시간이 얼마나 필요한가요?", + "answer": "초당 60프레임이면 한 프레임에 약 16.7ms가 주어집니다. 이 안에 자바스크립트, 스타일, 레이아웃, 페인트, 합성을 모두 끝내야 부드럽게 보이며, 초과하면 프레임 드롭으로 끊김이 생깁니다." + }, + { + "id": "perf-rendering-006", + "question": "레이아웃 스래싱이 성능에 미치는 영향은?", + "answer": "스타일 변경과 레이아웃 읽기를 번갈아 하면 브라우저가 반복적으로 강제 레이아웃을 수행해 프레임이 지연됩니다. 읽기와 쓰기를 분리해 배치 처리하면 이를 방지할 수 있습니다." + }, + { + "id": "perf-rendering-007", + "question": "이미지 지연 로딩으로 렌더링을 어떻게 개선하나요?", + "answer": "loading=lazy 속성이나 IntersectionObserver로 화면에 들어올 때 이미지를 로드합니다. 초기 렌더링에 필요 없는 이미지의 디코딩·페인트를 미뤄 첫 화면 성능을 높입니다." + }, + { + "id": "perf-rendering-008", + "question": "content-visibility 속성은 어떤 효과가 있나요?", + "answer": "화면 밖 콘텐츠의 렌더링을 건너뛰도록 브라우저에 지시해 초기 렌더링 비용을 줄입니다. 긴 문서에서 보이지 않는 영역의 레이아웃·페인트를 생략해 표시 속도를 크게 개선할 수 있습니다." + }, + { + "id": "perf-rendering-009", + "question": "스켈레톤 UI는 성능 인식에 어떤 도움을 주나요?", + "answer": "실제 데이터가 로드되기 전 윤곽을 보여주어 사용자가 기다림을 덜 느끼게 합니다. 실제 로딩 시간을 줄이진 않지만 체감 성능(perceived performance)을 향상시켜 이탈을 줄입니다." + }, + { + "id": "perf-rendering-010", + "question": "IntersectionObserver는 무엇이고 왜 효율적인가요?", + "answer": "요소가 뷰포트에 들어오고 나가는 것을 비동기로 감지하는 API입니다. 스크롤 이벤트로 매번 위치를 계산하는 방식보다 부하가 적어 지연 로딩과 무한 스크롤 구현에 효율적입니다." + } + ] + }, + { + "id": "perf-image", + "name": "이미지 최적화", + "questions": [ + { + "id": "perf-image-001", + "question": "이미지 최적화가 중요한 이유는?", + "answer": "이미지는 보통 웹 페이지 용량의 큰 비중을 차지하기 때문입니다. 적절히 최적화하면 전송량과 로딩 시간이 크게 줄어 LCP 같은 핵심 지표와 사용자 경험이 개선됩니다." + }, + { + "id": "perf-image-002", + "question": "WebP, AVIF 같은 최신 포맷의 장점은?", + "answer": "JPEG/PNG보다 같은 화질에서 파일 크기가 더 작아 전송량을 줄입니다. AVIF가 압축률이 가장 높은 편이며, picture 요소로 미지원 브라우저에는 대체 포맷을 제공하는 방식이 권장됩니다." + }, + { + "id": "perf-image-003", + "question": "반응형 이미지(srcset, sizes)는 어떻게 동작하나요?", + "answer": "srcset에 여러 해상도의 이미지를, sizes에 표시 크기를 지정하면 브라우저가 화면과 DPR에 맞는 최적 이미지를 선택해 받습니다. 작은 화면에 큰 이미지를 보내는 낭비를 막습니다." + }, + { + "id": "perf-image-004", + "question": "이미지 지연 로딩은 어떻게 구현하나요?", + "answer": "img 태그에 loading=lazy를 주거나, IntersectionObserver로 뷰포트 진입 시 src를 설정합니다. 초기에 화면 밖 이미지를 불러오지 않아 초기 로딩 부담과 대역폭을 줄입니다." + }, + { + "id": "perf-image-005", + "question": "벡터(SVG)와 래스터 이미지는 어떻게 선택하나요?", + "answer": "아이콘·로고처럼 단순하고 확대해도 깨지면 안 되는 그래픽은 SVG가 적합합니다. 사진처럼 복잡한 이미지는 래스터(JPEG/WebP)가 적합합니다. 용도에 따라 품질과 용량의 균형을 맞춥니다." + }, + { + "id": "perf-image-006", + "question": "이미지에 width/height를 지정하는 이유는?", + "answer": "이미지 영역을 미리 확보해 로드 후 레이아웃이 밀리는 현상을 막기 위해서입니다. 이는 CLS(누적 레이아웃 이동)를 줄여 사용자 경험과 핵심 웹 지표를 개선합니다." + }, + { + "id": "perf-image-007", + "question": "이미지 스프라이트(sprite)는 무엇이고 지금도 유효한가요?", + "answer": "여러 작은 이미지를 하나로 합쳐 요청 수를 줄이는 기법입니다. HTTP/1.1에서 효과적이었으나, 멀티플렉싱이 있는 HTTP/2 환경에서는 이점이 줄어 SVG 아이콘 등으로 대체되는 추세입니다." + }, + { + "id": "perf-image-008", + "question": "LQIP/블러업(blur-up) 기법이란?", + "answer": "아주 작은 저화질 placeholder를 먼저 흐릿하게 보여주고 원본이 로드되면 교체하는 기법입니다. 빈 공간 대신 미리보기를 제공해 체감 로딩 속도를 높입니다." + }, + { + "id": "perf-image-009", + "question": "이미지 CDN은 어떤 이점을 주나요?", + "answer": "요청 시점에 포맷 변환, 리사이즈, 압축, 품질 조정을 자동으로 해주고 엣지에서 캐싱합니다. 기기와 화면에 맞는 최적 이미지를 자동 제공해 관리 부담과 전송량을 동시에 줄입니다." + }, + { + "id": "perf-image-010", + "question": "above-the-fold 이미지는 어떻게 다루어야 하나요?", + "answer": "첫 화면에 보이는 핵심 이미지는 지연 로딩하지 말고 오히려 preload나 fetchpriority=high로 우선 로딩합니다. LCP 대상인 경우가 많아 빠른 표시가 지표 개선에 직접적인 영향을 줍니다." + } + ] + }, + { + "id": "perf-bundle", + "name": "번들 최적화", + "questions": [ + { + "id": "perf-bundle-001", + "question": "번들 크기를 줄이는 방법에는 무엇이 있나요?", + "answer": "트리 셰이킹, 코드 스플리팅, 미니피케이션, 사용하지 않는 의존성 제거, 가벼운 대체 라이브러리 사용 등이 있습니다. 또 동적 import로 필요 시 로딩하면 초기 번들을 줄일 수 있습니다." + }, + { + "id": "perf-bundle-002", + "question": "번들 분석은 어떻게 하나요?", + "answer": "webpack-bundle-analyzer나 vite의 시각화 도구로 어떤 모듈이 번들 크기를 차지하는지 확인합니다. 큰 의존성과 중복을 찾아 최적화 우선순위를 정하는 데 활용합니다." + }, + { + "id": "perf-bundle-003", + "question": "동적 import(dynamic import)는 어떤 역할을 하나요?", + "answer": "import()를 사용해 모듈을 런타임에 비동기로 불러오는 기능입니다. 코드 스플리팅의 기반이 되며, 라우트나 무거운 컴포넌트를 필요한 시점에만 로드해 초기 로딩을 줄입니다." + }, + { + "id": "perf-bundle-004", + "question": "vendor 청크를 분리하는 이유는?", + "answer": "자주 바뀌지 않는 외부 라이브러리를 별도 청크로 분리하면, 앱 코드가 바뀌어도 vendor 청크는 캐시를 유지할 수 있기 때문입니다. 재방문 시 다시 받아야 할 양이 줄어 로딩이 빨라집니다." + }, + { + "id": "perf-bundle-005", + "question": "사이드 이펙트(sideEffects) 설정은 트리 셰이킹과 어떤 관계인가요?", + "answer": "package.json의 sideEffects를 false로 표시하면 번들러가 사용되지 않는 모듈을 안전하게 제거할 수 있습니다. 부수 효과가 있는 파일을 명시하면 잘못 제거되는 것을 방지합니다." + }, + { + "id": "perf-bundle-006", + "question": "라이브러리 선택이 번들 크기에 미치는 영향은?", + "answer": "같은 기능이라도 라이브러리에 따라 크기 차이가 큽니다. 무거운 전체 라이브러리 대신 필요한 함수만 import하거나 경량 대안을 쓰면 번들이 작아집니다. moment 대신 day.js 사용이 대표적 예입니다." + }, + { + "id": "perf-bundle-007", + "question": "미니피케이션(minification)이란?", + "answer": "공백, 주석, 긴 변수명 등을 제거·축약해 코드 크기를 줄이는 과정입니다. 기능은 그대로 유지하면서 전송량을 줄이며, 빌드 단계에서 terser 같은 도구로 자동 수행됩니다." + }, + { + "id": "perf-bundle-008", + "question": "중복 의존성(duplicate dependencies) 문제는 어떻게 해결하나요?", + "answer": "여러 패키지가 같은 라이브러리의 다른 버전을 포함하면 번들이 커집니다. 버전을 통일하거나 resolutions/peerDependencies, dedupe로 단일 버전을 공유하게 해 중복을 제거합니다." + }, + { + "id": "perf-bundle-009", + "question": "ESM과 CommonJS가 번들링에 미치는 차이는?", + "answer": "ESM은 정적 구조라 트리 셰이킹이 잘 되지만, CommonJS는 동적 require 때문에 미사용 코드 제거가 어렵습니다. 따라서 ESM을 제공하는 라이브러리가 번들 최적화에 유리합니다." + }, + { + "id": "perf-bundle-010", + "question": "청크 분할 전략을 세울 때 고려할 점은?", + "answer": "너무 잘게 나누면 요청 수와 오버헤드가 늘고, 너무 크면 캐싱·초기 로딩에 불리합니다. 라우트 기반 분할, 공통 모듈 추출, 캐시 안정성을 균형 있게 고려해 적절한 크기로 나눠야 합니다." + } + ] + }, + { + "id": "perf-metric", + "name": "성능 지표", + "questions": [ + { + "id": "perf-metric-001", + "question": "Core Web Vitals란 무엇인가요?", + "answer": "구글이 정의한 사용자 경험 핵심 지표로 LCP(로딩), INP(상호작용 반응성), CLS(시각적 안정성)로 구성됩니다. 검색 순위에도 영향을 주어 프런트엔드 성능 관리의 기준으로 널리 쓰입니다." + }, + { + "id": "perf-metric-002", + "question": "LCP(Largest Contentful Paint)란?", + "answer": "뷰포트에서 가장 큰 콘텐츠 요소가 화면에 그려지는 시점으로 로딩 성능을 나타냅니다. 보통 2.5초 이내가 권장되며, 이미지·폰트 최적화와 서버 응답 개선으로 단축할 수 있습니다." + }, + { + "id": "perf-metric-003", + "question": "CLS(Cumulative Layout Shift)란?", + "answer": "페이지 로딩 중 예기치 않게 요소가 이동한 정도를 측정하는 시각적 안정성 지표입니다. 이미지 크기 지정, 광고·배너 공간 예약, 폰트 교체 관리 등으로 값을 낮출 수 있습니다." + }, + { + "id": "perf-metric-004", + "question": "INP(Interaction to Next Paint)란?", + "answer": "사용자 상호작용에 대해 다음 화면이 갱신되기까지 걸리는 반응성을 측정하는 지표입니다. FID를 대체했으며, 긴 작업을 줄이고 메인 스레드를 비워 입력 응답을 빠르게 하면 개선됩니다." + }, + { + "id": "perf-metric-005", + "question": "FCP와 LCP의 차이는?", + "answer": "FCP(First Contentful Paint)는 첫 콘텐츠가 처음 그려지는 시점이고, LCP는 가장 큰 핵심 콘텐츠가 그려지는 시점입니다. FCP는 초기 반응, LCP는 주요 콘텐츠 로딩 체감을 나타냅니다." + }, + { + "id": "perf-metric-006", + "question": "TTFB(Time To First Byte)는 무엇을 의미하나요?", + "answer": "요청 후 서버로부터 첫 바이트를 받기까지 걸린 시간입니다. 서버 처리 속도와 네트워크 지연을 반영하며, 값이 크면 백엔드·CDN·캐싱 최적화가 필요하다는 신호입니다." + }, + { + "id": "perf-metric-007", + "question": "TBT(Total Blocking Time)란?", + "answer": "FCP와 TTI 사이에서 메인 스레드가 입력에 응답하지 못하게 막힌 총 시간입니다. 긴 작업이 많을수록 커지며, 코드 분할과 작업 분산으로 줄이면 상호작용 반응성이 좋아집니다." + }, + { + "id": "perf-metric-008", + "question": "랩 데이터와 필드 데이터의 차이는?", + "answer": "랩 데이터는 Lighthouse 등 통제된 환경에서 측정한 값이고, 필드 데이터는 실제 사용자들의 측정값(RUM)입니다. 랩은 디버깅에, 필드는 실사용 경험 파악에 적합해 둘을 함께 봐야 합니다." + }, + { + "id": "perf-metric-009", + "question": "Lighthouse는 어떤 도구인가요?", + "answer": "구글이 만든 웹 품질 측정 도구로 성능, 접근성, SEO, PWA 등을 점검해 점수와 개선안을 제시합니다. 자동화된 감사로 최적화 우선순위를 잡는 데 유용하지만 랩 데이터라는 한계가 있습니다." + }, + { + "id": "perf-metric-010", + "question": "성능 예산(performance budget)이란?", + "answer": "번들 크기, 로딩 시간, 지표 점수 등에 상한선을 정해 두고 이를 넘지 않도록 관리하는 기준입니다. CI에 통합하면 성능 저하를 조기에 발견해 점진적 악화를 방지할 수 있습니다." + } + ] + } + ] + }, + { + "id": "security", + "name": "보안", + "categories": [ + { + "id": "security-xss", + "name": "XSS", + "questions": [ + { + "id": "security-xss-001", + "question": "XSS(Cross-Site Scripting)란 무엇인가요?", + "answer": "공격자가 악성 스크립트를 웹 페이지에 주입해 다른 사용자의 브라우저에서 실행시키는 공격입니다. 쿠키·토큰 탈취, 세션 하이재킹, 페이지 변조 등으로 이어질 수 있습니다." + }, + { + "id": "security-xss-002", + "question": "XSS의 종류를 설명해 주세요.", + "answer": "저장형(Stored)은 악성 스크립트가 서버에 저장되어 여러 사용자에게 노출됩니다. 반사형(Reflected)은 요청 값이 즉시 응답에 반영되어 실행됩니다. DOM 기반은 클라이언트 스크립트가 입력을 위험하게 처리할 때 발생합니다." + }, + { + "id": "security-xss-003", + "question": "XSS를 방어하는 방법은?", + "answer": "사용자 입력을 출력 맥락에 맞게 이스케이프/인코딩하고, innerHTML 대신 textContent를 사용하며, 입력을 검증·정제(sanitize)합니다. 또 CSP를 적용하고 HttpOnly 쿠키로 토큰 노출을 줄입니다." + }, + { + "id": "security-xss-004", + "question": "CSP(Content Security Policy)란?", + "answer": "브라우저가 어떤 출처의 스크립트·스타일·이미지 등을 로드·실행할 수 있는지 제한하는 보안 헤더입니다. 허용되지 않은 인라인 스크립트나 외부 자원을 차단해 XSS의 영향을 크게 줄입니다." + }, + { + "id": "security-xss-005", + "question": "출력 인코딩(이스케이프)이 중요한 이유는?", + "answer": "사용자 입력에 포함된 특수 문자를 그대로 출력하면 스크립트로 해석될 수 있기 때문입니다. <, >, & 등을 엔티티로 변환하면 데이터가 코드로 실행되지 않아 XSS를 막을 수 있습니다." + }, + { + "id": "security-xss-006", + "question": "DOM 기반 XSS는 일반 XSS와 어떻게 다른가요?", + "answer": "서버를 거치지 않고 클라이언트 자바스크립트가 location, innerHTML 등으로 신뢰할 수 없는 입력을 처리할 때 발생합니다. 서버 측 방어만으로는 막을 수 없어 클라이언트 코드의 안전한 처리가 중요합니다." + }, + { + "id": "security-xss-007", + "question": "React는 XSS에 어떻게 대응하나요?", + "answer": "JSX로 렌더링하는 값은 기본적으로 이스케이프되어 문자열이 코드로 실행되지 않습니다. 다만 dangerouslySetInnerHTML을 사용하면 이 보호가 사라지므로, 신뢰할 수 없는 HTML은 반드시 정제해야 합니다." + }, + { + "id": "security-xss-008", + "question": "sanitize(정제)와 escape(이스케이프)의 차이는?", + "answer": "이스케이프는 특수 문자를 무해한 표현으로 바꿔 데이터로 취급하게 합니다. 정제는 허용된 태그·속성만 남기고 위험한 요소를 제거합니다. 일부 HTML을 허용해야 할 때는 DOMPurify 같은 정제 도구를 씁니다." + }, + { + "id": "security-xss-009", + "question": "인라인 스크립트가 XSS 관점에서 위험한 이유는?", + "answer": "CSP로 외부 스크립트를 막아도 인라인 스크립트가 허용되면 주입된 코드가 실행될 수 있기 때문입니다. 그래서 CSP에서 unsafe-inline을 피하고 nonce나 hash로 신뢰할 인라인만 허용하는 것이 좋습니다." + }, + { + "id": "security-xss-010", + "question": "javascript: URL이 위험한 이유는?", + "answer": "href나 src에 javascript: 스킴을 넣으면 클릭 시 임의 코드가 실행될 수 있기 때문입니다. 사용자 입력으로 URL을 만들 때는 스킴을 검증해 http/https 등 안전한 프로토콜만 허용해야 합니다." + } + ] + }, + { + "id": "security-csrf", + "name": "CSRF", + "questions": [ + { + "id": "security-csrf-001", + "question": "CSRF(Cross-Site Request Forgery)란?", + "answer": "사용자가 로그인된 상태를 악용해, 사용자가 의도하지 않은 요청을 다른 사이트에서 보내게 만드는 공격입니다. 브라우저가 쿠키를 자동 전송하는 점을 이용해 권한이 필요한 작업을 몰래 수행합니다." + }, + { + "id": "security-csrf-002", + "question": "CSRF 공격은 어떻게 이루어지나요?", + "answer": "공격자가 만든 페이지에 숨겨진 폼이나 이미지 요청을 두어, 피해자가 방문하면 인증 쿠키가 실린 요청이 대상 사이트로 전송됩니다. 서버는 정상 사용자의 요청으로 오인해 처리하게 됩니다." + }, + { + "id": "security-csrf-003", + "question": "CSRF 토큰은 어떻게 방어에 쓰이나요?", + "answer": "서버가 폼이나 페이지에 예측 불가능한 토큰을 심고, 요청 시 이를 함께 받아 검증합니다. 공격자는 이 토큰을 알 수 없으므로 위조 요청이 거부되어 CSRF를 막을 수 있습니다." + }, + { + "id": "security-csrf-004", + "question": "SameSite 쿠키 속성은 CSRF를 어떻게 막나요?", + "answer": "교차 사이트 요청에 쿠키 전송을 제한하는 속성입니다. Strict는 외부 사이트 요청에 쿠키를 보내지 않고, Lax는 안전한 일부만 허용합니다. 쿠키 자동 전송을 차단해 CSRF를 크게 완화합니다." + }, + { + "id": "security-csrf-005", + "question": "XSS와 CSRF의 차이는 무엇인가요?", + "answer": "XSS는 악성 스크립트를 실행시켜 데이터를 탈취·조작하는 공격이고, CSRF는 사용자의 인증 상태를 이용해 원치 않는 요청을 보내는 공격입니다. XSS가 성공하면 CSRF 방어도 무력화될 수 있습니다." + }, + { + "id": "security-csrf-006", + "question": "Double Submit Cookie 패턴이란?", + "answer": "토큰을 쿠키와 요청 파라미터(또는 헤더) 양쪽에 담아 서버가 두 값의 일치를 확인하는 방식입니다. 서버에 별도 상태를 저장하지 않아도 되는 무상태 CSRF 방어 기법입니다." + }, + { + "id": "security-csrf-007", + "question": "GET 요청으로 상태를 변경하면 왜 위험한가요?", + "answer": "GET은 링크·이미지로 쉽게 자동 호출되어 CSRF에 취약하기 때문입니다. 또 멱등·안전해야 한다는 규약에도 어긋납니다. 상태 변경은 반드시 POST/PUT/DELETE 등으로 처리해야 합니다." + }, + { + "id": "security-csrf-008", + "question": "Referer/Origin 헤더 검증은 CSRF 방어에 어떻게 쓰이나요?", + "answer": "서버가 요청의 Origin이나 Referer가 신뢰하는 도메인인지 확인해 외부에서 온 요청을 거르는 방법입니다. 보조 수단으로 유용하지만 헤더가 없거나 변조될 수 있어 토큰 방식과 함께 쓰는 것이 좋습니다." + }, + { + "id": "security-csrf-009", + "question": "토큰 기반 인증(Authorization 헤더)은 CSRF에 강한가요?", + "answer": "쿠키 대신 헤더에 토큰을 직접 실어 보내면 브라우저가 자동 전송하지 않으므로 CSRF에 비교적 강합니다. 다만 토큰을 localStorage에 두면 XSS에 노출될 수 있어 트레이드오프를 고려해야 합니다." + }, + { + "id": "security-csrf-010", + "question": "CSRF 방어를 위한 종합적인 권장 사항은?", + "answer": "상태 변경은 안전한 메서드로 처리하고, SameSite 쿠키와 CSRF 토큰을 함께 적용하며, 민감 작업에 재인증을 요구합니다. 여러 계층을 조합해 단일 방어 실패에 대비하는 것이 바람직합니다." + } + ] + }, + { + "id": "security-auth", + "name": "인증과 인가", + "questions": [ + { + "id": "security-auth-001", + "question": "인증(Authentication)과 인가(Authorization)의 차이는?", + "answer": "인증은 사용자가 누구인지 확인하는 과정(로그인)이고, 인가는 인증된 사용자가 무엇을 할 수 있는지 권한을 확인하는 과정입니다. 인증이 먼저, 인가가 그다음에 이루어집니다." + }, + { + "id": "security-auth-002", + "question": "세션 기반 인증과 토큰 기반 인증의 차이는?", + "answer": "세션 방식은 서버가 상태를 저장하고 클라이언트는 세션 ID 쿠키를 보냅니다. 토큰 방식(JWT)은 서버가 상태를 저장하지 않고 토큰 자체에 정보를 담습니다. 후자는 확장성이, 전자는 즉시 무효화가 강점입니다." + }, + { + "id": "security-auth-003", + "question": "JWT(JSON Web Token)란 무엇인가요?", + "answer": "헤더, 페이로드, 서명 세 부분으로 이루어진 토큰입니다. 페이로드에 사용자 정보를 담고 서명으로 위변조를 검증합니다. 무상태 인증에 쓰이지만 페이로드는 암호화가 아니라 인코딩일 뿐임에 유의해야 합니다." + }, + { + "id": "security-auth-004", + "question": "Access Token과 Refresh Token을 나누는 이유는?", + "answer": "Access Token은 짧은 수명으로 탈취 피해를 줄이고, Refresh Token은 긴 수명으로 재발급에 사용합니다. 자주 쓰는 토큰의 노출 위험을 낮추면서 사용자가 자주 로그인하지 않도록 균형을 맞춥니다." + }, + { + "id": "security-auth-005", + "question": "토큰을 어디에 저장하는 것이 안전한가요?", + "answer": "localStorage는 XSS에 취약하고, 쿠키는 CSRF에 주의가 필요합니다. 일반적으로 HttpOnly + Secure + SameSite 쿠키에 두어 자바스크립트 접근을 막는 방식이 권장됩니다. 상황에 따라 트레이드오프를 따져야 합니다." + }, + { + "id": "security-auth-006", + "question": "OAuth 2.0은 무엇을 위한 프로토콜인가요?", + "answer": "사용자의 비밀번호를 공유하지 않고 제3자 앱에 제한된 권한을 위임하기 위한 인가 프로토콜입니다. 구글·깃허브 로그인처럼 토큰을 발급받아 자원에 접근하며, 인증이 아니라 인가에 초점이 있습니다." + }, + { + "id": "security-auth-007", + "question": "OAuth와 OpenID Connect의 차이는?", + "answer": "OAuth는 권한 위임(인가)을 다루고, OpenID Connect는 그 위에 신원 확인(인증) 계층을 더한 것입니다. OIDC는 ID 토큰으로 사용자가 누구인지 표준화된 방식으로 알려줍니다." + }, + { + "id": "security-auth-008", + "question": "비밀번호는 어떻게 안전하게 저장해야 하나요?", + "answer": "평문이 아니라 bcrypt, scrypt, Argon2 같은 느린 해시 함수에 솔트를 더해 저장합니다. 솔트는 동일 비밀번호의 해시를 다르게 만들고, 느린 해시는 무차별 대입 공격을 어렵게 합니다." + }, + { + "id": "security-auth-009", + "question": "2단계 인증(2FA/MFA)은 왜 중요한가요?", + "answer": "비밀번호 외에 추가 인증 요소(OTP, 인증 앱, 생체 등)를 요구해 계정 보안을 강화합니다. 비밀번호가 유출되어도 두 번째 요소가 없으면 접근이 차단되어 피해를 크게 줄입니다." + }, + { + "id": "security-auth-010", + "question": "토큰 만료와 무효화는 어떻게 처리하나요?", + "answer": "Access Token에 짧은 만료 시간을 두고 Refresh Token으로 갱신합니다. 즉시 무효화가 필요하면 블랙리스트나 토큰 버전 관리, 서버 측 세션 병행 등을 사용합니다. 무상태 JWT는 즉시 폐기가 어렵다는 한계가 있습니다." + } + ] + }, + { + "id": "security-misc", + "name": "기타 보안", + "questions": [ + { + "id": "security-misc-001", + "question": "클릭재킹(Clickjacking)이란 무엇인가요?", + "answer": "투명한 iframe 등으로 정상 페이지를 덮어, 사용자가 의도와 다른 버튼을 클릭하게 속이는 공격입니다. X-Frame-Options나 CSP의 frame-ancestors로 다른 사이트의 프레임 삽입을 막아 방어합니다." + }, + { + "id": "security-misc-002", + "question": "주요 보안 HTTP 헤더에는 어떤 것이 있나요?", + "answer": "CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy 등이 있습니다. 각각 스크립트 제한, HTTPS 강제, 클릭재킹 방지, MIME 스니핑 차단, 리퍼러 노출 제어 역할을 합니다." + }, + { + "id": "security-misc-003", + "question": "X-Content-Type-Options: nosniff는 무엇을 막나요?", + "answer": "브라우저가 응답의 Content-Type을 무시하고 내용을 추측(MIME 스니핑)하는 것을 막습니다. 이를 통해 이미지로 위장한 스크립트가 실행되는 등의 콘텐츠 타입 혼동 공격을 방지합니다." + }, + { + "id": "security-misc-004", + "question": "민감 정보를 프런트엔드에서 다룰 때 주의점은?", + "answer": "API 키·비밀 값은 클라이언트 코드에 두면 누구나 볼 수 있으므로 노출하면 안 됩니다. 비밀은 서버에 두고, 프런트엔드에는 공개 가능한 값만 두며, 권한 검증은 반드시 서버에서 수행해야 합니다." + }, + { + "id": "security-misc-005", + "question": "의존성 보안(supply chain) 위협은 어떻게 관리하나요?", + "answer": "npm audit나 자동 스캐닝으로 취약한 패키지를 점검하고, 신뢰할 수 있는 패키지를 사용하며, 버전을 고정(lockfile)합니다. 불필요한 의존성을 줄이고 정기적으로 업데이트하는 것도 중요합니다." + }, + { + "id": "security-misc-006", + "question": "Referrer-Policy는 왜 설정하나요?", + "answer": "다른 사이트로 이동할 때 Referer 헤더에 담기는 URL 정보를 제어해 경로나 쿼리에 든 민감 정보가 외부로 새는 것을 막습니다. no-referrer나 strict-origin 등으로 노출 범위를 제한합니다." + }, + { + "id": "security-misc-007", + "question": "HTTPS 외에 전송 보안을 강화하는 방법은?", + "answer": "HSTS로 HTTPS를 강제하고, 보안 쿠키 속성(Secure, HttpOnly, SameSite)을 설정하며, 혼합 콘텐츠를 제거합니다. 또 최신 TLS 버전과 강력한 암호 스위트를 사용하도록 서버를 구성합니다." + }, + { + "id": "security-misc-008", + "question": "오픈 리다이렉트(Open Redirect) 취약점이란?", + "answer": "리다이렉트 대상 URL을 사용자 입력으로 받으면서 검증하지 않으면, 공격자가 피싱 사이트로 유도할 수 있는 취약점입니다. 허용 목록 기반으로 리다이렉트 대상을 검증해 방지합니다." + }, + { + "id": "security-misc-009", + "question": "입력 검증을 클라이언트와 서버 양쪽에서 하는 이유는?", + "answer": "클라이언트 검증은 사용자 경험을 위한 것으로 우회될 수 있습니다. 서버 검증은 신뢰의 경계로, 우회 불가능한 최종 방어선입니다. 따라서 보안을 위해서는 서버 검증이 필수입니다." + }, + { + "id": "security-misc-010", + "question": "최소 권한 원칙(Principle of Least Privilege)이란?", + "answer": "사용자나 시스템에 작업 수행에 꼭 필요한 최소한의 권한만 부여하는 원칙입니다. 권한을 좁히면 계정이 탈취되거나 코드에 문제가 생겨도 피해 범위를 줄일 수 있습니다." + } + ] + } + ] + }, + { + "id": "accessibility", + "name": "웹 접근성", + "categories": [ + { + "id": "a11y-basic", + "name": "접근성 기초와 ARIA", + "questions": [ + { + "id": "a11y-basic-001", + "question": "웹 접근성(Web Accessibility)이란 무엇인가요?", + "answer": "장애가 있는 사용자를 포함한 모든 사람이 웹을 동등하게 인식·이해·탐색·상호작용할 수 있도록 만드는 것입니다. 스크린리더 사용자, 키보드 사용자 등을 고려하며 WCAG가 대표 지침입니다." + }, + { + "id": "a11y-basic-002", + "question": "WCAG의 4가지 원칙은 무엇인가요?", + "answer": "인식 가능(Perceivable), 운용 가능(Operable), 이해 가능(Understandable), 견고함(Robust)입니다. 머리글자를 따 POUR라고 하며, 접근성을 평가하고 개선하는 기본 틀이 됩니다." + }, + { + "id": "a11y-basic-003", + "question": "ARIA란 무엇인가요?", + "answer": "Accessible Rich Internet Applications의 약자로, HTML만으로 표현하기 어려운 의미·상태·역할을 보조 기술에 전달하기 위한 속성 모음입니다. 동적 컴포넌트의 접근성을 보완할 때 사용합니다." + }, + { + "id": "a11y-basic-004", + "question": "ARIA 사용의 첫 번째 규칙은 무엇인가요?", + "answer": "가능하면 ARIA를 쓰지 말고 의미를 가진 네이티브 HTML 요소를 사용하라는 것입니다. button, nav 같은 시맨틱 요소는 접근성이 기본 내장되어 있어, 잘못 쓴 ARIA보다 항상 안전합니다." + }, + { + "id": "a11y-basic-005", + "question": "role 속성은 어떤 역할을 하나요?", + "answer": "요소가 어떤 역할(버튼, 탭, 대화상자 등)을 하는지 보조 기술에 알려줍니다. 의미 없는 div로 위젯을 만들 때 role을 부여하지만, 가능하면 해당 역할을 가진 시맨틱 태그를 쓰는 것이 좋습니다." + }, + { + "id": "a11y-basic-006", + "question": "aria-label과 aria-labelledby의 차이는?", + "answer": "aria-label은 문자열로 직접 접근 이름을 지정합니다. aria-labelledby는 다른 요소의 id를 참조해 그 텍스트를 이름으로 사용합니다. 화면에 보이는 라벨이 있으면 labelledby가, 없으면 label이 적합합니다." + }, + { + "id": "a11y-basic-007", + "question": "aria-hidden은 언제 사용하나요?", + "answer": "장식용 아이콘처럼 보조 기술에 노출할 필요가 없는 요소를 접근성 트리에서 숨길 때 사용합니다. 다만 포커스 가능한 요소에 적용하면 키보드 사용자에게 혼란을 주므로 주의해야 합니다." + }, + { + "id": "a11y-basic-008", + "question": "라이브 리전(aria-live)이란 무엇인가요?", + "answer": "내용이 동적으로 바뀔 때 스크린리더가 자동으로 변화를 읽어주도록 지정하는 영역입니다. polite는 한가할 때, assertive는 즉시 알리며, 알림·검색 결과 갱신 등에 활용합니다." + }, + { + "id": "a11y-basic-009", + "question": "이미지의 alt 텍스트는 어떻게 작성해야 하나요?", + "answer": "이미지의 의미와 맥락을 간결하게 전달하도록 작성합니다. 장식용 이미지는 alt를 빈 값으로 두어 건너뛰게 하고, 정보성 이미지는 내용을, 기능성 이미지는 동작을 설명합니다." + }, + { + "id": "a11y-basic-010", + "question": "접근 가능한 이름(Accessible Name)이란?", + "answer": "보조 기술이 요소를 식별해 읽어주는 이름입니다. 라벨, aria-label, alt, 콘텐츠 텍스트 등에서 정해진 우선순위로 계산됩니다. 모든 상호작용 요소는 의미 있는 접근 가능한 이름을 가져야 합니다." + } + ] + }, + { + "id": "a11y-semantic", + "name": "시맨틱과 스크린리더", + "questions": [ + { + "id": "a11y-semantic-001", + "question": "시맨틱 HTML이 접근성에 중요한 이유는?", + "answer": "시맨틱 태그는 역할과 구조 정보를 보조 기술에 자동으로 전달하기 때문입니다. 스크린리더 사용자가 제목으로 건너뛰고 랜드마크로 탐색할 수 있어, 별도 ARIA 없이도 접근성이 확보됩니다." + }, + { + "id": "a11y-semantic-002", + "question": "스크린리더는 페이지를 어떻게 읽나요?", + "answer": "접근성 트리를 기반으로 요소의 역할, 이름, 상태를 음성으로 전달합니다. 사용자는 제목, 링크, 폼, 랜드마크 목록으로 빠르게 탐색하므로, 구조가 올바르게 마크업되어야 효율적으로 이용할 수 있습니다." + }, + { + "id": "a11y-semantic-003", + "question": "제목(heading) 구조는 왜 중요한가요?", + "answer": "h1~h6의 계층은 문서의 목차 역할을 해 스크린리더 사용자가 구조를 파악하고 건너뛰며 탐색하게 합니다. 레벨을 건너뛰지 않고 논리적 순서로 사용하는 것이 중요합니다." + }, + { + "id": "a11y-semantic-004", + "question": "랜드마크(landmark) 영역이란?", + "answer": "header, nav, main, aside, footer 같은 영역으로, 페이지의 주요 구역을 나타냅니다. 스크린리더 사용자가 본문이나 내비게이션으로 곧바로 이동할 수 있게 해 탐색 효율을 높입니다." + }, + { + "id": "a11y-semantic-005", + "question": "폼 입력에 label을 연결해야 하는 이유는?", + "answer": "label과 input을 연결하면 스크린리더가 입력의 용도를 읽어주고, 라벨 클릭으로 입력에 포커스할 수 있기 때문입니다. placeholder는 라벨을 대체할 수 없으므로 명시적 label이 필요합니다." + }, + { + "id": "a11y-semantic-006", + "question": "버튼과 링크는 어떻게 구분해 사용하나요?", + "answer": "링크(a)는 다른 위치로 이동할 때, 버튼(button)은 동작을 수행할 때 사용합니다. 역할이 맞아야 키보드 동작과 스크린리더 안내가 올바르며, div에 클릭만 붙이는 방식은 피해야 합니다." + }, + { + "id": "a11y-semantic-007", + "question": "색상만으로 정보를 전달하면 안 되는 이유는?", + "answer": "색각 이상이 있는 사용자나 흑백 환경에서는 색 차이를 인지하지 못할 수 있기 때문입니다. 색과 함께 텍스트, 아이콘, 패턴 등 추가 단서를 제공해야 모두가 정보를 이해할 수 있습니다." + }, + { + "id": "a11y-semantic-008", + "question": "명도 대비(contrast)는 왜 중요한가요?", + "answer": "텍스트와 배경의 대비가 충분해야 저시력 사용자도 내용을 읽을 수 있기 때문입니다. WCAG는 일반 텍스트에 4.5:1 이상을 권장하며, 대비가 낮으면 가독성과 접근성이 떨어집니다." + }, + { + "id": "a11y-semantic-009", + "question": "스크린리더 전용 텍스트(visually hidden)는 어떻게 제공하나요?", + "answer": "화면에는 보이지 않지만 보조 기술은 읽을 수 있도록 sr-only 스타일을 적용한 텍스트를 둡니다. display:none은 읽히지 않으므로, 위치를 화면 밖으로 보내는 기법을 사용합니다." + }, + { + "id": "a11y-semantic-010", + "question": "table을 접근성 있게 만들려면 어떻게 하나요?", + "answer": "th로 헤더 셀을 지정하고 scope로 행/열을 명시하며, caption으로 표의 목적을 설명합니다. 이렇게 하면 스크린리더가 각 데이터 셀과 헤더의 관계를 정확히 읽어줄 수 있습니다." + } + ] + }, + { + "id": "a11y-keyboard", + "name": "키보드와 포커스", + "questions": [ + { + "id": "a11y-keyboard-001", + "question": "키보드 접근성이 중요한 이유는?", + "answer": "마우스를 쓰기 어려운 사용자나 스크린리더 사용자는 키보드로 모든 기능을 이용하기 때문입니다. 모든 상호작용 요소는 키보드만으로 접근하고 조작할 수 있어야 합니다." + }, + { + "id": "a11y-keyboard-002", + "question": "포커스 표시(focus indicator)를 없애면 안 되는 이유는?", + "answer": "키보드 사용자가 현재 어떤 요소에 있는지 알 수 없게 되기 때문입니다. outline을 제거하려면 반드시 더 나은 대체 포커스 스타일을 제공해야 접근성을 유지할 수 있습니다." + }, + { + "id": "a11y-keyboard-003", + "question": "tabindex 값은 어떻게 사용해야 하나요?", + "answer": "0은 자연스러운 순서로 포커스에 포함, -1은 스크립트로만 포커스 가능하게 합니다. 양수 값은 탭 순서를 인위적으로 바꿔 혼란을 주므로 피하고, DOM 순서를 논리적으로 두는 것이 좋습니다." + }, + { + "id": "a11y-keyboard-004", + "question": "포커스 트랩(focus trap)이란 무엇인가요?", + "answer": "모달이 열렸을 때 포커스가 모달 내부에만 머물도록 가두는 기법입니다. 배경 요소로 포커스가 빠져나가지 않게 해 키보드 사용자가 모달을 벗어나지 않고 조작하게 합니다." + }, + { + "id": "a11y-keyboard-005", + "question": "Skip to content(건너뛰기 링크)는 왜 제공하나요?", + "answer": "반복되는 내비게이션을 건너뛰고 본문으로 바로 이동하게 해주는 링크입니다. 키보드·스크린리더 사용자가 매 페이지마다 메뉴를 모두 거치지 않아도 되어 탐색 효율이 크게 좋아집니다." + }, + { + "id": "a11y-keyboard-006", + "question": "모달을 닫은 뒤 포커스는 어디로 가야 하나요?", + "answer": "모달을 열었던 트리거 요소로 포커스를 되돌려야 합니다. 그래야 키보드 사용자가 맥락을 잃지 않고 이전 위치에서 자연스럽게 작업을 이어갈 수 있습니다." + }, + { + "id": "a11y-keyboard-007", + "question": "커스텀 위젯에 키보드 상호작용을 어떻게 구현하나요?", + "answer": "WAI-ARIA Authoring Practices의 패턴에 따라 화살표, Enter, Space, Esc 등 기대되는 키 동작을 구현합니다. 예를 들어 탭은 화살표로 이동하고 메뉴는 Esc로 닫히도록 만듭니다." + }, + { + "id": "a11y-keyboard-008", + "question": "포커스 순서(focus order)는 어떻게 관리하나요?", + "answer": "시각적 순서와 DOM 순서를 일치시켜 탭 이동이 자연스럽게 흐르도록 합니다. CSS로 순서를 바꿨더라도 DOM이 논리적이어야 하며, 그렇지 않으면 키보드 탐색이 혼란스러워집니다." + }, + { + "id": "a11y-keyboard-009", + "question": "클릭 이벤트만 있는 요소의 접근성 문제는?", + "answer": "div 등에 onClick만 붙이면 키보드로 포커스·실행이 안 되고 역할도 전달되지 않습니다. button을 쓰거나, 불가피하면 role, tabindex, 키 이벤트 처리를 모두 추가해 동등하게 만들어야 합니다." + }, + { + "id": "a11y-keyboard-010", + "question": "접근성 테스트는 어떻게 진행하나요?", + "answer": "자동화 도구(axe, Lighthouse)로 기본 문제를 점검하고, 키보드만으로 전체 기능을 사용해 보며, 스크린리더로 실제 흐름을 확인합니다. 자동 검사로 잡히지 않는 부분은 수동 테스트로 보완해야 합니다." + } + ] + } + ] + }, + { + "id": "tooling", + "name": "개발 도구", + "categories": [ + { + "id": "tooling-bundler", + "name": "번들러", + "questions": [ + { + "id": "tooling-bundler-001", + "question": "모듈 번들러란 무엇인가요?", + "answer": "여러 모듈과 의존성을 분석해 브라우저가 실행할 수 있는 하나 또는 소수의 파일로 묶어주는 도구입니다. 모듈 시스템 호환, 최적화, 자원 변환을 처리하며 webpack, Vite, esbuild 등이 대표적입니다." + }, + { + "id": "tooling-bundler-002", + "question": "Vite가 빠른 이유는 무엇인가요?", + "answer": "개발 시 전체를 번들링하지 않고 브라우저의 네이티브 ESM을 활용해 필요한 모듈만 즉시 제공하기 때문입니다. 또 사전 번들링에 esbuild를 써서 의존성 처리가 매우 빠릅니다. 변경 반영(HMR)도 거의 즉각적입니다." + }, + { + "id": "tooling-bundler-003", + "question": "webpack의 핵심 개념(entry, output, loader, plugin)을 설명해 주세요.", + "answer": "entry는 번들의 시작점, output은 결과 파일 설정입니다. loader는 JS가 아닌 파일(CSS, 이미지 등)을 변환하고, plugin은 번들 최적화·자산 관리 등 더 넓은 작업을 수행합니다." + }, + { + "id": "tooling-bundler-004", + "question": "HMR(Hot Module Replacement)이란?", + "answer": "앱을 새로고침하지 않고 변경된 모듈만 실시간으로 교체해 반영하는 기능입니다. 상태를 유지한 채 수정 결과를 즉시 확인할 수 있어 개발 생산성을 크게 높입니다." + }, + { + "id": "tooling-bundler-005", + "question": "개발 빌드와 프로덕션 빌드의 차이는?", + "answer": "개발 빌드는 빠른 재빌드와 디버깅을 위해 소스맵·HMR을 포함하고 최적화를 덜 합니다. 프로덕션 빌드는 미니피케이션, 트리 셰이킹, 코드 분할 등 최적화를 적용해 작고 빠른 결과물을 만듭니다." + }, + { + "id": "tooling-bundler-006", + "question": "esbuild와 SWC는 왜 빠른가요?", + "answer": "각각 Go와 Rust로 작성되어 네이티브로 컴파일되고 병렬 처리에 최적화되어 있기 때문입니다. 자바스크립트 기반 도구보다 수십 배 빠른 변환 속도를 제공해 빌드 시간을 크게 단축합니다." + }, + { + "id": "tooling-bundler-007", + "question": "소스맵(source map)이란 무엇인가요?", + "answer": "변환·압축된 코드를 원본 소스와 연결해 주는 파일입니다. 브라우저 개발자 도구에서 원본 기준으로 디버깅할 수 있게 해주며, 프로덕션에서는 노출 범위를 신중히 결정해야 합니다." + }, + { + "id": "tooling-bundler-008", + "question": "번들러와 태스크 러너(gulp 등)의 차이는?", + "answer": "태스크 러너는 파일 변환·복사 같은 작업을 순서대로 자동화하는 도구입니다. 번들러는 모듈 의존성 그래프를 이해해 묶고 최적화하는 데 특화되어 있어, 모던 프런트엔드에서는 번들러가 중심이 됩니다." + }, + { + "id": "tooling-bundler-009", + "question": "Rollup은 어떤 경우에 적합한가요?", + "answer": "ESM 기반으로 트리 셰이킹이 뛰어나고 깔끔한 출력물을 만들어 라이브러리 번들링에 특히 적합합니다. 애플리케이션에는 Vite(내부적으로 Rollup 사용) 같은 도구가, 라이브러리에는 Rollup이 자주 선택됩니다." + }, + { + "id": "tooling-bundler-010", + "question": "코드 스플리팅을 번들러에서 어떻게 구현하나요?", + "answer": "동적 import()를 사용하면 번들러가 해당 지점을 기준으로 청크를 분리합니다. 라우트 단위 분할이나 공통 모듈 추출 설정과 함께 사용해 초기 로딩 크기를 줄일 수 있습니다." + } + ] + }, + { + "id": "tooling-transpiler", + "name": "트랜스파일러", + "questions": [ + { + "id": "tooling-transpiler-001", + "question": "트랜스파일러란 무엇인가요?", + "answer": "한 언어/버전의 코드를 같은 추상화 수준의 다른 코드로 변환하는 도구입니다. 최신 자바스크립트나 TypeScript를 구형 브라우저가 이해하는 코드로 바꾸는 Babel, tsc가 대표적입니다." + }, + { + "id": "tooling-transpiler-002", + "question": "Babel은 어떤 역할을 하나요?", + "answer": "최신 자바스크립트 문법(ES6+)이나 JSX를 구형 환경에서도 동작하는 코드로 변환합니다. 프리셋과 플러그인으로 변환 범위를 설정하며, 폴리필과 함께 광범위한 호환성을 제공합니다." + }, + { + "id": "tooling-transpiler-003", + "question": "트랜스파일링과 폴리필의 차이는?", + "answer": "트랜스파일링은 문법을 변환하는 것이고(화살표 함수 → 일반 함수), 폴리필은 없는 기능(Promise, fetch 등)을 런타임에 구현해 채워 넣는 것입니다. 문법은 변환으로, 누락된 API는 폴리필로 해결합니다." + }, + { + "id": "tooling-transpiler-004", + "question": "Babel과 tsc의 타입 처리 차이는?", + "answer": "tsc는 타입 검사를 수행하고 컴파일합니다. Babel은 타입을 검사하지 않고 단순히 타입 구문을 제거해 변환만 합니다. 그래서 Babel을 쓰면 별도로 tsc --noEmit 같은 타입 검사를 병행하는 경우가 많습니다." + }, + { + "id": "tooling-transpiler-005", + "question": "browserslist는 무엇이고 왜 중요한가요?", + "answer": "지원할 브라우저 범위를 선언하는 설정으로, Babel·Autoprefixer 등이 이를 참고해 필요한 변환과 접두사만 적용합니다. 타깃을 명확히 하면 불필요한 변환을 줄여 결과물이 가벼워집니다." + }, + { + "id": "tooling-transpiler-006", + "question": "AST(추상 구문 트리)는 변환에서 어떤 역할을 하나요?", + "answer": "코드를 구조화된 트리로 표현한 것으로, 트랜스파일러는 소스를 AST로 파싱하고 이를 변형한 뒤 다시 코드로 생성합니다. 린터, 포매터, 코드모드 등도 AST를 기반으로 동작합니다." + }, + { + "id": "tooling-transpiler-007", + "question": "폴리필을 필요한 만큼만 포함하려면?", + "answer": "core-js와 browserslist를 연동하고 Babel의 useBuiltIns를 usage로 설정하면, 실제 사용한 기능과 타깃 브라우저에 필요한 폴리필만 자동 주입됩니다. 번들 크기를 불필요하게 키우지 않습니다." + }, + { + "id": "tooling-transpiler-008", + "question": "JSX는 어떻게 변환되나요?", + "answer": "JSX는 브라우저가 직접 이해하지 못하므로 Babel/tsc가 React.createElement(또는 자동 런타임의 jsx 함수) 호출로 변환합니다. 결국 일반 자바스크립트 함수 호출이 되어 실행됩니다." + }, + { + "id": "tooling-transpiler-009", + "question": "타입스크립트를 자바스크립트로 컴파일할 때 타입은 어떻게 되나요?", + "answer": "타입 정보는 런타임에 존재하지 않으므로 컴파일 과정에서 모두 제거됩니다. 타입은 개발 시점의 검사에만 쓰이고, 출력된 자바스크립트에는 타입 구문이 남지 않습니다." + }, + { + "id": "tooling-transpiler-010", + "question": "최신 문법을 변환 없이 쓰면 어떤 문제가 생기나요?", + "answer": "구형 브라우저에서 문법 오류로 스크립트 전체가 실행되지 않을 수 있습니다. 타깃 환경을 고려해 트랜스파일링과 폴리필을 적용해야 넓은 호환성을 보장할 수 있습니다." + } + ] + }, + { + "id": "tooling-package", + "name": "패키지 매니저", + "questions": [ + { + "id": "tooling-package-001", + "question": "npm, yarn, pnpm의 차이는 무엇인가요?", + "answer": "셋 다 패키지 매니저지만 설치 방식과 속도에 차이가 있습니다. pnpm은 콘텐츠 주소 저장소와 하드링크로 디스크를 절약하고 빠르며, yarn은 병렬 설치와 워크스페이스를, npm은 기본 표준 도구로 널리 쓰입니다." + }, + { + "id": "tooling-package-002", + "question": "package.json의 역할은 무엇인가요?", + "answer": "프로젝트의 메타데이터, 의존성 목록, 스크립트, 설정을 담는 파일입니다. 의존성 버전 범위와 실행 명령을 정의해 협업과 재현 가능한 환경 구성의 기준이 됩니다." + }, + { + "id": "tooling-package-003", + "question": "lockfile(package-lock.json 등)은 왜 필요한가요?", + "answer": "의존성의 정확한 버전과 트리를 고정해 어떤 환경에서나 동일하게 설치되도록 보장하기 때문입니다. 이를 커밋하면 '내 컴퓨터에선 됐는데' 같은 버전 불일치 문제를 방지할 수 있습니다." + }, + { + "id": "tooling-package-004", + "question": "dependencies와 devDependencies의 차이는?", + "answer": "dependencies는 앱 실행에 필요한 패키지이고, devDependencies는 개발·빌드·테스트에만 쓰여 배포 결과물에는 포함되지 않습니다. 적절히 구분하면 프로덕션 의존성을 깔끔하게 유지할 수 있습니다." + }, + { + "id": "tooling-package-005", + "question": "시맨틱 버저닝(SemVer)이란?", + "answer": "버전을 MAJOR.MINOR.PATCH로 표기하는 규칙입니다. 호환성을 깨는 변경은 MAJOR, 기능 추가는 MINOR, 버그 수정은 PATCH를 올립니다. 의존성 범위 지정과 안전한 업데이트의 기준이 됩니다." + }, + { + "id": "tooling-package-006", + "question": "캐럿(^)과 틸드(~) 버전 범위의 차이는?", + "answer": "^1.2.3은 MAJOR가 같은 범위(1.x.x) 내 최신을 허용하고, ~1.2.3은 주로 PATCH 수준(1.2.x)만 허용합니다. 자동 업데이트 범위를 조절해 호환성과 최신성 사이를 조정합니다." + }, + { + "id": "tooling-package-007", + "question": "peerDependencies는 언제 사용하나요?", + "answer": "플러그인이나 라이브러리가 호스트 앱의 특정 패키지(예: react)를 함께 사용해야 할 때 선언합니다. 중복 설치를 막고 호환 버전을 호스트가 제공하도록 요구하는 용도입니다." + }, + { + "id": "tooling-package-008", + "question": "모노레포(monorepo)와 워크스페이스란?", + "answer": "여러 패키지를 하나의 저장소에서 함께 관리하는 방식이며, 워크스페이스는 패키지 간 의존성을 연결하고 공통 의존성을 공유하게 해줍니다. 코드 공유와 일관된 버전 관리에 유리합니다." + }, + { + "id": "tooling-package-009", + "question": "node_modules가 비대해지는 문제를 어떻게 완화하나요?", + "answer": "pnpm의 하드링크 기반 저장소로 중복을 제거하거나, 불필요한 의존성을 정리하고, 의존성 호이스팅·중복 제거를 활용합니다. 또 가벼운 대안 패키지를 선택하는 것도 도움이 됩니다." + }, + { + "id": "tooling-package-010", + "question": "npx는 무엇을 하는 도구인가요?", + "answer": "패키지를 전역 설치 없이 일회성으로 실행할 수 있게 해주는 도구입니다. 설치되지 않은 CLI를 즉석에서 받아 실행하거나, 특정 버전의 도구를 임시로 사용할 때 편리합니다." + } + ] + }, + { + "id": "tooling-git", + "name": "버전 관리(Git)", + "questions": [ + { + "id": "tooling-git-001", + "question": "Git이란 무엇인가요?", + "answer": "코드 변경 이력을 추적하고 여러 사람이 협업할 수 있게 해주는 분산 버전 관리 시스템입니다. 각 개발자가 전체 이력을 로컬에 가지며, 브랜치로 작업을 분리하고 병합할 수 있습니다." + }, + { + "id": "tooling-git-002", + "question": "merge와 rebase의 차이는 무엇인가요?", + "answer": "merge는 두 브랜치를 합치며 병합 커밋을 남겨 이력을 그대로 보존합니다. rebase는 커밋을 다른 기준 위로 재배치해 선형적인 깔끔한 이력을 만듭니다. 공유된 브랜치 rebase는 주의해야 합니다." + }, + { + "id": "tooling-git-003", + "question": "git pull과 git fetch의 차이는?", + "answer": "fetch는 원격의 변경 사항을 가져오기만 하고 현재 브랜치에 반영하지 않습니다. pull은 fetch에 더해 자동으로 병합(merge 또는 rebase)까지 수행합니다. 안전하게 확인하려면 fetch 후 병합이 좋습니다." + }, + { + "id": "tooling-git-004", + "question": "브랜치 전략(Git Flow, GitHub Flow)을 설명해 주세요.", + "answer": "Git Flow는 main, develop, feature, release, hotfix 등 역할별 브랜치를 두는 체계적인 방식입니다. GitHub Flow는 main과 짧은 기능 브랜치, PR 중심의 단순한 방식으로 지속적 배포에 적합합니다." + }, + { + "id": "tooling-git-005", + "question": "git reset과 git revert의 차이는?", + "answer": "reset은 브랜치 포인터를 이전 커밋으로 옮겨 이력을 되돌리며 공유 이력에서는 위험합니다. revert는 변경을 취소하는 새 커밋을 추가해 이력을 보존하므로 공유 브랜치에서 안전합니다." + }, + { + "id": "tooling-git-006", + "question": "충돌(conflict)은 왜 발생하고 어떻게 해결하나요?", + "answer": "여러 사람이 같은 부분을 다르게 수정해 병합할 때 발생합니다. Git이 표시한 충돌 구간을 직접 확인해 원하는 결과로 수정하고, 해결 후 다시 커밋해 병합을 완료합니다." + }, + { + "id": "tooling-git-007", + "question": "Pull Request(Merge Request)의 목적은?", + "answer": "변경 사항을 본 브랜치에 병합하기 전에 코드 리뷰, 논의, 자동 검사를 거치기 위한 절차입니다. 품질을 높이고 지식을 공유하며, 변경 맥락을 기록으로 남기는 협업의 핵심입니다." + }, + { + "id": "tooling-git-008", + "question": "git stash는 언제 사용하나요?", + "answer": "작업 중인 변경을 커밋하지 않고 임시로 보관할 때 사용합니다. 급히 다른 브랜치로 전환해야 할 때 현재 변경을 치워 두었다가 나중에 다시 적용할 수 있어 편리합니다." + }, + { + "id": "tooling-git-009", + "question": "의미 있는 커밋 메시지를 작성하려면?", + "answer": "무엇을 왜 바꿨는지 간결하게 요약하고, 한 커밋은 하나의 논리적 변경을 담도록 합니다. 명령형 제목과 필요한 본문 설명, 컨벤셔널 커밋 같은 규칙을 따르면 이력 추적이 쉬워집니다." + }, + { + "id": "tooling-git-010", + "question": ".gitignore는 어떤 역할을 하나요?", + "answer": "버전 관리에서 제외할 파일·폴더를 지정하는 설정입니다. node_modules, 빌드 산출물, 환경 변수 파일처럼 추적이 불필요하거나 민감한 항목을 커밋되지 않게 막아줍니다." + } + ] + }, + { + "id": "tooling-test", + "name": "테스트", + "questions": [ + { + "id": "tooling-test-001", + "question": "단위/통합/E2E 테스트의 차이는?", + "answer": "단위 테스트는 함수·컴포넌트 같은 작은 단위를 격리해 검증합니다. 통합 테스트는 여러 단위의 상호작용을 확인하고, E2E 테스트는 실제 사용자 흐름을 브라우저에서 전체적으로 검증합니다." + }, + { + "id": "tooling-test-002", + "question": "테스트 피라미드란 무엇인가요?", + "answer": "빠르고 많은 단위 테스트를 아래에, 적당한 통합 테스트를 중간에, 느리고 적은 E2E 테스트를 위에 두는 균형 전략입니다. 비용과 속도, 신뢰도의 균형을 맞춰 효율적으로 품질을 확보합니다." + }, + { + "id": "tooling-test-003", + "question": "Jest는 어떤 도구인가요?", + "answer": "자바스크립트 테스트 러너이자 단언(assertion), 모킹, 커버리지 기능을 갖춘 프레임워크입니다. 설정이 간단하고 스냅샷 테스트를 지원해 프런트엔드 단위·통합 테스트에 널리 쓰입니다." + }, + { + "id": "tooling-test-004", + "question": "React Testing Library의 철학은 무엇인가요?", + "answer": "구현 세부가 아니라 사용자가 보는 방식대로 테스트하라는 것입니다. DOM 텍스트·역할 기준으로 요소를 찾아 상호작용을 검증해, 리팩터링에 강하고 실제 사용성에 가까운 테스트를 작성하게 합니다." + }, + { + "id": "tooling-test-005", + "question": "모킹(mocking)은 왜 필요한가요?", + "answer": "외부 의존성(API, 모듈, 타이머)을 가짜로 대체해 테스트를 빠르고 결정적으로 만들기 위해서입니다. 통제된 환경에서 특정 동작을 검증하고 네트워크 같은 불안정 요소를 제거할 수 있습니다." + }, + { + "id": "tooling-test-006", + "question": "스냅샷 테스트의 장단점은?", + "answer": "렌더 결과를 저장해 두고 변경을 감지하므로 회귀를 빠르게 잡습니다. 다만 의미를 검증하지 않아 무분별하게 쓰면 변경 시마다 갱신만 반복하게 될 수 있어, 작고 안정적인 출력에 쓰는 것이 좋습니다." + }, + { + "id": "tooling-test-007", + "question": "Cypress와 Playwright 같은 E2E 도구의 특징은?", + "answer": "실제 브라우저에서 사용자 시나리오를 자동화해 검증합니다. 자동 대기, 디버깅 도구, 다양한 브라우저 지원을 제공하며, Playwright는 멀티 브라우저·병렬 실행에 강점이 있습니다." + }, + { + "id": "tooling-test-008", + "question": "TDD(테스트 주도 개발)란?", + "answer": "실패하는 테스트를 먼저 작성하고, 통과시키는 최소 코드를 구현한 뒤, 리팩터링하는 사이클을 반복하는 개발 방식입니다. 설계를 개선하고 회귀를 막으며 요구사항을 명확히 하는 데 도움이 됩니다." + }, + { + "id": "tooling-test-009", + "question": "테스트 커버리지는 어떻게 해석해야 하나요?", + "answer": "코드가 테스트로 실행된 비율을 나타내는 지표입니다. 낮으면 검증이 부족하다는 신호지만, 100%라고 품질을 보장하진 않습니다. 수치보다 중요한 로직이 의미 있게 검증되는지가 더 중요합니다." + }, + { + "id": "tooling-test-010", + "question": "좋은 테스트의 조건은 무엇인가요?", + "answer": "빠르고, 독립적이며, 반복 실행해도 같은 결과가 나오고(결정적), 실패 시 원인을 알기 쉬워야 합니다. 또 구현이 아닌 동작을 검증해 리팩터링에 견디는 테스트가 좋은 테스트입니다." + } + ] + } + ] + } + ] +} \ No newline at end of file