✅ 면접 기초지식 총정리 (+꼬리질문)


🔷 1. 객체지향 (OOP)

  • 정의: 객체(데이터 + 행위) 단위로 프로그램을 구성하여 유연하고 확장 가능한 구조를 만드는 프로그래밍 패러다임
  • 핵심 개념:
    • 캡슐화: 데이터 보호, 접근 제한
    • 상속: 코드 재사용
    • 다형성: 인터페이스 다양성
    • 추상화: 공통 행위 추출

꼬리질문: 추상 클래스와 인터페이스의 차이는?

  • 답변: 추상 클래스는 일부 구현을 포함할 수 있으며 단일 상속만 가능, 인터페이스는 모든 메서드가 추상이며 다중 구현 가능

🔷 2. JWT (JSON Web Token)

  • 정의: 인증과 권한 검증을 위한 JSON 기반의 토큰 포맷. Header, Payload, Signature 3부분으로 구성
  • 특징: 자체 정보를 포함하며, 서버의 상태 저장이 필요 없음 (stateless)

꼬리질문: JWT는 안전한가요?

  • 답변: 서명으로 위변조는 막을 수 있으나, Payload는 Base64로 인코딩되기 때문에 민감정보는 암호화 필요

🔷 3. OAuth

  • 정의: 사용자 인증과 권한 위임을 위한 프로토콜. 타 서비스에 내 계정 정보 접근을 안전하게 허용
  • 흐름: 인증 요청 → 권한 부여 → Access Token 발급 → API 접근

꼬리질문: OAuth에서 Access Token과 Refresh Token의 차이는?

  • 답변: Access Token은 짧은 기간 동안 리소스 접근에 사용, Refresh Token은 Access Token 재발급용

🔷 4. Java

  • 정의: 객체지향 기반의 범용 프로그래밍 언어. JVM 위에서 동작하며, 풍부한 라이브러리와 플랫폼 독립성이 강점

꼬리질문: Java에서 메모리 영역에는 어떤 것이 있나요?

  • 답변: Heap, Stack, Method Area, PC Register, Native Method Stack

🔷 5. Spring Framework

  • 정의: Java 기반의 경량 프레임워크로, DI와 AOP 기반의 유연한 구조 제공
  • 주요 기능: DI(의존성 주입), AOP, MVC 아키텍처, 트랜잭션 처리 등

꼬리질문: Spring의 장점은?

  • 답변: 느슨한 결합, 모듈화 용이, 테스트 용이, 유연한 구조

🔷 6. DispatcherServlet

  • 정의: Spring MVC에서 모든 HTTP 요청을 받아 컨트롤러에 전달하는 Front Controller
  • 역할: 요청 → HandlerMapping → Controller → ViewResolver → 응답 흐름 제어

꼬리질문: DispatcherServlet이 없다면 어떤 문제가 생길까요?

  • 답변: 요청 분기, 일관성 유지, 보안, 에러 처리 등 공통 기능이 흩어지고 복잡도가 상승함

🔷 7. JVM (Java Virtual Machine)

  • 정의: Java 바이트코드를 실행하는 가상 머신
  • 구성요소: 클래스 로더, 실행 엔진, GC, 메모리 영역(Heap, Stack 등)

꼬리질문: JVM이 Java의 플랫폼 독립성을 어떻게 보장하나요?

  • 답변: Java 코드는 바이트코드로 컴파일되고, 각 OS에 맞는 JVM이 바이트코드를 실행함

🔷 8. 파싱 & 매핑

  • 파싱: 데이터를 구문 분석하여 의미 있는 구조로 변환 (예: JSON → 객체)
  • 매핑: 구조화된 데이터(객체)를 다른 표현(예: DB Row)로 연결

꼬리질문: JSON을 파싱하면 어떤 객체가 만들어지나요?

  • 답변: 보통 언어별 DTO나 VO 객체로 매핑됨. Java에서는 Jackson, Gson 사용

🔷 9. 직렬화 & 역직렬화

  • 직렬화: 객체를 바이트 스트림으로 변환
  • 역직렬화: 바이트 스트림을 객체로 복원
  • 사용처: 네트워크 전송, 파일 저장, 캐시 등

꼬리질문: 직렬화 시 transient 키워드는 왜 사용하나요?

  • 답변: 직렬화 대상에서 제외하기 위한 키워드, 보안 또는 불필요한 필드 제외 목적

🔷 10. Spring DI / IoC

  • DI(Dependency Injection): 객체 간의 의존성을 외부에서 주입 (생성자, 필드, Setter 방식)
  • IoC(Inversion of Control): 객체 생성과 제어 권한을 개발자에서 프레임워크로 위임

꼬리질문: 생성자 주입과 필드 주입의 차이는?

  • 답변: 생성자 주입은 테스트와 불변성 확보에 유리, 필드 주입은 간단하지만 테스트가 어려움

🔷 11. Spring MVC

  • 정의: 모델-뷰-컨트롤러 패턴 기반의 웹 애플리케이션 구조
  • 구성: Controller, Service, Repository, View (Thymeleaf 등)

꼬리질문: Controller에서 Service를 호출하는 이유는?

  • 답변: Controller는 요청을 받고 전달만, 로직은 Service에 분리하여 유지보수성과 재사용성을 확보함

🔷 12. N+1 문제

  • 정의: 하나의 쿼리 실행 후, 연관된 N개의 쿼리가 추가로 실행되어 성능 저하 발생
  • 원인: Lazy Loading된 엔티티의 반복 조회
  • 해결법: Fetch Join, @EntityGraph, batch-size 설정

꼬리질문: Lazy Loading은 왜 쓰나요?

  • 답변: 초기 성능 최적화를 위해 필요 시점까지 로딩을 미루는 방식. 단, N+1 문제 주의 필요

🔷 1. AOP (관점 지향 프로그래밍)

  • 정의: 핵심 로직 외의 공통된 관심사를 분리하여 모듈화하는 기법 (ex. 로깅, 트랜잭션 등)
  • Spring AOP: 프록시 기반으로 동작하며, 주로 @Aspect와 @Around, @Before, @After 등으로 구현

꼬리질문: AOP와 OOP는 어떤 관계인가요?

  • 답변: OOP는 기능 단위, AOP는 관심사 단위로 모듈화. AOP는 OOP를 보완하여 횡단 관심사를 처리

🔷 2. Django

  • 정의: Python 기반의 웹 프레임워크로 MTV(Model-Template-View) 아키텍처 사용
  • 특징: ORM 내장, admin 자동 생성, 빠른 개발 속도, 보안 기능 탑재

꼬리질문: Django의 ORM이 하는 일은?

  • 답변: 객체와 데이터베이스 레코드를 매핑해 SQL 없이도 DB 조작 가능

🔷 3. TDD (Test Driven Development)

  • 정의: 테스트를 먼저 작성한 후 기능 구현을 진행하는 개발 방법론
  • 순서: 실패하는 테스트 작성 → 코드 구현 → 테스트 통과 → 리팩토링

꼬리질문: TDD의 장점은?

  • 답변: 유지보수성 증가, 리팩토링 용이, 요구사항 정확도 상승, 버그 사전 방지

🔷 4. 오버라이딩 vs 오버로딩

  • 오버라이딩: 부모 클래스의 메서드를 자식 클래스가 재정의 (동적 바인딩)
  • 오버로딩: 같은 이름의 메서드를 매개변수 다르게 정의 (정적 바인딩)

꼬리질문: 오버라이딩 시 주의할 점은?

  • 답변: 접근 제한자는 같거나 더 넓어야 하고, 예외는 같거나 더 좁아야 함

🔷 5. 트랜잭션

  • 정의: 데이터베이스 작업의 논리적 단위로, 모두 성공하거나 모두 실패해야 함
  • ACID: 원자성, 일관성, 고립성, 지속성

꼬리질문: 트랜잭션의 고립성이란?

  • 답변: 동시에 실행되는 트랜잭션들이 서로 영향을 주지 않도록 보장 (격리 수준 설정 가능)

🔷 6. 정규화 / 반정규화

  • 정규화: 데이터 중복 제거 및 무결성 확보 (1NF ~ 5NF)
  • 반정규화: 성능 향상을 위해 일부 중복 허용 (조회 속도 개선 등)

꼬리질문: 반정규화는 언제 사용하나요?

  • 답변: 복잡한 조인이 성능 저하를 유발할 때 조회 위주의 시스템에서 사용

🔷 7. Redis

  • 정의: In-memory 기반 Key-Value 저장소. 캐시, 세션 저장 등에 활용
  • 특징: 빠른 속도, 다양한 자료구조 지원 (List, Set, Hash 등), 퍼시스턴스 기능 존재

꼬리질문: Redis는 언제 사용하는 게 좋나요?

  • 답변: 빠른 조회가 필요한 경우, 세션 저장, 캐시 서버, Pub/Sub 구현 시 적합

🔷 8. MySQL

  • 정의: 대표적인 오픈소스 관계형 데이터베이스
  • 특징: SQL 기반, 다양한 저장 엔진(InnoDB, MyISAM 등), ACID 지원

꼬리질문: InnoDB와 MyISAM 차이점은?

  • 답변: InnoDB는 트랜잭션과 외래키 지원, MyISAM은 빠르지만 트랜잭션 미지원

🔷 9. 프로세스 vs 스레드

  • 프로세스: 실행 중인 프로그램, 독립된 메모리 공간 사용
  • 스레드: 프로세스 내 실행 단위, 메모리 공간 공유

꼬리질문: 스레드 사용의 장점은?

  • 답변: 메모리 공유로 자원 효율적, 컨텍스트 스위칭 비용 감소, 병렬성 향상

🔷 10. 가상메모리

  • 정의: 물리적 메모리보다 큰 주소 공간을 제공하는 메모리 관리 기법
  • 기법: 페이징(Paging), 스와핑(Swapping) 등

꼬리질문: 가상메모리의 장점은?

  • 답변: 실제 메모리보다 많은 프로그램 실행 가능, 메모리 보호, 주소 공간 확장

🔷 11. 교착상태 (Deadlock)

  • 정의: 여러 프로세스가 자원을 점유한 채 서로 다른 자원을 기다리며 무한 대기 상태에 빠지는 현상
  • 조건: 상호 배제, 점유 대기, 비선점, 순환 대기 (4가지 조건이 모두 충족될 때 발생)

꼬리질문: 교착상태를 예방하는 방법은?

  • 답변: 자원 순서를 정하거나, 타임아웃, 자원 선점 전략 등으로 예방 가능

🔷 12. 기아상태 (Starvation)

  • 정의: 특정 프로세스가 자원을 오랫동안 할당받지 못해 실행되지 못하는 상태

꼬리질문: 기아상태는 언제 발생하나요?

  • 답변: 우선순위가 낮은 프로세스가 자원을 계속 선점당할 때 발생. Aging 기법 등으로 해결 가능

🔷 1. 기아 상태 (Starvation)

  • 정의: 우선순위가 낮은 프로세스가 자원을 장시간 할당받지 못해 실행되지 못하는 상태
  • 원인: 높은 우선순위 프로세스가 지속적으로 자원을 선점할 때 발생

꼬리질문: 기아 상태를 해결하려면?

  • 답변: Aging 기법으로 시간이 지남에 따라 우선순위를 높여주는 방식 사용

🔷 2. 프로세스 동기화

  • 정의: 여러 프로세스/스레드가 공유 자원에 안전하게 접근할 수 있도록 순서를 제어하는 것
  • 기법: 뮤텍스(Mutex), 세마포어(Semaphore), 모니터(Monitor)

꼬리질문: 세마포어와 뮤텍스의 차이는?

  • 답변: 뮤텍스는 1개의 쓰레드만 접근 가능, 세마포어는 지정된 수만큼 동시 접근 가능

🔷 3. TCP 3-Way Handshake

  • 정의: TCP 연결 설정 시 클라이언트와 서버 간의 3단계 연결 절차
  • 절차:
    1. 클라이언트 → SYN
    2. 서버 → SYN + ACK
    3. 클라이언트 → ACK

꼬리질문: 3-Way Handshake가 필요한 이유는?

  • 답변: 양측의 수신 가능 여부와 초기 순서 번호를 동기화하기 위함

🔷 4. TCP vs UDP

  • TCP: 연결 지향, 신뢰성 보장, 순서 보장, 느림
  • UDP: 비연결 지향, 신뢰성 없음, 빠름, 실시간성 요구 시스템에 적합

꼬리질문: TCP가 신뢰성을 보장하는 방식은?

  • 답변: 순서 번호, 재전송, 수신 확인(ACK), 흐름 제어, 혼잡 제어 등으로 보장

🔷 5. RESTful API

  • 정의: HTTP 메서드(GET, POST, PUT, DELETE 등)를 활용한 자원 중심의 API 설계 방식
  • 원칙: URI는 자원을 표현하고, 행위는 HTTP 메서드로 표현함

꼬리질문: RESTful 설계에서 URI는 어떻게 구성해야 하나요?

  • 답변: 명사 중심으로 자원을 표현하며, 동사는 HTTP 메서드로 표현 (예: /users/1)

🔷 6. HTTP vs HTTPS

  • HTTP: HyperText Transfer Protocol, 암호화되지 않은 웹 통신 프로토콜
  • HTTPS: HTTP + SSL/TLS를 통한 암호화된 보안 통신

꼬리질문: HTTPS 통신은 어떤 방식으로 암호화되나요?

  • 답변: SSL/TLS 프로토콜을 이용해 대칭키를 안전하게 주고받은 후, 본문은 대칭키로 암호화

🔷 7. 비대칭키 암호화

  • 정의: 공개키(Public Key)와 개인키(Private Key)를 사용하는 암호화 방식
  • 특징: 한쪽 키로 암호화한 데이터를 다른 쪽 키로만 복호화 가능

꼬리질문: 비대칭키는 어디에 사용되나요?

  • 답변: SSL 인증서, 디지털 서명, 전자 서명 등에서 주로 사용됨

🔷 8. 대칭키 암호화

  • 정의: 암호화와 복호화에 같은 키를 사용하는 방식
  • 특징: 처리 속도가 빠르지만, 키 전달 시 보안에 취약

꼬리질문: 대칭키의 단점은?

  • 답변: 키가 노출되면 모든 통신이 해독 가능, 키 분배가 어렵다는 점

🔷 9. 단방향 암호화

  • 정의: 복호화가 불가능한 암호화 방식 (해시함수)
  • 사용 예시: 비밀번호 저장 (SHA-256, bcrypt 등)

꼬리질문: 해시 함수의 충돌이란?

  • 답변: 서로 다른 입력값이 동일한 해시값을 갖는 현상, 안전한 해시 알고리즘은 충돌 가능성이 낮음

🔷 10. 제네릭 (Generic)

  • 정의: 클래스나 메서드를 다양한 타입으로 일반화하여 재사용성과 타입 안정성 향상
  • 사용 예시: List<String>, Map<String, Integer> 등

꼬리질문: 제네릭을 사용하는 이유는?

  • 답변: 타입 안정성 확보, 컴파일 타임 오류 방지, 코드 재사용성 증가

 

✅ 면접 기초지식 총정리 (+꼬리질문)


🔷 1. 어노테이션 (Annotation)

  • 정의: 자바 코드에 메타데이터를 추가하는 문법 요소로, 컴파일러나 프레임워크에 의미를 전달함
  • 예시: @Override, @Autowired, @RestController

꼬리질문: 어노테이션은 어떻게 동작하나요?

  • 답변: 리플렉션(Reflection)을 통해 런타임에 처리되며, 프레임워크가 해당 어노테이션을 분석해 동작을 결정함

🔷 2. 인터페이스 vs 추상 클래스

  • 인터페이스: 모든 메서드가 추상적이며, 다중 구현 가능
  • 추상 클래스: 일부 구현 가능, 단일 상속만 가능

꼬리질문: 언제 인터페이스를, 언제 추상 클래스를 쓰나요?

  • 답변: 공통 기능 없이 명세만 필요할 땐 인터페이스, 공통 로직 포함할 땐 추상 클래스 사용

🔷 3. 클래스 vs 객체

  • 클래스: 객체를 생성하기 위한 설계도
  • 객체: 클래스를 기반으로 메모리에 생성된 실체

꼬리질문: 객체를 여러 개 만들면 메서드는 복사되나요?

  • 답변: 아니요. 객체마다 데이터(인스턴스 변수)는 따로지만, 메서드는 공유됩니다

🔷 4. SOLID 원칙

  • S: 단일 책임 원칙
  • O: 개방 폐쇄 원칙
  • L: 리스코프 치환 원칙
  • I: 인터페이스 분리 원칙
  • D: 의존 역전 원칙

꼬리질문: SOLID 원칙 중 가장 중요하다고 생각하는 것은?

  • 답변: 상황에 따라 다르지만, 유지보수 측면에서는 단일 책임 원칙이 핵심이라 생각함

🔷 5. Autowiring

  • 정의: 스프링이 의존성 주입을 자동으로 수행하는 기능
  • 방법: @Autowired, 생성자 주입, 필드 주입, 세터 주입

꼬리질문: Autowiring이 실패하면 어떻게 되나요?

  • 답변: 기본적으로 예외 발생. required = false 옵션으로 방지 가능

🔷 6. 파이썬 코루틴 (Coroutine)

  • 정의: 중단 가능한 함수로, async/await 키워드를 사용해 비동기 처리를 지원
  • 특징: 이벤트 루프 기반으로 동작하며, I/O 효율이 높음

꼬리질문: 코루틴과 스레드의 차이점은?

  • 답변: 코루틴은 싱글 스레드 기반이며 문맥 전환 비용이 적고, 스레드는 병렬 실행 가능하지만 비용이 큼

🔷 7. 파이썬 데코레이터 (Decorator)

  • 정의: 함수의 동작을 변경하거나 확장할 수 있는 함수
  • 예시: @staticmethod, @login_required, @app.route() 등

꼬리질문: 데코레이터는 언제 쓰나요?

  • 답변: 공통 기능(로깅, 인증, 캐싱 등)을 코드 수정 없이 재사용하고자 할 때 사용

🔷 8. GIL (Global Interpreter Lock)

  • 정의: CPython에서 하나의 스레드만 실행되도록 보장하는 전역 락
  • 영향: 멀티스레드 CPU 병렬 처리에 제약이 있음

꼬리질문: GIL이 있는 이유는?

  • 답변: 메모리 안전성과 GC 처리의 간단화를 위해 도입됨

🔷 9. MRO (Method Resolution Order)

  • 정의: 다중 상속 시 메서드 호출 순서를 결정하는 규칙
  • Python 방식: C3 Linearization 알고리즘

꼬리질문: MRO 순서를 확인하는 방법은?

  • 답변: ClassName.__mro__ 또는 ClassName.mro()를 사용하면 확인 가능

객체지향 프로그래밍 (OOP)

더보기
  • 의도 : 이 카테고리는 객체지향 프로그래밍(OOP)의 기본 개념을 이해하고 있는지 평가합니다. OOP는 백엔드 개발에서 매우 중요한 패러다임이므로, 지원자가 클래스, 객체, 상속, 다형성 등 OOP의 기본 원리를 제대로 이해하고, 실제 코딩에 어떻게 적용하는지를 확인하려고 합니다. 또한 디자인 패턴이나 SOLID 원칙을 알고 있으면, 지원자가 유지보수 가능한 코드를 작성할 수 있는 능력을 가진지 판단하는 데 도움이 됩니다.
  • 답변에 포함해야 할 키워드
    • 클래스(Class): 객체를 생성하기 위한 템플릿
    • 객체(Object): 클래스의 인스턴스, 상태와 동작을 가짐
    • 다형성(Polymorphism): 동일한 인터페이스를 구현하는 여러 객체가 다양한 방식으로 동작
    • 상속(Inheritance): 클래스 간 코드 재사용
    • 캡슐화(Encapsulation): 객체의 내부 상태를 숨기고 외부와 상호작용을 제어
    • SOLID 원칙: OOP 설계 원칙 (단일 책임, 개방-폐쇄 원칙 등)

✅ 객체지향 및 설계 원칙 면접 질문 정리 + 실무 연관 질문


