라이브러리 vs 프레임워크
- 라이브러리
- 공통으로 사용될 수 있는 특정한 기능들을 모듈화한 것을 의미
- 폴더명, 파일명 등에 대한 규칙이 없고 프레임워크에 비해 자유로움
- 프레임 워크
- 공통으로 사용될 수 있는 특정한 기능들을 모듈화한 것을 의미
- 폴더명, 파일명 등에 대한 규칙이 있으며 라이브러리에 비해 좀 더 엄격
- 다른 곳으로 이동할 때 ‘도구‘인 비행기를 타고 이동하지만 ‘비행기‘가 컨트롤하고 나는 가만히 앉아 있어야 함. 프레임워크는 이와 비슷함
디자인 패턴
디자인 패턴이란 프로그램을 설계할 때 발생했던 문제점들을 객체 간의 상호 관계 등을 이용하여 해결할 수 있도록 하나의 ‘규약‘ 형태로 만들어 놓은 것
- 싱글톤 패턴
- 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴
- 하나의 클래스를 기반으로 여러 개의 개별적인 인스턴스를 만들 수 있지만, 그렇게 하지 않고 하나의 클래스를 기반으로 단 하나의 인스턴스를 만들어 이를 기반으로 로직을 만드는데 쓰임
- 장점 : 하나의 인스턴스를 만들어 놓고 해당 인스턴스를 다른 모듈들이 공유하며 사용하기 때문에 인스턴스를 생성할 때 드는 비용이 줄어듬
- 단점
- 의존성이 높아짐(의존성이란 종속성이라고도 하며 A가 B에 의존성이 있다는 것은 B의 변경 사항에 대해 A 또한 변해야 된다는 것을 의미)
- TDD할때 단위 테스트를 주로 하는데, 단위 테스트는 테스트가 서로 독립적이어야 하며 테스트를 어떤 순서로든 실행할 수 있어야 하는데 걸림돌이 됨
- 모듈 간의 결합을 강하게 만들 수 있음
- 의존성 주입
- 의존성 주입자가 의존성을 ‘직접‘줌으로써 메인 모듈이 ‘간접‘적으로 의존성을 주입하는 방식
- 장점
- 유연성 향상: 코드 변경 없이 구성 요소를 쉽게 교체할 수 있음
- 재사용성 및 유지보수성: 객체 간 의존성을 분리하여 코드 재사용이 쉬움
- 테스트 용이성: Mock 객체 등을 이용한 단위 테스트가 수월해짐
- 단점
- 복잡성 증가: 초기에 의존성 설정을 위한 코드가 필요하고, 구조가 단순하지 않을 수 있음
- 추적의 어려움: 실제 동작 방식이 코드 내부에 명시되지 않아 흐름을 파악하기 어려울 수 있음
- 의존성 주입 원칙
- 상위 모듈은 하위 모듈에서 어떻나 것도 가져오지 않아야 함
- 둘 다 추상화에 의존해야 함
- 추상화는 세부 사항에 의존하지 말아야 함
class Singleton{
private static class singleInstanceHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return singleInstanceHolder.INSTANCE;
}
}
public class HellowWorld {
public static void main(String[] args) {
Singleton a = SingleTon.getInstance();
Singleton b = SingleTon.getInstance();
System.out.println(a.hashCode());
System.out.println(b.hashCode());
if (a == b) {
System.out.println(true);
}
}
}
상속 vs 구현
- 상속(extends) : 자식 클래스가 부모 클래스의 메서드 등을 상속받아 사용하며 자식 클래스에서 추가 및 확장을 할 수 있는 것, 이로 인해 재사용성, 중복성의 최소화
- 구현(implements) : 부모 인터페이스(interface)를 자식 클래스에서 재정의하여 구현하는 것, 부모 클래스의 메서드를 재정의하여 구현해야 함
객체지향 프로그래밍
정의
- 객체들의 집합으로 프로그램의 상호 작용을 표현하며 데이터를 객체로 취급하여 객체 내부에 선언된 메서드를 활용하는 방식
- 설계에 많은 시간이 소요되며 처리 속도가 다른 프로그래밍 패러다임에 비해 상대적으로 느림
특징
- 추상화 : 복잡한 시스템으로부터 핵심적인 개념 또는 기능을 간추려내는 것
- 캡슐화 : 객체의 속성과 메서드를 하나로 묶고 일부를 외부에 감추어 은닉 하는 것
- 상속성 : 상위 클래스의 특성을 하위 클래스가 이어받아서 재사용하거나 추가, 확장하는 것
- 다형성 : 하나의 매서드나 클래스가 다양한 방법으로 동작하는 것
설계 원칙
- SOLID 원칙 : 객체지향 설계에서 유지보수성, 확장성, 가독성을 높이기 위해 지켜야 할 5가지 핵심 원칙
- SRP (단일 책임 원칙, Single Responsibility Principle): 모든 클래스는 단 하나의 책임(기능)만 가져야 하며, 클래스를 변경하는 이유는 오직 하나여야 합니다.
- OCP (개방-폐쇄 원칙, Open/Closed Principle): 소프트웨어 요소는 확장에는 열려 있으나, 변경에는 닫혀 있어야 합니다. 기존 코드를 수정하지 않고 기능 추가가 가능해야 합니다.
- LSP (리스코프 치환 원칙, Liskov Substitution Principle): 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 합니다. 즉, 부모 클래스 자리에 자식 클래스를 넣어도 작동해야 합니다.
- ISP (인터페이스 분리 원칙, Interface Segregation Principle): 클라이언트가 사용하지 않는 메서드에 의존하지 않도록, 인터페이스를 구체적으로 분리해야 합니다.
- DIP (의존 역전 원칙, Dependency Inversion Principle): 추상화에 의존해야 하며, 구체화(구현 클래스)에 의존해서는 안 됩니다. 상위 모듈이 하위 모듈에 의존하지 않는 구조입니다.
- 장점
- 유지보수성 향상: 코드가 분리되어 있어 수정이 용이합니다.
- 확장성: 기존 코드 수정 없이 기능을 쉽게 추가할 수 있습니다.
- 가독성 및 재사용성: 코드가 명확해지고 모듈화되어 재사용하기 좋습니다
프로그래밍 개념
- 오버헤드(Overhead) : 어떤 작업을 처리하는 데 필요한 실제 시간·메모리 외에, 추가로 드는 간접적인 자원이나 시간 비용을 의미
- 보일러플레이트 코드(Boilerplate code) : 최소한의 변경으로 여러 곳에서 재사용되며, 반복적으로 비슷한 형태를 띄는 표준화된 코드 조각
- 제네릭
- 데이터 타입을 일반화하여 클래스, 인터페이스, 메서드 설계 시 구체적인 타입을 지정하지 않고, 사용 시점에 타입을 지정하는 기능입니다. 컴파일 시 타입 체크로 안정성을 높이고, 형변환 번거로움과 오류를 줄입니다. 주로
<T> 형태의 타입 파라미터를 사용
- 컴파일 시점 타입 검사: 런타임에 발생할 수 있는
ClassCastException 같은 타입 에러를 컴파일 시점에 방지하여 안정성을 확보합니다.
- 형변환(Casting) 생략: 데이터를 가져올 때 구체적인 타입으로 형변환할 필요가 없어 코드가 간결해집니다.
- 코드 재사용성: 하나의 클래스나 메서드로 다양한 데이터 타입(Integer, String 등)을 처리할 수 있어 코드 재사용성이 높아집니다.
- 타입 이레이저 (Type Erasure): 제네릭은 컴파일 타임에만 작용하고 런타임에는 사라집니다
제어 흐름
- 블로킹(Blocking) vs 논블로킹(Non-blocking) & 동기(Sync) vs 비동기(Async)
- 동기/비동기: 작업의 완료를 기다리느냐(Sync), 완료 알림을 받느냐(Async)
- 블로킹/논블로킹: 제어권이 넘어가느냐(Blocking), 바로 돌아오느냐(Non-blocking)
API 설계
- RESTful API
- HTTP와 URI를 기반으로 리소스(자원)를 명확히 식별하고, HTTP 메소드(GET, POST, PUT, DELETE)를 사용하여 CRUD(생성, 조회, 수정, 삭제)를 처리하는 아키텍처 원칙을 준수한 API
- 리처드슨 성숙도 모델의 4단계
- 0단계 (The Swamp of POX): HTTP를 단순한 전송 수단으로 사용. 단일 엔드포인트(
POST /service)로 모든 요청 처리 (예: SOAP, XML-RPC).
- 1단계 (Resources): 개별 자원(Resource) 도입. 리소스마다 고유한 URI를 사용하여 구별.
- 2단계 (HTTP Verbs): HTTP 메서드(GET, POST, PUT, DELETE)를 사용하여 CRUD 기능 구현. HTTP 상태 코드를 활용해 결과 전달.
- 3단계 (Hypermedia Controls): HATEOAS(Hypermedia As The Engine Of Application State) 적용. 응답에 링크(Link)를 포함하여 클라이언트가 자원의 상태 전환을 탐색할 수 있게 함.
배포 전략
- 롤링 배포 (Rolling Deployment)
- 서비스 중단 없이 순차적으로 인스턴스를 교체하는 방식
- 방식: 전체 서버 중 일부를 차례로 새 버전으로 교체하며 배포를 진행
- 장점: 추가적인 인프라 자원이 거의 필요 없어 비용 효율적
- 단점: 배포 중 구버전과 신버전이 동시에 존재하여 호환성 문제가 발생할 수 있으며, 롤백 시 시간이 오래 걸릴 수 있음
- 블루-그린 배포 (Blue-Green Deployment)
- 동일한 규모의 새로운 환경을 구축하여 트래픽을 한 번에 전환하는 방식
- 방식: 기존 환경(Blue)과 동일한 신규 환경(Green)을 띄운 후, 로드밸런서를 통해 트래픽을 100% 전환
- 장점: 롤백이 매우 빠르고(라우터 스위칭만으로 가능), 구/신버전 공존 시간이 거의 없어 호환성 리스크가 적음
- 단점: 인프라 자원이 2배로 필요하여 비용 부담이 큼
- 카나리 배포 (Canary Deployment)
- 소수 사용자에게 먼저 배포하여 안정성을 검증한 뒤 전체로 확대하는 방식
- 방식: 신규 버전을 소수의 서버에만 배포하고, 특정 트래픽(예: 5%)만 유도하여 모니터링한 뒤 점진적으로 늘려감
- 장점: 실제 운영 환경에서 리스크를 최소화하며 성능과 버그를 테스트할 수 있음
- 단점: 트래픽 제어(Traffic Routing)를 위한 정교한 설정이 필요하며 관리 복잡도가 높음