Published on
👁️

5월16일 기술 공부 - 기타

Authors
  • avatar
    Name
    River
    Twitter
6자료구조 스택에 대해서 설명해주세요쉬움
스택은 LIFO, 즉 후입선출 구조로 나중에 넣은 값이 먼저 나오는 자료구조다. 예를 들어 함수 호출이 중첩될 때 가장 마지막에 호출된 함수부터 종료되는 구조와 같은 기능을 스택이 처리한다. 실무에서는 DFS(깊이 우선 탐색)과 같은 알고리즘, 웹 브라우저 뒤로가기, 함수 호출 스택 등에 자주 사용된다.
상세 설명

스택의 기본 개념

  • LIFO(후입선출) 구조의 자료구조
  • 나중에 들어간 데이터가 먼저 나온다.
  • 기본 연산: push(데이터 추가), pop(데이터 제거), peek(맨 위 데이터 조회)
  • 연산의 시간 복잡도는 대부분 O(1)
  • 함수 호출 스택, 웹 브라우저 뒤로가기, 깊이 우선 탐색(DFS) 등에 활용됨
7동시성과 병렬성에 대해서 설명해주세요보통
동시성은 여러 작업이 논리적으로 동시에 실행되는 것처럼 보이게 하는 소프트웨어적 처리 방식이다. 실제로는 CPU의 하나의 코어가 컨텍스트 스위칭을 통해 여러 작업을 빠르게 전환하며 처리합니다. 사용자 입장에서는 동시에 실행되는 것처럼 보이며, 대표적인 예시로 비동기 처리가 있다. 반면 병렬성은 여러 작업을 물리적으로 동시에 같은 시점에 실행되는 개념이다. 이를 위해서 멀티코어나 분산시스템처럼 하드웨어적 지원이 필요하다.
상세 설명

동시성(Concurrency)의 개념

  • 여러 작업이 논리적으로 동시에 수행되는 것처럼 보이는 개념
  • 하나의 코어가 여러 작업을 빠르게 전환하며 처리 (컨텍스트 스위칭)
  • 사용자 입장에선 동시에 실행되는 것처럼 느껴짐
  • 소프트웨어적 동시 처리
  • Ex. 단일 스레드에서 I/O 작업 중 다른 작업 수행 (비동기)
참고

동시성은 "동시에 진행되는 것처럼 보이는" 개념으로, 실제로는 빠른 작업 전환을 통해 이루어진다. 사용자 입장에서는 여러 작업이 동시에 진행되는 것처럼 느끼지만, 실제로는 한 번에 하나의 작업만 처리하고 있을 수 있다.

병렬성(Parallelism)의 개념

  • 여러 작업이 물리적으로 동시에 실행되는 개념 (정확히 같은 시점)
  • 멀티코어 CPU나 분산 시스템에서 각 작업을 동시에 실행
  • 하드웨어적 실제 동시 처리
  • 하드웨어적 지원이 필수적이다.
  • Ex. 4개의 코어가 각각 다른 작업을 동시에 처리

List의 parallelStream()란?

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
int sum = numbers.parallelStream()
                .filter(n -> n % 2 == 0)
                .mapToInt(n -> n * n)
                .sum();
  • parallelStream()은 내부적으로 ForkJoinPool.commonPool을 사용해 작업을 멀티 스레드로 분산시켜 실행
  • 즉, 사용자가 따로 스레드를 만들지 않아도 JVM이 멀티코어 환경을 활용하여 자동으로 병렬로 처리한다
  • 하지만, 작은 데이터에서는 stream()보다 느릴 수 있다. (스레드에 관한 오버헤드)
주의

parallelStream() 실행한다고 무조건 병렬로 처리하지 않을 수 있다. (항상 병렬 처리를 보장하지 않음)