🔹 1. [하] Class와 Object에 대해 설명해주세요.

  • 답변: 클래스는 객체를 생성하기 위한 설계도이며, 객체는 클래스의 인스턴스입니다. 클래스는 속성과 행위를 정의하고, 객체는 그 클래스를 기반으로 생성된 구체적인 실체입니다.
  • 예시: class Car {}는 설계도이고, Car myCar = new Car();는 객체입니다.

🔹 2. [중] Polymorphism 개념에 대해 설명하고, 개인/팀 프로젝트에 적용한 사례가 있다면 이야기해주세요.

  • 답변: 다형성은 동일한 인터페이스로 서로 다른 구현을 실행할 수 있게 하는 객체지향의 핵심 개념입니다. 오버로딩(컴파일타임)과 오버라이딩(런타임) 두 가지 방식이 있습니다.
  • 프로젝트 예시: 결제 모듈에서 Payment 인터페이스를 구현한 KakaoPay, CreditCardPay 클래스를 다형적으로 처리했습니다.

🔹 3. [하] Encapsulation(캡슐화)이란 무엇인가요?

  • 답변: 캡슐화는 객체의 데이터와 메서드를 하나로 묶고, 외부에 직접 접근하지 못하도록 제한하는 것입니다. 주로 접근 제어자(private, public 등)를 통해 구현됩니다.
  • 장점: 보안성 증가, 코드 변경 최소화, 유지보수 용이성

🔹 4. [중] 상속(Inheritance)의 개념을 설명하고, 상속의 장단점을 이야기해주세요.

  • 답변: 상속은 부모 클래스의 속성과 기능을 자식 클래스가 물려받는 개념입니다.
  • 장점: 코드 재사용, 유지보수 용이
  • 단점: 결합도 증가, 복잡성 상승, 잘못된 계층 구조로 인한 오용 가능성

🔹 5. [상] SOLID 원칙이란 무엇인지, 각 원칙을 설명해주세요.

  • 답변:
    • S: 단일 책임 원칙(SRP) - 하나의 클래스는 하나의 책임만 가져야 함
    • O: 개방/폐쇄 원칙(OCP) - 확장엔 열려 있고 변경엔 닫혀야 함
    • L: 리스코프 치환 원칙(LSP) - 자식 클래스는 부모 클래스의 역할을 대체할 수 있어야 함
    • I: 인터페이스 분리 원칙(ISP) - 하나의 인터페이스는 하나의 역할만 가져야 함
    • D: 의존 역전 원칙(DIP) - 고수준 모듈은 저수준 모듈에 의존하지 않아야 함. 둘 다 추상화에 의존해야 함

🔹 6. [상] 인터페이스(Interface)와 추상 클래스(Abstract Class)의 차이점은 무엇인가요?

  • 답변:
    • 인터페이스: 다중 구현 가능, 메서드 선언만 포함 (Java 8 이후 default/static 메서드 허용)
    • 추상 클래스: 단일 상속, 일부 메서드 구현 포함 가능
  • 사용 기준: 공통 기능이 없고 명세만 필요할 때는 인터페이스, 공통 로직이 필요할 경우 추상 클래스 사용

🔹 7. [중] 추상화(Abstraction)란 무엇이며, 코드로 어떻게 구현할 수 있는지 설명해주세요.

  • 답변: 추상화는 불필요한 세부정보는 숨기고 핵심 개념만 표현하는 것. 인터페이스나 추상 클래스를 통해 구현 가능
  • 예시:
interface Animal {
  void makeSound();
}
class Dog implements Animal {
  public void makeSound() { System.out.println("Bark"); }
}

🔹 8. [중] 다형성(Polymorphism)을 프로젝트에서 어떻게 활용했는지 예를 들어 설명해주세요.

  • 답변: 쇼핑몰 프로젝트에서 다양한 할인 정책(DiscountPolicy)을 구현하여, calculateDiscount() 메서드를 오버라이딩한 클래스를 동적으로 주입해 다형성 활용했습니다.
  • 장점: 새로운 할인 정책이 추가되어도 기존 코드를 수정하지 않고 확장 가능

🔹 9. [상] 의존성 주입(Dependency Injection)이란 무엇이며, 이를 적용했을 때의 장점을 설명해주세요.

  • 답변: 객체 간의 의존성을 외부에서 주입받는 방식으로, Spring에서는 생성자/필드/세터를 통해 DI를 구현합니다.
  • 장점: 느슨한 결합, 테스트 용이성, 객체 간 책임 명확화
  • 예시: @Autowired, 생성자 주입 등으로 서비스에 리포지토리를 주입함

🔹 10. [상] 디자인 패턴 중 싱글톤(Singleton) 패턴을 설명하고, 실제로 구현할 때 고려해야 할 사항을 이야기해주세요.

  • 답변: 싱글톤 패턴은 클래스의 인스턴스를 하나만 생성하도록 제한하는 패턴입니다.
  • 구현 시 고려사항: 멀티스레드 환경에서는 동기화 처리 필수
  • 예시:
public class Singleton {
  private static final Singleton instance = new Singleton();
  private Singleton() {}
  public static Singleton getInstance() {
    return instance;
  }
}

🔍 참고: 실무 연관 질문

🔸 1. [중] SRP 위반 시 문제점과 해결 경험은?

  • 답변: 하나의 클래스가 여러 책임을 가지면, 하나의 변경이 다른 기능에도 영향을 줘 유지보수가 어려워집니다. 실제로 사용자 관리 클래스에서 인증과 알림 기능이 섞여 있었는데, 이를 UserService, NotificationService로 분리하여 변경 영향도를 줄였습니다.

🔸 2. [상] 프로젝트에 DI 적용 방식과 장점은?

  • 답변: Spring의 생성자 주입을 사용해 서비스에 DAO를 주입했습니다. 이를 통해 테스트 시 Mock 객체로 쉽게 대체 가능했고, 객체 간 결합도를 낮추고 유연한 설계가 가능했습니다.

🔸 3. [중] 인터페이스-구현체 분리 설계 예시?

  • 답변: 로그 저장 기능을 LogRepository 인터페이스로 정의하고, 파일/DB/클라우드 구현체를 분리하여 설정에 따라 유연하게 교체할 수 있도록 설계했습니다.

🔸 4. [중] 상속 대신 구성을 선택한 사례는?

  • 답변: 여러 유틸리티 기능을 공통 부모로 상속하려 했으나, 객체 간 관계가 명확하지 않아 책임 분리가 어려웠습니다. 대신 UtilService를 별도로 두고 필요한 클래스에 주입하여 구성(Composition) 방식으로 전환해 해결했습니다.

🔸 5. [상] 싱글톤의 문제점과 해결 방안은?

  • 답변: 상태를 공유하는 싱글톤은 멀티스레드 환경에서 동시성 문제가 발생할 수 있습니다. 이를 해결하기 위해 ThreadLocal, 불변 객체 사용 또는 Spring에서의 @Component + @Scope("singleton")으로 안전하게 관리했습니다.

 

데이터 구조와 알고리즘

더보기
  • 의도 : 이 카테고리는 데이터를 효과적으로 관리하고 알고리즘을 통해 문제를 해결하는 능력을 평가합니다. 개발자는 다양한 데이터 구조(배열, 리스트, 해시맵 등)를 이해하고, 시간 복잡도와 공간 복잡도를 고려하여 적절한 알고리즘을 선택할 수 있어야 합니다. 이 질문들은 실무에서 효율적인 코드 작성과 성능 최적화를 얼마나 잘할 수 있는지 평가하는데 사용됩니다.
  • 답변에 포함해야 할 키워드
    • 스택(Stack), 큐(Queue): 선입선출/후입선출 원칙
    • 해시맵(HashMap): 키-값 쌍으로 데이터를 저장하는 구조
    • 트리(Tree), 그래프(Graph): 계층적 데이터 구조와 네트워크 데이터 구조
    • 시간 복잡도(Big-O): 알고리즘의 효율성 측정
    • 정렬 알고리즘: 퀵 정렬, 병합 정렬 등의 시간 복잡도 비교

✅ 자료구조 및 알고리즘 면접 질문 정리 (+실제 답변 및 꼬리질문)


🔹 1. [하] Object의 특성에 따라 사용할 수 있는 데이터 구조에는 어떤 것이 있는지 설명해주세요.

  • 답변: 객체는 상태와 행위를 포함하는 단위이므로, 객체들을 효율적으로 저장하거나 처리할 수 있도록 리스트(List), 집합(Set), 딕셔너리(Map), 큐/스택 등의 자료구조를 사용합니다.
  • 꼬리질문: 객체의 특성(예: 식별자, 상태, 행동)에 따라 어떤 자료구조가 적합한지 실제 예시를 들어 설명할 수 있나요?
    • 답변: 사용자 정보(고유 ID 필요)는 해시맵에 저장하고, 순차 처리 작업은 리스트 또는 큐가 적합합니다.

🔹 2. [중] 스택(Stack)과 큐(Queue)의 차이점과 실제로 사용되는 사례를 설명해주세요.

  • 답변: 스택은 후입선출(LIFO), 큐는 선입선출(FIFO) 구조입니다.
  • 사례: 스택은 함수 호출 기록(콜 스택), 큐는 프린터 작업 대기열 등에 사용됩니다.
  • 꼬리질문: DFS/BFS 탐색 시 어떤 구조가 사용되며, 왜 그렇게 사용하는지 설명해보세요.
    • 답변: DFS는 스택 기반으로 깊이 우선 탐색, BFS는 큐 기반으로 최단 경로 탐색에 효과적입니다.

🔹 3. [중] 연결 리스트(Linked List)의 구조와 사용 사례를 설명해주세요.

  • 답변: 각 노드가 데이터와 다음 노드 주소를 가지는 구조로, 삽입/삭제가 빠릅니다.
  • 사례: 운영체제의 메모리 관리, 삽입/삭제가 빈번한 큐/스택 내부 구조에 사용됩니다.
  • 꼬리질문: 연결 리스트 기반 큐와 배열 기반 큐의 메모리 처리 방식 차이를 설명해보세요.
    • 답변: 배열은 고정 크기와 연속 메모리, 연결 리스트는 동적 크기와 불연속 메모리 사용

🔹 4. [상] 해시맵(HashMap)과 트리(Tree)의 차이점은 무엇이며, 각각 언제 사용하면 좋을지 설명해주세요.

  • 답변: 해시맵은 키 기반 검색에 빠르며 평균 O(1), 트리는 정렬된 상태 유지와 범위 검색에 강점이 있습니다.
  • 꼬리질문: 실무에서 트리를 사용해야 하는 구체적인 사례를 말해보세요.
    • 답변: DB의 인덱스(B+Tree), 사용자 권한 계층, 폴더 구조 등 계층적 탐색이 필요한 경우에 사용됩니다.

🔹 5. [상] 트리(Tree)와 그래프(Graph)의 차이점을 설명하고, 각각의 장단점을 이야기해주세요.

  • 답변: 트리는 계층적이며 루트가 있고 순환이 없지만, 그래프는 방향/무방향, 순환 허용 등 관계 표현이 더 자유롭습니다.
  • 꼬리질문: 실제 서비스 예시에서 그래프가 필요한 경우는?
    • 답변: 추천 알고리즘(사용자-아이템 관계), 도로망 탐색, 소셜 네트워크 분석 등

🔹 6. [중] 배열(Array)과 연결 리스트(Linked List)의 차이점과 시간 복잡도를 설명해주세요.

  • 답변:
    • 배열: 인덱스 접근 O(1), 삽입/삭제 O(n)
    • 연결 리스트: 인덱스 접근 O(n), 삽입/삭제 O(1) (노드 위치 알고 있어야 함)
  • 꼬리질문: 실무에서 연결 리스트보다 배열이 선호되는 이유는?
    • 답변: CPU 캐시 최적화, 고정 크기 데이터 처리, 빠른 랜덤 접근이 필요할 때 유리하기 때문입니다.

🔹 7. [중] 빅오(Big-O) 표기법이란 무엇이며, 자주 사용되는 데이터 구조의 시간 복잡도를 설명해주세요.

  • 답변: 알고리즘의 성능을 입력 크기 n에 대한 함수로 표현한 것으로, 최악의 경우 성능을 가늠할 수 있습니다.
  • 예시:
    • 배열 탐색 O(1), 삽입 O(n)
    • 해시맵 탐색 O(1), 최악 O(n)
    • 트리 탐색 O(log n), 최악 O(n)
  • 꼬리질문: 빅오만 보는 것이 위험할 수 있는 이유는?
    • 답변: 실제 성능은 상수 계수, 캐시 적중률, 입력 특성 등 다양한 요소에 영향을 받기 때문입니다.

🔹 8. [상] 이진 탐색(Binary Search) 알고리즘을 설명하고, 시간 복잡도를 이야기해주세요.

  • 답변: 정렬된 배열에서 중간값을 기준으로 탐색 범위를 절반으로 줄이며 찾는 알고리즘입니다.
  • 시간 복잡도: O(log n)
  • 꼬리질문: 이진 탐색이 실패하는 실무 사례는?
    • 답변: 데이터가 정렬되지 않았거나, 연결 리스트처럼 중간 인덱스 접근이 느린 구조에서 비효율적입니다.

🔹 9. [상] 정렬 알고리즘 중 퀵 정렬(Quick Sort)과 병합 정렬(Merge Sort)의 차이점을 설명하고, 각각의 시간 복잡도를 이야기해주세요.

  • 답변:
    • 퀵 정렬: 평균 O(n log n), 최악 O(n²), 제자리 정렬
    • 병합 정렬: 항상 O(n log n), 안정 정렬, 추가 메모리 필요
  • 꼬리질문: 병합 정렬이 퀵 정렬보다 유리한 상황은?
    • 답변: 안정 정렬이 필요하거나 데이터 크기가 매우 크고 디스크 기반 외부 정렬을 할 때

🔹 10. [상] 그래프에서 깊이 우선 탐색(DFS)과 너비 우선 탐색(BFS)의 차이점과 사용 사례를 설명해주세요.

  • 답변:
    • DFS: 스택/재귀 기반, 깊이 우선 순회
    • BFS: 큐 기반, 최단 경로 탐색에 적합
  • 사용 사례:
    • DFS: 퍼즐 탐색, 사이클 감지
    • BFS: 최단 경로, AI 게임 캐릭터 이동 경로
  • 꼬리질문: BFS가 DFS보다 유리한 상황은?
    • 답변: 최단 경로를 찾는 문제나, 레벨별로 데이터를 처리해야 할 때 BFS가 더 적합합니다.

데이터베이스

더보기
  • 의도 : 데이터베이스 카테고리는 데이터베이스 설계 및 관리 능력을 평가합니다. RDBMS와 NoSQL의 차이를 이해하고, 데이터베이스 내에서 데이터를 어떻게 저장하고 조회할지에 대한 기본적인 이해를 확인하려는 의도입니다. 정규화, 인덱스, 트랜잭션 등의 개념을 알고 있는지는 실무에서 중요한 데이터 처리 성능과 무결성을 보장하는 능력으로 이어집니다.
  • 답변에 포함해야 할 키워드
    • RDB vs NoSQL: 관계형 데이터베이스와 비관계형 데이터베이스의 차이
    • 정규화(Normalization): 데이터 중복을 최소화하여 데이터 구조를 최적화하는 과정
    • 인덱스(Index): 데이터를 빠르게 검색하기 위한 구조
    • 트랜잭션(Transaction): 일련의 데이터베이스 작업의 일관성을 보장하는 방법
    • ACID 특성: 데이터베이스 트랜잭션의 신뢰성을 보장하는 특성 (원자성, 일관성, 고립성, 지속성)

✅ 데이터베이스 면접 질문 정리 (+실제 답변 및 꼬리질문)


🔹 1. [중] 개인/팀 프로젝트에 적용해 보았거나 사용할 줄 아는 RDB에 대해 이야기해주세요.

  • 답변: MySQL과 PostgreSQL을 주로 사용했습니다. 사용자 관리, 주문 내역, 상품 데이터 등을 정규화된 테이블로 구성하고, 인덱스를 적절히 설정해 성능을 개선했습니다.
  • 꼬리질문: ERD 설계 시 어떤 기준으로 테이블을 분리했나요?
    • 답변: 실세계 엔티티를 기준으로 정규화 원칙에 따라 중복을 제거하고, 관계 중심으로 모델링했습니다.

🔹 2. [중] RDB와 NoSQL DB의 차이점을 설명해주세요.

  • 답변: RDB는 테이블 기반의 정형 데이터 저장, 관계/트랜잭션 강점. NoSQL은 비정형/반정형 데이터 저장, 수평 확장에 유리합니다.
  • 꼬리질문: NoSQL이 적합한 서비스는?
    • 답변: 빠른 확장성과 다양한 데이터 구조를 처리해야 하는 실시간 채팅, 캐시, 로그 수집 시스템 등

🔹 3. [상] 데이터베이스에서 인덱스를 사용하는 이유와 인덱스가 성능에 미치는 영향을 설명해주세요.

  • 답변: 인덱스는 데이터 검색 속도를 향상시키는 자료구조입니다. 조회 성능이 빨라지지만, 데이터 추가/수정 시 인덱스 유지 비용이 발생합니다.
  • 꼬리질문: SELECT 문에서 인덱스가 무시되는 경우는?
    • 답변: LIKE '%값', 계산된 컬럼, 데이터 소량 등은 인덱스 사용이 비효율적이라 무시될 수 있습니다.

🔹 4. [중] 데이터베이스 정규화(Normalization)와 역정규화(Denormalization)의 차이점에 대해 설명해 주세요.

  • 답변: 정규화는 중복 제거와 무결성 확보를 위한 테이블 분리, 역정규화는 조회 성능을 위해 일부 중복을 허용하는 구조입니다.
  • 꼬리질문: 역정규화를 적용한 경험이 있다면?
    • 답변: 게시판 목록 출력에서 JOIN이 성능 병목이 되어 사용자명 컬럼을 중복 저장한 적 있습니다.

🔹 5. [상] 트랜잭션(Transaction)이 무엇이며, ACID 특성을 설명해 주세요.

  • 답변: 트랜잭션은 하나의 논리적 작업 단위로, 반드시 전부 성공하거나 실패해야 합니다.
    • A: 원자성(Atomicity)
    • C: 일관성(Consistency)
    • I: 고립성(Isolation)
    • D: 지속성(Durability)
  • 꼬리질문: 고립성 수준은 어떻게 조정하나요?
    • 답변: DBMS에서 READ COMMITTED, REPEATABLE READ, SERIALIZABLE 등으로 설정 가능합니다.

🔹 6. [상] 데이터베이스에서 JOIN의 개념과 사용 사례를 설명해주세요.

  • 답변: JOIN은 두 개 이상의 테이블을 공통 키로 연결해 하나의 결과로 만드는 연산입니다.
  • 사례: 사용자와 주문 테이블을 JOIN하여 특정 사용자의 구매 내역을 조회
  • 꼬리질문: INNER JOIN과 OUTER JOIN의 차이는?
    • 답변: INNER는 교집합, OUTER는 한쪽에만 존재하는 데이터도 포함

🔹 7. [중] 외래 키(Foreign Key)와 참조 무결성(Referential Integrity)에 대해 설명해주세요.

  • 답변: 외래 키는 다른 테이블의 기본 키를 참조하는 컬럼이며, 참조 무결성은 참조 대상이 실제로 존재해야 하는 제약입니다.
  • 꼬리질문: ON DELETE CASCADE는 언제 쓰나요?
    • 답변: 부모 데이터 삭제 시 자식도 함께 삭제되어야 하는 구조(예: 게시글과 댓글)에서 사용합니다.

🔹 8. [상] 데이터베이스에서 발생할 수 있는 데드락(Deadlock)을 방지하는 방법을 설명해주세요.

  • 답변: 데드락은 서로 자원을 점유한 채 대기하며 발생합니다. 자원 획득 순서 고정, 타임아웃, 트랜잭션 최소화로 방지할 수 있습니다.
  • 꼬리질문: 트랜잭션 내 여러 UPDATE를 처리할 때 데드락을 피하는 전략은?
    • 답변: 항상 정해진 순서로 테이블을 갱신하거나, 범위를 명확히 지정하여 락 충돌을 줄입니다.

