> For the complete documentation index, see [llms.txt](https://leehyokyun.gitbook.io/openbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://leehyokyun.gitbook.io/openbook/1-1.-cs-basic-2.md).

# 1-1. CS / Basic #2

CS 기초 및 알고리즘에 대하여 - 2장

### 1. 메모리 용량 단위 정리

#### 가장 기본적인 메모리 점유/용량 크기

* 기본 1 bit
* 1 Byte = 8 Bit
* 1 KByte = 1024 Byte
* 1 MByte = 1024 KByte
* 1 GByte = 1024 MByte
* 1 TByte = 1024 GByte

#### Java기준 JVM에서 원시형 자료를 저장하기 위해 필요한 메모리 용량(크기 고정)

* byte  = 1 byte = -128 \~ 127
* short = 2byte = -32768 \~ 32767
* int = 4byte = +- 21억
* long = 8byte = +- 9경
* float = 4byte = 소수
* double = 8byte = 정밀소수
* char = 2byte = Unicode 문자
* boolean = 1byte

### 문자별 크기(인코딩 방식이 결정, DB 메모리 고려할때 보통UTF-8 기준 고려)

* ASCII : 문자/숫자 1byte
* UTF-8 : 문자(A/a) : 1byte , 숫자(1) : 1byte, 한글 : 3byte, 특수문자 : 1\~4byte

### 2. StringBuilder, StringBuffer, String 차이점

* StringBuilder는 가변(mutual) 객체이다.
  * StringBuilder 객체를 중복으로 생성하지 않는다. 하지만, 내부적으로 char 배열의 내용을 직접 바꿀 수 있다.
* StringBuffer는 가변(mutual) 객체이다.
  * StringBuilder와 동일하다. 하지만 내부 배열의 내용을 수정할 때 동기화 처리(synchronized)가 추가된다.
* String은 불가변(Immutable) 객체이다.
  * String 객체는 한번 생성한 후 그 값을 절대 수정할 수 없다.
  * replace 등의 API 결과를 추출하기 위해서는 반드시 다른 변수를 사용해야 하며, API 사용 이후에도 객체는 불변이다.
  * 직접 할당의 경우 String pool에, new String 객체는 heap에 변수의 value가 위치한다.
  * ```
    String a = "hello"; 
    String b = "hello"; 
    System.out.println(a == b); // true (String pool 참조 일치) 
    String c = new String("hello"); System.out.println(a == c); // false (heap 객체 주소 다름)
    ```

### 3. == 연산자와 equals 메서드 차이

* \== 연산자: 참조하는 주소값의 일치 여부, 즉 동일한 객체인지를 확인한다. int와 같은 primitive 타입의 경우 객체 참조가 아닌, 값 자체가 stack에 들어있고 이 값을 비교하기에 value 비교(내부 값 비교)가 성립된다.
* equals 메서드: 본래 Object 클래스의 equals는 ==와 같이 객체 동등 여부를 판단하지만, String이나 List 및 Wrapper 클래스가 이를 오버라이딩하여 값 동등으로 구현한다. 이 오버라이딩 과정은 템플릿 메서드 패턴(template method pattern)을 기반으로 동작한다.
* Reference 타입 (String, Integer, Object 등)의 메커니즘&#x20;
* ```
  Integer a = 1; 
  Integer b = 1; 
  String aStr = "hello"; 
  String bStr = "hello"; // a, b 자체는 stack에서 값을 비교할 수 있는 형태이거나 String pool을 참조한다. 
  System.out.println(aStr == bStr); // true (String pool 일치) // 객체를 가리키는 참조값(주소)를 가지고 있는 경우의 격리: // a가 0x100 (Integer 객체), b가 0x200 (Integer 객체)일 때는 주소 비교가 수행된다. 
  String cStr = new String("hello"); 
  System.out.println(aStr == cStr); // false (heap 객체 주소 비교 결과 상이)
  ```

### 4. 오토 박싱(Autoboxing)과 언박싱

* List와 같은 컬렉션에는 Wrapper 클래스만 등록이 가능하다.
* 그러나 int와 같은 primitive 타입도 Wrapper 클래스화하여 등록이 가능하다.
* 이 등록이 가능하도록 원시 타입을 Wrapper 클래스로 자동으로 변환해 주는 과정을 오토박싱이라 한다.
* 반대로 Wrapper 클래스를 primitive 타입으로 변환하는 역과정을 언박싱(Unboxing)이라 한다.

### 5. 분리된 모듈에서의 컴포넌트 스캔 (의존성 컴포넌트 추가)

* 주 도메인 내의 Configuration은 컴포넌트 스캔 대상이며, 애플리케이션 컨텍스트 초기화 시 자동으로 CacheConfig 클래스를 감지하고 빈으로 등록한다.
* 이때 util 성 모듈(common 모듈 등)을 함께 스캔하기 위해 META-INF/spring.factories 파일에 명시하거나 @Import를 통하여 Configuration 및 외부 의존성 모듈을 명시적으로 등록하고 사용할 수 있도록 조율해 주는 구조를 취한다.
* 캐싱 동작 원리 및 Caching Aspect AOP 동작원리와 연계된다.

### 6. 스프링 계층형 아키텍처 어노테이션 (Layered Architecture)

* @Controller: 스프링 MVC 패턴에서 클라이언트의 Request를 전달받아 View 혹은 HTML 응답을 resolve해주는 Presentation 레이어의 진입점 역할을 수행한다.
* @RestController: API Controller 상에서 XML 또는 JSON 기반의 데이터를 직접 HTTP 응답 Response 바디로 사용한다. @Controller와 @ResponseBody를 조합하여 사용한 결과와 완벽히 동일하며, View 이름이 아닌 데이터 자체를 반환한다.
* @Service: Spring AOP 측에서 비즈니스 로직이 수행되는 Service layer를 명시하고, 이에 대한 트랜잭션 및 예외 처리 등의 부가 기능을 쉽게 묶어서 적용할 수 있도록 돕는다.
* 단순한 빈 등록을 넘어, Spring Web에서의 계층과 역할을 분명하게 구분하고 명시하기 위한 목적으로 사용된다.

### 7. @Component와 @Configuration의 싱글톤 동작 차이

* @Component: 대상 클래스를 빈 객체로 등록하기 위해 컴포넌트 스캔 메타정보를 알려주는 기능이다. 수동 빈 등록이 아닌 경우에도 Component 어노테이션을 명시하여 역할을 명확히 할 수 있다.
  * 주의점: @Component 클래스 내부에서 @Bean 어노테이션을 사용하여 다른 메서드를 호출할 경우, 프록시가 걸리지 않아 해당 메서드 호출 시마다 매번 새로운 객체를 생성하므로 싱글톤이 깨질 수 있다.
* @Configuration: Component와 마찬가지로 Spring Container에 빈으로 등록하지만, 단순한 부품 빈 객체가 아닌 "설계도" 역할을 하는 설정 클래스이다. 내부에 선언된 @Bean 메서드들이 반환하는 빈 클래스 및 객체들이 철저하게 싱글톤으로 유지되도록 보장한다. 클래스를 CGLIB 기반의 프록시 기술로 Wrapping하여 호출을 제어하기 때문에, 컨테이너 조회 후 이미 객체가 있으면 기존 객체를 반환하고 없을 때만 새로 생성하여 등록하는 메커니즘으로 움직인다.
* 역할 비유: @Component가 단순 스캔 및 의존성 주입 대상이 되는 \[부품]이라면, @Configuration은 Batch, Kafka, Redis 등 인프라의 더 깊은 설정을 규정하는 \[설계도] 기준 클래스의 역할을 수행한다.

### 8. 얕은 복사와 깊은 복사의 차이점

* 얕은 복사(Shallow Copy): 겉모양만 복사하는 형태이다. 외부적으로 보여지는 상자나 컨테이너 자체는 다르게 생성되지만, 내부적으로 참조하는 알맹이(객체 주소값)는 서로 공유한다. 따라서 복사본 리모컨의 내부 인스턴스를 바꾸면 원본 데이터도 공유 형태로 인해 함께 바뀐다.
* 깊은 복사(Deep Copy): 외부 객체뿐만 아니라 내부에서 참조하는 객체까지 모든 것을 메모리 공간에 완전히 새롭게 생성한다. 두 객체가 완벽하게 독립적이므로 한쪽의 연산이 다른 쪽에 아무런 영향을 주지 않는다.

### 9. CORS와 CSRF 개념 및 공격 대응

* CORS (Cross-Origin Resource Sharing): 웹 브라우저는 Same-Origin Policy(SOP, 동일 출처 정책)에 의해 기본적으로 a.com 사이트가 b.com 사이트의 데이터를 함부로 불러올 수 없도록 통제한다. SOP 정책을 부적절하게 완화하였을 때, a.com의 쿠키를 가진 사용자가 b.com의 민감 정보를 불러오는 과정에서 데이터를 가로채거나 악용하는 위협 상황 및 이를 통제하는 보안 체계를 다룬다.
* CSRF (Cross-Site Request Forgery): 교차 사이트 요청 위조 공격이다. 사용자가 특정 사이트(예: bank.com)의 로그인 쿠키(SESSION-abcd1234)를 브라우저에 보유한 상태에서, 공격자가 만든 악성 링크나 스크립트가 포함된 악성 페이지에 접근할 때 발생한다. 브라우저는 사용자의 인지 없이 bank.com으로 자동으로 돈 송금(GET /transfer?...) 등의 가짜 요청을 보내게 되며, bank.com 서버는 브라우저가 함께 보낸 정상 쿠키를 보고 인증된 요청으로 간주하여 처리함으로써 공격자에게 이득이 발생하게 만든다.

### 10. JSON 처리 라이브러리 특징 비교 (Jackson, Gson, org.json)

* Jackson: 가장 범용적으로 실무와 스프링 프레임워크 생태계에서 많이 사용하는 JSON 라이브러리이다. Streaming 기반 API를 제공하여 대용량 JSON 처리가 가능하며, @JsonIgnore, @JsonProperty 등 풍부한 어노테이션 기반 커스터마이징을 지원한다. Spring 내부적으로 JSON을 변환할 때 가장 선호하는 체계이며 ObjectMapper 클래스가 핵심 도구로 작동한다.
* Gson: 구글에서 제공하는 JSON 매퍼 라이브러리이다. 매우 가볍고 직렬화(Object to JSON) 및 역직렬화(JSON to Object) 메커니즘이 직관적이고 단순하다. 다만 Jackson에 비하면 상대적으로 제공 기능이 단순하며, 대용량 JSON 스트리밍 최적화 처리에는 부적합하다.
* org.json: JsonObject, JsonArray 객체를 직접 다루는, 가장 오래되고 원시적인 형태의 JSON 처리 라이브러리이다. 자바 객체와 자동으로 매핑해 주는 Data binding API를 별도로 제공하지 않으므로, 개발자가 리플렉션 가공 코드를 거치지 않고 직접 객체 매핑 로직을 수동으로 구현해야 한다.
* 관련 기술 정의: JSON 데이터를 자바 객체화하는 매핑 과정의 내부 밑바닥에는 리플렉션(Reflection) 기술이 핵심으로 자리 잡고 있다.

### 11. 정적 내부 클래스(Static Nested Class)의 메모리 구조와 특징

* Static의 핵심 개념은 인스턴스가 아닌 "어떤 클래스 자체"에 소속되도록 격리하는 것이다. 따라서 인스턴스를 생성하지 않고 클래스 네임스페이스를 통해 직접 접근할 수 있다. 최상위 클래스(Top-level class)는 인스턴스화의 주체이므로 static 타입 선언이 불가능하며, 반드시 귀속 대상 클래스가 존재해야 한다.
* JVM 관점의 메커니즘: Method Area에 저장되며, 정적 내부 클래스(Static Nested Class)의 경우 JVM 컴파일 시 Outer$Inner.class 형태로 분리되어 Method Area(MetaSpace) 영역에 메타 정보가 적재된다(이 메타정보를 바탕으로 데이터 참조가 이루어진다).
* 일반 내부 클래스와 달리 외부 클래스의 인스턴스(this)에 대한 참조 종속성이 완전히 제거된다. 외부 객체 생성 없이 독립적으로 인스턴스를 생성하여 Heap 영역을 할당받을 수 있기 때문에, 불필요한 외부 인스턴스의 동시 유지를 방지하고 메모리 누수(Memory Leak) 오류를 원천 차단하여 메모리 효율성을 최적화한다.
* 중요한 점은 인스턴스의 귀속이 아닌, 특정 클래스의 귀속이라는 점이다. 그렇기에 클래스 로딩 시점에서 static 컨텍스트 내부에서 인스턴스를 확정할 수 없는 this의 사용은 원칙적으로 불가능하다. 다만, Static nested Class 생성자의 경우 인스턴스를 확정할 수 있기에 this를 사용할 수 있다.
  * static 클래스는 기본적으로 단독 존재가 아닌, 특정 클래스에 귀속이 되는 존재이다.
  * 즉, static nested class나 method의 경우 meta space(Method Area)에 저장이 된다. 여기서 만들어진설계도에 따라 내부 데이터 및 변수(원시형도 마찬가지)들이 Heap에저장되며, Heap을 통해 참조가 되는 것이다.
  * 다만, 중첩 클래스를 사용하더라도, 인스턴스의 개념은 동일하게 유지된다. static은 귀속의 개념이되, 인스턴스 속박없이 해당 인스턴스를 "직접"/"바로" 생성할 수 있다는 점이 중요하다(static nested class든om ethod든 outer에 대한 this 정보($outer)를 참조하지 않기에, this 키워드 사용 자체가 불가능하며, 생성자의 경우 인스턴스를 확정할 수 있기에 예외적으로 사용 가능)&#x20;
  * 클래스 메타 데이터 정보는 단일하게 존재하지만, static의 경우 인스턴스 생성 이후 본인을 참조하는 관계가 outer라는 인스턴스가 아닌 "클래스 그 자체"이므로 바깥에서는 반드시 outer.inner로 명시해주어야 한다. 참고로, outer 내부에서는 outer 명시없이 바로 인스턴스 생성(new)이 가능하다.
  * 본질적으로 클래스라는 것은 인스턴스가 만들어져야 사용이 가능하다는 점을 잊지 말자.

### 12. ThreadLocal의 독립 공간 격리 및 주의점

* JVM에서 실행되는 프로세스의 처리 단위인 스레드(Thread)별로 변수를 완전히 독립하여 저장하기 위해 사용하는 특수 클래스이다.
* 멀티 스레드 환경에서는 여러 스레드가 Heap에 저장된 공유 객체의 데이터를 동시에 수정하다가 자원 경쟁 및 동시성(Race Condition) 문제를 일으킨다. ThreadLocal을 활용하면 각 스레드가 고유한 독립 저장소를 가지므로 주소를 공유하지 않고 격리된 값을 안전하게 유지할 수 있다.
* 치명적인 주의점: 톰캣과 같은 WAS 환경은 성능 향상을 위해 스레드 풀(Thread Pool)을 활용하여 스레드를 재사용한다. 작업이 끝난 스레드가 소멸하지 않고 풀로 반환될 때, 만약 ThreadLocal 내부의 데이터를 명시적으로 remove하여 초기화하지 않으면 해당 스레드를 배정받은 다음 사용자가 이전 사용자의 민감 데이터를 그대로 참조하게 되는 치명적인 보안 오동작 버그를 초래한다.

### 13. 스레드 풀 포화 정책 (Saturation Policies)

* Thread Pool이 완벽하게 가득 차서 새로 유입되는 작업을 더 이상 수용할 수 없는 임계 포화 상태일 때 적용하는 거절 대응 정책이다.
* ThreadPoolExecutor 인프라를 설정할 때 내부 제어 로직은 세 가지 핵심 수치를 기준으로 스레드 확장을 조율한다.
  * corePoolSize: 상시 유지 및 대기하는 기본 스레드 개수.
  * workQueueSize: 작업 대기열(임시 큐)의 크기.
  * maxPoolSize: 큐까지 가득 찬 경우 확장하여 생성할 수 있는 스레드의 최대 한도 개수.
* 만약 maxPoolSize 한도 수치까지 스레드가 풀 가동되고 workQueueSize 대기열까지 완전히 가득 찬 상태에서 추가 작업 요청이 들어오면, 시스템은 RejectedExecutionHandler 인터페이스 동작에 의해 요청을 거절한다. 이 연산 매커니즘 전체를 스레드 풀 포화 정책이라고 명칭한다.

### 14. 템플릿 메서드 패턴에서의 동적 디스패치 (Dynamic Dispatch)

* Template Method Pattern의 핵심은 전체적인 실행 명세와 알고리즘의 과정이 부모 클래스에 미리 정적으로 정해져 있다는 점이다.
* 자식 구현체들은 부모 클래스에 그러한 실행 과정을 그대로 위임하여 처리할 수 있다.
* 그러나 자식 구현체 측에서 특정 세부 과정의 대체 및 변경이 필요하여 메서드를 오버라이드했다면, 런타임에 인스턴스의 실제 메서드를 찾아 구현체가 오버라이드한 함수를 최우선으로 호출하게 된다.
* 자바 JVM이 런타임에 실제 다형성 객체의 타입을 보고 오버라이딩된 메서드를 찾아 호출하는 이 과정을 Template Method Pattern의 동적 디스패치(Dynamic Dispatch)라고 한다.

### 15. 의존성 주입(DI) 방식별 리플렉션(Reflection) 단계의 제어

* 메서드 주입 및 Setter 주입: Bean 객체를 생성한 후에 특정 메서드나 Setter를 호출하면서 필요한 의존 객체를 전달받는다. 스프링은 컨테이너 내부에서 대상이 되는 타입(예: Job 타입)의 빈 객체를 모두 찾아 컬렉션으로 묶어둔다. 그 후 구동 초기 리플렉션(Reflection) 단계에서 Autowired 어노테이션 명세를 해석하여 의존성 주입 연산을 수행한다. 필드 주입도 동일한 리플렉션 단계를 거친다. 객체를 온전히 생성한 후에 주입되므로 의존 객체가 없을 수도 있는 상황을 대비해 required = false 처리가 가능하다.
* 생성자 주입: 명시적으로 생성자 파라미터를 통해 의존 객체를 주입받아 내부의 불변 상수 객체(final 필드)를 안전하게 사용할 수 있게 한다. 앞선 방식들과 달리 autowired에 의한 사후 리플렉션 주입 동작에 의존하는 것이 아니라, Bean 인스턴스를 생성(new 인스턴스화)하는 시점에 즉시 의존성 주입이 강제되고 완료된다는 결정적인 메커니즘 차이가 존재한다.

### 16. @Repository 어노테이션의 존재 이유와 예외 추상화

* Interface 기반 구현체 혹은 Redis, RDB 등 외부 데이터 인프라 체계와 상호작용하기 위한 영속성(Persistence) 계층 클래스 상단에 명시한다.
* 단순히 빈 등록을 통해 컴포넌트 스캔 대상으로 지정하는 기능에 그치지 않는다.
* 결정적인 역할: 스프링 프레임워크 측에서 하부 데이터베이스나 기술 벤더별로 제각각 발생하는 고유한 Checked Exception 및 에러 경로들을 일일이 지정할 필요가 없도록, 스프링 고유의 공통 데이터 액세스 예외 체계로 자동 변환 및 추상화해 준다.
* Spring Data JPA 환경 등에서 런타임에 프록시 구현체를 동적으로 생성할 때 이 메커니즘이 빛을 발한다. 만약 하부 DB 인프라가 완전히 바뀌더라도 Service 영역의 비즈니스 로직을 전면 수정할 필요 없이 영속성 계층의 변경점을 최소화하여 시스템 결합도를 낮추는 결정적인 이유가 된다.

### 17. 어떤 예외가 발생하면 트랜잭션을 롤백하나요?

* Spring Transaction 무대에서 롤백(Rollback) 동작은 프레임워크 측에서 '현재 비즈니스 로직 상 회복하기가 매우 어려운 치명적인 상황'으로 가정한 경우에 실행된다.
* 기본 전략 주의점: 자바의 예외 체계 중 시스템이 예방하기 어려운 RuntimeException(Unchecked Exception)이나 Error가 발생하면 트랜잭션 롤백이 정상적으로 유발된다. 하지만 명시적인 예외 처리를 요구하는 체크 예외(Checked Exception)가 발생할 경우에는 Spring Transaction은 기본적으로 롤백을 발생시키지 않고 커밋을 시도하므로, 필요시 rollbackFor 속성 설정을 통해 경로를 확장해야 한다.

### 18. 빌드 포맷의 실행 메커니즘 차이 (JAR vs WAR)

* JAR (Java Archive): 자바 애플리케이션 프로젝트 전체 코드를 컴파일하여 압축한 범용 포맷이다. 내부에 class 파일 및 META-INF 설정을 담는다. 일반적인 .jar 파일은 단순한 도구 모음(유틸성 라이브러리)을 의미하므로 내부에 main 메서드가 없어 단독 실행이 불가능하다.
  * Executable JAR (Fat JAR 형태): 스프링 부트 환경의 실행 가능한 JAR는 내부에 내장 톰캣(Embedded Tomcat) 엔진을 직접 품고 있다. main 클래스의 위치가 MANIFEST 파일에 명확히 지정되어 있어, 외부 WAS 장치 없이 java -jar 명령어로 단독 구동이 가능하다. 자체 구동 능력을 기반으로 격리된 가상화 컨테이너 배포 환경에 매우 최적화되어 있다.
* WAR (Web Application Archive): 온전히 웹 애플리케이션 표준 구조에 맞추어 콘텐츠를 패키징한 전용 포맷이다. Jar와 달리 내부에 Embedded Tomcat을 포함하지 않고 압축되므로 단독 실행이 절대 불가능하다. Servlet 기반 애플리케이션 실행 구조 체계에 맞춰 정형화되어 있으며, 반드시 외부 인프라에 별도로 구동 중인 정식 WAS 장치(Tomcat, JBoss, Jeus, WildFly 등)에 배포 플러그인 형태로 업로드되어 톰캣의 관리를 받아야만 기동한다. 이러한 중앙 집중식 WAS 배포 환경은 특정 애플리케이션의 장애가 WAS 전체의 쓰레드 고갈 및 가용성 마비로 이어져 시스템 장애 전파 위험성을 내포한다.

### 19. 시스템 콜(System Call)과 외부 전송 과정

* 유저 모드(User Mode)에서 작동하는 일반 애플리케이션이, 운영체제 핵심 권한인 커널 모드(Kernel Mode)의 자원을 안전하게 빌려 쓰기 위해 OS 커널에 요청하는 유일한 권한 진입점 인터페이스이다.
* 애플리케이션은 시스템 보안 및 하드웨어 격리 정책으로 인해 네트워크 장비, 파일 I/O, 메모리, 프로세스 제어 물리 장치에 직접 접근할 권한이 전혀 없다. 모든 물리 제어는 커널만 가능하므로 무조건 커널을 거쳐야 한다.
* 특히 자바 애플리케이션 측에서 데이터베이스(DB)와 같은 원격지 외부 체계로 쿼리 요청 패킷의 전송을 요할 때, 이 전송 요청을 네트워크 인터페이스 밖으로 밀어내는 과정에서 OS 커널의 프로토콜 스택 프로그래밍 스택 기능을 빌려 써야 하므로 반드시 시스템 콜을 호출하여 커널 대행 연산을 거치게 된다.

### 20. 네트워크 포트(Port)의 Listen 메커니즘

* Web Server의 포트(Port) 지정이란, Web Server 프로세스가 해당 포트 번호로 유입되는 네트워크 요청 패킷을 항상 감시하고 수신하겠다는 의미(Listening)이다.
* 로컬 환경(localhost)에서의 테스트 구동 시, Host OS의 네트워크 스택 내부에 존재하는 네트워크 연결 테이블 구조에 해당 포트 번호와 Listening을 수행하는 웹 서버 프로세스의 PID 정보를 상호 바인딩하여 등록하는 개념으로 동작한다.
* localhost 요청의 특이점: localhost의 경우 127.0.0.1이라는 루프백(Loopback) 주소지로 요청을 보내도록 운영체제 내부적으로 완전하게 약속되어 있기 때문에, 공유기나 외부 게이트웨이를 거치는 실제 물리 네트워킹 인프라 연산 없이 Host OS 내부 네트워크 스택에서 즉시 내부 처리가 완료된다.
* 도커(Docker) 컨테이너 환경의 경우, 도커 가상화 엔진이 일종의 Wrapper 역할을 수행하므로 가상 가상화 컨테이너 환경 내부에서 제공하는 포트 구조와 실제 Host OS가 노출하는 물리 포트의 구조가 서로 상이하게 격리되며 포트 포워딩 설정을 통해 두 포트 사이의 관문을 연결한다.

### 21. static 블록의 용도와 초기화 실행 시점

* 정적(static) 멤버 변수를 클래스 로딩 단계에서 안전하게 초기화하기 위해 사용하는 특수 블록이다.
* 실행 시점: JVM에 의해 클래스가 메모리(Method Area)에 최초로 로딩되는 시점에 변수가 Metaspace에 생성된 후, 단 한 번만 이 static 블록 로직을 실행하게 된다.
* 특징: static 필드 선언과 동시에 대입 연산자로 초기화하는 단순 대입식과 달리, static { users.add(new User(...)); } 등 리스트 객체 생성 후 다수의 기본 객체를 미리 넣어두는 복잡한 초기화 로직을 안전하게 실행할 수 있다. 주로 테스트 목적에서 단순 기본 객체 세팅 구조를 잡을 때도 유용하게 고려된다.

### 22. 자바 Enum의 구조와 속성 활용

* Enum은 연관된 고정 상수들의 집합을 정의하는 특수한 클래스 형태의 체계이다.
* 단순히 상수의 이름만 나열하는 것을 넘어, 내부적으로 고유한 코드 수치(int)나 상세 문자열 설명(String message)을 속성으로 포함하여 관리할 수 있다.
* 구조적 매핑: 상수가 선언될 때 지정된 속성값들은 Enum 클래스 내부의 private 생성자를 통해 인스턴스 필드에 강제로 매핑된다. 외부에서는 getter 메서드를 통해 특정 Enum 상수가 가지고 있는 고유 속성 수치를 언제든지 추출할 수 있다.

### 23. 보일러플레이트(Boilerplate) 코드의 개념과 대책

* 여러 곳에서 거의 수정 없이 반복적으로 복사 붙여넣기 하여 사용해야 하는 지루하고 고정된 코드 덩어리를 의미한다.
* 과거 금속 인쇄판에 자주 사용하는 문장을 미리 새겨놓고 반복 인쇄하던 인쇄용어 유래에서 나온 개념이다.
* 클래스의 필드를 선언할 때마다 매번 기계적으로 작성해야 하는 Getter, Setter, 생성자 주입용 명시적 생성자 코드, toString 메서드 등이 대표적인 자바의 보일러 플레이트이다.
* 해결 방안: 최근 현대 개발 환경에서는 롬복(Lombok) 등의 라이브러리를 통한 어노테이션화 기법을 도입하거나 표준화된 자바 컨벤션(Convention) 표준 설계를 적용하여 지루한 코드를 숨기고 보완한다.

### 24. String 형변환 방식의 예외 위험성 차이

* (String) value 방식 (명시적 타입 캐스팅): 대상 객체가 실제로 String 타입 구조를 취하고 있지 않을 경우 런타임에 ClassCastException을 일으켜 프로그램이 죽는다. 또한 value가 null인 상태에서 주소 변환을 시도하면 즉시 NullPointerException이 발생하여 어플리케이션의 비정상 종료를 유발한다.
* String.valueOf(value) 방식: 대상 value의 형태 및 값 상태를 내부 함수가 먼저 판별한다. 파라미터가 null인 경우 예외를 터뜨리지 않고 안전하게 문자열 "null"로 변환 및 대체하여 반환하도록 설계되어 있어 런타임 안정성을 크게 확보할 수 있다. String 형태라면 그대로 문자열을 안전하게 반환한다.

### 25. SpEL (Spring Expression Language)

* 스프링 프레임워크가 자체적으로 제공하는 강력한 표현식 언어이다.
* 런타임 시점에 동적으로 객체 그래프의 속성값을 조회, 저장, 가공할 수 있도록 다양한 유틸리티와 동적 제어 기능을 제공해 주는 핵심 도구이다.
* 핵심 가치: 애플리케이션 컴파일 시점에 정적으로 확보된 고정 수치나 텍스트 값에 의존하지 않고, 유연한 설정 정보나 런타임 동적 로직에 의하여 설정 및 표현식을 코드와 완전히 분리하여 추출 및 처리할 수 있도록 지원하는 고도화된 메커니즘을 제공한다.

### 26. POJO (Plain Old Java Object)

* 특정 프레임워크나 외부 기술 벤더, 그리고 특정 라이브러리에 전혀 의존하지 않고 결합도를 극도로 낮춘 순수한 자바 객체를 의미한다.
* 역사적 배경 사상: 과거 EJB 등 초창기 자바 엔터프라이즈 프레임워크 환경에서는 단순한 기능 하나를 구현하기 위해서도 프레임워크가 제공하는 무거운 특정 클래스를 강제로 상속(Inheritance)받거나 인터페이스를 강제로 구현해야만 했고, 이로 인해 기술 종속성과 결합도가 파멸적으로 증가했었다.
* 이에 반발하여 다른 상속 객체 및 외부 환경 인터페이스의 제약에 의존하지 않고, 객체 지향 본연의 목적과 객체 내부 자체의 핵심 비즈니스 도메인 설계에만 완벽하게 집중하자는 순수 사상이 담긴 자바 백엔드 진영의 핵심 개념이다.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://leehyokyun.gitbook.io/openbook/1-1.-cs-basic-2.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