컨텍스트 스위칭(Context Switching)

  • CPU가 실행 중인 작업(스레드)의 상태(Context)를 저장하고, 다른 작업의 상태를 불러와 실행을 전환하는 과정을 말한다.
  • 이 과정은 일정한 오버헤드가 발생하며, 스위칭이 잦아지면 성능 저하의 원인이 될 수 있다.

멀티 스레드를 쓰면 무조건 병렬성인가?

  • 멀티 스레드를 사용한다고 해서 반드시 물리적인 병렬 처리(실제 동시에 실행)가 일어나는 것은 아니다.
  • 이는 CPU의 코어 수와 스케줄링 방식에 따라 달라진다.
중요

우리가 병렬로 실행되도록 요청하더라도, 실제로 병렬 처리가 될지는 CPU 스케줄러의 판단과 시스템 자원 상황에 따라 달라진다. 예를 들어, 4코어 CPU인데 동시에 10개의 스레드가 실행 중이면 4개만 병렬 실행하고 나머지 6개는 컨텍스트 스위칭으로 처리해야 한다.

8JVM의 Garbage Collection 알고리즘에 대해 설명해주세요어려움
Garbage Collection(GC) 알고리즘은 더 이상 사용되지 않는 객체를 자동으로 감지하고 메모리에서 제거함으로써, JVM의 메모리를 효율적으로 관리하는 역할을 한다. JVM에서는 다양한 알고리즘이 제공되며, 대표적으로 Serial GC, Parallel GC, CMS, G1 GC, ZGC, Shenandoah GC가 있다. 현재는 Serial GC, Parallel GC, CMS는 거의 사용되지 않고 java 9부터 기본값으로 G1 GC가 설정되어 있다. 또한 JVM Heap이 매우 큰 경우나, 실시간 금융 거래나 대화형 AI 처럼 Latency가 아주 중요한 경우 초저지연 GC인 ZGC나 Shenandoah를 쓰는 것이 권장된다.
상세 설명

GC(Garbage Collection) 알고리즘이란?

  • 더 이상 사용되지 않는 객체를 자동으로 찾아서 메모리에서 제거하는 알고리즘
  • 주요 알고리즘
    • Serial GC, Parallel GC, CMS(Concurrent Mark and Sweep)
    • G1 GC(Garbage First), ZGC(Z Garbage Collector), Shenandoah GC
  • JVM은 GC를 통해 불필요한 객체를 자동으로 정리
    • 이때 사용하는 알고리즘은 Java 9 이상인 경우 G1 GC를 기본값으로 사용한다.

Serial GC

  • 단일 스레드로 GC 수행 (Minor / Full GC 모두)
  • Stop-the-world 시간이 길고 병렬 처리 안 됨
  • 클라이언트 애플리케이션이나 작은 Heap에서 유리
  • 존재는 하지만, 거의 사용 안 함
  • 사용 옵션: XX:+UseSerialGC

Parallel GC (또는 Throughput GC)

  • 여러 스레드로 GC를 병렬 수행 (주로 Minor GC)
  • 전체 애플리케이션 처리량(Throughput)을 높이는 데 초점
  • 잠깐 멈추지만 빠르게 정리해서 다시 실행 가능
  • 사용 옵션: XX:+UseParallelGC (Java 8의 기본값)

CMS (Concurrent Mark and Sweep)

  • 응답 속도(지연 시간) 최소화 목표
  • Stop-the-world 시간을 줄이기 위해 GC를 앱 스레드와 병행 실행
  • 단계: 초기 마크 → 마크 → 리마크 → 스윕
  • 단점: 프래그멘테이션(Heap 조각화), Full GC 느림
  • 오래된 방식의 알고리즘으로 G1 GC가 모두 대체
  • 사용 옵션: XX:+UseConcMarkSweepGC (Java 9부터 deprecated, Java 14부터 제거됨)