🔹 9. [중] 데이터베이스 샤딩(Sharding)이란 무엇인가요?

  • 답변: 큰 테이블을 여러 서버나 DB에 나누어 저장하는 방식으로, 수평 확장을 통해 성능과 가용성을 높입니다.
  • 꼬리질문: 샤딩 시 데이터 일관성을 어떻게 보장하나요?
    • 답변: 글로벌 트랜잭션보다는 eventual consistency 전략이나 중앙 샤드 ID 매니저 사용으로 조율합니다.

🔹 10. [상] 데이터베이스에서 파티셔닝(Partitioning)을 적용하는 이유를 설명하고, 수평/수직 파티셔닝의 차이점을 설명해주세요.

  • 답변: 파티셔닝은 하나의 테이블을 논리적으로 분할해 성능과 관리성을 높이는 방법입니다.
    • 수평 파티셔닝: 행 기준 분할 (예: 월별 데이터)
    • 수직 파티셔닝: 컬럼 기준 분할 (자주 쓰는 컬럼만 분리)
  • 꼬리질문: 파티셔닝을 통해 어떤 성능 개선을 기대할 수 있나요?
    • 답변: 파티션 프루닝을 통해 전체 스캔 없이 필요한 파티션만 조회하므로 쿼리 속도가 크게 향상됩니다.

백엔드 프레임워크

더보기
  • 의도 : 백엔드 프레임워크 카테고리는 Spring과 같은 백엔드 프레임워크에 대한 이해도를 평가하는 질문입니다. 의존성 주입(Dependency Injection), AOP, 트랜잭션 관리와 같은 개념들은 백엔드에서 코드를 모듈화하고 유지보수를 쉽게 할 수 있도록 도와줍니다. 또한 Spring Boot와 같은 최신 프레임워크의 특징을 이해하고, 실무에서 자동 설정(Auto Configuration)과 JPA를 어떻게 활용하는지 묻습니다.
  • 답변에 포함해야 할 키워드
    • Spring Boot: Spring의 경량화된 프레임워크로, 빠른 개발 환경 제공
    • 의존성 주입(Dependency Injection): 객체 간 결합도를 낮추는 설계 원칙
    • AOP(Aspect-Oriented Programming): 공통 기능을 모듈화하여 코드 중복을 줄이는 방식
    • JPA vs Hibernate: Java Persistence API와 Hibernate 프레임워크의 차이
    • Bean의 라이프사이클: 객체의 생성, 초기화, 소멸 과정

✅ Spring & Kotlin/Java 면접 질문 정리 (+실제 답변 및 꼬리질문)


🔹 1. [상] Java(Kotlin)으로 구성된 프로젝트의 Kotlin(Java) 컨버팅 작업이 가능한지, 무엇을 염두에 두어야 하는지 이야기해주세요.

  • 답변: 가능합니다. Kotlin은 Java와 100% 상호 운용되며, IntelliJ의 자동 변환 도구도 활용할 수 있습니다. 그러나 null 처리, 람다 표현식, 클래스 구조 등의 관점에서 수동 점검이 필요합니다.
  • 꼬리질문: Kotlin 변환 후 주요 이슈는 무엇이었나요?
    • 답변: null 안정성 문제, data class 사용 시 equals/hashCode 재정의 로직, lateinit 초기화 누락 등이 있었습니다.

🔹 2. [중] Legacy Spring과 최근 Spring 또는 Spring Boot의 차이점을 설명해주세요.

  • 답변: Legacy Spring은 XML 설정 기반이고 수동 빈 등록이 많았습니다. Spring Boot는 자동 설정, 내장 서버, Starter 패키지 제공 등으로 설정 부담이 적고 생산성이 높습니다.
  • 꼬리질문: Spring Boot의 application.properties가 중요한 이유는?
    • 답변: 설정값을 외부화하여 환경별로 유연하게 애플리케이션 설정을 변경할 수 있게 해줍니다.

🔹 3. [중] Spring의 의존성 주입(Dependency Injection)이란 무엇이며, 이를 사용하는 이유를 설명해 주세요.

  • 답변: 객체 간 의존 관계를 직접 생성하지 않고, 스프링 컨테이너가 주입해주는 방식입니다. 결합도를 낮추고 테스트 용이성, 유지보수성이 향상됩니다.
  • 꼬리질문: 생성자 주입이 필드 주입보다 나은 이유는?
    • 답변: 불변성 보장, 테스트 시 명시적 주입 가능, 순환 참조 방지 효과 때문입니다.

🔹 4. [상] AOP(Aspect Oriented Programming)가 무엇이며, Spring에서 AOP를 어떻게 구현할 수 있는지 설명해 주세요.

  • 답변: AOP는 공통 관심사를 핵심 로직과 분리하여 모듈화하는 방식입니다. Spring에서는 @Aspect, @Around, @Before, @AfterReturning 등을 통해 구현합니다.
  • 꼬리질문: 실무에서 어떤 공통 기능을 AOP로 분리했나요?
    • 답변: 로깅, 트랜잭션 관리, 사용자 권한 체크, API 요청 타이머 등을 AOP로 구현했습니다.

🔹 5. [상] Spring Boot에서 JPA와 Hibernate의 차이점을 설명해 주세요.

  • 답변: JPA는 자바 ORM 기술에 대한 인터페이스 표준이고, Hibernate는 JPA를 구현한 대표적인 구현체입니다.
  • 꼬리질문: Spring Boot에서 Hibernate 설정을 직접 건드려본 경험이 있다면?
    • 답변: hibernate.ddl-auto, fetch 전략, naming strategy 등을 커스터마이징한 경험이 있습니다.

🔹 6. [중] Spring에서 @Transactional 애너테이션의 역할을 설명해 주세요.

  • 답변: @Transactional은 메서드 실행 시 트랜잭션을 시작하고, 예외 발생 시 롤백, 정상 종료 시 커밋을 자동으로 처리합니다.
  • 꼬리질문: checked exception 발생 시 롤백되지 않는 이유는?
    • 답변: 기본적으로 unchecked(RuntimeException)만 롤백 대상이며, checked 예외는 명시적으로 설정해야 합니다.

🔹 7. [상] Spring Security의 기본 개념을 설명해 주세요.

  • 답변: 인증(Authentication)과 권한(Authorization)을 제공하는 보안 프레임워크입니다. 필터 기반 구조로 동작하며, 사용자 로그인, 권한 검사, 세션/토큰 처리 등을 제공합니다.
  • 꼬리질문: JWT 기반 인증을 구현한 경험이 있다면?
    • 답변: 필터 커스터마이징하여 JWT를 추출하고, 토큰 유효성 검증 후 SecurityContext에 유저 정보를 저장했습니다.

🔹 8. [상] Spring Boot의 자동 설정(Auto Configuration) 기능이 무엇이며, 이를 어떻게 활용할 수 있는지 설명해주세요.

  • 답변: 자동 설정은 클래스패스의 라이브러리, 애플리케이션 설정을 기준으로 관련 빈을 자동으로 등록하는 기능입니다. @EnableAutoConfiguration, spring.factories 메커니즘을 기반으로 작동합니다.
  • 꼬리질문: 자동 설정이 잘못 동작할 때 디버깅하는 방법은?
    • 답변: @ConditionalOn... 조건을 확인하거나 debug=true 설정을 통해 로딩 여부를 로그로 확인합니다.

🔹 9. [중] Spring에서 Bean의 라이프사이클을 설명하고, 이를 관리하는 방법을 이야기해주세요.

  • 답변: Bean 생성 → 의존성 주입 → 초기화 → 사용 → 소멸 순으로 관리됩니다. @PostConstruct, @PreDestroy, InitializingBean, DisposableBean 등을 통해 커스터마이징 가능합니다.
  • 꼬리질문: Bean 생명주기를 컨트롤해야 했던 사례가 있다면?
    • 답변: 외부 리소스를 연결하거나 캐시 초기화를 위한 초기화 작업에 사용했습니다.

🔹 10. [상] Spring에서 REST 컨트롤러와 일반 컨트롤러의 차이점에 대해 설명해 주세요.

  • 답변: @RestController는 @Controller + @ResponseBody로 JSON을 기본 응답으로 반환하고, @Controller는 주로 View 템플릿을 반환합니다.
  • 꼬리질문: REST 컨트롤러에서 예외 처리 방식은?
    • 답변: @ControllerAdvice, @ExceptionHandler를 활용하여 공통 예외 응답 구조를 구성했습니다.

API 설계 및 통신

더보기
  • 의도 : API 설계와 통신 카테고리는 RESTful API, GraphQL 등의 통신 방식에 대한 이해를 평가합니다. API 버전 관리는 서비스의 유지보수성, 확장성을 높이는 중요한 요소이며, OAuth 2.0과 같은 인증 방식은 보안에 대한 기본적인 이해를 평가하는 질문입니다. API의 상태 코드, 멱등성(Idempotency) 등의 개념도 실무에서 자주 다뤄지는 주제입니다.
  • 답변에 포함해야 할 키워드
    • RESTful API: HTTP 메서드(GET, POST, PUT, DELETE)의 활용
    • GraphQL: 클라이언트가 원하는 데이터만 요청할 수 있는 API 방식
    • OAuth 2.0: 사용자 인증과 권한 부여를 위한 프로토콜
    • 멱등성(Idempotency): 동일한 요청을 여러 번 보내도 결과가 동일한지 여부
    • HTTP 상태 코드: 200(성공), 404(페이지 없음), 500(서버 오류) 등의 의미

✅ REST API 및 웹 통신 면접 질문 정리 (+실제 답변 및 꼬리질문)


🔹 1. [하] RESTful API의 설계 원칙을 설명해주세요.

  • 답변: RESTful API는 자원을 URI로 표현하고, HTTP 메서드(GET, POST, PUT, DELETE 등)를 활용하여 상태를 조작하는 방식입니다. 무상태성, 일관된 URI, 계층 구조, 캐시 처리 등을 지켜야 합니다.
  • 꼬리질문: REST API 설계 시 URI에 동사를 쓰지 않는 이유는?
    • 답변: 행위는 HTTP 메서드로 표현하고 URI는 자원만 표현해야 자원의 의미가 명확해지기 때문입니다.

🔹 2. [중] REST와 SOAP의 차이점을 설명해 주세요.

  • 답변: REST는 경량의 HTTP 기반 방식이며 JSON/XML 등 다양한 포맷을 지원합니다. SOAP은 XML 기반의 무거운 메시지 구조와 엄격한 스펙을 따릅니다.
  • 꼬리질문: 보안 측면에서 SOAP이 유리한 이유는?
    • 답변: WS-Security, 메시지 수준 암호화 등 더 정교한 보안 규격을 내장하고 있기 때문입니다.

🔹 3. [중] API 버전 관리의 중요성과 방법을 설명해 주세요.

  • 답변: 기존 클라이언트와의 호환을 유지하면서 기능 확장을 위해 버전 관리가 필요합니다. URI에 버전을 포함하는 방식(/v1/…), Header 또는 Query Parameter 방식이 있습니다.
  • 꼬리질문: 실무에서 어떤 방식으로 버전을 관리했나요?
    • 답변: URI 방식으로 관리하여 명시적이고 직관적인 접근이 가능하게 했습니다.

🔹 4. [상] GraphQL과 REST API의 차이점을 설명하고, 실무에서 어떤 상황에 적합한지 이야기해주세요.

  • 답변: REST는 고정된 endpoint 기반이고, GraphQL은 단일 endpoint에서 필요한 데이터만 쿼리할 수 있습니다. 복잡한 관계형 데이터를 효율적으로 조회할 때 GraphQL이 유리합니다.
  • 꼬리질문: GraphQL 도입 시 주의할 점은?
    • 답변: 복잡한 쿼리로 인해 성능 문제가 발생할 수 있으므로, 쿼리 깊이 제한이나 Batching 기술을 함께 고려해야 합니다.

🔹 5. [중] OAuth 2.0이 무엇이며, 이를 사용한 인증 방식에 대해 설명해주세요.

  • 답변: OAuth 2.0은 타 서비스에 사용자 자원 접근 권한을 위임하는 프로토콜입니다. Authorization Code, Implicit, Resource Owner Password, Client Credentials 방식이 있습니다.
  • 꼬리질문: Authorization Code Flow를 사용하는 이유는?
    • 답변: 클라이언트와 자원 서버 간 보안을 강화하고, 토큰을 안전하게 주고받기 위한 중간 인증 코드 단계를 거치기 때문입니다.

🔹 6. [중] HTTP 상태 코드 중 200, 404, 500의 차이와 각각의 의미를 설명해주세요.

  • 답변: 200은 성공, 404는 요청 자원이 존재하지 않음, 500은 서버 내부 오류를 의미합니다.
  • 꼬리질문: 클라이언트 요청이 잘못된 경우 어떤 상태 코드를 사용하나요?
    • 답변: 400 Bad Request가 적절하며, 입력값 오류 또는 형식 오류 시 주로 사용됩니다.

🔹 7. [상] 멱등성(Idempotency)이란 무엇이며, API 설계 시 이를 어떻게 고려할 수 있는지 설명해주세요.

  • 답변: 동일한 요청을 여러 번 보내도 결과가 같아야 하는 성질입니다. GET, PUT, DELETE는 기본적으로 멱등해야 하며, POST는 비멱등이지만 비즈니스에 따라 조정될 수 있습니다.
  • 꼬리질문: PUT과 PATCH의 차이는?
    • 답변: PUT은 전체 자원을 대체, PATCH는 일부만 수정합니다. 둘 다 멱등성을 유지해야 합니다.

🔹 8. [중] API 문서를 자동으로 생성하는 방법(Spring REST Docs 등)에 대해 설명해주세요.

  • 답변: Spring REST Docs는 테스트 기반으로 API 문서를 생성하고, Swagger는 코드 기반으로 문서를 생성합니다. Spring REST Docs는 테스트 신뢰성이 높고, Swagger는 실시간 인터페이스 제공이 강점입니다.
  • 꼬리질문: 둘 중 어떤 도구를 실무에서 사용했고, 이유는?
    • 답변: REST Docs를 사용했으며, 테스트 기반으로 실제 스펙과 일치하는 문서를 유지할 수 있었기 때문입니다.

🔹 9. [상] HATEOAS(Hypermedia as the Engine of Application State)란 무엇이며, RESTful API에 어떻게 적용할 수 있는지 설명해 주세요.

  • 답변: HATEOAS는 응답에 다음 수행 가능한 링크를 포함시켜 클라이언트가 상태 전이를 안내받을 수 있게 합니다. REST의 자가 발견(self-descriptive) 성격을 강화합니다.
  • 꼬리질문: HATEOAS를 도입한 API는 어떤 장점이 있나요?
    • 답변: 클라이언트가 서버의 URI 구조를 몰라도 링크만으로 흐름을 따라갈 수 있어 유연성과 유지보수성이 향상됩니다.

🔹 10. [상] HTTP/2와 HTTP/1.1의 차이점을 설명해 주세요.

  • 답변: HTTP/2는 멀티플렉싱, 헤더 압축, 서버 푸시 등의 기능을 통해 성능을 대폭 개선했습니다. 반면 HTTP/1.1은 요청/응답 순차 처리로 인해 지연이 많습니다.
  • 꼬리질문: HTTP/2의 멀티플렉싱이란?
    • 답변: 하나의 TCP 연결로 여러 요청/응답을 병렬로 처리해 HOL 블로킹 문제를 해결합니다.

성능 최적화 및 캐싱

더보기
  • 의도 : 성능 최적화 카테고리는 데이터베이스 및 서버 성능을 최적화하는 능력을 평가합니다. 특히 캐싱, 쿼리 최적화, CDN 등은 실무에서 서버 부하를 줄이고 사용자 경험을 향상시키기 위해 필수적으로 알아야 하는 기술입니다. 면접관은 지원자가 성능 문제를 식별하고, 이를 해결할 수 있는 방법을 얼마나 잘 알고 있는지를 확인하고 싶어합니다.
  • 답변에 포함해야 할 키워드
    • 캐시(Cache): 자주 사용되는 데이터를 메모리에 저장하여 성능 향상
    • Redis: 자주 사용되는 캐시 저장소
    • 쿼리 최적화: 복잡한 데이터 조회 시 인덱스 사용, JOIN 최적화
    • CDN(Content Delivery Network): 콘텐츠 전송 속도를 높이기 위한 네트워크
    • 성능 모니터링: 애플리케이션 성능을 지속적으로 추적하고 문제를 해결

✅ 백엔드 성능 최적화 면접 질문 정리 (+실제 답변 및 꼬리질문)


🔹 1. [중] 백엔드 성능 최적화 방법을 설명해 주세요.

  • 답변: 불필요한 I/O 최소화, 캐싱 전략 활용, DB 쿼리 최적화, 비동기 처리, 병렬 처리, GC 튜닝 등을 통해 전체 응답 속도를 개선할 수 있습니다.
  • 꼬리질문: 실제로 어떤 병목을 발견하고 어떻게 개선했나요?
    • 답변: 반복 조회 쿼리를 캐싱 처리하거나, 블로킹 I/O를 비동기로 바꿔 응답 시간을 줄였습니다.

🔹 2. [상] 데이터베이스 쿼리 최적화를 위한 방법을 설명해 주세요.

  • 답변: 인덱스 사용, N+1 문제 방지(Fetch Join), 적절한 정규화/역정규화, LIMIT, WHERE 절 조건 정리, 실행 계획(EXPLAIN) 분석 등을 활용합니다.
  • 꼬리질문: 실행 계획(Explain)을 실제로 활용한 경험이 있다면?
    • 답변: FULL SCAN이 발생한 쿼리에 인덱스를 추가하여 RANGE SCAN으로 개선한 경험이 있습니다.

🔹 3. [중] Redis의 주요 사용 사례를 설명해 주세요.

  • 답변: 세션 저장소, 캐시, 실시간 순위표, Pub/Sub 메시징, 분산 락 등에 사용됩니다.
  • 꼬리질문: Redis에서 캐시로 사용할 때 주의할 점은?
    • 답변: 적절한 만료 설정, 캐시 무효화 전략, Redis 장애 시 fallback 로직을 고려해야 합니다.

🔹 4. [중] 캐시(Cache) 메커니즘을 설명하고, 캐시를 사용하는 이유를 이야기해주세요.

  • 답변: 캐시는 자주 접근하는 데이터를 미리 저장해두고 빠르게 읽기 위한 메모리 기반 저장소입니다. 처리 속도 향상과 데이터베이스 부하 감소가 주요 이유입니다.
  • 꼬리질문: 어떤 데이터를 캐시하면 안 되나요?
    • 답변: 실시간으로 변하는 중요 정보나 보안성이 민감한 정보는 캐시에 적합하지 않습니다.

🔹 5. [상] CDN(Content Delivery Network)이 무엇이며, 성능 최적화에 어떤 기여를 하는지 설명해 주세요.

  • 답변: CDN은 전 세계에 분산된 캐시 서버를 통해 사용자와 가까운 위치에서 정적 리소스를 제공하는 네트워크입니다. 지연 시간 감소와 트래픽 분산에 효과적입니다.
  • 꼬리질문: CDN 적용이 실패하는 상황은?
    • 답변: 동적 콘텐츠나 사용자별 커스터마이징된 데이터는 CDN으로 캐싱하기 어렵습니다.

🔹 6. [중] 캐시 무효화(Cache Invalidation) 전략에 대해 설명해주세요.

  • 답변: TTL(Time to Live), Write-through, Write-behind, Cache Aside 전략 등이 있습니다.
  • 꼬리질문: Cache Aside 전략은 어떤 상황에서 유용한가요?
    • 답변: 캐시가 자주 변경되지 않지만, 일관성을 유지해야 하는 경우에 적합합니다.

🔹 7. [상] Redis에서 데이터가 영구적으로 저장되지 않는 이유와 이를 방지하기 위한 방법을 설명해 주세요.

  • 답변: Redis는 메모리 기반이므로 장애 시 데이터가 손실될 수 있습니다. RDB 스냅샷 저장, AOF(Append Only File) 설정으로 영속성을 확보할 수 있습니다.
  • 꼬리질문: AOF와 RDB의 차이점은?
    • 답변: AOF는 변경 사항을 로그에 기록해 복구가 정확하고 RDB는 일정 주기로 전체 데이터를 저장해 빠르지만 손실 위험이 있습니다.

