cs 면접 준비를 하며 공부했던 내용을 정리한 것입니다.
설명이 미흡할 수 있고, 순서가 뒤죽박죽인 점, 중복 개념이 있을 수 있는 점 양해 부탁드립니다🙂
✅ JAVA의 OOP(객체지향 프로그래밍) 원칙은 무엇인가요?
OOP(Object-Oriented Programming)의 4대 원칙:
- 캡슐화 (Encapsulation) → 데이터 보호 및 정보 은닉 (getter/setter 활용)
- 상속 (Inheritance) → 코드 재사용성 증가 (extends, super 활용)
- 다형성 (Polymorphism) → 하나의 인터페이스로 다양한 구현 가능 (오버로딩/오버라이딩)
- 추상화 (Abstraction) → 중요한 정보만 노출, 불필요한 세부 사항 숨김 (interface, abstract class 활용)
✚
1. 캡슐화 ➡️ 객체가 맡은 역할 수행을 위한 하나의 목적을 위해 <데이터 + 기능> 묶는 것 / 외부에서 직접 접근하지 못하도록 제한 / 즉, 데이터 무결성 유지
2. 상속 ➡️ 부모 클래스 기능 -> 자식 클래스도 사용 ⭕️ / 유지보수 용이 / 재사용성 ⬆️
3. 다형성 ➡️ 하나의 객체가 여러가지 타입 가지는 것 / 하나의 기능 다양하게 사용⭕️
4. 추상화 ➡️ 객체들의 공통된 특징 (데이터 및 기능) 뽑아내는 것 / 중요한 속성 드러내고, 불필요한 내용 숨김
✅ JAVA의 객체지향 설계 원칙은 무엇인가요?
SOLID 원칙:
- SRP(Single Responsibility Principle): 단일 책임 원칙
- 모든 클래스(객체)는 단 하나의 책임만 가져야한다.
- 즉, 하나의 클래스는 하나의 기능 담당하여 하나의 책임만 가지도록 클래스를 여러개 따로 설계하라는 것
- OCP(Open Closed Priciple): 개방 폐쇄 원칙
- 확장에는 개방적이며, 수정에는 폐쇄적이야 한다.
- 기능 추가 요청 시 클래스를 확장을 통해 손쉽게 구현하며, 확장에 따른 클래스 수정은 최소화한다.
- 즉, 다형성과 확장 가능하게 함
- LSP(Listov Substitution Priciple): 리스코프 치환 원칙
- 서브 타입은 언제나 기반(부모) 타입으로 교체할 수 있다.
- 다형성의 특징을 이용하기 위해 상위 클래스 타입으로 객체를 선언하여 하위 클래스의 인스턴스를 받으면, 업캐스팅된 상태에서 부모의 메서드를 사용해도 동작이 의도대로 흘러가야 하는 것
- 즉, 다형성 원리를 이용하기 위한 원칙 개념
- ISP(Interface Segregation Principle): 인터페이스 분리 원칙
- 이용하지 않는 메소드에 의존하지 않아야 한다. (= 인터페이스 단일 책임)
- 인터페이스를 사용하는 클라이언트를 기준으로 분리함으로써, 클라이언트의 목적과 용도에 적합한 인터페이스 만을 제공하는 것
- DIP(Dependency Inversion Principle): 의존 역전 원칙
- 상위 클래스는 하위 클래스에 의존하지 않는다.
- 의존 관계를 맺을 때 변화하기 쉬운 것 또는 자주 변화하는 것보다는, 변화하기 어려운 것 거의 변화가 없는 것에 의존하라는 것
- 즉, 구현 클래스에 의존하지 말고, 인터페이스에 의존
✅ Java에서 final 키워드의 역할은?
- 변수에 사용 → 값 변경 불가 (final int x = 10;)
- 메서드에 사용 → 오버라이딩 불가 (final void method() {})
- 클래스에 사용 → 상속 불가 (final class MyClass {})
✅ Spring MVC 구조와 동작 방식에 대해 설명해주세요.
Spring MVC 구조:
- DispatcherServlet → 요청을 받아 컨트롤러로 전달
- Controller → 비즈니스 로직 처리 후 서비스 호출
- Service → 실제 로직을 처리 후 DAO에 전달
- DAO (Repository) → 데이터베이스와의 연결
- View (Thymeleaf, JSP 등) → 사용자에게 결과 반환
✅ Spring Boot에서 DI(의존성 주입)와 IoC(제어의 역전)의 개념을 설명해주세요.
- DI (Dependency Injection) → 객체 생성을 개발자가 직접 하지 않고, Spring이 자동으로 관리
- IoC (Inversion of Control) → 객체의 생성과 생명주기를 컨테이너(Spring)가 관리
✅ JPA와 MyBatis의 차이점은?
✅ RESTful API란 무엇이며, 좋은 API 설계 원칙은?
- RESTful API → 자원을 URL로 표현하고, HTTP 메서드(GET, POST, PUT, DELETE)를 활용하는 API 설계 방식
- 좋은 API 설계 원칙 6가지:
- URL 구조 설계에 맞게 동사 사용 ❌ / 리소스 나타내는 명사 ⭕️
- 리소스에 대한 행위는 HTTP 메서드로 올바르게 표현
- 슬래시 구분자(/)는 계층 관계를 나타내는데 사용
- URI 마지막 문자로 슬래시(/)를 포함 ❌
- 하이픈(-)은 URI 가독성을 높이는데 사용
- 언더바(_)는 URI에 사용 ❌
- URI 경로에는 소문자를 사용
- 파일 확장자는 URI에 포함 ❌
✚ REST 특징
- 일관된 인터페이스 규칙
- 클라이언트 - 서버 분리: REST 서버는 API 제공 / 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보) 등을 직접 관리하는 구조로 각각의 역할을 확실하게 구분 / 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로 간 의존성 ⬇️
- 무상태성 유지 : 이전 정보 저장 ❌ / 매 요청마다 필요 정보 포함 / ex) JWT 인증을 위에 헤더에 인증 토큰 ⭕️
- 캐싱 가능하게 설계
- 계층화된 시스템 구조: 다중 계층 구성 ⭕️ / 보안, 로드 밸런싱, 암호화 계층 추가해 구조 상의 유연성 ⭕️ / PROXY, 게이트웨이 같은 네트워크 기반의 중간 매체 사용 ⭕️
- Self-descriptiveness : REST API 메시지만 보고도 이를 쉽게 이해할 수 있는 자체 표현 구조
✚ REST API
: HTTP 메소드를 사용해서 자원에 대한 CRUD 오퍼레이션 적용하는 것을 의미
✅ JAVA의 HashMap과 ConcurrentHashMap의 차이는 무엇인가요?
- 단일 스레드 환경 ➡️ HashMap 사용
- 멀티스레드 환경 (웹 서버, 캐싱 등) ➡️ ConcurrentHashMap 사용
✅ String과 StringBuilder, StringBuffer의 차이점은?
- 문자열 변경이 적은 경우 ➡️ String 사용
- 성능이 중요한 경우 (단일 스레드) ➡️ StringBuilder 사용
- 멀티스레드 환경 ➡️ StringBuffer 사용
✚
- String : 한 번 값이 할당 -> 공간 변하지 ❌ -> 불변객체
- StringBuffer: 값 변경 ⭕️ / 동기화 지원 ⭕️ -> 멀티스레드 환경에서 사용
- StringBuilder: 동기화 지원❌ -> 싱글 스레드 환경에서 사용
⊕ 불변객체
- 재할당 가능
- 한 번 할당 -> 내부 데이터 변경 ❌
- 문자열 값 바꾸는 것 ❌ -> 보안 유리
- 동기화 고려 ❌
✅ Spring에서 Bean이란 무엇이며, 싱글톤 패턴과의 관계는?
- 스프링 컨테이너가 관리하는 객체
- @Component, @Service, @Repository 등을 사용하면 자동으로 Bean으로 등록됨
🔹 싱글톤 패턴과의 관계
- Spring의 기본 Bean 스코프는 싱글톤(Singleton)임
- 즉, 스프링 컨테이너가 한 개의 인스턴스를 생성하고, 여러 곳에서 재사용함
-------- 데이터베이스 관련 ---------
✅ MySQL과 MariaDB의 차이는?
- MariaDB는 MySQL의 오픈소스 대체 버전
- MySQL은 Oracle이 관리, MariaDB는 커뮤니티 중심
- MariaDB가 성능 면에서 일부 개선됨
✅ 트랜잭션과 ACID 원칙이 무엇인가요?
- 트랜잭션(Transaction): 데이터의 일관성을 보장하기 위한 작업 단위
- ACID 원칙:
- Atomicity (원자성) ➡️ 트랜잭션이 모두 완전히 실행되거나, 전혀 수행되지 않음.
- Consistency (일관성) ➡️ 데이터베이스가 일관된 상태 유지 / 트랜잭션 수행 전과 후가 같음.
- Isolation (고립성) ➡️ 동시 실행 시 다른 트랜잭션에 영향을 주지 않음.
- Durability (지속성) ➡️ 트랜잭션이 성공할 시, 영구적으로 반영됨.
✅ Index란? 어떻게 작동하며, 언제 사용해야 하나요?
- Index → 검색 속도를 향상시키는 데이터베이스 구조
- 사용 시점: WHERE, JOIN, ORDER BY가 자주 사용될 때
- 단점: 인덱스가 많아지면 INSERT/UPDATE 속도 저하
📌 즉, 자주 조회되는 데이터 & Join 연산 많은 테이블 & 검색 성능 높이고 싶은 컬럼에 적용
✅ JOIN과 UNION의 차이점은?
JOIN은 두 개 이상의 테이블을 연결할 때 사용 / UNION은 같은 컬럼 구조의 데이터를 결합할 때 사용
성능 면에서는 JOIN이 일반적으로 더 효율적이며, UNION은 중복 제거를 위해 추가 연산이 필요할 수 있어 성능이 저하될 수 있음.
✅ 정규화는 무엇이며, 장점과 단점은?
🔹 정규화 (Normalization)란?
- 데이터베이스 설계에서 데이터 중복을 최소화하고, 일관성을 유지하기 위한 과정
- 데이터를 작은 논리적 단위로 분리하여 데이터 무결성을 보장
🔹 정규화의 단계 (1NF → 2NF → 3NF → BCNF)
- 제1정규형(1NF) → 중복된 열을 제거, 모든 컬럼이 원자값(Atomic Value)만 가지도록 함
- 제2정규형(2NF) → 부분 함수 종속 제거 (기본 키가 아닌 컬럼은 기본 키 전체에 종속)
- 제3정규형(3NF) → 이행적 함수 종속 제거 (A → B, B → C일 때 A → C 관계 제거)
- BCNF → 모든 결정자가 후보 키가 되도록 보장
🔹 정규화의 장점
⭕️ 데이터 중복 감소 → 저장 공간 절약
⭕️ 데이터 무결성 보장 → 데이터 변경 시 일관성을 유지
⭕️ 데이터 삽입/삭제 이상(Anomaly) 방지
🔹 정규화의 단점
❌ JOIN 연산 증가 → 테이블이 세분화되면서 조인 성능 저하 가능
❌ 복잡성 증가 → 설계와 쿼리가 복잡해질 수 있음
✅ JAVA: 객체지향 프로그래밍 언어
특징
- JVM(자바 가상 머신) 위에서 동작하기 때문에 운영체제 독립적
- 가비지 콜렉터를 통한 메모리 관리 ⭕️
- 멀티스레드 지원
- 상속, 추상화, 캡슐화, 다형성 특징 ⭕️
✚
- 가비지 컬렉션 : 힙 메모리 관리를 위해 참조되고 있지 않은 객체들을 메모리에서 삭제하는 것
(힙 영역: 객체 저장 / 스택 영역: 이를 가리키는 주소값 저장)
=> 힙 영역에서 자신들 가르키는 주소값이 없으면 참조하지 않은 것으로 판단 => 삭제ㄷ
✅ 생성자: 클래스와 같은 이름의 메소드로 객체가 생성도리 때 호출되는 메소드
- static
: 클래스가 로딩될 때 메모리 공간 할당 ⭕️ -> 처음 설정된 메모리 공간이 변하지 ❌ -> 인스턴스 생성없이 바로 사용 ⭕️ -> 공통으로 사용되는 데이터 관리할 때 사용함 - final
: 한 번 초기화되면 그 이후 변경 ❌ => 한 번만 할당하고 싶을 때 사용함
✅ 멀티 프로세스와 멀티 스레드 차이점
- 멀티 프로세스
📍장점: 하나의 프로세스가 죽어도 다른 프로세스에 영향 끼치지 ❌ (리소스 공유)
📍단점: 멀티 스레드보다 많은 메모리 공간과 시간 차지 ⭕️ - 멀티 스레드
📍장점: 멀티 프로세스보다 적은 공간 및 시간 차지 ⭕️
📍단점: 교착 상태에 빠지거나 동기화의 문제 ⭕️
✅ 교착상태 (데드락) : 하나 또는 그 이상의 프로세스나 스레드가 서로 자원을 기다리면서 무한히 기다리게 되는 상태
4가지 필요조건
- 상호배제 : 한 자원에 대한 여러 프로세스가 동시 접근 ❌
- 점유와 대기: 하나의 자원을 소유한 상태에서 다른 자원에 대한 접근 권한을 요구하는 것
- 비선점: 다른 프로세스에서 자원을 사용하는 동안 자원을 강제로 가져올 수 ❌
- 환형대기: 각 프로세스가 다른 프로세스가 요구하는 자원 가지고 있는 상태
해결법
- 예방
- 회피
- 탐지
- 복구 : 프로세스 중지, 자원 선점 하는 것
✚ 기아상태 : 영원히 자원 할당 ❌
해결 : 우선순위 변경 또는 큐 활용
✅ 동기화와 비동기화 차이
- 동기화
: 하나의 자원을 여러 데스크가 사용하려 할 때, 한 시점에서 하나의 테스크만이 사용될 수 있게 하는 것.
(작업 -> 순차적으로 진행 ⭕️ / 다음 작업 -> 이전 작업의 완료를 기다림) - 비동기화
: 한 작업이 시작되면 다른 작업이 완료되지 않아도 기다리지 않고 다음 작업 진행
ex) UI 이벤트 처리, 파일 다운
✅ 오버로딩과 오버라이딩 차이
- 오버로딩
: 같은 클래스 내에서 메소드 이름은 같지만, 매개변수의 개수나 데이터 형식을 다르게 정의하는 것. - 오버라이딩
: 부모 클래스 메소드가 자식 클래스에서 재정의 되는 것 (-> 매개변수 개수 & 데이터 형식 같아야 함)
✅ DAO와 DTO 차이
- DAO
: DB의 데이터에 접근하기 위한 객체 / DB에 접근하기 위한 로직과 비즈니스 로직 분리하기 위해 사용 ⭕️ - DTO
: 각 계층간의 데이터 교환하기 위한 JAVA Bean을 말함 / 프로젝트 시 엔터티에서 필요한 데이터만 추출하기 위해 사용 ⭕️
✅ 접근제한자
: 변수 또는 메소드의 접근 범위 설정을 하기 위함
- Public : 제한 ❌
- Private: 같은 클래스 내 허용⭕️
- Protected: 같은 패지키 내 허용 ⭕️ / 다른 패키지 자손 클래스에서 접근 ⭕️
- default: 같은 패키지 내에서만 허용 ⭕️
✅ 값에 의한 호출과 참조에 의한 호출 차이
- 값에 의한 호출
: 인자로 받은 값 복사하여 처리
📍장점: 복사하여 처리 -> 원본 값 변경 ❌ -> 안전
📍단점: 복사 -> 메모리 사용량 ⬆️ - 참조에 의한 호출
: 인자로 값은 값의 주소 참조해서 전달
📍장점: 복사 ❌ -> 직접 참조 -> 빠름
📍단점: 직접 참조 -> 원본 값 영향 ⭕️
✅ Error과 Exception 차이
- Error
: 실행 중 일어날 수 있는 치명적 오류로 발생 -> 비정상적 종료 ⭕️ - Exception
: Error 보다 경미한 오류 / try - catch를 이용해 비정상적 종료 막을 수 있음 -> 비정상적 종료 ❌
✅ RuntimeException과 Exception 차이
- RuntimeException
: 예외 처리 ❌ / 프로그래머 실수 - Exception
: 반드시 예외 처리 ⭕️ / 외부 영향
✅ throw와 throws 차이
- throw
: 강제로 예외 발생 / 개발자 판단으로 처리 ⭕️ / 상위 블럭이나 catch문으로 예외 던짐 - throws
: 자신 호출하는 메소드에 예의 처리 책임 떠넘기는 것 / 상위메서드로 예외를 던짐
✅ 추상클래스와 인터페이스 (➡️ 추상적인 설계 정의하는 데 사용)
- 추상클래스
: 일부 메서드 구현되어 있고, 일부는 추상 메서드 / 생성자 ⭕️ / 단일 상속만 ⭕️
is-a 관계일 때 사용 / 주로 공통된 기능 제공하는 부모 클래스 역할
💡공통 기능 정의 & 상속 통해 재사용 할 때 사용 - 인터페이스
: 기능을 정의하는 추상적 개념 / 구현된 메서드 포함 ❌ / 다중 구현 ⭕️ (= can-do 관계)
변수 public, static, final 상수만 선언 ⭕️
💡다양한 클래스에서 동일한 기능을 구현해야 할 때 사용
✅ MVC 패턴
- Model : 동작 수행 ex) @Service, @Repository(db table)
- View : 모델로부터 값 가져와 사용자에게 보여줌
- Controller: 사용자 요청에 맞는 데이터를 모델에 요청, 데이터를 뷰에 반영 ➡️ 어떻게 모델이 처리할지 정의
📍장점 : 유연 & 확장 쉬움 / 동시 다발적 개발 가능 ⭕️
📍단점 : 모델과 뷰 사이 의존성 ⬆️ / 설계 단계에 클래스 수 ⬆️
✅ JSP (Java Server Pages)
: HTML 내부에 자바 코드를 삽입하여 동적 웹 페이지를 생성하는 웹애플리케이션 도구
- JSP 가 실행되면 자바 서블릿(Servlet) 으로 변환되며 웹 어플리케이션 서버에서 동작되면서 필요한 기능을 수행하고 그렇게 생성된 데이터를 웹페이지와 함께 클라이언트로 응답한다.
- JSP
: HTML 내부에 JAVA 소스코드가 들어감으로 인해 HTML 코드를 작성하기 간편 ⭕️ - 서블릿
: HTML 코드가 있어서 읽고 쓰기가 굉장히 불편하므로 작업 효율성 ⬇️
- JSP
✅ final 변수, 메서드, 클래스 차이
- final 변수 : 값 변경없는 상수 / 한 번 초기화되면 변경 ❌
- final 메서드 : 오버라이딩 불가능한 메서드 (자식 클래스에서 변경 ❌)
- final 클래스 : 상속할 수 없는 클래스 ( 자식 클래스를 만들 수 ❌)
✚ 오버라이딩
: 부모 클래스 메서드 자식 클래스에서 재정의 ⭕️ / 매개변수 개수 & 데이터 형식 같아야 함
✅ Stack과 Heap 비교
- 자바에서 메모리는 크게 Stack(정적 메모리)과 Heap(동적 메모리) 영역으로 나뉨
- 다른 방식으로 데이터 저장하고 관리함
- Stack
- LIFO (Last In First Out)
- 메모리 높은 주소 ➡️ 낮은 주소 방향으로 할당
- 지역 변수 & 함수 호출 정보(메서드 실행 정보) 저장
- 메서드 종료 시 자동 해제 ( = 할당 해제 할 필요 ❌)
- 빠른 접근 속도 ( = 빠른 액세스 = 할당 & 해제 빠름)
- 메모리 크기 제한 ⭕️
- Heap
- 동적으로 객체 생성
- 메모리 낮은 주소 ➡️ 높은 주소 방향으로 할당
- 객체 & 인스턴스 변수 저장
- 전역변수 다룸
- GC(가비지 콜렉터): 더이상 사용되지 않는 객체 탐색하여 자동으로 메모리 정리하는 기능
- 프로그램 종료까지 유지 -> 자동으로 해제 되지 않음 -> 사용자가 메모리 관리 해야 함 (변수 할당 & 해제 책임 ⭕️)
- 상대적으로 접근 속도 느림 ( 할당, 해제 느림)
- 운영체제마다 메모리 관리다 달라서 어려움
✚ Stack [LIFO] ↔️ Queue [FIFO]
-------------------------------------
장점 / 단점
✅ List, Set, Map 비교
- List : 순서있는 데이터 저장 / 중복 허용 ⭕️
- Set : 중복 허용 ❌ / 순서 ❌
- Map : 키 - 값 쌍으로 저장 / 키 중복 ❌
✅ ArrayList, LinkedList 비교
- ArrayList : 동적 배열 기반 리스트
- 검색속도 ⬆️ (인덱스 사용) / 중간 삽입 & 삭제 시 성능 저하 발생 (요소들을 이동시켜야 하므로)
💡데이터 접근 빈번 & 삽입, 삭제가 상대적으로 적은 경우 적합
- 검색속도 ⬆️ (인덱스 사용) / 중간 삽입 & 삭제 시 성능 저하 발생 (요소들을 이동시켜야 하므로)
- LinkedList : 이중 연결 리스트 기반 리스트
- 요소가 이전 요소 가리키는 포인터 포함 / 중간 삽입 & 삭제 빠름 (링크만 조정하면 됨) / 검색 속도 ⬇️ (링크를 따라가야 하므로)
💡데이터 삽입, 삭제 빈번 & 데이터 순서가 자주 변경되는 경우 적합
- 요소가 이전 요소 가리키는 포인터 포함 / 중간 삽입 & 삭제 빠름 (링크만 조정하면 됨) / 검색 속도 ⬇️ (링크를 따라가야 하므로)