G1 GC (Garbage First)

  • 대규모 Heap에서 좋은 성능
  • Heap을 여러 영역(region)으로 나눠서 관리
  • 필요할 때마다 GC를 부분적으로 수행 → Full GC 적음 (짧은 STW)
  • 낮은 지연 시간과 적당한 처리량의 균형
  • 대부분의 서버 애플리케이션은 G1 GC로 충분
  • 사용 옵션: XX:+UseG1GC (Java 9 이후 기본값)

ZGC (Z Garbage Collector)

  • 초저 지연 시간 (10ms 이하)을 목표로 함
  • GC 중에도 대부분의 작업을 애플리케이션과 병행해서 수행
  • 수 TB 단위의 대용량 Heap에서도 잘 동작
  • 사용 옵션: XX:+UseZGC (Java 11 이상)

Shenandoah GC

  • Red Hat에서 개발한 초저지연 GC

  • GC 시간 중 대부분의 작업을 애플리케이션과 병행 수행하며,

    Stop-the-world 정지 시간을 sub-millisecond 수준(0.001초 미만)으로 최소화하는 것이 목표

  • G1처럼 region 기반 + 동시 compacting 지원

  • 다만, G1은 compacting이 STW 동안 수행되지만, 여기서는 병렬 수행

  • 사용 옵션: XX:+UseShenandoahGC (Java 12 이상)

9결합도와 응집도에 대해 설명해주세요보통
결합도와 응집도는 소프트웨어 설계 원칙 중 하나로, 결합도(Coupling)는 모듈 간 의존성의 강도를 의미하며, 낮을수록 유연하고 유지보수가 쉬운 시스템이다. 응집도(Cohesion)는 하나의 모듈이 얼마나 밀접하게 관련된 책임들로 구성되어 있는가를 나타내며, 높을수록 명확하고 재사용 가능한 구조이다. 좋은 소프트웨어 설계는 낮은 결합도, 높은 응집도를 목표로 한다
상세 설명

결합도(Coupling)

  • 모듈 간의 의존 관계나 연결 정도를 의미
  • 낮은 결합도(Low Coupling)는 다른 모듈의 변경에 영향을 덜 받는다는 의미로 변경에 강하고 테스트가 용이하다. 반대로 높은 결합도인 경우 변경에 취약해 유연성 낮아 유지보수가 어렵다
  • Ex. Service가 Repository를 인터페이스로 주입받는 구조 ⇒ 낮은 결합도
중요

낮은 결합도를 달성하기 위해 의존성 주입(DI), 인터페이스 활용, 추상화 등의 기법을 사용
이를 통해 한 모듈의 변경이 다른 모듈에 미치는 영향을 최소화할 수 있다.

응집도(Cohesion)

  • 하나의 모듈이 얼마나 관련성 높은 기능들로 구성되어 있는가를 의미

  • 높은 응집도(High Cohesion)는 하나의 책임/관심사에 집중된 모듈로 재사용성이 높고, 코드 이해도가 높다. 반면 낮은 응집도(Low Cohesion)인 경우 서로 다른 책임이 섞여 있어서 유지보수가 어렵다

  • Ex. 회원 관련 기능만 포함된 UserService는 높은 응집도

    여기에 로그인, 결제, 이메일 발송 기능이 섞여 있다면 낮은 응집도

참고

SOLID의 단일 책임 원칙(SRP)은 높은 응집도를 달성하기 위한 핵심 원칙이다.
하나의 클래스나 모듈은 변경의 이유가 오직 하나여야 한다.

결합도의 종류

  • 내용 결합도(Content Coupling) : 한 모듈이 다른 모듈의 내부 구현에 직접 의존 (최악)
  • 공통 결합도(Common Coupling) : 여러 모듈이 전역 데이터를 공유
  • 제어 결합도(Control Coupling) : 한 모듈이 다른 모듈의 내부 논리 흐름을 제어
  • 스탬프 결합도(Stamp Coupling) : 모듈 간에 자료 구조를 전달
  • 데이터 결합도(Data Coupling) : 모듈 간에 매개변수를 통해 데이터만 주고받음 (가장 좋음)