🔹 8. [상] JVM 튜닝을 통한 성능 최적화 방법을 설명해주세요.

  • 답변: Heap 크기 조정(-Xms, -Xmx), GC 정책 선택(G1GC, CMS 등), 스레드 수 조절, JIT 설정 등을 통해 성능을 최적화할 수 있습니다.
  • 꼬리질문: GC 튜닝을 했던 구체적인 사례가 있다면?
    • 답변: Full GC가 빈번했던 서비스를 G1GC로 교체하고, Old 영역 크기 확장으로 GC 시간 감소를 이끌었습니다.

🔹 9. [상] 스레드 풀(Thread Pool)과 비동기 작업을 사용한 성능 최적화 방법을 설명해주세요.

  • 답변: 스레드 풀은 제한된 수의 스레드를 재사용하여 리소스 낭비를 막고, 비동기 작업은 I/O 대기 시간을 줄여 응답 속도를 개선합니다.
  • 꼬리질문: 스레드 풀 크기는 어떻게 정하나요?
    • 답변: CPU 바운드 작업은 코어 수 기반, I/O 바운드는 대기 비율 고려해 더 크게 설정합니다.

🔹 10. [상] 서버의 CPU, 메모리 사용률을 모니터링하고 최적화하는 방법을 설명해 주세요.

  • 답변: top, htop, jstat, VisualVM, Prometheus + Grafana 등을 활용해 모니터링하고, 과도한 GC, 메모리 누수, 쓰레드 폭주 등을 분석하여 리소스를 조정합니다.
  • 꼬리질문: 실무에서 메모리 누수를 발견했던 사례는?
    • 답변: 캐시된 객체를 해제하지 않아 Old 영역이 지속 증가했고, WeakReference로 교체하거나 TTL을 설정해 해결했습니다.
    •  

보안 및 인증

더보기
  • 의도 : 보안 및 인증 카테고리는 웹 애플리케이션의 보안을 유지하는 방법을 평가합니다. 특히 CSRF, XSS, SQL Injection과 같은 웹 보안 문제를 해결하는 능력은 매우 중요합니다. 또한 OAuth, JWT와 같은 인증 방법을 통해 사용자 인증의 보안을 어떻게 강화할 수 있는지를 이해하고 있는지 확인합니다.
  • 답변에 포함해야 할 키워드
    • JWT(Json Web Token): 사용자 인증에 사용되는 토큰 기반 인증 방식
    • 쿠키 vs 세션: 각각의 차이점과 데이터 저장 방식
    • XSS(Cross-Site Scripting): 클라이언트 측에서 발생하는 스크립트 공격 방지 방법
    • CSRF(Cross-Site Request Forgery): 사용자의 요청을 악용하는 공격 방지 방법
    • SSL/TLS: HTTPS를 통해 데이터 전송 시 암호화를 보장

✅ 서버 보안 및 인증 면접 질문 정리 (+실제 답변 및 꼬리질문)


🔹 1. [중] 서버 보안의 기본 원칙에 대해 설명해 주세요.

  • 답변: 최소 권한 원칙, 보안 패치 적용, 방화벽 설정, 접근 제어, 민감정보 암호화, 로그 모니터링 등입니다.
  • 꼬리질문: 실무에서 가장 먼저 점검해야 할 보안 요소는 무엇인가요?
    • 답변: 외부 노출된 포트와 관리 계정 접근 제어, SSL 인증서 적용 등을 우선 점검합니다.

🔹 2. [하] 쿠키와 세션의 차이점이 무엇인지 설명해 주세요.

  • 답변: 쿠키는 클라이언트에 저장되고, 세션은 서버에 저장됩니다. 쿠키는 사용자 설정 저장에 적합하고, 세션은 인증 상태 유지에 적합합니다.
  • 꼬리질문: 세션이 만료되었을 때 사용자는 어떤 경험을 하게 되나요?
    • 답변: 로그인 정보가 사라지고 다시 로그인 화면으로 리다이렉트됩니다.

🔹 3. [중] CSRF(Cross-Site Request Forgery) 공격이 무엇이며, 이를 방지하는 방법을 설명해주세요.

  • 답변: 사용자가 인증된 상태에서 악의적인 요청을 유도하는 공격입니다. CSRF 토큰, SameSite 쿠키 설정, Referer 검증 등으로 방지합니다.
  • 꼬리질문: CSRF 토큰은 어떻게 동작하나요?
    • 답변: 서버가 발급한 고유 토큰을 폼에 포함시키고, 요청 시 동일한 값을 검증함으로써 위조 요청을 차단합니다.

🔹 4. [상] HTTPS와 SSL 인증서의 역할에 대해 설명해 주세요.

  • 답변: HTTPS는 HTTP 위에 SSL/TLS를 추가한 프로토콜로, 데이터 암호화와 무결성을 보장합니다. SSL 인증서는 서버의 신원을 확인하고, 암호화 통신을 위한 공개키 교환에 사용됩니다.
  • 꼬리질문: SSL 인증서의 루트 체인은 무엇이고 왜 중요한가요?
    • 답변: 클라이언트는 루트 인증기관(CA)까지 신뢰 체인을 따라가며 서버 인증서의 유효성을 검증합니다.

🔹 5. [상] JWT(Json Web Token)의 개념과 이를 사용한 인증 방식을 설명해 주세요.

  • 답변: JWT는 Header, Payload, Signature 세 부분으로 구성된 토큰입니다. 사용자 인증 후 클라이언트에 토큰을 발급하고, 서버는 이를 검증해 인증을 수행합니다.
  • 꼬리질문: JWT에 민감 정보를 담으면 안 되는 이유는?
    • 답변: Payload는 Base64 인코딩이라 누구나 열람 가능하므로, 암호화 없이 민감 정보를 포함하면 보안에 취약합니다.

🔹 6. [중] XSS(Cross-Site Scripting) 공격이 무엇이며, 이를 방지하는 방법을 설명해 주세요.

  • 답변: 악성 스크립트를 삽입하여 클라이언트에서 실행되게 하는 공격입니다. 입력값 검증, 출력 시 이스케이프 처리, CSP 설정으로 방지할 수 있습니다.
  • 꼬리질문: React나 Vue는 XSS에 강한가요?
    • 답변: 기본적으로 바인딩 시 HTML을 escape 처리하므로 안전하지만, v-html, dangerouslySetInnerHTML 사용 시 취약해질 수 있습니다.

🔹 7. [상] 서버에서 비밀번호를 안전하게 저장하기 위한 방법(예: 해시 함수, 솔팅 등)을 설명해 주세요.

  • 답변: 비밀번호는 단방향 해시(SHA-256, bcrypt 등)로 암호화하고, 동일한 값 방지를 위해 salt를 추가합니다. bcrypt는 자체적으로 salt를 포함합니다.
  • 꼬리질문: SHA256보다 bcrypt를 권장하는 이유는?
    • 답변: bcrypt는 연산 비용이 높아 무차별 대입 공격에 강하고, 내부적으로 salt를 포함하여 보안성이 높습니다.

🔹 8. [상] SQL 인젝션(SQL Injection)이 무엇이며, 이를 방지하기 위한 방법을 설명해 주세요.

  • 답변: 사용자의 입력값에 악의적인 SQL을 삽입해 DB를 조작하는 공격입니다. PreparedStatement 사용, 입력값 검증, ORM 활용 등으로 방지할 수 있습니다.
  • 꼬리질문: ORM을 사용해도 SQL 인젝션이 발생할 수 있나요?
    • 답변: 네, Raw SQL 또는 JPQL 동적 문자열 조합 시 여전히 위험할 수 있습니다. 바인딩을 지켜야 합니다.

🔹 9. [상] OAuth 2.0과 OpenID Connect의 차이점을 설명해 주세요.

  • 답변: OAuth 2.0은 권한 위임을 위한 프로토콜이고, OpenID Connect는 OAuth 2.0 위에 사용자 인증을 추가한 확장입니다. ID Token을 통해 사용자 정보 확인이 가능합니다.
  • 꼬리질문: OpenID Connect의 ID Token과 Access Token의 차이는?
    • 답변: ID Token은 사용자 정보 인증용, Access Token은 API 접근 권한 부여용입니다.

🔹 10. [중] CORS(Cross-Origin Resource Sharing)가 무엇이며, 이를 해결하는 방법을 설명해 주세요.

  • 답변: CORS는 브라우저에서 도메인이 다른 서버로 요청 시 보안 정책상 차단되는 현상을 말합니다. 서버에서 Access-Control-Allow-Origin 등을 설정해 허용할 수 있습니다.
  • 꼬리질문: Credential 포함 요청에서 CORS 처리는 어떻게 다르나요?
    • 답변: Access-Control-Allow-Credentials: true와 함께, Allow-Origin은 *가 아닌 특정 도메인으로 지정해야 합니다.
    •  

배포 및 운영

더보기
  • 의도 : 배포 및 운영 카테고리는 애플리케이션을 실제 환경에 배포하고 운영하는 능력을 평가합니다. CI/CD 파이프라인을 구축하거나, 무중단 배포를 할 수 있는 방법을 알고 있는지 평가합니다. 또한 컨테이너 도구(Docker, Kubernetes)와 같은 도구를 사용해 서버 환경을 효율적으로 관리할 수 있는 능력도 중요합니다.
  • 답변에 포함해야 할 키워드
    • 무중단 배포: 서비스가 중단되지 않도록 서버를 업데이트하는 방법
    • CI/CD: 지속적인 통합과 배포를 위한 자동화 파이프라인 구축
    • 도커(Docker): 애플리케이션을 컨테이너로 패키징하는 도구
    • Kubernetes: 컨테이너 오케스트레이션 도구로, 애플리케이션 확장 및 관리
    • 로깅 및 모니터링: 서버의 상태를 추적하고 문제 발생 시 대응

✅ 인프라 및 배포 면접 질문 정리 (+실제 답변 및 꼬리질문)


🔹 1. [중] 서버를 무중단 배포(Zero Downtime Deployment)하는 방법에 대해 설명해 주세요.

  • 답변: 무중단 배포는 기존 인스턴스를 중단하지 않고 새 인스턴스를 점진적으로 배포하는 방식입니다. 로드 밸런서를 활용한 Blue-Green 배포, 무중단 롤링 업데이트, Kubernetes의 RollingUpdate 전략 등을 사용합니다.
  • 꼬리질문: 무중단 배포 시 세션 상태 유지를 어떻게 하나요?
    • 답변: 세션 클러스터링, 외부 세션 저장소(Redis 등)를 통해 상태를 공유합니다.

🔹 2. [중] CI/CD(Continuous Integration/Continuous Deployment) 파이프라인을 구축한 경험이 있나요? 사용한 도구를 설명해 주세요.

  • 답변: GitHub Actions와 Jenkins를 사용하여 테스트, 빌드, 배포까지 자동화했습니다. Docker 이미지 빌드 후 AWS ECS에 배포하는 플로우를 구성한 경험이 있습니다.
  • 꼬리질문: CI/CD 도입 전후의 가장 큰 차이는?
    • 답변: 배포 속도와 신뢰도가 향상되었고, 코드 병합 후 자동 테스트로 오류를 조기 발견할 수 있었습니다.

🔹 3. [상] 도커(Docker) 컨테이너와 가상 머신(VM)의 차이점을 설명해주세요.

  • 답변: Docker는 호스트 OS의 커널을 공유하는 경량 컨테이너이며, VM은 독립된 OS를 포함한 무거운 가상화 기술입니다. Docker는 실행 속도와 리소스 효율이 높습니다.
  • 꼬리질문: 컨테이너 격리 수준은 VM과 비교해 얼마나 안전한가요?
    • 답변: OS 커널을 공유하므로 VM보다 격리 수준은 낮지만, 네임스페이스, cgroup 등을 통해 충분한 보안 분리가 가능합니다.

🔹 4. [상] 마이크로서비스 아키텍처(MSA)란 무엇이며, 이를 사용해야 하는 이유를 설명해 주세요.

  • 답변: MSA는 애플리케이션을 독립적인 서비스 단위로 나누어 개발, 배포, 확장을 유연하게 하는 아키텍처입니다. 팀 간 독립성 확보, 서비스 확장성, 장애 격리에 유리합니다.
  • 꼬리질문: MSA 전환 시 주의할 점은?
    • 답변: 서비스 간 통신 안정성, 트랜잭션 분산 처리, 공통 로깅/모니터링 구조 설계가 중요합니다.

🔹 5. [중] 모니터링 도구(예: Prometheus, Grafana)를 사용해 서버 성능을 추적한 경험을 설명해 주세요.

  • 답변: Prometheus로 애플리케이션 지표를 수집하고, Grafana 대시보드로 시각화했습니다. CPU, 메모리, 응답 시간, 에러율 등을 실시간으로 모니터링했습니다.
  • 꼬리질문: 알람 임계값 설정 기준은 어떻게 정했나요?
    • 답변: 평균 부하 기준 + 표준편차 또는 SLA 기준 임계값을 설정했습니다.

🔹 6. [중] Blue-Green 배포와 Canary 배포의 차이점과 사용 사례를 설명해주세요.

  • 답변: Blue-Green은 전체 트래픽을 전환하는 방식이고, Canary는 소수 트래픽으로 점진적으로 검증하는 방식입니다.
    • Blue-Green: 중단 없는 전체 교체가 필요한 경우
    • Canary: 실시간 피드백이 필요한 경우
  • 꼬리질문: Canary 배포 시 이상 징후는 어떻게 탐지하나요?
    • 답변: 에러율, 응답 시간, 로그 패턴을 기준으로 A/B 테스트 형태로 비교 분석합니다.

🔹 7. [상] Kubernetes에서 Pod가 무엇인지 설명하고, Pod의 라이프사이클을 설명해주세요.

  • 답변: Pod는 Kubernetes에서 배포 가능한 가장 작은 단위로, 하나 이상의 컨테이너를 포함할 수 있습니다. 라이프사이클은 Pending → Running → Succeeded/Failed/CrashLoopBackOff 등입니다.
  • 꼬리질문: Pod 재시작이 반복될 때 어떻게 디버깅하나요?
    • 답변: kubectl describe pod, kubectl logs, liveness/readiness probe 설정 확인 등으로 분석합니다.

🔹 8. [상] 컨테이너 오케스트레이션 도구(Kubernetes 등)를 사용해 본 경험이 있나요? 이를 통해 얻은 이점을 설명해주세요.

  • 답변: Kubernetes를 사용해 자동 배포, 롤링 업데이트, 서비스 디스커버리, 오토스케일링 등을 경험했습니다. 특히 서비스 장애 격리와 스케일 아웃이 용이했습니다.
  • 꼬리질문: Kubernetes 사용 시 가장 유용했던 기능은?
    • 답변: HPA(Horizontal Pod Autoscaler)를 활용한 자동 확장과 ConfigMap/Secret 관리가 인상적이었습니다.

🔹 9. [중] 로깅(logging)의 중요성과 서버 애플리케이션에서 로그를 효과적으로 관리하는 방법을 설명해 주세요.

  • 답변: 로깅은 문제 추적, 성능 분석, 보안 감사를 위한 핵심 도구입니다. 로그 수준(Level), 포맷 통일, 외부 수집기(ELK, Fluentd 등)와 연계하여 중앙 집중형 로그 관리를 구축합니다.
  • 꼬리질문: 로그 저장 비용이 부담될 때는 어떻게 하나요?
    • 답변: 로그 레벨 조정, 보관 주기 설정, 중요 이벤트만 필터링하여 저장합니다.

🔹 10. [상] 애플리케이션 배포 시 발생할 수 있는 다운타임 최소화 방법을 설명해 주세요.

  • 답변: 무중단 배포 전략(롤링 업데이트, Blue-Green), 로드 밸런서 헬스체크, 예열(warm-up) 로직을 통해 다운타임을 최소화할 수 있습니다.
  • 꼬리질문: 롤링 업데이트 중 에러가 발생하면 어떻게 대응하나요?
    • 답변: 헬스체크 실패 시 롤백 트리거를 설정하거나, Canary로 먼저 테스트 후 전체 배포로 전환합니다.

네트워크와 통신

더보기
  • 의도 : 이 카테고리는 네트워크와 서버 간의 통신을 이해하고 관리하는 능력을 평가합니다. HTTP와 HTTPS, TCP와 UDP와 같은 기본적인 통신 프로토콜을 이해하고, 로드 밸런싱을 통해 서버의 부하를 분산하는 방법을 알고 있는지를 확인합니다. 또한 웹소켓을 활용한 실시간 통신 구현 능력도 평가됩니다.
  • 답변에 포함해야 할 키워드
    • HTTP vs HTTPS: 보안이 적용된 통신 방식
    • TCP vs UDP: 신뢰성 있는 데이터 전송(TCP)과 빠른 전송(UDP)의 차이
    • 로드 밸런싱: 서버 부하를 여러 대의 서버로 분산
    • 웹소켓(WebSocket): 실시간 양방향 통신 프로토콜
    • CORS: 다른 도메인 간의 자원 요청을 관리하는 보안 정책

✅ 네트워크 및 웹 통신 면접 질문 정리 (+실제 답변 및 꼬리질문)


🔹 1. [하] HTTP와 HTTPS의 차이점을 설명해 주세요.

  • 답변: HTTP는 데이터를 암호화하지 않고 전송하며, HTTPS는 SSL/TLS를 이용해 데이터를 암호화하여 보안을 강화합니다.
  • 꼬리질문: HTTPS 통신 과정에서의 공개키와 개인키 역할은?
    • 답변: 서버는 공개키로 암호화한 데이터를 받아, 개인키로 복호화함으로써 보안성을 확보합니다.

🔹 2. [하] TCP와 UDP의 차이점을 설명해주세요.

  • 답변: TCP는 연결 지향적이며 신뢰성이 보장되며 순서가 유지됩니다. UDP는 비연결 지향적이고 속도는 빠르지만 신뢰성이 없습니다.
  • 꼬리질문: TCP가 사용되는 예시와 UDP가 사용되는 예시는?
    • 답변: TCP는 웹 브라우징, 이메일에, UDP는 스트리밍, 게임 등 실시간성이 중요한 곳에 사용됩니다.

🔹 3. [중] 서버 사이드 렌더링과 클라이언트 사이드 렌더링의 차이점을 설명해주세요.

  • 답변: 서버 사이드 렌더링(SSR)은 HTML을 서버에서 완성해 보내고, 클라이언트 사이드 렌더링(CSR)은 자바스크립트가 클라이언트에서 렌더링을 수행합니다.
  • 꼬리질문: SSR의 장점은 무엇인가요?
    • 답변: SEO에 유리하고, 초기 로딩 속도가 빠릅니다.

🔹 4. [상] 웹소켓(WebSocket)이란 무엇이며, 실시간 통신에서 이를 어떻게 사용할 수 있는지 설명해주세요.

  • 답변: 웹소켓은 클라이언트와 서버 간의 지속적인 양방향 통신을 가능하게 하는 프로토콜입니다. HTTP 요청 후 업그레이드를 통해 연결을 유지합니다.
  • 꼬리질문: 웹소켓 대신 폴링이나 SSE와 비교했을 때 장점은?
    • 답변: 지속 연결로 인한 낮은 오버헤드, 빠른 반응속도, 양방향 통신이 가능한 점이 장점입니다.

🔹 5. [중] 웹훅(Webhook)이란 무엇인지 설명해주세요.

  • 답변: 웹훅은 특정 이벤트 발생 시 서버가 지정된 URL로 HTTP 요청을 보내는 방식입니다.
  • 꼬리질문: 실무에서 웹훅을 사용한 사례는?
    • 답변: 결제 승인 완료 후 주문 상태 자동 업데이트, GitHub 푸시 이벤트 알림 등에 사용했습니다.

🔹 6. [중] IP 주소와 DNS(Domain Name System)의 관계를 설명해 주세요.

  • 답변: IP 주소는 서버의 위치를 나타내는 숫자 주소이고, DNS는 도메인 이름을 IP 주소로 변환해주는 시스템입니다.
  • 꼬리질문: DNS 캐싱은 어떤 영향을 미치나요?
    • 답변: 같은 도메인에 대한 반복 요청 시 더 빠른 응답을 가능하게 합니다.

