기술 면접 겁나 빡세다는 블로그 후기를 여러개 봤고 질문들을 많이 봤습니다.
다른 분들께도 도움이 될까 해서 나름의 답변을 공유하고자 글을 작성합니다.
챗지피티 없이 제가 순수하게 해낼 수 있을까요??
PNG와 JPG 차이점은?
PNG는 무손실 압축 방식입니다. rgba로 표현이되는 alpha 채널을 지원하며 이는 불투명도와 투명도를 나타낼 수 있습니다. (0이 투명합니다)
어떻게 무손실 압축이 일어나냐면 스캔과 + LZ77 방식과 허프만 코딩 방식을 통해서 압축을 합니다.
[ 100, 110, 120 ] 으로 이루어진 RGB 값이 있다고한다면 좌, 상, 평균 등의 값을 통해 차이로 값을 바꿔줍니다.
그러면 0 이나 1등의 숫자가 많이 나오게 되는데 이를 허프만 코딩으로 표현을 해줍니다.
🧐 허프만 코딩이란?
자주나오는 문자 기준으로 트리 형태를 구성해서 0101010 형태로 바꿔주는 것을 말합니다. 주로 다른 문자가 prefix가 되지 않는 것이 포인트입니다.
🧐 LZ77이란?
000000000000 -> 0이 10개 나왔다 라고 표현하는 방식입니다.
그래서 PNG는 단조로운 색을 압축하는데 유리한 특징을 가지고 있습니다. 주로 아이콘등에 사용되는 이유가 있죠.
+ PNG의 파일 시그니처는 89 50 4E 47 0D 0A 1A 0A 인데 50 4E 47이 아스키 코드로 PNG라고 합니다.
그리고 4바이트의 청크 단위로 이루어져 있어서 건너뛰기나 CRC 등에 유리합니다.
JPG는 손실 압축입니다. rgb를 YcBcR로 바꿔서 표현을 합니다. 여기서 Y는 밝기, cB는 블루가 포함된 정도 cR은 레드가 포함된 정도 라고 합니다. 사람의 눈은 색 정보에는 둔감하고 빛 정보에는 민감하기 때문에 이를 통해 DCT ( 퓨리에 변환에 일종입니다 )로 양자화를 거칩니다.
손실은 이과정에서 일어나게 되고 다시 돌아갈 수 없습니다 :(
일반적으로 풍경이나 사진등에 자주 적용이 됩니다.
JPG는 압축률이 좋아서 보통 갤러리에 저장되는 방식으로 잘 사용이 됩니다.
예전에 Flutter로 CameraImage 처리할 때 안드로이드가 YUV420, iOS가 BGRA8888 이었나? 썼던 기억이 나네요
base64 란?
사진, 이미지, 동영상과 같은 바이너리 데이터들을 ASCII 문자로 변환한 방식입니다.
이는 압축 방식이 아니며 오히려 용량이 1/3 정도 늘어나는 방식입니다.
입력인 컴퓨터의 바이트 스트림은 보통 8비트로 들어오는데요.
base64는 이름에서 볼 수 있듯 64개의 문자로 표현이 됩니다.
64개 문자는 2 ^ 6이고 이는 6비트입니다.
입력인 8비트와 출력인 6비트의 최소공배수인 24비트가 사용이 되어야 효율적이고,
인코딩의 단위는 24비트는 -> 3바이트 ( 1바이트는 8비트 )입니다.
그래서 결국 출력은 ASCII 4문자(24비트 나누기 6비트)로 나타납니다.
공백이 있으면 = 으로 채워주고요
Base64는 어디에 쓰이냐면 사진이나 이미지 같은 파일들이 있는데 이거를 지원안해주는 DB가 있을 수 있습니다.
이때 그냥 시원하게 base64로 변환해서 저장한담에 꺼내서 인코딩 디코딩 하는거죠 ㅋ
단점은 일단 용량이 커진다가 있을 수 있고, 네트워크 통신 간 이걸 인코딩 디코딩을 다시 해줘야 하는 작업이 추가가 되고 공백이 = 으로 채워지는데 이때 삑사리 나면 데이터가 유실날 수 있다는 단점도 있습니다.
1Byte에 대해 다 말해보세요
1바이트는 8비트입니다. 왜 8비트일까요??
잘 모르긴 하는데 아마 미국에서 IBM이 잘나가던 시절에 이걸 주로 써서 그랬다고 하긴 합니다. 이건 찾아보고 수정해놓아요
그리고 아스키 코드가 7비트인데 1비트를 패리티로 붙이면 용이하다? 뭐 그래서 쓰게 됐다고도 하고요.
1px은 색상 정보를 나타내는 단위인데
rgb라면 3바이트 ( 0 ~ 255 , 0 ~ 255 , 0 ~ 255 )
rgba라면 4바이트 ( 0 ~ 255 , 0 ~ 255 , 0 ~ 255 , 0 ~ 255 )가 되겠죠.
한바이트로 우리는 256개의 숫자를 표현할 수 있습니다.

음수는 어떻게 표현을 할까요?
signed 와 unsigned 방식이 있습니다.
맨앞에 0을 체크하지 않는 방식은 unsigned 이고 이는 0 ~ 255 입니다.
0을 체크하는 방식은 -> signed 방식이고 - 128 ~ 127까지 입니다.
맨 앞자리를 부호로 나두고 7비트를 숫자로 쓰는 방식입니다.
부동 소수점이 뭐죠?
부동소수점은 실수를 더 다양하게 표현을 하는 방식입니다. 이와 반대로는 고정 소수점이 있습니다.
부동은 뜰 부에 움직일 동을 써서 움직인다는 뜻이에요. 고정이 고정되어 있다는 뜻이죠
64비트에서는 1을 음수/양수 판별, 11비트를 exponential, 52비트를 fraction으로 나타냅니다.
10진법에서 나타나는 소수를 2진법으로 바꿀 때 문제가 발생하게 됩니다.
0.5와 같은 경우는 2 ^ -1 로 0.1_2 이런식으로 깔끔하게 표현이 되지만
0.1과 같은 경우는 0.0001100110011 ... 으로 무한반복이 됩니다.
그래서 소숫점 아래에 미세한 값들이 많기 때문에 0.1 + 0.2 == 0.3 -> false가 나오는 것입니다.
만약에 타이머를 구현한다 했을 때 100ms 대신 0.1s를 10번 더한다면 시간이 맞지 않을 수도 있겠죠.
디지털 시계 프로그램 초 단위 어떻게 설계할 것인가?
new Date() 또는 Date.now()로 현재 시각을 기준으로 표시하겠습니다.
new Date()는 런타임이 제공하는 현재 시간을 가져오며 내부적으로 UTC 기준 1970-01-01T00:00:00부터 경과한 밀리초를 Number로 표현한 타임스탬프를 사용합니다.
JS 타이머(setInterval, setTimeout)는 지정한 시각에 콜백 실행을 보장하지 않고 해당 시각 이후 실행 가능한 태스크로 예약됩니다.
메인 스레드가 바쁘면 콜백 실행이 지연되어 드리프트가 발생할 수 있으므로 setInterval로 1초를 누적하는 방식은 정확도를 보장할 수 없겠죠
구현은 누적이 아니라 현재 시각 기반으로 합니다. requestAnimationFrame으로 프레임마다 현재 시간을 읽고 초 값이 바뀐 경우에만 화면을 갱신합니다.
Dynamic Programming이란?
하나의 문제가 반복되는 성질의 작은 문제로 분해되며 이전 값들이 다음 값에 의미 있게 사용될 수 있도록 저장하며 나가는 프로그래밍 기법입니다. 부분 문제의 최적해가 전체 문제의 최적해로 이어질 때 사용합니다. 중복된 계산을 줄일 수 있습니다. 타뷸레이션과 메모이제이션 등의 방법이 있습니다.
Virtual Memory란?
가상 메모리는 프로세스에 독립적이고 연속적인 가상 주소 공간을 제공하고 한정된 물리 메모리의 공간을 더 많이 사용할 수 있는 것처럼 보이게 해주는 기법입니다,
하나의 프로세스가 실행이 되기 위해 메모리에 적재가 되어야 하는데 이때 모든 프로세스를 전부 다 올리는 것이 아니라 실행이되는 부분만 올리게 됩니다. 프로세스를 페이지 단위로 나누고 메모리를 프레임 단위로 나누어서 할당을 해줍니다. 이렇게 되면 물리적으로는 떨어져 있지만 논리적으로는 가상 주소 공간을 연속적으로 제공해서 프로그래밍/메모리 관리가 쉬워지고 ( 배열, 외부 단편화 등 ) 실제 적재는 페이지 단위로 이뤄져 필요 페이징 및 캐시 정책과 결합해 효율을 높일 수 있습니다.
또한 이렇게 관리를 하면 프로세스를 격리할수 있어 페이지 별로 보안/권한 등을 설정할 수 있게 됩니다.
CPU는 가상 메모리를 물리 메모리 주소를 변환해주는 MMU라는 장치를 통해 관리를 하게 됩니다.
다만 만약 64비트 짜리 운영체제를 사용한다고 가정을 하면 주소 공간은 최대 2의 64승 정도가 되기 때문에 이를 가상 페이징 하는 것은 주소공간이 커서 페이지테이블이 커질 수 있어 멀티레벨로 희소하게 관리합니다. 페이지테이블 엔트리가 물리 프레임 번호와 플래그를 저장합니다.
주소값을 가져올 때 시간이 느린데 이는 TLB라는 페이지 매핑 캐시를 활용해서 이를 완화 합니다.
외부 단편화/내부 단편화 차이?
외부 단편화 -> 10MB가 필요한데 2MB씩 흩어져 있어서 할당을 못해주는 경우
내부 단편화 -> 페이지 크기가 4kb인데 3kb만 필요한 경우 -> 1kb 남음
TLB miss와 page fault 차이?
TLB miss -> 캐시 미스 가벼움, 페이지가 메모리에 있을수도 없을 수도 있음
page fault -> page demand 시에 아직 메모리에 적재가 되지 않는 경우 or 권한이나 매핑 문제 -> OS가 개입
프로세스 간 통신(IPC) 이란?
프로세스끼리 데이터를 공유하기 위한 방법들입니다. 프로세스는 고유의 메모리 공간을 가지기 때문에 IPC를 통해 공유를 합니다.
파이프라인, 메시지 큐, 공유 메모리 사용, 소켓 등이 있습니다.
VM과 컨테이너의 차이점은?
VM은 프로세스가 하드웨어를 가상화하여 host의 os와 다른 OS와 커널을 가질 수 있습니다. 격리가 강하지만 무겁다는 단점이 존재합니다. 컨테이너는 호스트의 OS를 따르고 커널을 공유하지만 하나의 프로세스가 자식 프로세스를 생성하여 namespace와 cgroup을 통해 격리되어 독립된 데이터를 가지게 됩니다. 배포가 빠르고 가볍습니다.
프로세스와 스레드 차이점
프로세스는 독립된 가상 주소 공간을 가진 실행 단위이고 OS가 PCB로 관리합니다. 스레드는 같은 프로세스 안의 실행 흐름으로 코드/데이터/힙을 공유하지만 스택과 레지스터 컨텍스트, TLS는 스레드별로 분리됩니다. 멀티프로세스는 주소 공간 격리가 강해 장애 전파가 상대적으로 적지만 IPC 비용과 프로세스 전환 비용이 커질 수 있습니다. 멀티스레드는 같은 주소 공간을 공유해 통신이 빠르고 전환이 가벼운 편이지만 동기화 문제로 레이스 컨디션, 데드락 같은 오류에 취약합니다
OS 에서 동시성, 병렬성 이렇게 두개의 키워드에 대해서 설명해주세요.
CPU가 하나일때를 가정해보면 프로세스가 여러개 실행되는 것처럼 보이게 해주는 것이 동시성입니다. 하나의 프로세스가 CPU를 독점하는 것이 아닌 백그라운드 처리, 비동기 처리 등을 하여 동시에 일어나는 것 처럼 보이게 해줍니다.
CPU가 여러개 인 경우에는 실제로 작업이 여러개가 병렬적으로 진행이 됩니다. 이를 병렬성이라고 합니다.
뮤텍스와 세마포어의 차이는 뭘까요?
뮤텍스는 상호배제를 위한 락으로 동시에 하나만 들어가게 하고 락에 소유권이 있어 획득한 스레드가 해제하는 것이 원칙입니다.
세마포어는 카운터 기반으로 동시에 N개까지 자원 접근을 허용하며 wait/signal로 카운트를 줄이고 늘려 접근을 제어합니다
바이너리 세마포어와 뮤텍스의 차이는 뭘까요?
둘 다 하나의 실행흐름만 공유 자원에 접근할 수 있다는 점이지만 기본적으로 소유권에서 차이가 있습니다.
뮤텍스는 락을 가지게 되어 실행 주체가 분명해집니다. 따라서 락의 소유와 해제는 같은 주체가 해야한다가 있습니다. 어떤 작업이 실행 중인지를 명확하게 알 수 있습니다.
하지만 바이너리 세마포어는 소유권 모델이 아니라서 동일하게 적용하기는 어렵습니다.
그 예시로 우선순위 역전이 있습니다. L, M, H가 있다고 가정할 때 작업순위가 낮은 L 가장 먼저 들어와 락을 소유하고 임계 영역에서 작업을 하고 있습니다. 이후에 H가 들어와 L이 끝나기를 기다리며 대기 상태로 들어갑니다. CPU는 락이 필요하지 않은 M의 작업을 먼저 수행하게 되고 단일 코어에서는 M -> L -> H 의 순서로 마무리가 되어 결국 무관한 M 때문에 L이 락을 풀 기회를 못 받아 결과적으로 H가 더 오래 대기하게 됩니다.
OS는 이때 누가 락을 가지고 있는지 알 수 있기 때문에 L의 우선순위를 가장 높여 CPU가 L을 먼저 처리하게 할 수 있습니다. 그렇게 되면
L -> H -> M 이렇게 우선순위가 높은 작업이 순서대로 잘 수행이 됩니다.
바이너리 세마포어도 비슷한 기능을 제공하기는 하지만 소유권이라는 개념이 명확하느냐의 차이가 있습니다.
linux의 fork 함수의 내부 구동 방식이 어떻게 되죠?
리눅스에서 쉘은 보통 명령 실행을 위해 fork()로 자식 프로세스를 만든 뒤, 자식에서 execve()로 실행 파일로 프로세스 이미지를 교체합니다. fork()는 부모에겐 자식 PID를, 자식에겐 0을 반환하며 두 프로세스는 fork 다음 줄부터 실행되는 것처럼 보입니다. 핵심은 메모리를 즉시 통째로 복사하지 않고 Copy-on-Write로 처리하여, 처음엔 페이지를 공유하다가 쓰기가 발생하는 페이지만 복사한다는 점입니다. 파일 디스크립터 같은 커널 자원은 참조를 공유할 수 있어 오프셋 등이 영향을 줄 수 있습니다
Cache란?
캐시는 느린 계층(메모리/디스크/네트워크/연산)의 결과를 더 빠른 저장소에 저장해 평균 접근 시간을 줄이는 기법입니다. 효과는 히트율뿐 아니라, 히트 시 지연 시간과 미스 페널티에 의해 결정됩니다. 캐시는 지역성에 기반하는데, 시간 지역성은 최근 접근한 데이터/코드를 곧 다시 접근할 가능성이 높다는 것이고, 공간 지역성은 한 주소를 접근하면 근처 주소도 곧 접근할 가능성이 높다는 성질입니다.
Garbage Collection이란?
사용자가 메모리를 직접 할당하고 해제하지 않고 VM이 하도록 하는 방법입니다.
레퍼런스 카운트로 체크를 하여 0이되는 경우 메모리를 해제하는 방법이 있는데 이는 순환 참조나 자기 참조등의 문제가 발생합니다. 이를 해결하기 위해서는 GC root부터 시작해 도달할 수 없는 객체를 메모리해제하는 마크엔 스윕 방식이 존재합니다.
Memory Leak의 대처방법은?
메모리 릭 대처의 출발은 ‘릭의 정의’라고 생각합니다. 동일한 동작을 반복했을 때 메모리가 일시적으로 증가하는 건 정상일 수 있지만, 시간이 지나도 회수되지 않고 우상향으로 누적되면 릭으로 판단합니다. 그래서 먼저 Grafana나 프로세스 지표로 ‘상승 후 안정화인지, 지속 누적인지’를 확인하고, 재현 가능한 시나리오를 고정해 반복 실행 후 힙/RSS의 추세를 비교합니다. 릭이 의심되면 프로세스를 특정한 뒤 힙 스냅샷/덤프로 어떤 객체가 GC 대상이 아닌지(캐시, 리스너, 구독 등 참조 유지)를 추적하고, 수정 후 다시 추세가 안정화되는지로 검증합니다
WeakReference란?
GC가 객체의 생존 여부를 판단할 때, 약한 참조를 생존 근거로 인정하지 않도록 런타임이 규칙을 정해 둔 것입니다. 즉, 약한 참조는 포인터처럼 객체를 가리키지만, 도달 가능(reachable) 판정에 포함되지 않는 참조입니다 약한 참조만 남은 대상 객체가 GC 대상이 될 수 있음(약한 참조는 생존을 보장하지 않음)
Database Index 추가의 장단점은?
인덱스는 특정 컬럼(또는 컬럼 조합)을 키로 한 정렬된 탐색 구조(B+Tree) 를 별도 유지해, 풀스캔 대신 필요한 범위만 빠르게 찾아 조회 성능을 개선합니다. 특히 선택도가 높은 WHERE 조건, JOIN 키, 범위 조회, 정렬/Top-N 조회에서 효과가 큽니다. 반면 INSERT/UPDATE/DELETE마다 인덱스도 갱신되어 쓰기 성능이 저하될 수 있고, 디스크/메모리 공간 및 단편화·통계 관리 같은 유지보수 비용이 증가합니다. B+Tree는 내부 노드는 키 범위로 분기하고 리프 노드에 엔트리가 저장되며 리프가 연결되어 범위 스캔에 유리합니다.
NoSQL의 장단점은?
수평확장에 유리하다. 읽기 성능이 좋다.
데이터 정규화가 아쉽다. 수정이 어렵다.
Node.js의 특징은?
Node.js는 자바스크립트를 서버 사이드에서 실행하는 런타임으로 기본적으로 단일 스레드에서 동작하며 비동기 I/O 모델을 기반으로 동시 요청을 효율적으로 처리합니다. call stack에서 코드가 실행되며 이벤트 루프를 중심으로 비동기 작업의 콜백과 Promise 처리 순서를 태스크 큐와 마이크로태스크 큐를 통해 스케줄링합니다. 이 구조는 I/O 바운딩 작업에서 높은 처리량에 유리하지만 CPU 바운딩 작업이 길어지면 이벤트 루프가 블로킹되어 지연이 커질 수 있어 워커 스레드나 프로세스 분리 같은 설계가 필요합니다. 또한 CommonJS와 ES Modules을 모두 지원합니다.
javascript 특징은?
동적 타이핑(Dynamic typing) 런타임에 타입이 결정되며, 변수는 어떤 타입 값도 가질 수 있습니다.
프로토타입 기반 객체 모델(Prototype-based OOP) 클래스 문법이 있어도 내부적으로는 프로토타입 체인으로 상속/위임이 동작합니다.
함수는 1급 객체(First-class function) 함수를 값처럼 전달/반환/저장 가능하며, 콜백·함수형 패턴이 자연스럽습니다.
클로저(Closure) 함수가 생성될 때의 렉시컬 스코프(외부 변수 환경)를 캡처해 이후에도 접근 가능합니다.
실행 컨텍스트 & 스코프 체인(Execution context) 호출 스택에 컨텍스트가 쌓이며, 렉시컬 환경을 통해 식별자 탐색이 이뤄집니다.
이벤트 루프 기반 비동기 모델(Event loop) 동기 코드는 콜스택에서 실행되고, 비동기 결과는 큐를 통해 순차적으로 처리됩니다.
단일 스레드 기반 실행(메인 스레드에서 JS 실행) JS 실행은 기본적으로 한 스레드에서 이뤄지며, 긴 CPU 작업은 UI/응답성을 막을 수 있습니다.
프로미스/async·await(비동기 추상화) 콜백 대신 Promise와 async/await로 비동기 흐름을 구조화할 수 있습니다.
ES6+ 표준 및 모듈 시스템(ESM) let/const, 화살표 함수, 구조 분해, 템플릿 리터럴, 클래스, 모듈(import/export) 등 현대 문법을 표준으로 제공합니다.
가비지 컬렉션(GC) 기반 메모리 관리 대부분의 런타임이 GC로 메모리를 자동 회수하나, 참조 유지로 누수는 발생할 수 있습니다.
호이스팅/TDZ(선언 처리 규칙): var 함수 스코프/호이스팅, let/const TDZ 차이 엄격 모드(strict mode): 오류를 더 엄격히 처리하고 일부 위험한 동작을 제한
런타임별 차이(브라우저 vs Node.js): Web API/DOM, Node의 fs/net 등 환경 제공 API가 다름
Higher Order Function이란?
고차 함수는 함수를 인자로 받거나 함수를 반환하는 함수입니다. 자바스크립트에서 함수는 1급 객체이므로 변수에 할당하거나 인자로 전달/반환할 수 있고, 이를 이용해 map, filter, reduce 같은 함수형 유틸을 만들 수 있습니다. 또한 함수를 반환하는 형태로 커링이나 부분 적용 같은 패턴도 구현할 수 있습니다.
GIT의 장점은?
Git은 분산 버전 관리 시스템으로 변경 이력을 커밋 단위로 추적하고 브랜치를 활용해 기능별로 병렬 개발한 뒤 안정적으로 병합할 수 있어 협업에 유리합니다. 또한 로컬에 전체 히스토리가 남아 있어 비교, 롤백, 문제 원인 추적이 빠르고 운영 안정성에도 도움이 됩니다. 추가로 GitHub에서는 Codex, Code rabit과 같은 AI PR 기반 코드 리뷰와 자동 테스트, Actions를 통한 CI/CD 도구 연계 등으로 협업과 품질 관리를 체계적으로 할 수 있습니다.
비대칭 암호화란?
비대칭 암호화는 공개키/개인키 두 키를 쓰는 방식입니다. 공개키로 암호화하면 개인키로만 복호화되어 기밀성을 제공하고, 개인키로 서명하면 공개키로 검증할 수 있어 무결성과 인증을 제공합니다. 실무에서는 비대칭은 느리기 때문에 TLS에서 서버 인증과 세션 키 교환에 쓰고, 실제 데이터 전송은 AES 같은 대칭키로 처리하는 하이브리드 구조가 일반적입니다
패스워드를 안전하게 전송/보관하는 방법은?
전송은 HTTPS(TLS)로 보호하고, 저장은 비밀번호를 평문이나 복호화 가능한 형태로 저장하지 않고 사용자별 salt를 추가한 뒤 Argon2id/bcrypt 같은 KDF로 해시해 저장합니다. 로그인 시 동일한 KDF로 계산해 비교합니다
HDD, SSD, DRAM 각각의 성능은?
HDD는 기계식이라 랜덤 접근 지연이 커서 느리지만 용량 대비 가격이 싸고, SSD는 반도체 저장장치라 지연과 랜덤 IOPS가 크게 개선되며, DRAM은 CPU가 직접 접근하는 메모리라 지연이 SSD보다 훨씬 낮고 대역폭이 가장 크지만 휘발성입니다
CPU와 GPU의 차이는?
CPU는 중앙 프로세스 장치로 복잡한 분기처리나 낮은 지연에 유리합니다. GPU는 처리량이 많은 작업에 유리합니다.
그래픽카드를 이용한 하드웨어 가속이란?
GPU 하드웨어 가속은 CPU 대신 GPU 같은 특화 하드웨어가 대량의 동일 연산을 병렬로 처리해 성능을 높이는 방식입니다. GPU는 많은 코어로 픽셀/벡터/행렬 같은 데이터를 동시에 계산하고 메모리 대역폭도 커서 렌더링, 영상 처리, 딥러닝의 행렬곱·컨볼루션 같은 작업에서 효과가 큽니다. 반면 CPU↔GPU 데이터 전송 오버헤드가 크거나 분기와 불규칙 접근이 많은 작업은 효과가 제한적일 수 있습니다
UTF-8 이란?
UTF-8은 유니코드 문자를 바이트 시퀀스로 표현하는 가변 길이 인코딩 방식입니다. ASCII 범위는 1바이트로 동일하게 표현되어 호환되고, 그 외 문자는 2~4바이트로 표현합니다. 또한 연속 바이트가 10xxxxxx 패턴을 가져서 경계 식별이 쉬워 웹과 파일 포맷에서 표준처럼 널리 쓰입니다
HTTP/2의 특징은?
바이너리 프레이밍, 멀티 플렉싱, 서버 푸시 기능, 헤더 압축
이미지 리스트의 성능 향상법은?
이미지 리스트는 (1) 다운로드, (2) 디코딩/리사이즈, (3) 렌더링/스크롤, (4) 메모리 네 가지가 병목이 될 수 있습니다. 그래서 CDN/캐시로 전송을 줄이고, 썸네일 리사이즈 및 포맷 최적화로 바이트를 줄이며, lazy loading과 리스트 가상화로 렌더링 부담을 낮추고, 마지막으로 캐시 크기 제한과 썸네일/원본 분리로 메모리 안정성을 확보합니다
고해상도 이미지의 로딩 방법은?
고해상도 이미지는 원본을 한 번에 내려받기보다, 서버에서 썸네일/중간/원본 등 여러 해상도를 제공하고 뷰포트와 DPR에 맞게 선택해 로딩합니다. 먼저 LQIP/blur 같은 프리뷰로 즉시 보여 체감 성능을 확보하고, 실제 이미지는 lazy loading과 비동기 디코딩으로 렌더링 부담을 줄입니다. 또한 필요한 크기로 다운샘플링 디코딩하고 캐시 크기를 제한해 메모리 폭증과 스크롤 프레임 드랍을 방지합니다
네트워크에서의 멱등성이 무엇인지 정확히 뭔지 알고 계신가요?
멱등성은 동일한 요청을 여러 번 반복해도 시스템의 최종 상태가 동일하게 유지되는 성질입니다. 네트워크에서는 타임아웃 등으로 재시도가 발생하므로 중요합니다. 예를 들어 PUT은 같은 리소스를 같은 값으로 덮어쓰면 여러 번 보내도 결과가 같아 멱등이고, POST로 ‘새 리소스 생성’은 반복 시 중복 생성이 되어 보통 멱등이 아닙니다.
웹브라우저 URL에 http://www.naver.com을 치고 나서 네이버 첫페이지가 표시되기까지 일어나는 일을 본인이 알고 있는대로 최대한 상세하게 설명해 보라. 레이어를 아무리 내려가도 좋고, 설명이 아무리 길어져도 좋다. 10분 동안 해도 된다
브라우저에서 URL을 파싱한 뒤 네비게이션을 시작합니다. 호스트가 도메인이면 OS 리졸버를 통해 먼저 로컬 캐시와 hosts를 확인하고, 없으면 네트워크 설정에 등록된 DNS 서버(공유기/ISP/사내 DNS)에 질의하여 도메인을 IP로 해석합니다. IP를 얻으면 라우팅을 통해 패킷이 전달되고, 전송 계층에서 TCP 3-way handshake로 연결을 수립한 뒤 HTTP 요청을 보내 최초 HTML을 받습니다(필요 시 리다이렉트/압축 포함). 이후 HTML을 파싱해 DOM을 만들고 CSS를 파싱해 CSSOM을 만든 다음, Render Tree를 구성하여 Layout→Paint→Composite 과정을 거쳐 화면에 그립니다. 이 과정에서 추가로 필요한 CSS/JS/이미지 리소스는 병렬로 요청되며, 브라우저는 가능한 범위에서 점진적으로 화면을 렌더링합니다.
React 란?
React는 Meta가 개발한 선언형 UI 라이브러리로, UI를 컴포넌트 단위로 구성하고 state/props 변화에 따라 UI를 자동으로 재렌더링하는 방식으로 화면을 관리합니다. 렌더 결과는 Virtual DOM 형태로 표현되고, 변경된 부분만 실제 DOM에 반영하기 위해 reconciliation과 commit 단계를 수행합니다. 또한 브라우저와 분리된 렌더러 구조를 통해 다양한 플랫폼에 UI를 렌더링할 수 있습니다.
Web Browser 의 프로세싱 중 Reflow 란?
Reflow는 DOM/CSS 변경으로 인해 요소들의 크기·위치를 다시 계산하는 레이아웃 재계산 과정이며, paint보다 비용이 큰 편이라 애니메이션이나 반복 DOM 업데이트에서는 reflow를 최소화하도록 설계합니다
MVC가 어떤 문제를 해결하기 위해 나온 것일까요?
MVC는 UI가 커지고 기능이 늘어날수록 데이터(비즈니스 로직)와 화면 코드가 뒤섞여 변경 영향 범위가 커지고, 테스트·재사용·협업이 어려워지는 문제를 해결하기 위해 등장한 패턴입니다. Model(도메인/상태/규칙), View(표현/UI), Controller(입력 처리/흐름 제어)로 책임을 분리하여 변경을 국소화하고, 관심사 분리(SoC) 를 통해 유지보수성과 테스트 용이성을 높입니다.
가상 dom 의 단점은 무엇인가
가상 DOM은 UI 변경을 추상화해 관리하기 좋지만, 가상 트리를 유지하고 diff/커밋을 수행하는 오버헤드가 있어 메모리·CPU 비용이 증가할 수 있고, 큰 리스트나 불필요한 리렌더가 있으면 diff 자체가 병목이 될 수 있습니다. 또한 레이아웃/페인트 같은 브라우저 렌더링 비용은 가상 DOM만으로 해결되지 않습니다
함수형 프로그래밍 패러다임이란?
함수형 프로그래밍은 프로그램을 상태 변경(명령) 중심이 아니라, 함수 조합과 평가(식) 중심으로 구성하는 패러다임입니다. 핵심은 순수 함수(pure function) 를 기반으로 부수효과(side effect)를 최소화하고, 불변성(immutable data) 과 선언적(declarative) 구성을 통해 예측 가능성과 테스트 용이성을 높이는 것입니다. 또한 고차 함수, 함수 합성, 커링 같은 기법을 적극적으로 사용합니다.
async I/O 란? 논블로킹 이란?
Async I/O는 I/O를 요청만 해두고 기다리지 않은 채 다른 일을 수행하다가, 완료되면 이벤트/콜백/Promise로 결과를 받는 모델이며, 구현은 보통 논블로킹 I/O + 이벤트 루프(epoll/kqueue/IOCP)로 이루어집니다
논블로킹은 I/O 요청 시 작업이 준비되지 않았더라도 호출이 즉시 반환되어, 호출한 스레드의 실행 흐름이 멈추지 않는 방식입니다. 준비 상태는 EAGAIN 같은 반환이나 이벤트(epoll 등)로 확인합니다
공유기의 원리는?
가정용 공유기는 라우터+스위치+무선 AP가 합쳐진 장비입니다. 내부에서는 스위치/브리지로 MAC 기반 L2 전달을 하고, 단말에는 DHCP로 사설 IP와 게이트웨이/DNS를 임대합니다. 인터넷으로 나갈 때는 라우터가 NAT(PAT)를 수행해 여러 내부 사설 IP를 하나의 공인 IP로 매핑하고, 외부에서 들어오는 응답 패킷은 NAT 테이블을 보고 올바른 내부 단말로 전달합니다. Wi-Fi는 단말이 SSID를 탐색해 AP와 연결(association)하고 WPA2/3 핸드셰이크 후, 네트워크 계층은 DHCP로 설정받는 흐름입니다.
와이파이로 어떻게 인터넷을 사용할 수 있는지
휴대폰은 Wi-Fi로 AP에 연결하고(WPA2/3면 핸드셰이크로 암호화 키를 만든 뒤), DHCP로 사설 IP와 게이트웨이, DNS를 받습니다. 도메인을 입력하면 DNS로 서버 IP를 얻고, 목적지가 외부망이므로 패킷을 기본 게이트웨이인 공유기로 보냅니다. 이때 ARP로 공유기의 MAC을 알아내고 프레임을 전송합니다. 공유기는 라우팅을 수행하면서 NAT(PAT)로 내부 사설 IP:포트를 공인 IP:포트로 변환해 인터넷으로 내보내고, 응답이 돌아오면 NAT 테이블을 보고 다시 내부 주소로 복원해 휴대폰에 전달합니다.
python 특징 10개 말해보세요
1. 동적 타이핑과 자동 메모리 관리(GC/레퍼런스 카운팅 기반)
2. 멀티 패러다임(객체지향/절차/함수형 스타일 가능)
3. (CPython 기준) GIL로 인해 한 프로세스의 Python 바이트코드 실행은 동시 병렬이 제한되며, IO 중심 작업은 스레딩으로, CPU 병렬은 multiprocessing/네이티브 확장으로 해결
4. 모든 것이 객체(함수/클래스/모듈 등)
5. 생태계와 표준 라이브러리가 풍부해 생산성이 높음(웹/자동화/데이터/AI)
6. 들여쓰기 기반 블록 구조로 가독성이 좋고 스타일이 강제됨
7. 인터프리터 실행 모델(소스 → 바이트코드 → VM 실행), 플랫폼 독립성이 높음
8. 예외 중심 오류 처리가 일반적
9. 리스트/딕트 등 고수준 자료구조가 기본 제공
10. C 확장과의 결합이 용이(성능 병목을 네이티브로 내릴 수 있음
11. 다중 상속 불가
interpreter vs. compiler 언어 차이점이 정확히 뭐죠?
컴파일러는 소스를 미리 기계어(또는 오브젝트)로 변환하고 링크해서 실행 파일을 만든 뒤 실행하는 방식이고, 인터프리터는 실행 시점에 소스나 바이트코드를 VM이 해석하며 수행하는 방식입니다. 일반적으로 컴파일은 사전 최적화와 네이티브 실행으로 빠르기 쉽고, 인터프리트는 해석 오버헤드가 있을 수 있지만 현대에는 바이트코드+JIT처럼 혼합이 많아 단순히 ‘인터프리터는 한 줄씩 실행’으로 보긴 어렵습니다.
python에서 코드를 실행하는 과정은 어떻게 진행되죠?
CPython은 .py를 파싱해 AST를 만든 뒤 바이트코드로 컴파일하고, 이를 Python VM이 실행합니다. .pyc는 이 바이트코드를 import 시 재사용하려고 저장하는 캐시입니다
데이터가 대부분 0 이고, 일부만 1이라면 - 그러니까 일부 유저들만 1의 값을 가지고 있는데, 유저들의 로그가 다 필요한 경우에 이를 담는 자료구조로는 뭐가 좋을까요?
Roaring Bitmap
정렬 알고리즘 아는 거 다 말해봐요
1) 선택 정렬(Selection)
- 아이디어: 최솟값을 찾아 앞에 배치 반복
- 시간: O(N²) (최선/평균/최악 동일)
- 공간: O(1), in-place, stable 아님(일반 구현)
2) 삽입 정렬(Insertion)
- 아이디어: 앞부분을 정렬 상태로 유지하며 하나씩 끼워 넣기
- 시간: 평균/최악 O(N²), 최선 O(N)(거의 정렬)
- 공간: O(1), in-place, stable
3) 퀵 정렬(Quick)
- 아이디어: pivot 기준으로 partition 후 재귀
- 시간: 평균 O(N log N), 최악 O(N²)(pivot 나쁘면)
- 공간: 평균 O(log N)(재귀), in-place 가능, stable 아님
- 실무 포인트: 상수항 작고 캐시 친화적이라 평균적으로 빠름(라이브러리는 보통 변형 사용)
4) 힙 정렬(Heap)
- 아이디어: 최대/최소 힙 구성 후 하나씩 꺼내 정렬
- 시간: O(N log N)(최선/평균/최악)
- 공간: O(1), in-place, stable 아님
- 포인트: 최악 보장 필요할 때
5) 병합 정렬(Merge)
- 아이디어: 분할정복 + merge(선형 병합)
- 시간: O(N log N)(항상)
- 공간: O(N), stable, 보통 not in-place
6) 계수/기수 정렬(Counting/Radix) (비교 기반 아님)
- Counting: 값 범위 K가 작을 때 O(N+K), 공간 O(K), stable 가능
- Radix: 자릿수 d, 기수 k일 때 O(d(N+k)) (보통 선형에 가깝게 사용)
- Bucket sort: 분포가 균일하다는 가정 하에 평균적으로 선형에 가까움