응집도의 종류

  • 우연적 응집도(Coincidental) : 관련 없는 기능들이 한 모듈에 모여 있음 (최악)
  • 논리적 응집도(Logical) : 논리적으로 관련된 기능들이 한 모듈에 있음
  • 시간적 응집도(Temporal): 특정 시점에 함께 실행되는 기능들의 모음
  • 절차적 응집도(Procedural) : 특정 절차나 순서로 실행되는 기능들의 모음
  • 교환적 응집도(Communicational) : 같은 입출력 데이터를 사용하는 기능들의 모음
  • 순차적 응집도(Sequential) : 한 기능의 출력이 다른 기능의 입력이 되는 형태
  • 기능적 응집도(Functional) : 단일 목적을 위한 모든 기능이 한 모듈에 있음 (가장 좋음)

실무에서의 응용

  • Spring Framework : 의존성 주입(DI)으로 낮은 결합도를 구현
  • 마이크로서비스 아키텍처(MSA) : 서비스 간 낮은 결합도, 서비스 내 높은 응집도 지향
  • SOLID 원칙 : 특히 단일 책임 원칙(SRP)과 의존성 역전 원칙(DIP)이 응집도와 결합도에 관련
10React의 서버 컴포넌트에 대해서 설명해주세요보통
서버 컴포넌트는 React 18에서 도입된 기능으로, 컴포넌트를 서버에서 렌더링한 뒤 HTML만 클라이언트로 전송하는 방식이다. 이를 통해 보안성과 성능을 높이고, 초기 로딩 속도와 JS 번들 크기를 줄일 수 있지만, 브라우저에 JS가 포함되지 않아서 클릭, 입력 등의 이벤트를 처리할 수 없다는 제한이 있다.
상세 설명

서버 컴포넌트(Server Component)란?

  • React 컴포넌트 중 서버에서만 렌더링되는 컴포넌트
  • 서버에서 실행되어 HTML만 생성한 후 클라이언트에 전달되며, JavaScript는 번들되지 않음
  • React 18 + Next.js 13 이상에서 기본적으로 Server Component 방식을 사용
  • 보안이 중요한 비즈니스 로직, DB 직접 호출 등에 적합
  • 브라우저에서 실행되지 않기 때문에 JS 이벤트 핸들링 불가
참고

서버 컴포넌트는 기존의 SSR(Server-Side Rendering)과는 다른 개념입니다. SSR은 초기 렌더링만 서버에서 수행하고 이후 JS가 클라이언트에 로드되어 "하이드레이션" 과정을 거치지만, 서버 컴포넌트는 아예 클라이언트에 JS 코드를 보내지 않는다.

서버 컴포넌트를 쓰면 좋은 상황

  • DB에서 직접 데이터를 가져와 화면을 구성할 때 (API 호출 불필요)
  • 인증/인가 로직 등 민감한 로직이 포함된 경우
  • 첫 페이지 로딩 속도를 중요하게 여길 때
  • JS 번들 크기를 최소화하고 싶을 때
  • 클라이언트 컴포넌트와 혼합 사용하여 효율적 분리하고자 할 때
중요

서버 컴포넌트에서는 useState, useEffect 같은 React 훅을 사용할 수 없으며, 브라우저 API에 접근할 수 없고, 이벤트 리스너를 추가할 수 없다. 이러한 기능이 필요한 경우 클라이언트 컴포넌트를 사용해야 한다.

클라이언트 컴포넌트와 서버 컴포넌트 비교

특성서버 컴포넌트클라이언트 컴포넌트
렌더링 위치서버에서만 렌더링클라이언트에서 렌더링
JS 번들 포함 여부미포함 (HTML만 전송)포함
React 훅 사용불가능 (useState 등)가능
이벤트 처리불가능가능
브라우저 API 접근불가능가능
서버 리소스 접근직접 접근 가능불가능 (API 필요)
파일 정의 방식기본 방식'use client' 지시문 필요