🔹 7. [중] NAT(Network Address Translation)이란 무엇이며, 이를 사용하는 이유를 설명해 주세요.

  • 답변: NAT는 사설 IP와 공인 IP 간의 주소를 변환하여 내부 네트워크의 보안을 강화하고 IP 주소 부족 문제를 해결합니다.
  • 꼬리질문: NAT 환경에서 포트포워딩이 필요한 이유는?
    • 답변: 외부에서 특정 내부 서버에 접근하려면 NAT 라우터가 어떤 내부 IP와 포트를 매핑해야 하기 때문입니다.

🔹 8. [상] HTTP Keep-Alive의 역할과 성능에 미치는 영향을 설명해 주세요.

  • 답변: Keep-Alive는 하나의 TCP 연결을 재사용하여 여러 요청을 처리하는 방식입니다. 연결 설정 오버헤드를 줄여 성능을 향상시킵니다.
  • 꼬리질문: HTTP/1.1에서 Keep-Alive는 기본인가요?
    • 답변: 네, HTTP/1.1에서는 기본적으로 Keep-Alive가 활성화되어 있습니다.

🔹 9. [중] TLS(Transport Layer Security)와 SSL(Secure Sockets Layer)의 차이점을 설명해 주세요.

  • 답변: TLS는 SSL의 후속 프로토콜로 보안성과 성능이 향상된 버전입니다. SSL은 더 이상 권장되지 않으며 TLS 1.2 또는 1.3이 현재 표준입니다.
  • 꼬리질문: TLS 핸드셰이크 과정은 어떻게 진행되나요?
    • 답변: 클라이언트 Hello → 서버 인증서 및 공개키 → 키 교환 → 세션 키 설정 및 암호화 시작

🔹 10. [상] 서버 부하 분산(Load Balancing) 방식 중 라운드 로빈(Round Robin) 방식과 IP 해시 방식의 차이점을 설명해 주세요.

  • 답변: 라운드 로빈은 요청을 순차적으로 서버에 분배하고, IP 해시는 클라이언트 IP를 해싱하여 특정 서버로 고정 분배합니다.
  • 꼬리질문: IP 해시 방식의 단점은?
    • 답변: 서버 수가 변경되면 해시 결과가 바뀌어 세션 일관성이 깨질 수 있습니다.
    •  

분산 시스템 및 클라우드

더보기
  • 의도 : 분산 시스템과 클라우드는 현대 애플리케이션의 확장성 및 고가용성을 위한 필수 요소입니다. 면접관은 지원자가 마이크로서비스 아키텍처(MSA), 클라우드 인프라, 오토스케일링 등을 이해하고, 대규모 애플리케이션에서 발생할 수 있는 문제를 해결할 수 있는 능력을 평가합니다.
  • 답변에 포함해야 할 키워드
    • 마이크로서비스(MSA): 서비스를 작은 단위로 나누어 독립적으로 배포 및 운영
    • 오토스케일링(Auto-scaling): 클라우드에서 트래픽 증가에 따라 서버를 자동으로 확장
    • 로드 밸런싱: 여러 서버에 트래픽을 분산하여 성능 최적화
    • CAP 이론: 일관성(Consistency), 가용성(Availability), 파티션 허용성(Partition tolerance) 간의 트레이드오프
    • Kubernetes: 분산 환경에서 컨테이너 관리

✅ 인프라 및 분산 시스템 면접 질문 정리 (+실제 답변 및 꼬리질문)


🔹 1. [중] 로드 밸런싱(Load Balancing)이 무엇이며, 이를 통해 얻을 수 있는 이점은 무엇인가요?

  • 답변: 로드 밸런싱은 여러 서버에 트래픽을 분산시켜 서버 부하를 고르게 하고, 장애 발생 시 자동으로 다른 서버로 요청을 전환해 가용성과 확장성을 높이는 기술입니다.
  • 꼬리질문: 로드 밸런싱 방식에는 어떤 종류가 있나요?
    • 답변: 라운드로빈, IP 해시, 가중치 기반, 최소 연결 수 방식 등이 있습니다.

🔹 2. [상] 마이크로서비스 아키텍처(MSA)에서 서비스 간 통신을 위한 메시지 브로커(Message Broker)를 사용하는 이유를 설명해 주세요.

  • 답변: 비동기 메시지 처리를 통해 서비스 간 느슨한 결합을 유지하고, 장애 전파를 줄이며 확장성과 유연성을 확보하기 위해 사용됩니다.
  • 꼬리질문: 어떤 메시지 브로커를 사용했고 어떤 기준으로 선택했나요?
    • 답변: Kafka를 사용했으며, 대용량 처리와 내구성, 분산 처리 성능을 고려해 선택했습니다.

🔹 3. [상] 분산 트랜잭션(Distributed Transaction)이란 무엇이며, 이를 관리하는 방법을 설명해 주세요.

  • 답변: 둘 이상의 데이터베이스나 시스템에 걸쳐 일어나는 트랜잭션을 의미하며, 일반적인 트랜잭션처럼 원자성을 보장하기 어렵습니다. 해결 방법으로 2PC, SAGA 패턴, 이벤트 기반 보상 트랜잭션 등이 있습니다.
  • 꼬리질문: SAGA 패턴의 장점과 단점은?
    • 답변: 장점은 유연하고 분산 시스템에 적합하며, 단점은 보상 로직 관리가 복잡하다는 점입니다.

🔹 4. [중] 클라우드에서의 오토스케일링(Auto-scaling)이 무엇이며, 이를 구현할 때 고려해야 할 요소는 무엇인가요?

  • 답변: 오토스케일링은 트래픽 부하에 따라 자동으로 인스턴스 수를 조정하는 기능입니다. 고려 요소로는 메트릭 기준(CPU, Memory), 쿨다운 시간, 최소/최대 인스턴스 수 등이 있습니다.
  • 꼬리질문: CPU 외에 오토스케일링 조건으로 어떤 지표를 사용할 수 있나요?
    • 답변: 네트워크 I/O, 요청 수, 애플리케이션 응답 시간, 큐 길이 등이 사용됩니다.

🔹 5. [상] Kubernetes의 역할과 사용 이유에 대해 설명해 주세요.

  • 답변: Kubernetes는 컨테이너화된 애플리케이션의 배포, 스케일링, 관리를 자동화하는 오케스트레이션 도구입니다. 고가용성, 자가 치유, 로드밸런싱, 롤링 업데이트 등의 기능을 제공합니다.
  • 꼬리질문: 실제 운영에서 Kubernetes가 가장 유용했던 사례는?
    • 답변: 롤링 업데이트 시 다운타임 없이 배포하거나, 장애 Pod의 자동 복구가 매우 효과적이었습니다.

🔹 6. [중] AWS, GCP, Azure와 같은 클라우드 서비스 제공자가 제공하는 주요 서비스에 대해 설명해 주세요.

  • 답변:
    • AWS: EC2(컴퓨팅), S3(스토리지), RDS(DB), Lambda(서버리스)
    • GCP: Compute Engine, Cloud Storage, BigQuery, Cloud Functions
    • Azure: Virtual Machines, Blob Storage, SQL Database, Azure Functions
  • 꼬리질문: 멀티 클라우드 전략의 장점은?
    • 답변: 특정 벤더 종속 방지, 장애 대응력 강화, 비용 및 성능 최적화가 가능합니다.

🔹 7. [상] 분산 시스템에서 데이터 일관성(Consistency)과 가용성(Availability)의 트레이드오프를 설명해 주세요.

  • 답변: 분산 시스템에서는 네트워크 파티션 상황에서 일관성과 가용성을 동시에 만족시킬 수 없습니다. 일관성을 유지하면 일부 요청은 거부되고, 가용성을 선택하면 일시적 불일치가 발생할 수 있습니다.
  • 꼬리질문: 어떤 상황에서 일관성보다 가용성을 선택하나요?
    • 답변: 실시간 채팅, 피드 시스템처럼 최신 데이터보다 응답 속도가 중요한 서비스에서는 가용성이 우선됩니다.

🔹 8. [상] CAP 이론이란 무엇이며, 분산 시스템에서 어떻게 적용되는지 설명해 주세요.

  • 답변: CAP 이론은 Consistency(일관성), Availability(가용성), Partition Tolerance(분할 허용성) 중 두 가지만 동시에 보장 가능하다는 이론입니다. 분산 시스템에서는 파티션 허용이 필수이므로, 일관성과 가용성 중에서 선택해야 합니다.
  • 꼬리질문: Cassandra와 같은 시스템은 CAP 중 어떤 조합을 따르나요?
    • 답변: Cassandra는 AP(가용성 + 파티션 허용)을 선택하고, eventual consistency 모델을 따릅니다.

🔹 9. [중] 클라우드 환경에서의 데이터 백업과 복구 전략에 대해 설명해 주세요.

  • 답변: 자동 백업 설정, 스냅샷 주기적 생성, 지역 간 복제, 복구 테스트 시나리오 설계 등을 포함합니다. RTO(복구 시간 목표)와 RPO(복구 시점 목표)를 기준으로 정책을 세웁니다.
  • 꼬리질문: 백업은 되었는데 복구가 실패하는 경우는 왜 발생하나요?
    • 답변: 복구 테스트 미실시, 버전 불일치, 네트워크 설정 오류 등으로 인해 실제 복구 실패가 발생할 수 있습니다.

🔹 10. [상] 컨테이너 기반 마이크로서비스 아키텍처를 운영할 때의 장점과 단점을 설명해 주세요.

  • 답변:
    • 장점: 빠른 배포, 독립적 스케일링, 기술 스택 분리, 이식성
    • 단점: 복잡한 네트워크 구성, 서비스 디스커버리/보안 이슈, 운영 인프라 부담
  • 꼬리질문: 컨테이너 기반 MSA에서 가장 어려웠던 점은?
    • 답변: 로그 집계 및 트래픽 추적이 어려웠고, 이를 해결하기 위해 중앙 로깅 시스템과 분산 트레이싱을 도입했습니다.

테스트 및 디버깅

더보기
  • 의도 : 이 카테고리는 코드의 신뢰성 및 성능을 보장하기 위해 테스트와 디버깅을 수행하는 능력을 평가합니다. 단위 테스트, 통합 테스트를 통해 개발된 기능이 제대로 작동하는지 검증할 수 있는 능력을 확인하고, TDD나 성능 테스트와 같은 테스트 주도 개발 방식을 이해하고 있는지를 묻습니다.
  • 답변에 포함해야 할 키워드
    • 단위 테스트(Unit Test): 코드의 개별 단위를 테스트
    • 통합 테스트(Integration Test): 여러 모듈이 함께 동작하는지 확인
    • TDD(Test Driven Development): 테스트를 먼저 작성하고 기능을 구현하는 방식
    • 디버깅(Debugging): 코드 실행 중 발생하는 오류를 찾고 수정하는 과정
    • 로깅(logging): 서버 애플리케이션에서 발생하는 로그 기록 및 분석

✅ 테스트 및 디버깅 면접 질문 정리 (+실제 답변 및 꼬리질문)


🔹 1. [하] 단위 테스트(Unit Test)와 통합 테스트(Integration Test)의 차이점을 설명해 주세요.

  • 답변: 단위 테스트는 하나의 메서드나 컴포넌트를 독립적으로 검증하며, 통합 테스트는 여러 모듈이 함께 동작하는지 확인합니다.
  • 꼬리질문: 각각의 테스트는 어떤 시점에서 수행해야 하나요?
    • 답변: 단위 테스트는 개발 직후, 통합 테스트는 기능 구현 후 혹은 배포 전에 수행합니다.

🔹 2. [중] TDD(Test Driven Development)가 무엇이며, 이를 적용한 경험이 있나요?

  • 답변: 테스트 코드를 먼저 작성하고, 이를 통과하는 최소한의 코드를 구현하는 방식입니다. 기능 개발에 대한 명확한 설계와 빠른 피드백이 장점입니다.
  • 꼬리질문: TDD의 단점은 무엇인가요?
    • 답변: 초기 구현 속도가 느릴 수 있고, 복잡한 테스트 작성이 부담이 될 수 있습니다.

🔹 3. [중] 로깅(logging)이 중요한 이유와 효과적인 로깅 전략을 설명해 주세요.

  • 답변: 로깅은 시스템 상태를 추적하고, 에러 발생 시 원인을 분석하는 데 필수입니다. 레벨 구분(INFO, WARN, ERROR), 구조화 로그, 중앙 로깅 시스템(ELK 등)을 도입해 효과적으로 관리합니다.
  • 꼬리질문: 민감한 정보가 로그에 노출되지 않도록 하려면?
    • 답변: 개인정보 마스킹, 보안 로그 필터링, 접근 권한 설정이 필요합니다.

🔹 4. [상] 서버에서 발생한 성능 문제를 디버깅한 경험이 있나요? 어떻게 해결했나요?

  • 답변: 특정 API 응답 지연 문제를 분석한 결과, N+1 쿼리와 GC 과다 발생이 원인이었습니다. JPA fetch 전략 수정과 G1GC 설정 조정으로 해결했습니다.
  • 꼬리질문: GC 로그를 분석하는 방법은?
    • 답변: GC 로그를 통해 Full GC 발생 주기, heap 사용량 등을 확인하여 튜닝 포인트를 찾습니다.

🔹 5. [중] JUnit을 사용한 테스트 작성 경험이 있나요? 기본적인 사용법을 설명해 주세요.

  • 답변: @Test 애너테이션으로 메서드를 테스트 단위로 정의하고, assertEquals, assertThrows 등을 활용하여 결과를 검증합니다.
  • 꼬리질문: 테스트 코드에서 공통 설정은 어떻게 관리하나요?
    • 답변: @BeforeEach, @BeforeAll 등을 활용해 공통 초기화 로직을 구성합니다.

🔹 6. [상] 테스트 자동화를 구현하는 방법과 이를 통해 얻을 수 있는 이점에 대해 설명해주세요.

  • 답변: GitHub Actions, Jenkins 등을 사용해 CI/CD 파이프라인에서 테스트가 자동으로 실행되도록 설정합니다. 오류를 빠르게 발견하고 코드 품질을 유지하는 데 큰 도움이 됩니다.
  • 꼬리질문: 테스트가 불안정하게 실패할 경우 어떻게 대응하나요?
    • 답변: 테스트 격리 여부 확인, 의존성 제거, mock 객체 사용 여부 등을 점검합니다.

🔹 7. [상] 성능 테스트(Performance Testing)와 부하 테스트(Load Testing)의 차이점을 설명해 주세요.

  • 답변: 성능 테스트는 시스템의 응답 시간, 처리량을 측정하는 테스트이고, 부하 테스트는 정상 상태에서의 최대 처리 용량을 측정하는 테스트입니다.
  • 꼬리질문: 성능 테스트 도구로 어떤 걸 써봤나요?
    • 답변: JMeter, Gatling을 사용해 요청 수와 응답 시간 등을 분석했습니다.

🔹 8. [중] 버그가 발생했을 때 이를 추적하는 방법과 해결 과정에 대해 설명해주세요.

  • 답변: 로그 분석, 재현 시나리오 구성, 버전 이력 확인, 디버거 사용 등을 통해 원인을 파악하고, 단위 테스트를 작성한 후 수정합니다.
  • 꼬리질문: 재현이 어려운 버그는 어떻게 추적하나요?
    • 답변: 입력/환경 로깅을 강화하고, Sentry 등 오류 수집 도구를 활용해 사용자 환경에서의 정보를 확보합니다.

🔹 9. [상] 코드 품질을 유지하기 위한 정적 분석 도구(예: SonarQube)를 사용한 경험이 있나요? 이를 어떻게 활용했는지 설명해 주세요.

  • 답변: SonarQube를 Jenkins와 연동하여 빌드 시 자동 분석되도록 했고, 코드 스멜, 복잡도, 커버리지 등의 지표를 기준으로 리팩토링 우선순위를 정했습니다.
  • 꼬리질문: 코드 커버리지는 얼마나 확보해야 하나요?
    • 답변: 프로젝트 특성에 따라 다르지만, 핵심 로직은 80% 이상 확보하는 것을 목표로 합니다.

🔹 10. [상] 데이터베이스에서 발생하는 성능 문제를 디버깅한 경험을 설명해 주세요.

  • 답변: 대량 데이터 조회 시 응답 지연 문제가 발생해 쿼리 실행 계획을 분석한 결과, 인덱스 미사용과 JOIN 최적화 부족이 원인이었습니다. 인덱스 추가와 쿼리 구조 개선으로 해결했습니다.
  • 꼬리질문: DB 성능 문제를 예방하기 위한 방법은?
    • 답변: 정기적인 실행 계획 점검, 느린 쿼리 로그 확인, 통계 갱신, 캐시 활용 등이 있습니다.

'취업' 카테고리의 다른 글

면접 정리 [test]  (0) 2025.04.15

아래는 NOWBartend 프로젝트를 기반으로 예상되는 면접 질문 리스트모범 답변입니다. 기술 면접에서 자주 나오는 **‘왜’, ‘어떻게’**에 대한 내용을 중심으로 구성했습니다.


🔍 전체 면접 예상 질문 리스트 + 답변

1. AOP 기반 Lock 구성

Q. 락을 AOP로 구성한 이유는 무엇인가요?

A. AOP는 공통된 기능을 모듈화해 핵심 로직과 분리할 수 있기 때문에 락과 같은 횡단 관심사를 깔끔하게 처리하기 적합했습니다. 예약 처리 같은 트랜잭션 로직마다 락을 일일이 적용하는 것보다, 공통 인터셉터 방식으로 선언적 락 제어를 가능하게 하여 유지보수성을 높일 수 있었습니다.


Q. 락이 전체 로직에 적용되어 병목이 생긴다고 했는데, 어떤 식으로 개선했나요?

A. 초기에는 예약 처리 전체에 락을 걸어 조회·검증 단계에서도 병목이 발생했습니다. 이후 조회/검증 단계에서는 락을 제거하고, 실제 DB 변경이 일어나는 구간에만 락을 걸도록 수정했습니다. 이를 통해 락 점유 시간을 수초 단위에서 수십 ms로 줄였고, TPS도 2배 이상 향상되었습니다.


Q. 분산 락은 어떤 방식으로 구현하셨나요?

A. Redis 기반의 Redisson 라이브러리를 활용해 분산 락을 구현했습니다. 인터페이스 기반 AOP에서 메서드 호출 시 특정 키를 기준으로 락을 획득하고, 트랜잭션 수행 이후 락을 해제하는 구조입니다. 락 키는 예약 대상의 바 ID와 사용자 ID를 기준으로 설정했습니다.


2. 성능 테스트 및 개선

Q. 성능 테스트는 어떻게 진행했나요?

A. JMeter를 사용하여 3,700명 이상의 가상 사용자를 설정한 부하 테스트를 진행했습니다. 테스트 결과, 락이 전체 로직에 적용된 경우 평균 응답 시간이 100160초까지 증가했으며, TPS는 200300에 머물렀습니다. 이후 로직 분리와 락 최적화로 3060초 내 응답, 400500 TPS까지 개선되었습니다.


Q. TPS가 낮아진 원인은 무엇이었나요?

A. 락이 전체 로직에 걸리면서, 병렬 처리가 가능한 단순 조회 요청까지 직렬화되어 병목이 발생했습니다. 특히 알림 로직까지 동기적으로 처리하면서 응답 지연이 커졌습니다.


3. 비동기 처리 & 메시지 큐

Q. 알림 시스템을 비동기화한 이유와 방식은?

A. 예약 완료 시 알림 생성 및 전송까지 동기적으로 처리되면, 전체 응답 지연의 원인이 됩니다. 이를 해결하기 위해 메시지 큐를 도입했습니다. 예약 성공 시 이벤트를 발행하고, 별도의 알림 서비스에서 큐를 구독해 알림을 생성 및 전송하게 했습니다. 이를 통해 응답 시간과 락 점유 시간을 모두 줄일 수 있었습니다.


Q. 메시지 큐는 어떤 방식으로 구현하셨나요?

A. Spring의 @Async를 사용한 단순 비동기 처리로 시작했지만, 확장성과 장애 대응을 고려해 Redis Stream 기반의 메시지 큐로 전환했습니다. 이벤트 발행 시 Redis Stream에 메시지를 넣고, 별도 스레드에서 구독하여 알림을 처리했습니다.


4. 지리 기반 탐색 & 카카오 API

Q. 카카오 지도 API는 어떻게 활용했나요?

A. 카카오의 장소 검색 API를 통해 사용자의 현재 위치 기반으로 반경 내 바 리스트를 조회했습니다. 프론트엔드에서 현재 위치 정보를 전달받고, 서버에서 해당 좌표 기준의 반경 검색을 수행하여 가까운 가게 목록을 제공합니다.


Q. 위치 기반 검색의 정렬 기준은 무엇이었나요?

A. 거리순으로 정렬하며, 서버에서 좌표간 거리를 계산해 정렬했습니다. 추후에는 사용자 평점이나 예약 가능 여부를 함께 고려한 정렬 방식도 적용할 계획입니다.


5. 보안 및 인증 처리

Q. Spring Security를 어떻게 적용하셨나요?

A. JWT 기반 인증 시스템을 구축했고, 사용자 인증 시 토큰을 발급해 이후 요청의 Header에 포함해 인증하는 방식으로 구현했습니다. Role 기반 인가도 설정하여, 관리자와 일반 사용자의 접근 권한을 구분했습니다.


Q. 소셜 로그인은 어떻게 구현했나요?

A. Spring Security OAuth2 클라이언트를 활용하여 카카오, 구글 로그인을 구현했습니다. 사용자 정보는 최초 로그인 시 DB에 저장하고, 이후 JWT 토큰 기반으로 인증 처리합니다. 이를 통해 사용자의 접근 편의성을 높이고 회원가입 절차를 간소화했습니다.


6. 전반적인 설계와 기여

Q. 프로젝트에서 가장 도전적이었던 부분은?

A. 동시성 제어와 관련된 트랜잭션 정합성 문제 해결이 가장 도전적이었습니다. 단순히 락을 거는 것에서 끝나는 것이 아니라, 병목의 원인을 정확히 진단하고 조회와 변경 구간을 분리하여 성능을 유지하면서도 정합성을 지키는 데 중점을 뒀습니다.


Q. 지금 돌아본다면 개선할 여지가 있던 부분은?

A. 락 처리 로직의 세분화와 큐 처리 방식에서 좀 더 범용적인 이벤트 기반 아키텍처 (예: Kafka)를 적용하면 추후 확장성에 더 유리했을 것 같습니다. 이번 프로젝트에선 Redis Stream으로 충분했지만, 대규모 트래픽 시점에는 메시지 브로커를 바꾸는 것도 고려하고 있습니다.


 

완벽하게 준비할 수 있도록, 당신의 HANSUNG STOCK 프로젝트를 면접에서 처음 소개하는 방식 → 이어지는 질문 흐름 → 예상 질문 & 답변까지 대화형 시뮬레이션처럼 구성해드릴게요. 이 흐름대로 말하면 자연스럽고 논리적으로 강하게 어필할 수 있습니다.


🧭 1. 면접에서 프로젝트 소개하는 방식

🎙️ 자기 입으로 설명할 1분 스크립트

“제가 진행한 HANSUNG STOCK은 딥러닝을 활용한 주가 예측 및 자동매매 웹 서비스입니다. Python과 Django 기반으로, 사용자가 종목 이름을 입력하면 해당 주가를 예측하고, 지정된 전략에 따라 자동으로 매매까지 수행할 수 있게 구현했습니다.

Keras 기반 LSTM 모델을 사용했고, 실제 매매는 대신증권 CYBOS Plus API를 통해 수행했습니다.
매매 로직은 변동성 돌파 전략 기반이며, 자동매매 프로세스는 Django 웹 서버와 독립적으로 돌아가야 했기 때문에 subprocess를 활용해 백그라운드에서 매매가 유지되도록 했습니다.

또한, 종목별 뉴스는 BeautifulSoup으로 크롤링해서 시각화했고, Chart.js를 활용해 주가 변동도 직관적으로 보여줬습니다.”


🔁 2. 연계형 면접 예상 질문 + 답변


📌 Q1. 왜 딥러닝을 사용해서 주가를 예측하려 했나요?

A. 단순 시계열 모델보다 LSTM 같은 딥러닝 기반 모델이 시계열 예측에서 장기 의존성(Lag)을 잡는 데 더 효과적이라 판단했습니다. 물론 주가 자체는 예측이 어렵지만, 사용자에게 데이터 기반 참고 지표를 제공하고자 활용했습니다.


📌 Q2. 예측 정확도는 어느 정도였나요?

A. 초기에는 RMSE가 다소 컸고, 사용자 피드백에서도 만족도가 낮았습니다. 그래서 ‘변동성 돌파 + 이동평균’ 조건을 활용한 보완 전략으로 수정했고, 예측 자체보다는 "어떤 조건에서 매수/매도를 자동화할 것인가"를 더 현실적인 방향으로 집중했습니다.


📌 Q3. CYBOS Plus API는 어떤 방식으로 연동하셨나요?

A. Windows 기반의 로컬 환경에서 실행 가능한 COM 기반 API입니다. Python의 win32com.client를 활용해 로그인, 종목 검색, 계좌 조회 등을 구현했고, 종목명 → 종목코드 매핑도 직접 구현했습니다.


📌 Q4. 자동매매 로직은 어떻게 실행되나요?

A. 사용자가 종목을 선택하고 매매를 설정하면, Django에서 subprocess.Popen()으로 별도 Python 스크립트를 실행해 장 종료 전까지 백그라운드로 매매를 수행합니다. 이를 통해 웹 서버가 중단돼도 매매 로직은 영향을 받지 않습니다.


📌 Q5. subprocess가 아니라 Celery 같은 큐를 사용하지 않은 이유는?

A. 당시 목표가 간단한 실험 시스템 구축이었고, 실시간성이 강한 작업은 아니었기 때문에 subprocess로 충분했습니다. 실제 서비스 수준이라면 Celery나 Redis 기반 작업 큐 도입이 더 바람직하다고 생각합니다.


📌 Q6. 딥러닝 말고 다른 예측 모델도 테스트해봤나요?

A. 네, Sklearn 기반으로 RandomForest, SVR도 테스트했지만, 예측 흐름상 LSTM이 가장 부드럽고 시계열 연속성에 적합하다는 결과를 얻었습니다. 다만, 데이터가 제한적일 땐 간단한 모델이 더 유리할 수도 있다는 점도 확인했습니다.


📌 Q7. BeautifulSoup 크롤링은 어떤 용도로 활용했나요?

A. 사용자가 특정 종목을 선택하면, 해당 종목과 관련된 뉴스 상위 5건을 네이버 금융에서 크롤링해 롤링 배너 형식으로 제공합니다. 종목 관련 이슈를 실시간으로 제공해 예측 신뢰도를 높이는 보조 수단으로 활용했습니다.


📌 Q8. 프로젝트에서 가장 어려웠던 점은?

A. 장시간 실행되는 자동매매 로직을 Django와 분리해 유지하는 부분이 가장 어려웠습니다. 중간에 웹이 꺼지거나 예외 발생 시 매매가 멈추는 문제가 발생해서, subprocess와 예외 처리 로직을 통해 이를 안정화하는 데 가장 시간을 많이 썼습니다.


📌 Q9. 프로젝트를 통해 배운 점은?

A. 딥러닝만으로는 예측의 한계가 분명하다는 걸 체감했고, 실용성을 고려한 전략 보완이 중요하다는 걸 배웠습니다. 또한, 사용자 입력 처리 → 예측 모델 → 매매 실행 → 시각화까지 하나의 End-to-End 시스템을 설계하는 경험을 할 수 있었습니다.


📌 Q10. 지금 한다면 어떻게 개선하고 싶나요?

A.

  • API 의존성 낮추기: CYBOS 대신 Python 기반의 OpenDart + WebSocket 기반 실시간 API로 전환
  • 예측 전략 고도화: 강화학습 기반의 전략 적용
  • 아키텍처 개선: Celery 도입, 모델 추론 서버와 웹 분리
  • 실사용자 피드백 기반의 자동매매 커스터마이징 추가

✅ 정리: 면접 핵심 포인트

구분 내용

목표 예측 + 자동매매 End-to-End 웹 서비스 구축
강점 딥러닝 적용 + 실매매 전략 설계 + API 연동
어려움 프로세스 분리와 예외 처리
개선 여지 실시간성 강화, 전략 정교화, MSA 구조 전환

원하신다면 이 내용을 기반으로 6슬라이드 발표자료도 바로 구성해드릴 수 있어요.
지금 같이 정리해볼까요?

 

정확한 방향을 짚어주셔서 좋아요!
면접은 결국 "왜 그걸 썼는지"를 이해하는 질문,
지원 포지션이 백엔드라면 “AI 모델 자체”보다 “서비스화, 아키텍처, 통합 기술 선택 이유”가 중요합니다.

그래서 지금부터는 HANSUNG STOCK 프로젝트를 "백엔드 개발자 관점"에서 설명하고,
왜 이 구조를 썼는지 = 설계 의도 중심으로 면접 답변을 구성해 드릴게요.


🧠 HANSUNG STOCK – 백엔드 관점 설명 (면접용)

🎙️ 1분 요약 (왜를 중심으로 설명)

“딥러닝 예측보다는 예측 기반 자동매매 시스템을 서비스화한 전체 구조 설계에 집중했습니다.
Django를 선택한 이유는 빠른 웹 API 개발과 Python 생태계와의 통합 때문이고, CYBOS API로 주가 정보를 받아와 사용자 요청에 따라 종목 검색, 시각화, 자동매매를 수행하는 구조입니다.
백엔드 입장에서 특히 고려한 점은 장시간 실행되는 자동 매매 프로세스를 메인 서버와 분리해 안정적으로 운영하는 것이었고, 이를 위해 subprocess로 백그라운드 프로세스를 분리했습니다.
또한, 주가 정보와 뉴스 데이터를 한 화면에 통합 제공하고, 변동성 기반 전략을 조건화하여 사용자마다 맞춤 실행이 가능하게 설계했습니다.”


🔗 면접 질문 + 백엔드 관점의 “왜” 중심 답변


Q1. 왜 Django를 사용하셨나요? (vs Flask)

A.
Flask는 가볍지만 확장 구조가 부족하고, 자동매매처럼 폼 기반 데이터 처리, ORM, Admin, 인증 같은 내장 기능이 필요한 상황에선 Django가 훨씬 유리했습니다.
또한 Python 생태계에서 주가 예측 모델, API 연동, 시각화까지 모두 포함하려면 Django에서 빠르게 백엔드 구조를 잡는 것이 더 실용적이라 판단했습니다.


Q2. 왜 subprocess를 사용해 자동매매 로직을 따로 실행했나요?

A.
자동매매는 장중 6시간 이상 돌아가는 로직입니다. 이걸 Django 서버 내부에서 처리하면 웹 요청 지연, 메모리 점유, 예외 발생 시 전체 서버 중단 가능성이 있었습니다.
그래서 웹 서버는 요청만 받고, 실제 매매는 별도 백그라운드 프로세스에서 지속 실행되도록 subprocess.Popen()을 사용했습니다. 이는 MSA의 관점에서도 로직 분리가 된 구조입니다.


Q3. 백엔드 개발자로서 자동매매 서비스에서 가장 신경 쓴 부분은?

A.

  1. API 연동 신뢰성 – 대신증권 API는 호출 횟수 제한이 있으므로, 호출 주기를 제어하고 재시도 로직을 넣었습니다.
  2. 프로세스 분리 – 장시간 자동매매가 서버와 별도로 돌아야 했기에 비동기 처리 구조를 명확히 했습니다.
  3. 에러 처리와 유저 입력 검증 – 종목명이 오타나 잘못된 경우, 예외 없이 graceful fallback 되도록 예외처리를 강화했습니다.

Q4. 뉴스 크롤링을 왜 서버에서 직접 구현하셨나요?

A.
사용자 입장에서 종목 예측만으로는 불안하기 때문에, **정성적 정보(뉴스)**를 함께 제공하면 신뢰도가 높아집니다. 그래서 뉴스 크롤링을 서버에서 수행하고, 롤링 배너로 제공합니다.
또한 이는 주가 예측의 context로도 활용할 수 있어 미래 확장성까지 고려한 설계였습니다.


Q5. 왜 Chart.js로 시각화했나요?

A.
Chart.js는 클라이언트에서 렌더링하는 가벼운 라이브러리이며, Django의 템플릿 엔진과도 잘 연동됩니다.
백엔드에서 JSON 형태로 가공한 주가 데이터를 템플릿에 전달하고, 프론트에서 Chart.js로 시각화하여 성능 이슈 없이 처리할 수 있었습니다.


Q6. 왜 LSTM을 사용했나요? → (AI 질문으로 넘어오면 간결하게)

A.
AI가 목적이 아니라 예측 기반 로직을 API화하고 서비스화하는 것이 목적이었습니다.
그 중 시계열 예측에 적합한 LSTM을 선택했고, 실제 전략은 단순 예측보다는 조건 기반 자동매매로 연결되기 때문에 모델 자체보다 모델을 어떻게 서비스에 통합했는지가 핵심이었습니다.


Q7. 지금 한다면 백엔드 구조에서 어떤 걸 개선하고 싶나요?

A.

  • subprocess → Celery + Redis 구조로 변경해 분산 처리 및 로그 추적 개선
  • Django 단일 서버 → FastAPI + 추론 서버 분리(MSA화)
  • API 연동은 증권사 오픈 API로 교체하거나, Kafka를 이용한 실시간 스트리밍 기반 분석 구조 도입

✅ 정리 – 백엔드 면접 핵심 요약

면접 포인트 설명

왜 Django? 빠른 서비스 구축 + 내장 기능 풍부 (ORM, Admin 등)
왜 subprocess? 장시간 실행 로직 분리 → 안정성과 유연성 확보
어디에 집중했나? API 신뢰성, 사용자 예외처리, 서버 분리 설계
AI 모델은 부가적 수단 주가 예측이 아닌 백엔드 구조 설계와 안정성 중심

 

'취업' 카테고리의 다른 글

면접 CS 질문 정리  (0) 2025.04.16

무한 스크롤과 랜덤 정렬, 커서 기반 페이징과 함께 쓸 수 있을까?

인스타그램과 같은 피드 구조를 구현하실 때, 무한 스크롤과 랜덤 정렬을 동시에 적용하고 싶으셨던 적이 있으신가요?
저 역시 유사한 구조를 구현하려다 예상치 못한 충돌을 겪었고, 이를 해결하기 위해 고정된 랜덤 시드를 도입하는 방식으로 문제를 풀게 되었습니다.

 

이 글에서는 그 과정을 정리하여 공유드리고자 합니다. 특히 커서 기반 페이징과 랜덤 정렬은 어떻게 공존할 수 있는가에 대한 고민이 중심입니다.


문제 상황: 커서 기반 페이징과 랜덤 정렬의 충돌

처음 의도는 다음과 같았습니다.

  • 피드에 게시글을 무한 스크롤로 불러오고 싶다
  • 사용자마다 매번 다른 랜덤 정렬 순서로 보여주고 싶다

이 두 가지를 동시에 적용하려고 했을 때 한 가지 중요한 사실을 깨달았습니다.

커서 기반 페이징은 고정된 정렬 순서를 전제로 작동하는데,
랜덤 정렬은 매번 다른 결과를 만들기 때문에, 두 방식은 정면으로 충돌한다.”

커서 기반 방식은 이전 페이지의 마지막 항목을 기준으로 다음 항목의 위치를 정확히 예측할 수 있어야 합니다. 하지만 랜덤 정렬을 적용하면 동일한 조건에서조차 결과가 달라지므로, 페이징 커서가 무의미해지는 문제가 발생합니다.


해결 방향: 고정된 랜덤 시드(Random Seed)의 도입

그래서 다음과 같은 방식으로 문제를 해결하였습니다.

  1. 사용자가 피드를 처음 요청할 때, 서버가 랜덤 시드(seed) 를 생성하여 클라이언트에 전달합니다.
  2. 이후 무한 스크롤을 통해 페이지를 추가로 요청할 경우, 클라이언트는 이 랜덤 시드를 계속 유지합니다.
  3. 게시글 ID와 랜덤 시드를 조합하여 고정된 정렬 키(sort key) 를 계산합니다.
  4. 이 정렬 키를 기준으로 커서 기반 페이징을 적용합니다.

이렇게 하면 사용자에게는 세션 중 일관된 랜덤 정렬 피드를 보여줄 수 있으며, 커서 기반의 안정적인 페이징도 가능합니다.


구현 방식 예시

📌 정렬 키 계산 방식

게시글마다 다음과 같은 방식으로 정렬 키를 계산합니다:

sortKey = hash(seed + postId); // 예: CRC32 해시 사용

이 정렬 키는 동일한 시드에 대해서는 항상 같은 값을 반환하므로,
정렬 순서 역시 변하지 않습니다.


📌 커서 기반 페이징 로직

SELECT * FROM posts
WHERE hash(seed + post_id) > :lastCursor
ORDER BY hash(seed + post_id)
LIMIT 20;

이 방식은 해시값 기준으로 오름차순 정렬하여 커서 이후의 게시글을 페이징 처리합니다.
사용자가 계속 스크롤할수록, 정해진 랜덤 순서대로 다음 게시글이 불러와집니다.


추가 고민: 새로운 게시글이 추가된다면?

이 구조에서 새롭게 떠오른 질문이 하나 있었습니다.

“그렇다면, 피드를 보는 도중에 새로운 게시글이 생긴다면 어떻게 되는가?”

결론부터 말씀드리면, 문제 없습니다.
새로운 게시글은 동일한 시드로 해시 계산을 하게 되므로 기존 피드 내 적절한 위치에 배치되지만,
사용자는 계속해서 기존 커서 이후 정렬된 게시글만 불러오기 때문에,
세션 중에는 피드 순서가 유지되고 새 게시글로 인한 페이징 오류도 발생하지 않습니다.


사용자 경험 흐름 정리

  1. 피드 최초 요청 시
    • 서버는 고정된 random_seed를 생성해 응답에 포함합니다.
  2. 무한 스크롤 페이지 요청 시
    • 클라이언트는 동일한 random_seed를 포함하여 요청합니다.
  3. 새로고침 또는 앱 재시작 시
    • 새로운 random_seed가 발급되어, 전혀 새로운 랜덤 피드가 생성됩니다.

정리하며

처음에는 무한 스크롤과 랜덤 정렬을 동시에 사용한다는 것이 불가능해 보였지만,
랜덤 시드 기반의 정렬 키 생성이라는 아이디어를 통해 이 둘을 자연스럽게 결합할 수 있었습니다.

항목 설명
문제 커서 기반 페이징과 매번 달라지는 랜덤 정렬은 충돌하는 구조
해결 고정된 랜덤 시드를 발급하고 해시 정렬 키를 만들어 커서 기반 페이징에 활용
결과 한 세션 동안은 일관된 랜덤 순서, 새로고침 시 새로운 피드 제공 가능
장점 성능과 UX의 균형 유지, 확장성 있는 구조

후속 과제

  • 추후 팔로우/팔로잉 기능이 추가되었을 때, 정렬 기준이 복합적으로 될 수 있어 정렬 로직을 재조정할 필요가 있습니다.
  • 사용자 맞춤형 피드에 적용하려면, 시드 외에도 필터/우선순위 로직과의 결합을 고려해야 합니다.
  • 캐싱 전략, 정렬 키 생성의 성능 최적화 등도 장기적으로는 고민해볼 만한 부분입니다.

 

1. MSA의 부상과 현실적인 문제

마이크로서비스 아키텍처(MSA)는 IT 산업이 발전하면서 많은 직군이 기술 중심적으로 변화하고, 트래픽 증가에 따라 확장성 요구가 커지면서 주목받게 되었다. 초기에는 MSA가 서비스 확장성과 분산 환경에 적합한 솔루션으로 각광받았지만, 실제 운영에서 여러 문제점이 드러나면서 MSA를 도입할지 여부를 두고 논쟁이 벌어지는 상황이 되었다.

현재 IT 업계에서는 "MSA를 도입해야 하는가?" 또는 "MSA를 포기하고 다시 모놀로틱으로 돌아갈 것인가?" 하는 두 가지 입장이 대립하고 있다.


2. MSA 도입의 주요 문제점

 

(1) 기술적 부채 증가

MSA를 도입하면 서비스가 여러 개로 나뉘면서 개별적인 테스트가 어려워지고, 전체 시스템의 일관성을 유지하기 위한 테스트 코드와 통합 테스트 비용이 기하급수적으로 증가한다.

  • 단위 테스트(Unit Test) 관리 어려움: 각 마이크로서비스별로 독립적인 테스트 코드 작성 필요
  • 통합 테스트(Integration Test) 부담 증가: 여러 서비스가 동시에 동작해야 하므로 통합 테스트가 어렵고 불완전할 가능성이 높음
  • QA 과정 복잡화: 모든 서비스가 올바르게 동작하는지 확인하기 위해 QA 단계가 많아짐

결과적으로, 테스트 비용 증가와 유지보수 부담으로 인해 기술적 부채가 누적되기 쉬운 구조가 된다.

 

 

(2) 운영 관리 및 인프라 비용 부담

MSA는 서비스가 분리됨에 따라 운영 및 인프라 관리의 복잡도가 증가하고, 이를 유지하기 위해서는 상당한 자본과 인력이 필요하다.

  • 각 서비스의 배포 및 유지보수 관리 필요: 배포 자동화(CI/CD), 모니터링, 로깅, 보안 등을 위한 추가적인 인프라가 필요함
  • 네트워크 비용 증가: 마이크로서비스 간 통신이 많아지면서 네트워크 트래픽이 증가하고, API Gateway, Service Mesh 같은 추가적인 계층이 필요해짐
  • 데이터 일관성 유지 어려움: 각 서비스가 독립적인 데이터베이스를 가질 경우, 분산 트랜잭션 관리가 복잡해짐 (예: SAGA 패턴 적용 부담)
  • 전문적인 운영 인력 필요: DevOps, SRE(Site Reliability Engineering) 등의 역할이 필수적으로 요구됨

대기업 수준의 자본력이 있는 기업이 아니라면, MSA를 완전히 운영하는 것이 현실적으로 어렵다.

 

 

(3) 개발 및 배포 속도 저하
MSA의 핵심 목표 중 하나는 빠른 배포와 지속적인 배포를 가능하게 하는 것이다. 하지만 실제 운영 환경에서는 다음과 같은 이유로 인해 배포 속도가 예상보다 느려질 수 있다.

1. 서비스 간 의존성 증가   

마이크로서비스가 서로 긴밀하게 연결되어 있을 경우, 특정 서비스의 변경이 다른 서비스에 영향을 미칠 가능성이 높아진다. 특히, 도메인 경계를 명확하게 나누지 못하면 여러 서비스 간 동시 배포가 필요해지고, 배포 전 조율이 복잡해졌다.

2. 데이터 마이그레이션 및 버전 관리의 어려움

개별 서비스의 데이터 스키마가 변경될 경우, 해당 데이터를 참조하는 모든 서비스에서 이를 반영해야 한다.

API 버전 관리 및 데이터 이중화(Migration + Shadow DB) 등의 기법을 적용하지 않으면, 배포 시 충돌이 발생할 가능성이 높았다.  

3. 장애 대응 복잡화
모놀리식 환경에서는 하나의 애플리케이션 내부에서 오류를 수정할 수 있지만, 제대로 MSA에서 고찰하지 않으면 오히려 특정 서비스 장애가 다른 서비스로 전파될 가능성이 크다. 서킷 브레이커(Circuit Breaker), 폴백(Fallback) 전략, 분산 트랜잭션 관리(Saga Pattern) 등이 적절히 적용되지 않으면 장애가 전체 시스템에 영향을 미칠 수 있다. 실제로 인지하지 못하고 있던 부분에서 문제가 발생하는 경우가 많았다. 이는 MSA 사용에 깊은 고민이 필요하다는 반증이었다.   

결론적으로, 이론적으로는 MSA가 빠른 배포를 가능하게 하지만, 실제로는 이러한 복잡성을 해결하지 않으면 오히려 배포 속도가 저하될 수 있었다.


3. 왜 MSA를 포기하는가?

MSA는 특정 조건에서는 효과적인 아키텍처지만, 모든 기업이나 모든 프로젝트에 적합한 것은 아니다. 특히, MSA를 유지하는 데 필요한 비용, 인력, 인프라 등의 현실적인 문제가 존재하며, 다음과 같은 이유로 MSA를 포기하는 기업도 늘어나고 있다. [ 우리의 이번 프로젝트도 같은 이유이다. ]

 

(1) 초기 개발 속도와 유지보수 비용의 불균형

  • 스타트업이나 소규모 프로젝트에서는 MSA보다 모놀로틱 아키텍처가 개발 속도 면에서 유리
  • 초기부터 MSA를 도입하면 개발 복잡도가 높아지고, 핵심 비즈니스 로직보다 아키텍처 관리에 더 많은 시간을 소비하게 됨
  • 시간이 지날수록 MSA 유지보수 비용이 증가하여 개발 속도가 저하됨

(2) MSA가 필요한 수준의 트래픽이 아님

  • MSA는 수백만 이상의 트랜잭션을 처리해야 하는 대규모 트래픽 환경에서 빛을 발함
  • 하지만, 트래픽이 적은 경우에는 분리된 서비스 간 통신 비용이 오히려 증가하여 성능이 저하될 수 있음
  • 즉, 트래픽 대비 과도한 아키텍처 분리가 오히려 시스템 성능을 떨어뜨릴 수 있다

(3) 대규모 시스템을 운영할 인프라와 인력이 부족

  • MSA를 제대로 운영하려면 DevOps, SRE, CI/CD 엔지니어, 클라우드 아키텍트 등의 전문 인력이 필요
  • 그러나, 소규모 조직이나 중견 기업에서는 이러한 인력을 충분히 확보하기 어렵고, 운영 비용도 감당하기 어려움

4. 결론: 언제 MSA를 도입해야 하는가?

⭕ MSA가 적합한 경우

  1. 고트래픽, 글로벌 서비스 운영 → 수백만 트랜잭션을 처리해야 하는 서비스 (예: Netflix, Amazon)
  2. 독립적으로 확장해야 하는 서비스 → 특정 기능(예: 결제, 추천 엔진 등)만 빠르게 확장해야 하는 경우
  3. 다양한 기술 스택을 활용해야 하는 경우 → 각 서비스별로 최적의 기술을 적용해야 할 필요성이 있는 경우
  4. 서비스 간 의존성을 최소화할 수 있는 경우 → 비즈니스 도메인이 명확히 구분되는 경우

❌ MSA를 피하는 것이 나은 경우

  1. 소규모 프로젝트나 스타트업 → 초기 개발 속도가 중요한 경우
  2. 서비스 간 결합도가 높은 경우 → 데이터 정합성을 유지해야 하고, 트랜잭션이 강하게 결합된 경우
  3. 운영 비용을 감당하기 어려운 경우 → DevOps, SRE, CI/CD 엔지니어 등의 인력을 확보하기 어려운 경우
  4. 개발 및 배포 속도가 중요한 경우 → 팀 규모가 작고 빠른 피드백 루프가 필요한 경우

결론적으로, MSA는 특정 규모 이상의 시스템에서는 효과적일 수 있지만, 기술적 부채, 운영 비용, 유지보수 복잡성 등의 현실적인 문제를 고려해야 한다. 모놀로틱 아키텍처를 적절히 활용하면서 필요할 때만 MSA로 전환하는 점진적인 접근이 가장 현실적인 선택지일 것이다.

백엔드에서 "관리자"와 "사장"은 어떻게 다를까?

서비스를 개발하다 보면, 관리자(Admin)와 사장(Owner 혹은 CEO)의 개념을 시스템 내부에서 어떻게 정의할지 고민하게 됩니다.
현실 세계에서는 이 둘의 차이가 명확하지만, 백엔드 시스템 구조에서는 어떻게 구분하고 구현하는 게 좋을까요?
이 글에서는 실제 백엔드 설계 관점에서 "관리자"와 "사장"의 차이점을 정리해봅니다.


1. 현실 세계에서의 관리자 vs 사장

구분 관리자(Admin) 사장(Owner/CEO)
역할 시스템 또는 조직 내 운영 담당 조직 전체 방향성과 의사결정 담당
권한 운영 관리, 유저 승인/삭제 등 최고 권한자, 관리자까지 제어 가능
대상 실무 중심 전략 중심, 전체 소유자

일반적으로 관리자(admin)는 시스템이나 서비스 내부를 운영하는 사람이고, 사장(owner)는 그 시스템을 소유하거나 최종 책임을 지는 사람입니다.


2. 백엔드 시스템에서의 구분

백엔드 시스템에서는 흔히 Role 기반 권한 제어 또는 Permission 기반 권한 제어를 사용합니다.
이 경우 “관리자”와 “사장”은 다음과 같이 구현할 수 있습니다.

Role 기반 구현 예시

{
  "username": "adminUser",
  "role": "admin"
}
{
  "username": "ceoUser",
  "role": "owner"
}

권한 미들웨어 예시 (Node.js)

function authorize(role) {
  return function (req, res, next) {
    if (req.user.role !== role) {
      return res.status(403).json({ message: "권한이 없습니다." });
    }
    next();
  };
}

이처럼 role 값을 기준으로 각 사용자의 접근 권한을 제한할 수 있습니다.
여기서 owner는 모든 권한을 포함한 최상위 계정이고, admin은 실무 운영 권한을 가지는 경우가 일반적입니다.


3. 시스템 설계 시 고려할 점

항목 관리자(Admin) 사장(Owner)
역할 범위 서비스 운영 및 유지관리 전체 시스템 제어 및 계정 관리
구현 방식 role: "admin" role: "owner" 또는 is_owner: true
권한 범위 제한적 (콘텐츠, 유저 등) 무제한 (관리자 추가/삭제까지 가능)
사용자 수 여러 명 존재 가능 보통 한 명 (혹은 매우 제한적)

4. 더 세밀한 권한이 필요할 때: Permission 기반

간단한 시스템은 Role만으로도 충분하지만, 서비스가 복잡해지면 세분화된 권한(Permissions)이 필요합니다.

{
  "username": "adminUser",
  "permissions": ["user:read", "post:edit"]
}
{
  "username": "ceoUser",
  "permissions": ["*"]
}

사장은 모든 권한(*)을 부여받는 구조로, 보다 유연한 설계가 가능합니다.


5. 결론

  • 관리자와 사장은 현실에서는 명확히 다르지만, 백엔드에서는 어떻게 권한 구조를 설계했는지에 따라 달라집니다.
  • 보통 사장은 최고 권한자(owner)로, 관리자(admin)는 실무 권한을 가진 계정으로 구현합니다.
  • 작은 서비스는 role 기반으로 충분하지만, 세밀한 권한이 필요한 경우 permissions 기반으로 확장하는 것이 좋습니다.

 

1. 문제 상황

마이크로서비스 아키텍처(MSA)에서는 각 서비스가 독립적으로 운영되기 때문에 데이터 정합성 문제가 발생할 수 있다. 기존 모놀로틱 환경에서는 하나의 트랜잭션 내에서 데이터 정합성을 보장할 수 있었지만, MSA 환경에서는 서비스 간 네트워크 통신 지연, 장애, 중복 요청, 부분 실패 등으로 인해 정합성을 유지하기 어려운 상황이 발생했다.

 

(1) 주요 데이터 정합성 문제

  • 동기 호출 시 서비스 장애 문제:
    • 한 서비스가 다른 서비스를 호출하는 도중 장애가 발생하면 데이터 불일치 가능성 증가
    • 예: 주문 서비스에서 결제 요청을 보냈지만, 결제 서비스 장애로 인해 반영되지 않은 경우
  • 비동기 이벤트 기반 처리 시 중복 및 유실 문제:
    • 이벤트 처리 중 중복 실행이 발생하거나, 네트워크 문제로 인해 메시지가 유실될 가능성
    • 예: 결제 완료 이벤트가 Kafka에서 중복 소비되는 경우

2. 해결책: Feign Client & Kafka 활용

이러한 문제를 해결하기 위해 Spring Cloud Feign Client(동기 호출)와 Kafka(비동기 메시징) 를 결합하여 데이터 정합성을 유지하는 전략을 사용했다.


3. Feign Client를 이용한 동기 호출 정합성 관리

Feign Client는 서비스 간 REST API 호출을 쉽게 할 수 있도록 지원하는 Spring Cloud의 라이브러리이다.

 

(1) Feign Client 적용

Spring Cloud Feign Client를 사용하여 마이크로서비스 간 통신을 간소화하고, 서킷 브레이커를 적용하여 장애 감지 및 복구를 수행했다.

Feign Client 설정

@FeignClient(name = "payment-service", fallback = PaymentFallback.class)
public interface PaymentClient {
    @PostMapping("/payments")
    PaymentResponse processPayment(@RequestBody PaymentRequest request);
}

서킷 브레이커 적용 (Resilience4j 사용)

@Retry(name = "paymentRetry", fallbackMethod = "fallbackPayment")
public PaymentResponse processPayment(PaymentRequest request) {
    return paymentClient.processPayment(request);
}

public PaymentResponse fallbackPayment(PaymentRequest request, Throwable throwable) {
    System.err.println("Payment failed Order ID: " + request.getOrderId());
    System.err.println("Error: " + throwable.getMessage());

    // 1. 실패한 요청을 Dead Letter Queue로 전송
    sendToDLQ(request, throwable);

    // 2. 관리자에게 알림 발송
    notifyAdmin(request, throwable);

    // 3. 장애 내역을 데이터베이스에 저장
    logPaymentFailure(request, throwable);

    return new PaymentResponse("FAILED", request.getOrderId());
}

 

(2) Feign Client를 이용한 데이터 정합성 보장 방법

  1. 서킷 브레이커 적용: 서비스 장애 발생 시 빠르게 감지하고, 대체 로직을 실행하여 데이터 불일치 방지
  2. 재시도(Retry) 메커니즘 도입: 일시적인 네트워크 장애 시 자동으로 재시도하여 요청 실패 방지
  3. Fallback 처리: 결제 요청 실패 시 주문 상태를 "결제 대기"로 변경하고, 사용자를 위한 별도 알림 전송

4. Kafka를 이용한 비동기 이벤트 기반 정합성 관리

Kafka는 이벤트 드리븐 방식으로 데이터 정합성을 유지하는 데 효과적이다. 서비스 간 동기 통신을 최소화하고, 장애 발생 시에도 데이터가 유실되지 않도록 이벤트 저장 및 재처리 메커니즘을 적용했다.

 

(1) Kafka 이벤트 발행

주문이 완료되면 Kafka를 통해 결제 이벤트를 발행한다.

@Component
public class OrderEventPublisher {
    private final KafkaTemplate<String, PaymentEvent> kafkaTemplate;

    public void publishPaymentEvent(PaymentEvent event) {
        kafkaTemplate.send("payment-topic", event);
    }
}

 

(2) Kafka 이벤트 소비 (결제 서비스)

    @KafkaListener(topics = "payment-topic", groupId = "payment-group")
    public void processPayment(PaymentEvent event, Acknowledgment acknowledgment) {
        try {
            paymentService.processPayment(event);
            acknowledgment.acknowledge();
        } catch (Exception e) {
            System.err.println("Payment failed event: " + event.getOrderId() + ". Sending to DLQ.");
            sendToDLQ(event);
        }
    }

    private void sendToDLQ(PaymentEvent event) {
        kafkaTemplate.send(new ProducerRecord<>("payment-dlq", event));
    }

 

(3) Kafka를 이용한 데이터 정합성 보장 방법

  1. 이벤트 저장 및 재처리:
    • Kafka는 메시지를 저장하므로, 서비스 장애 발생 시 이벤트를 다시 처리할 수 있음
    • 예: 결제 서비스가 다운되었을 경우, 복구 후 동일한 결제 요청을 다시 처리 가능
  2. Idempotency(멱등성) 보장:
    • 이벤트 소비 시 동일한 요청이 중복 실행되지 않도록 결제 요청 ID를 기준으로 중복 확인
    • 예: 동일한 orderId에 대해 중복 결제 요청이 실행되지 않도록 데이터베이스에서 체크
  3. Dead Letter Queue(DLQ) 활용:
    • 여러 번 재시도 후에도 실패한 이벤트를 별도의 큐(DLQ)에 저장하여 추후 처리
    • 예: 결제 실패 이벤트를 DLQ로 이동 후 운영팀이 수동 확인

5. 결론

  • Feign Client를 사용하여 서비스 간 동기 호출 시 서킷 브레이커, 재시도, Fallback을 적용하여 데이터 정합성을 유지
  • Kafka를 활용하여 이벤트 기반 아키텍처를 구성하고, 장애 발생 시에도 이벤트를 재처리할 수 있도록 보장
  • Idempotency 및 Dead Letter Queue(DLQ) 기법을 활용하여 중복 처리 및 데이터 유실 문제 해결

 

Elasticsearch 클러스터는 마스터 노드, 데이터 노드, 코디네이터 노드로 구성되며, 각 노드가 다운될 경우 시스템의 안정성과 가용성에 영향을 미칠 수 있다. 따라서 각 노드 유형별로 장애 발생 시 대응 방안을 마련해야 한다.


1. 마스터 노드 장애 복구 전략

(1) 마스터 노드의 역할

  • 클러스터의 헬스 체크, 노드 관리, 샤드 할당, 설정 변경 등의 중요한 역할을 수행
  • 마스터 노드가 장애를 일으키면 클러스터 상태를 업데이트하거나 새로운 노드를 추가할 수 없음

(2) 마스터 노드 장애 발생 시 증상

  • GET _cluster/health 요청 시 red 또는 yellow 상태
  • 클러스터 상태 변경이 불가능
  • 노드 추가 및 샤드 할당 불가

(3) 복구 방법

  1. 다른 마스터 노드가 있는지 확인
    • 정상적으로 선출된 새로운 마스터 노드가 있으면 자동 복구 진행됨
  2. GET _cat/master?v
  3. 마스터 노드가 1개뿐인 경우 클러스터가 중단됨
    • 최소 3개의 마스터 노드를 유지해야 함
    • 마스터 노드가 모두 다운된 경우 수동 복구 필요
  4. 새로운 마스터 노드 추가
    • 기존 마스터 노드가 복구 불가능할 경우 새로운 노드를 추가하고 elasticsearch.yml에서 마스터 노드로 설정
    node.master: true
    
  5. 클러스터 재시작 후 상태 확인
  6. GET _cluster/health
  7. 마스터 노드 선출이 안 될 경우 강제 복구
    • 강제로 클러스터를 재구성하여 노드를 재배치
  8. curl -XPOST "http://localhost:9200/_cluster/reroute?retry_failed=true"

예방 조치

  • 마스터 노드는 반드시 3개 이상 유지하여 선출이 가능하도록 구성
  • 마스터 전용 노드를 설정하여 데이터 노드와 분리
  • 고가용성을 위해 마스터 노드를 다른 물리 서버에 배포

2. 데이터 노드 장애 복구 전략

(1) 데이터 노드의 역할

  • 인덱스 데이터 저장 및 검색 요청 처리
  • 장애 발생 시 저장된 데이터가 유실될 가능성이 있음

(2) 데이터 노드 장애 발생 시 증상

  • 일부 데이터 조회 불가
  • 클러스터 헬스 체크 시 yellow 또는 red 상태
  • 샤드 불균형 발생

(3) 복구 방법

  1. 장애 노드 상태 확인
    • 노드가 다운되었는지 확인하고 문제 원인 파악 (디스크 공간 부족, 메모리 문제 등)
  2. GET _cat/nodes?v
  3. 샤드 재할당 확인
    • UNASSIGNED 상태의 샤드가 있으면 자동 복구되지 않았음을 의미
  4. GET _cat/shards?v
  5. 노드 재시작 후 샤드 복구 확인
    • 데이터 노드를 다시 시작한 후, 클러스터가 자동으로 샤드를 복구하는지 확인
    systemctl restart elasticsearch
    
  6. 수동 샤드 복구 실행 (필요 시)
  7. POST _cluster/reroute?retry_failed=true
  8. 샤드 강제 할당 (긴급 복구 필요 시)
    • 할당이 실패한 이유를 확인한 후 적절한 노드로 수동 할당
  9. POST _cluster/allocation/explain

예방 조치

  • 복제 샤드 설정(number_of_replicas: 1 이상)으로 장애 발생 시 자동 복구 가능하도록 설정
  • 디스크 사용량 모니터링 (GET _cat/allocation?v 명령어 활용)
  • 데이터 노드 장애 발생 시 ILM(인덱스 수명 주기 관리) 적용하여 오래된 데이터를 자동으로 Cold 노드로 이동

3. 코디네이터 노드 장애 복구 전략

(1) 코디네이터 노드의 역할

  • 검색 쿼리 및 집계 요청을 분산하여 성능 최적화
  • 장애 발생 시 데이터 노드의 부하가 증가할 수 있음

(2) 코디네이터 노드 장애 발생 시 증상

  • 검색 및 집계 쿼리 속도 저하
  • CPU 사용량 증가
  • 클러스터 전체의 응답 속도 저하

(3) 복구 방법

  1. 장애 노드 상태 확인
    • 코디네이터 노드가 다운되었는지 확인
  2. GET _cat/nodes?v
  3. 노드 재시작
    • 노드가 단순한 장애(메모리 부족, 네트워크 문제)라면 재시작으로 해결 가능
  4. systemctl restart elasticsearch
  5. 노드 추가 및 부하 분산
    • 코디네이터 노드가 과부하로 다운되었다면 새로운 코디네이터 노드 추가
    node.master: false
    node.data: false
    node.ingest: false
    
  6. 쿼리 로드 밸런싱 설정
    • 애플리케이션에서 Elasticsearch에 요청할 때 라운드 로빈 방식을 사용하여 요청을 여러 노드로 분산

예방 조치

  • 검색 요청이 많은 경우 코디네이터 노드를 2개 이상 운영
  • 로드 밸런서를 활용하여 요청 부하를 분산
  • 쿼리 최적화 적용 (필요한 필드만 검색, 애그리게이션 최소화)

4. 결론

  • 마스터 노드 장애 시: 3개 이상의 마스터 노드를 유지하여 자동 선출 가능하도록 구성
  • 데이터 노드 장애 시: 복제 샤드를 설정하고 ILM을 적용하여 자동 복구 가능하도록 운영
  • 코디네이터 노드 장애 시: 로드 밸런서를 활용하여 부하를 분산하고, 검색 요청이 많은 경우 추가적인 코디네이터 노드를 운영

ELK vs Loki: 로깅 시스템 선택

1. 문제 발생

기존에는 ELK(Elasticsearch, Logstash, Kibana) 스택을 사용하여 데이터 분석과 로깅을 관리하고 있었으나, MSA(Microservices Architecture) 도입을 고려하면서 대용량 서버 운영에 대한 새로운 요구사항이 생겼다. 이에 따라 분석과 로깅의 역활이 분리될 필요가 있었고 로깅은 스케일링이 용이하고 관리 비용이 적은 시스템으로 도입될 필요가 생겼다.

 

생각의 발달은 아래의 우아한 형제들의 기술 블로그를 토대로 발전시켰다.

 

따끈따끈한 전사 로그 시스템 전환기: ELK Stack에서 Loki로 전환한 이유 | 우아한형제들 기술블로그

안녕하세요. 클라우드모니터링플랫폼팀의 이연수입니다. 우아한형제들의 모니터링시스템 구축 및 관리, 운영을 하고 있습니다. 작년부터 올해 초까지 팀에서 전사 로그 시스템을 전환을 진행

techblog.woowahan.com

 

2. 문제 원인

  • ELK는 강력한 검색 기능을 제공하지만, 운영 비용이 높음
    • Elasticsearch의 샤드 관리가 복잡하고, 인덱스 저장 공간을 많이 차지함.
    • 대량의 로그를 저장할 경우 샤드 개수 증가로 인해 성능 튜닝이 필요함.
    • Logstash의 리소스 사용량이 높고, 수많은 로그 데이터를 처리하기 위해 별도의 클러스터링이 필요함.
  • Loki는 메타데이터 기반의 경량 로그 저장 시스템
    • 로그 데이터를 직접 인덱싱하지 않고, 레이블을 기반으로 저장.
    • 레이블 단위로 로그를 청크(Chunk) 단위로 압축하여 저장하므로 저장 공간을 절약할 수 있음.
    • 복잡한 샤드 관리가 필요 없으며, 확장성이 뛰어남.

 

3. 문제 해결책 수립

해결 방법 비교

비교 항목 ELK (Elasticsearch, Logstash, Kibana) Loki (Grafana Loki)
로그 저장 방식 전체 로그를 인덱싱하여 검색 가능 로그 내용을 색인화하지 않고, 레이블을 기반으로 저장
검색 성능 고급 검색 기능 제공 (Full-text Search, Aggregation 지원) 레이블 기반 필터링, Full-text Search 미지원
저장 공간 인덱싱된 데이터로 인해 저장 공간 요구량 높음 청크 단위 압축 저장으로 공간 절약
운영 및 확장성 샤드 관리, 리소스 최적화 필요 샤드 관리 불필요, 간단한 확장 가능
리소스 사용량 높은 CPU, 메모리 사용량 상대적으로 낮은 리소스 사용량
적용 사례 정밀한 검색 및 분석이 필요한 환경 MSA 및 대용량 로그 저장이 필요한 환경

 

4. 문제 해결: Loki 도입 결정

(1) MSA 환경에서의 확장성 고려

  • MSA 기반 서비스는 여러 개의 마이크로서비스에서 로그를 생성하며, 각 서비스의 로그를 독립적으로 관리하면서도 효율적인 검색이 필요하다.
  • Loki는 샤드와 같은 복잡한 관리가 필요 없고, 로그 저장 방식이 가볍기 때문에 대량의 서버를 운영하는 데 적합하다.

(2) 저장 공간 최적화

  • ELK는 모든 로그를 색인화하는 방식이기 때문에 저장 공간이 많이 필요하며, 특히 대량 로그 저장 시 운영 비용이 증가한다.
  • Loki는 로그 내용을 직접 색인화하지 않고, 레이블 기반으로만 색인하여 저장 공간을 절약할 수 있다.

(3) 인프라 운영 비용 절감

  • ELK는 검색 기능이 강력하지만, Logstash와 Elasticsearch의 리소스 사용량이 높아 운영 비용이 증가한다.
  • 반면, Loki는 가벼운 구조를 가지고 있어 운영 비용이 낮고, 확장성이 뛰어나다.

 

5. 결론

  • 기존 ELK는 강력한 검색 기능이 필요할 때 유용하지만, 저장 공간과 운영 비용이 많이 소모된다.
  • MSA 기반 대규모 로그 관리에서는 Loki가 더 적합하며, 샤드 관리 없이 확장성이 뛰어나고 운영이 간편하다.
  • Loki는 로그 데이터를 직접 색인하지 않으며, 청크 단위로 저장하여 저장 공간을 절약할 수 있다.
  • 결과적으로, ELK에서 Loki로 전환하여 MSA 환경에서 더욱 효율적인 로그 관리를 수행할 수 있다.

1. 문제 상황

현재 진행 중인 프로젝트는 모놀로틱(monolithic) 아키텍처를 사용하고 있지만, 이를 운영하면서 몇 가지 한계를 경험하게 되었다.

  • 코드베이스가 커지면서 유지보수 부담 증가
  • 기능 추가 및 변경 시 배포 부담 증가
  • 특정 기능만 확장하고 싶어도 전체 시스템을 스케일링해야 하는 비효율성
  • 장애 발생 시 서비스 전체가 영향을 받는 단일 장애점(SPOF, Single Point of Failure) 문제

이러한 문제를 해결하기 위해 마이크로서비스 아키텍처(MSA, Microservices Architecture) 도입을 고려했다. 다만, 현재 프로젝트는 작은 규모의 애플리케이션이기 때문에 즉각적인 MSA 전환보다는 개념 이해와 학습을 통한 대규모 시스템 설계의 가능성을 탐색하는 것이 목적이다.


2. 모놀로틱 아키텍처의 한계

모놀로틱 아키텍처는 개발 초기에는 단순하고 빠르게 개발할 수 있다는 장점이 있지만, 규모가 커질수록 다음과 같은 문제가 발생한다.

 

(1) 유지보수 및 개발 속도 저하

  • 코드베이스가 방대해지면서 코드 변경 및 충돌이 증가
  • 여러 팀이 같은 코드베이스에서 작업하면서 작업 분리가 어려움
  • 특정 기능을 수정해도 다른 부분에 영향을 미칠 가능성이 높음

(2) 배포 및 확장성 문제

  • 작은 변경 사항이 있어도 전체 시스템을 다시 빌드하고 배포해야 함
  • 특정 기능만 확장하려 해도 전체 애플리케이션을 스케일링해야 하는 비효율성
  • 대용량 트래픽이 발생할 경우 서비스 일부만 확장할 수 없는 구조

(3) 장애 발생 시 전체 시스템 영향

  • 한 모듈에서 장애가 발생하면 전체 애플리케이션에 영향을 미침
  • 단일 장애점(SPOF, Single Point of Failure) 문제로 인해 특정 서비스의 오류가 전체 시스템을 다운시킬 수 있음

(4) 기술 스택 변경 어려움

  • 새로운 기술을 적용하려면 전체 시스템을 변경해야 함
  • 특정 기능만 최신 기술로 변경하고 싶어도 전체 애플리케이션을 수정해야 함

이러한 문제로 인해, 대규모 애플리케이션에서는 MSA가 더욱 적합한 아키텍처로 고려된다.


3. MSA(마이크로서비스 아키텍처) 적용 이유

MSA는 애플리케이션을 여러 개의 독립적인 서비스로 분리하여 개발, 배포, 확장성을 최적화하는 아키텍처이다.

 

(1) MSA의 주요 개념

  • 서비스 분리: 하나의 애플리케이션을 여러 개의 독립적인 서비스로 구성
  • 독립적인 배포: 각 서비스는 개별적으로 배포 가능
  • 개별 확장성: 특정 서비스만 개별적으로 확장 가능
  • 다양한 기술 스택 사용 가능: 서비스별로 적절한 기술을 선택하여 적용 가능

(2) MSA의 장점

항목 설명
유지보수 용이 서비스가 분리되어 있어 변경이 용이함
배포 유연성 특정 서비스만 개별 배포 가능, 전체 시스템 재배포 불필요
확장성 향상 특정 기능만 개별적으로 확장 가능하여 리소스 활용 최적화
기술 스택 다양화 각 서비스별로 다른 기술 및 데이터베이스 사용 가능
장애 영향 최소화 특정 서비스 장애 발생 시 전체 시스템에 영향 없음

 

(3) MSA 도입 시 고려해야 할 점

하지만, MSA는 모든 프로젝트에 적합한 것은 아니다. 특히, 작은 프로젝트에서는 오히려 관리 부담이 증가할 수 있다.

  • 운영 복잡성 증가: 여러 개의 마이크로서비스를 관리해야 함
  • 분산 시스템의 문제: 네트워크 트래픽 증가, 데이터 일관성 유지 어려움
  • 배포 및 모니터링 도구 필요: 개별 서비스의 배포 및 장애 감지를 위한 추가 인프라 필요

따라서, 현재 프로젝트는 소규모 애플리케이션이므로 MSA를 바로 적용하기보다는, 모듈화된 설계를 먼저 고려하고, 향후 대규모 시스템 설계 및 학습 목적으로 MSA 개념을 연구하는 방향이 적절하다.


4. 적용 방안: 현재 프로젝트에 맞는 전략

현재 진행 중인 프로젝트는 작은 규모이므로, 완전한 MSA 도입이 아니라 모놀로틱을 개선하는 형태로 접근하는 것이 적절하다.

 

(1) 멀티 모듈 아키텍처 도입

  • 현재 프로젝트를 하나의 코드베이스로 유지하되, 기능별로 모듈을 분리하여 관리
  • 예) user-service, order-service, payment-service 등으로 모듈화
  • 이를 통해 유지보수성과 확장성을 확보하면서도 운영 복잡도를 최소화

(2) MSA 전환을 대비한 설계 원칙 적용

  • 서비스 간의 명확한 API 설계를 통해 MSA로 확장할 수 있도록 준비
  • 데이터베이스를 하나로 묶지 않고, 서비스별로 논리적인 데이터 분리를 고려
  • 개별 서비스의 독립성을 유지하면서도, 초기에는 모놀로틱 환경에서 개발

(3) 학습 및 연구 목적으로 MSA 개념 도입

  • Kubernetes(K8s), 서비스 디스커버리, API Gateway 등 MSA 관련 기술을 학습하고 테스트 환경에서 운영
  • 실제 운영 환경에서는 작은 프로젝트에 적합한 구조를 유지하며, 대규모 프로젝트 전환 시 MSA를 본격적으로 적용할 계획

5. 결론

  • 현재 프로젝트는 작은 규모이므로 MSA를 도입하기보다는 모놀로틱을 개선하는 형태로 운영하는 것이 적절하다.
  • 그러나, 향후 대규모 시스템을 구상하고 학습하는 목적에서 MSA 개념을 연구하고 설계 원칙을 일부 도입할 필요가 있다.
  • 멀티 모듈 아키텍처를 우선 적용하고, 점진적으로 MSA로 전환할 수 있도록 유연한 설계를 고려하는 것이 바람직하다.

1. 문제 발생

엘라스틱 서치는 한번 생성한 인덱스의 매핑(테이블 구조)을 변경할 수 없다.

Long ㅁ
string ㅁ

위와 같이 2개의 타입으로 인덱스를 만들었다면, long2개인 인덱스나, 1개의 타입이 추가된 인덱스로 만드려면 무조건 새로 만들어야한다는 문제점이 존재한다.

 

그럼 엘라스틱 서치의 확장성을 위해서 해야하는 전략은 무엇이 있을까?

= 사실 처음부터 제대로 필요한 데이터만 미리 저장하고 인덱스를 수정할 일이 없으면 베스트이긴하다.

하지만 그렇지 못하면, 방법은 크게 5가지 존재한다.

 

2. 문제 원인

  • 엘라스틱 서치는 매핑이 고정되기 때문에 인덱스를 생성한 후에는 필드 타입을 변경할 수 없음.
  • 동적 매핑(Dynamic Mapping)을 사용할 수 있지만, 예상치 못한 데이터 타입 오류가 발생할 가능성이 있음.
  • **필드 개수 제한(1,000개)**이 있기 때문에, 동적 매핑을 사용할 경우 불필요한 필드가 쌓여 인덱스가 비효율적으로 커질 수 있음.
  • 실수로 잘못된 타입을 지정하면 전체 인덱스를 새로 만들어야 하는 부담이 생김.

 

3. 문제 해결책 수립

1. 동적 매핑(Dynamic Mapping)

  • 동적 매핑을 사용하면 새로운 필드가 자동으로 추가되고, 기본 매핑 유형이 설정된다.
  • 하지만 이 방법은 예상치 못한 매핑 오류가 발생할 수 있어 주의가 필요하다.

2. 별도 인덱스 생성 및 데이터 마이그레이션

  • 기존 인덱스를 유지한 상태에서 새로운 매핑을 가진 인덱스를 생성하고, 데이터를 점진적으로 이전하는 방법이다.
  • Zero-downtime 마이그레이션을 지원합니다.
  • 예: index_v1 -> index_v2 로 새 인덱스를 생성하고 데이터 이전 후 기존 인덱스를 삭제한다.

3. 인덱스 에일리어스(Index Alias) 사용

  • 인덱스 에일리어스를 사용하여 클라이언트 측에서 인덱스 이름을 변경하지 않고 새로운 인덱스로 리다이렉션할 수 있다.
  • 예: my_index_alias가 index_v1을 가리키다가, 이후 index_v2로 변경 가능하다.

4. 멀티 인덱스 전략

  • 여러 인덱스를 사용하는 방식으로, 시간 기반 인덱싱(예: 일별/월별)을 통해 확장성을 개선할 수 있다.
  • 오래된 인덱스를 분리 관리하거나, 필요 시 새 인덱스를 추가해도 전체 매핑 구조에 영향을 덜 받는다.

5. 스키마리스(No Schema) 접근

  • 데이터를 다소 유연하게 처리하는 방식으로, JSON 기반 필드를 최대한 활용한다.
  • 하지만 검색 성능과 정확도에 영향이 있을 수 있다.

 

4. 문제 해결

하지만 필자는 이 중 3개의 전략을 선택하게 되었다.

  1. 별도 인덱스 생성 및 데이터 마이그레이션
  2. 인덱스 Alias 사용
  3. 멀티 인덱스 전략

기술 선택의 이유는 실제로 동적 매핑은 비교적 간단하게, 인덱스 템플릿[인덱스 청사진]에서 지정할 수 있지만, 내가 원하지 않는 타입의 인덱스를 저장한다거나.

POST my_index/_doc/1
{
  "price": 10000
}

POST my_index/_doc/2
{
  "price": "10000원"
}

둘은 엄연히 타입이 다르다...

맨 처음 인덱스를 만들 당시 개발자가 실수로 다른 형태로 저장할 경우 인덱스 수정도 안되니 다시 만들어야한다.

실제로 바쁜 상황에서는 가끔 정신줄 놓고 string으로 구현할 걸 숫자가 보인다고 long으로 만드는 경우도 있었다.

거기에 별로 발생할 일은 없지만, 엘라스틱 서치 인덱스 내에 저장할 수 있는 필드의 수는 1000개가 한계인데, 동적 매핑의 경우 이 위험도 발생할 수 있다.

 

설령 위처럼 큰 에러가 발생하지 않더라도, 잘못된 타입을 매핑하면 결국 인덱싱 속도가 느려지고 클러스터 리소스 사용량이 증가한다.

 

마지막 방식인 스키마리스는 이 동적 매핑의 응용으로 사전에 데이터 구조(매핑)을 정의하지 않고 json 기반 동적 매핑을 활용하여 데이터를 유연하게 저장하는 방식을 사용한다.

자연스럽게 남은 선택지는

  1. 별도 인덱스 생성 및 데이터 마이그레이션
  2. 인덱스 Alias 사용
  3. 멀티 인덱스 전략

로 좁혀지게 되었다.

 

 

그러면 이중 1개만 사용해도 되는데 굳이 왜 3개를 다 사용하게 되었는가?

 

사실 1,2번은 세트이다. alias는 간단히 말하면 명찰이다.

예를 들어 노드 a1,a2,a3가 있다 이들은 모두 a라는 명찰사용하고 있다고 생각해보자, 그럼 손님은 a1,2,3를 같은 a라는 직원으로 여기게 된다.

 

손님 = 클라이언트

a = 노드의 별명

a1,2,3 = 실제 노드이름

 

클라이언트인 우리(스프링 프로젝트)의 입장에서는 결국 a에게 데이터를 달라고 하면되고, a1,a2,a3에 있는 데이터를 a라는 이름으로 받아올 수 있게된다.

 

그럼 메인 의사 결정인, 확장성의 이야기로 돌아가보자, alias로 2개의 노드를 1개의 대상으로 볼 수 있다면,

a1 = a

string a
long b

위와 같은 상황에서, a에 새로 필요한 인덱스 형태인 a2를 추가해보자

a2, a1 = a

string a
long b
string c

클라이언트 입장에서는 a에 a2가 추가되었어도 결국은 a로 보이고 a1이 없어져도 결국 a로만 보인다.

즉, 필요한 형태인 a2를 만들고 a1의 내용을 복사한 후 a2을 지우면, 클라이언트는 실상 코드 변경없이도 노드 연결을 유지할 수 있다.

 

이렇게

  1. 별도 인덱스 생성 및 데이터 마이그레이션
  2. 인덱스 Alias 사용

를 선택하게 되었다.

 

그럼 3번인 멀티 인덱스 전략은 왜 나왔는가, 위는 데이터 수정이 필요할 경우의 확장성이라면 아래는 말 그대로 데이터를 효율적으로 사용하기 위한 확장성이라 보면된다.

 

멀티 인덱스는 예시로 이야기하면, 시간 기반 인덱싱 처럼(일별, 월별로 데이터를 나눠서 저장) 데이터를 시간, 특징을 기준으로 나눠 저장하면 이미 분업이 되어 있으므로 특정 데이터 예를 들면, 1달간의 데이터만 요구된다면, 전체 다 저장된 인덱스에서 접근하기 보단 근 1달치만 저장된 인덱스를 가져오면 더 편하다.

 

인덱스 관리에도 유리하고 새 인덱스를 추가해도 전체 매핑 구조에 영향이 덜 미친다.

+ Recent posts