🎯 F-lab Java 5주차 학습 커리큘럼

5주차 자료의 모든 토픽을 두 개의 큰 흐름으로 정리한 학습 경로.
1) 동시성 마무리 (Atomic/CAS, 스레드 풀의 필요성)
2) 토비의 스프링 시작 (DAO 진화 → 관심사 분리 → 디자인 패턴 → IoC/DI)

자바 기초·동시성을 끝내고 Spring 프레임워크의 핵심 원리로 진입하는 다리 주차다.


📊 학습 경로 한눈에 보기

[Part A — 동시성 마무리]
  [Phase 1] 스레드 풀의 필요성 재정리
     ↓
  [Phase 2] 동시성 안전 도구 3종 비교 (synchronized/volatile/Atomic)

           ↓ (자바 기초 완성)

[Part B — 토비의 스프링: 객체 설계의 진화]
  [Phase 3] 전통 DAO의 문제
     ↓
  [Phase 4] 관심사의 분리
     ↓
  [Phase 5] 디자인 패턴 적용 (템플릿 메소드 / 팩토리 메소드)
     ↓
  [Phase 6] 객체지향 설계 원칙 (OCP, 전략 패턴)
     ↓
  [Phase 7] 제어의 역전 (IoC)
     ↓
  [Phase 8] Spring 컨테이너 (ApplicationContext + DI)

총 8 Phase × 26 Unit

🔗 1~5주차 흐름 정리

주차주제핵심 변화
1주차OOP·JVM·GC·컬렉션·I/O 개론자바 큰 그림
2주차JVM 내부·바이트코드·G1 GC"어떻게 돌아가나"
3주차컬렉션 전체 지도·제네릭·함수형자바 표현력 완성
4주차멀티스레딩·동시성·Executor동시성 첫 정복
5주차 (지금)Atomic + Spring IoC/DI 입문자바 → Spring 다리

🗓️ 권장 학습 일정 (압축 7일)

DayPhase학습 목표
1일차Phase 1 + 2동시성 마무리 (Atomic/CAS)
2일차Phase 3전통 DAO 분석
3일차Phase 4관심사 분리 (1·2단계)
4일차Phase 5템플릿 메소드 + 팩토리 메소드 패턴
5일차Phase 6OCP + 전략 패턴
6일차Phase 7IoC + 프레임워크 vs 라이브러리
7일차Phase 8ApplicationContext + DI

🧵 Part A — 동시성 마무리

📚 Phase 1 — 스레드 풀의 필요성 재정리

목표: 4주차에서 본 Executor 프레임워크가 "왜" 필요한지를 스레드 자체의 비용 관점에서 다시 한번 못 박는다.

Unit 1.1 — 스레드를 많이 쓸 때의 함정

선수 지식: 4주차 Phase 1, 7

핵심 개념

"스레드를 많이 쓸수록 항상 빠를까?" → NO

3가지 함정:
1. 컨텍스트 스위칭 오버헤드: 스레드 N개 ↑ → 스위칭 비용 ↑
2. 데드락: 락이 많을수록 데드락 가능성 ↑
3. 노는 스레드의 자원 낭비: 작업 안 해도 메모리 차지 + 스케줄링 비용

핵심 통찰: 스레드는 "공짜가 아니다". 존재 자체로 비용.

자기 점검

  • 멀티 프로세스보다 멀티 스레드가 컨텍스트 스위칭 비용이 적은 이유는? (힌트: 메모리 공유)
  • "노는 스레드"가 CPU에 부담을 주는 이유는?

Unit 1.2 — 컨텍스트 스위칭의 진짜 비용

선수 지식: Unit 1.1, 4주차 Phase 1

핵심 개념

스위칭 시 일어나는 일:
1. 현재 스레드의 CPU 레지스터 → 메모리에 백업
2. 다음 스레드의 이전 상태 → 메모리에서 복원
3. CPU 캐시 무효화 (캐시 미스 발생)
4. 스레드 스택, PC 카운터 등 컨텍스트 전환

스위칭 횟수 = 스레드 수 × 시간 비례 → 스레드 너무 많으면 CPU가 작업보다 스위칭에 더 많은 시간 소비

자기 점검

  • 코어 4개 시스템에서 스레드 4개 vs 100개의 처리 시간 차이는?
  • "노는 스레드도 스위칭 대상이 되는가"의 답은?

Unit 1.3 — 스레드 풀이라는 답

선수 지식: Unit 1.2, 4주차 Phase 7

핵심 개념

문제 → 해결:

  • 스레드 생성 비용 ↑ → 재사용
  • 무한 생성 위험 → 개수 제한
  • 자원 낭비 → idle 스레드 회수 (CachedThreadPool)

이게 4주차에서 본 Executor 프레임워크의 존재 이유다.

실무 결론:

"스레드를 직접 만들지 마라. ExecutorService를 써라. 풀 크기는 신중히 정하라."

자기 점검

  • 일반 웹 서버의 적정 스레드 수는 어떻게 결정하는가? (힌트: I/O 바운드 vs CPU 바운드)
  • Tomcat의 기본 maxThreads는 몇이며, 그 의미는?

📚 Phase 2 — 동시성 안전 도구 3종 비교

목표: 4주차에서 synchronized와 volatile을 본 다음, 이번엔 Atomic까지 더해 3가지 도구의 정확한 차이를 매트릭스로 잡는다.

Unit 2.1 — 두 가지 동시성 문제 구분

선수 지식: 4주차 Phase 4

핵심 개념

동시성 문제는 정확히 2가지 다:

문제정의예시
가시성(Visibility)한 스레드의 변경이 다른 스레드에 안 보임runFlag = false 했는데 무한 루프
동시 접근(Atomicity)동시 수정이 서로를 덮어씀count++ 가 일부 손실

이 둘을 분리해서 보는 것이 핵심. 도구마다 해결 범위가 다르다.

자기 점검

  • 가시성과 원자성을 둘 다 깨는 사례를 만들어보라
  • 가시성만 깨지고 원자성은 OK인 경우가 있을까?

Unit 2.2 — synchronized: 둘 다 해결, 대신 느림

선수 지식: Unit 2.1

핵심 개념

  • ✅ 가시성 보장 (synchronized 안 변수는 메인 메모리 동기화)
  • ✅ 원자성 보장 (한 스레드만 진입)
  • 성능 비용 — 다른 스레드는 BLOCKED

가장 안전하지만 가장 비싼 도구.

자기 점검

  • synchronized가 "전체 락"을 거는 것의 단점은?
  • 읽기만 하는데도 synchronized가 필요한 경우는?

Unit 2.3 — volatile: 가시성만, 원자성은 ❌

선수 지식: Unit 2.2

핵심 개념

  • ✅ 가시성 보장 (메인 메모리 직접 R/W)
  • 원자성 보장 안 됨
volatile int count = 0;
count++;  // ⚠️ 여전히 위험! (read → +1 → write 3단계)

적합한 사용처: 한 스레드만 쓰고, 여러 스레드가 읽는 플래그

volatile boolean shutdown = false;  // 한 곳에서만 true 설정

자기 점검

  • count++ 가 volatile로 안전하지 않은 이유를 어셈블리 수준으로?
  • volatile이 적합한 시나리오 3가지는?

Unit 2.4 — Atomic + CAS 알고리즘 (락 없이 원자성)

선수 지식: Unit 2.3

핵심 개념

CAS (Compare And Swap) 알고리즘:
1. 현재 값 읽기 → 레지스터에 저장 (A)
2. 새 값 계산 (B)
3. 메모리의 값과 A를 비교

  • 같으면 → B로 교체 ✅
  • 다르면 → 다른 스레드가 이미 수정 → 재시도

은행 잔액 예시:

  • 스레드1: 100 → 150 시도, 메모리 100과 일치 → 성공
  • 스레드2: 100 → 150 시도, 메모리는 이미 150 → 실패 → 재시도 → 150 → 200 성공
AtomicInteger num = new AtomicInteger(0);
num.incrementAndGet();  // 락 없이 원자적

비교 매트릭스:

도구가시성원자성방식성능
synchronized락 (블로킹)가장 느림
volatile메모리 동기화빠름
AtomicCAS (논블로킹)빠름

자기 점검

  • CAS의 "재시도"가 무한 반복될 수 있는가? (힌트: ABA 문제)
  • Atomic이 synchronized보다 빠른 이유는?

🌱 Part B — 토비의 스프링: 객체 설계의 진화

이 파트의 핵심 메시지:
"DAO 코드 한 줄이 어떻게 Spring의 IoC/DI까지 진화하는지" — 한 클래스의 리팩토링 여정을 따라가며 객체지향 설계 원칙과 Spring의 본질을 동시에 익힌다.

📚 Phase 3 — 전통 DAO의 문제

목표: Spring이 왜 필요한지를, "Spring 없이 짠 코드의 고통" 으로 직접 본다.

Unit 3.1 — DAO란 무엇인가

선수 지식: 1주차 Phase 7 (JDBC 개념)

핵심 개념

  • DAO (Data Access Object): DB 접근·조작 기능만 전담하는 객체
  • 비즈니스 로직과 DB 접근 로직을 분리 하는 패턴
  • 1990년대부터 자바 진영의 표준 패턴

자기 점검

  • DAO 분리 없이 비즈니스 로직 안에 SQL을 박으면 어떤 문제가?
  • DAO와 Repository의 차이는? (힌트: DDD)

Unit 3.2 — 전통 DAO의 코드 (모든 책임을 다 떠안은)

선수 지식: Unit 3.1

핵심 코드 분석

public void add(User user) throws ... {
    Class.forName("com.mysql.jdbc.Driver");        // ① 드라이버 로딩
    Connection c = DriverManager.getConnection(    // ② DB 접속 정보
        "jdbc:mysql://localhost/toby", "root", "*****");
    PreparedStatement ps = c.prepareStatement(     // ③ SQL 작성
        "insert into users(id, name, password) values (?,?,?)");
    ps.setString(1, user.getId());                 // ④ 파라미터 바인딩
    // ...
    ps.executeUpdate();                            // ⑤ 실행
    ps.close(); c.close();                         // ⑥ 자원 해제
}

자기 점검

  • 위 메서드가 신경 쓰는 "관심사"를 5개 이상 찾아보라
  • DB 종류를 MySQL → Oracle로 바꾸려면 몇 군데를 수정해야 하나?

원본 자료: 토비의 스프링 vol.1, p.56


Unit 3.3 — 무엇이 문제인가 — 책임 혼재

선수 지식: Unit 3.2

핵심 문제 진단

이 한 메서드 안에 섞여있는 책임:
1. DB 연결 정보 관리 (URL, user, password)
2. DB 드라이버 로딩
3. SQL 작성과 실행
4. 자원 해제
5. 예외 처리

왜 문제인가:

  • DB 종류 바뀌면 → 모든 메서드 수정
  • 접속 정보 바뀌면 → 모든 메서드 수정
  • 같은 코드(getConnection) 가 메서드마다 중복

변경 1번 = 수정 N곳 = 유지보수 지옥

자기 점검

  • "코드 중복"이 단순히 미관 문제가 아닌 이유는?
  • 이 코드를 1주차의 SOLID 5원칙에 비추면 어떤 원칙들을 위반하는가?

📚 Phase 4 — 관심사의 분리 (Separation of Concerns)

목표: 리팩토링의 가장 기본 원리를 코드 변화로 직접 본다.

Unit 4.1 — 관심사 분리 개념

선수 지식: Unit 3.3

핵심 개념

"관심이 같은 것끼리는 하나로 모으고, 관심이 다른 것은 떨어뜨려라"

관심사(Concern)의 의미:

  • 코드가 다루는 하나의 주제·책임
  • 변경의 이유와 일치 (1주차 SRP와 직결)

처음엔 한데 모은 게 편하지만, 시스템이 커지면 분리해야만 살아남는다.

자기 점검

  • "관심사"와 "책임(Responsibility)"은 같은 말인가?
  • DAO에서 분리해야 할 첫 번째 관심사는?

원본 자료: 토비의 스프링 vol.1, p.61


Unit 4.2 — 1단계: 메서드 추출 (getConnection)

선수 지식: Unit 4.1

핵심 변화

Before (각 메서드가 직접 연결):

public void add(...) {
    Class.forName(...);
    Connection c = DriverManager.getConnection(...);
    // ...
}
public User get(...) {
    Class.forName(...);                      // ← 중복
    Connection c = DriverManager.getConnection(...);  // ← 중복
    // ...
}

After (메서드 추출):

private Connection getConnection() throws ... {
    Class.forName("com.mysql.jdbc.Driver");
    return DriverManager.getConnection(...);
}
public void add(...) {
    Connection c = getConnection();  // 깔끔
    // ...
}
public User get(...) {
    Connection c = getConnection();  // 깔끔
    // ...
}

얻은 것:

  • 중복 제거
  • DB 정보 변경 시 한 곳만 수정

자기 점검

  • 이 단계에서 어떤 SOLID 원칙이 적용되었는가?
  • 아직 남은 문제는? (힌트: 다른 DB 지원)

Unit 4.3 — 2단계: 추상클래스로 확장 (다른 DB 지원)

선수 지식: Unit 4.2

핵심 변화

문제: "고객사마다 다른 DB를 쓰고 싶다. 그런데 UserDao 코드는 공개하고 싶지 않다."

해결: getConnection을 추상 메서드로

public abstract class UserDao {
    public void add(...) {
        Connection c = getConnection();  // 변하지 않는 흐름
        // ...
    }
    public abstract Connection getConnection();  // 변하는 부분
}

class NUserDao extends UserDao {
    public Connection getConnection() {
        // N사 DB 연결 코드
    }
}
class DUserDao extends UserDao {
    public Connection getConnection() {
        // D사 DB 연결 코드
    }
}

자기 점검

  • "변하지 않는 흐름"과 "변하는 부분"의 분리가 갖는 의미는?
  • 이 구조의 단점은? (힌트: 단일 상속)

원본 자료: 토비의 스프링 vol.1, p.65


📚 Phase 5 — 디자인 패턴의 적용

목표: Phase 4의 리팩토링이 사실은 디자인 패턴 2개의 적용 이었음을 알고, 그 한계까지 본다.

Unit 5.1 — 템플릿 메소드 패턴

선수 지식: Unit 4.3

핵심 개념

"슈퍼클래스에 기본 흐름을 만들고, 변하는 부분만 서브클래스에서 구현하게 하는 패턴"

구조:

[슈퍼클래스]
  ├─ 템플릿 메서드 (변하지 않는 흐름)
  └─ 추상 메서드 (변하는 부분)
        ↑ 오버라이드
        [서브클래스]

Phase 4-3의 UserDao 코드가 정확히 이 패턴.

자기 점검

  • Spring의 JdbcTemplate이 이름에 "Template"이 붙은 이유는?
  • 템플릿 메서드 패턴을 람다/함수형으로 대체할 수 있는가?

원본 자료: 토비의 스프링 vol.1, p.67


Unit 5.2 — 팩토리 메소드 패턴

선수 지식: Unit 5.1

핵심 개념

"객체 생성을 서브클래스에 위임하는 패턴"

getConnection() 도 사실은:

  • "어떤 Connection을 만들지" 결정하는 메서드
  • 객체 생성을 서브클래스에 맡김
  • → 팩토리 메소드 패턴

그래서 같은 코드가 두 패턴으로 동시에 해석된다:

  • "기본 흐름 + 변하는 부분" → 템플릿 메소드
  • "객체 생성을 서브클래스가 결정" → 팩토리 메소드

자기 점검

  • Spring의 BeanFactory 이름의 "Factory"는 이 패턴과 어떤 관련이 있는가?

원본 자료: 토비의 스프링 vol.1, p.67


Unit 5.3 — 두 패턴의 한계

선수 지식: Unit 5.2

핵심 한계

상속을 이용한 분리의 단점:

  • 단일 상속 제약 — UserDao를 상속받으면 다른 클래스 상속 불가
  • 컴파일 타임 결합 — 새 DB 추가하려면 새 클래스 만들고 컴파일
  • 상속 관계의 깨지기 쉬움 — 부모 변경 시 자식 다 영향

상속 대신 다른 방법이 필요하다: 인터페이스 + 합성(composition)

자기 점검

  • "Composition over Inheritance" 원칙의 의미는?
  • 상속을 인터페이스로 대체하면 무엇이 좋아지는가?

📚 Phase 6 — 객체지향 설계 원칙 (OCP & 전략 패턴)

목표: 인터페이스를 통한 결합도 낮추기로 OCP를 달성하고, 전략 패턴으로 더 유연한 구조를 만든다.

Unit 6.1 — 인터페이스로 결합도 낮추기

선수 지식: Unit 5.3

핵심 변화

public interface ConnectionMaker {
    Connection makeConnection();
}

public class UserDao {
    private ConnectionMaker connectionMaker;  // 인터페이스에 의존

    public UserDao(ConnectionMaker cm) {
        this.connectionMaker = cm;            // 외부에서 주입받음
    }

    public void add(User user) {
        Connection c = connectionMaker.makeConnection();
        // ...
    }
}

public class NConnectionMaker implements ConnectionMaker { ... }
public class DConnectionMaker implements ConnectionMaker { ... }

핵심 변화:

  • UserDao는 인터페이스에만 의존 → 어떤 구현체가 와도 OK
  • UserDao 코드는 새 DB 추가에도 변경 안 됨

자기 점검

  • 이 구조에서 ConnectionMaker 구현체를 결정하는 책임은 누구에게?
  • 1주차의 DIP(의존 역전 원칙)와 어떻게 연결되는가?

원본 자료: 토비의 스프링 vol.1, p.74~78


Unit 6.2 — OCP (개방폐쇄원칙)

선수 지식: Unit 6.1

핵심 개념

"확장에는 열려있고, 변경에는 닫혀있어야 한다"

UserDao의 변화:

  • 새 DB 지원 = ConnectionMaker 구현체 추가 (확장) ✅
  • UserDao 코드는 그대로 (변경 없음) ✅

OCP 만족

OCP가 깨지는 코드의 신호:

  • if (type.equals("MySQL")) ... else if (type.equals("Oracle"))
  • switch 문이 새 케이스 추가될 때마다 수정됨

자기 점검

  • OCP를 100% 지키는 게 가능한가?
  • OCP와 SRP는 어떻게 연결되는가?

원본 자료: 토비의 스프링 vol.1, p.83


Unit 6.3 — 전략 패턴

선수 지식: Unit 6.2

핵심 개념

"필요에 따라 변경되는 알고리즘을 인터페이스로 분리하고, 구체 구현을 외부에서 주입받는 패턴"

용어 매핑:

  • Context = UserDao
  • Strategy = ConnectionMaker (인터페이스)
  • ConcreteStrategy = NConnectionMaker, DConnectionMaker

전략 패턴은 곧 OCP의 구현 도구:

  • 새 전략 = ConcreteStrategy 추가 (확장)
  • Context 코드는 변경 없음

자기 점검

  • 전략 패턴과 템플릿 메소드 패턴의 차이는? (힌트: 상속 vs 합성)
  • Spring에서 전략 패턴이 사용되는 사례는?

원본 자료: 토비의 스프링 vol.1, p.87


📚 Phase 7 — 제어의 역전 (IoC)

목표: 객체 생성·연결·관리의 책임이 어디서 어디로 옮겨가는지 추적한다.

Unit 7.1 — IoC (제어의 역전) 개념

선수 지식: Phase 6

핵심 개념

전통 방식:

public class UserDao {
    public UserDao() {
        this.connectionMaker = new NConnectionMaker();  // 자기가 결정
    }
}

→ UserDao가 자신이 사용할 객체를 스스로 결정·생성

IoC 방식:

public class UserDao {
    public UserDao(ConnectionMaker cm) {
        this.connectionMaker = cm;  // 외부에서 주입
    }
}

→ "어떤 ConnectionMaker를 쓸지"의 결정 권한이 외부로 넘어감

제어의 역전:

  • 객체가 자신이 사용할 객체를 선택하지 않음
  • 누가 그 결정을 하나? → 다른 객체 / 프레임워크 / 컨테이너

자기 점검

  • "역전(Inversion)"에서 무엇이 무엇으로 뒤집히는가?
  • main() 메서드 외에 IoC가 어디에서 일어나는가?

원본 자료: 토비의 스프링 vol.1, p.92


Unit 7.2 — 프레임워크 vs 라이브러리

선수 지식: Unit 7.1

핵심 차이:

라이브러리프레임워크
누가 흐름을 제어내 코드프레임워크
호출 방향내 코드 → 라이브러리프레임워크 → 내 코드
비유망치 (필요할 때 꺼내 씀)공장 (들어가서 일함)

Hollywood Principle: "Don't call us, we'll call you" (프레임워크가 너를 부른다)

자기 점변

  • jQuery는 라이브러리인가, 프레임워크인가?
  • Spring이 프레임워크인 이유는?

원본 자료: 토비의 스프링 vol.1, p.93


Unit 7.3 — IoC 컨테이너의 역할

선수 지식: Unit 7.2

핵심 개념

IoC를 실제로 구현하려면 누군가가:

  • 객체를 생성
  • 객체 간 관계를 설정
  • 객체의 생명주기 관리

이 역할을 하는 게 IoC 컨테이너 = Spring의 ApplicationContext.

자기 점검

  • IoC 컨테이너 없이 IoC를 구현하면 어떻게 되는가? (힌트: main에서 다 만들기)
  • Spring 외에 IoC 컨테이너의 다른 예는?

원본 자료: 토비의 스프링 vol.1, p.94


📚 Phase 8 — Spring 컨테이너 (ApplicationContext + DI)

목표: Spring의 핵심 클래스 ApplicationContext와 DI의 동작을 이해한다.

Unit 8.1 — 빈 팩토리와 ApplicationContext

선수 지식: Phase 7

핵심 개념

  • 빈(Bean): Spring이 관리하는 객체
  • 빈 팩토리(BeanFactory): 빈을 생성·관리하는 가장 기본 인터페이스
  • ApplicationContext: BeanFactory를 확장한 더 풍부한 컨테이너 (실무 표준)
@Configuration
public class DaoFactory {
    @Bean
    public UserDao userDao() {
        return new UserDao(connectionMaker());
    }
    @Bean
    public ConnectionMaker connectionMaker() {
        return new DConnectionMaker();
    }
}

ApplicationContext ctx = new AnnotationConfigApplicationContext(DaoFactory.class);
UserDao dao = ctx.getBean("userDao", UserDao.class);

자기 점검

  • @Bean 메서드의 이름이 빈의 ID가 되는 이유는?
  • ApplicationContext가 BeanFactory보다 갖는 추가 기능은? (힌트: i18n, 이벤트)

원본 자료: 토비의 스프링 vol.1, p.95


Unit 8.2 — getBean()의 동작

선수 지식: Unit 8.1

핵심 동작

ctx.getBean("userDao") 호출 시 ApplicationContext는:
1. 빈 목록에서 "userDao" 찾기
2. 없으면 @Bean 메서드 호출 → 객체 생성
3. 의존하는 다른 빈도 자동으로 같이 생성·주입
4. 만들어진 빈 반환

자기 점검

  • 처음 호출과 두 번째 호출의 동작 차이는? (힌트: 다음 Unit)
  • @Bean 메서드를 직접 호출하는 것과 getBean()의 차이는?

원본 자료: 토비의 스프링 vol.1, p.100


Unit 8.3 — 싱글톤 레지스트리

선수 지식: Unit 8.2

핵심 개념

getBean()을 100번 호출해도 객체는 1개.

  • ApplicationContext = 싱글톤 레지스트리
  • 모든 빈은 기본적으로 싱글톤 (ApplicationContext 안에서)

왜 싱글톤?

  • 매 요청마다 객체 새로 만들면 메모리·GC 부담
  • DAO·Service 같은 무상태 객체는 1개로 충분
  • 전역 접근 가능

주의: 싱글톤 빈은 stateless 여야 안전:

  • 인스턴스 변수에 요청별 데이터 보관 ❌ (멀티스레드 충돌)
  • → 4주차의 동시성 문제와 연결됨!

자기 점검

  • 전통 싱글톤 패턴(getInstance())과 Spring 싱글톤의 차이는?
  • 싱글톤 빈이 ConcurrentHashMap을 필드로 가져도 되는 이유는?

원본 자료: 토비의 스프링 vol.1, p.104~106


Unit 8.4 — 의존관계 주입 (DI)

선수 지식: Unit 8.3

핵심 개념

DI (Dependency Injection):

"구체적인 의존 오브젝트와 그것을 사용할 클라이언트를 런타임에 연결해주는 작업"

3가지 핵심:
1. 의존: A가 B를 사용 (A → B)
2. 인터페이스 의존: A는 B의 인터페이스에만 의존 (구체 구현 모름)
3. 외부 주입: 컨테이너가 런타임에 구체 구현을 주입

3가지 주입 방식:

  • 생성자 주입 (권장 ✅)
  • Setter 주입
  • 필드 주입 (@Autowired 필드)

자기 점검

  • DI와 IoC의 관계는? (힌트: DI는 IoC의 한 형태)
  • 생성자 주입이 권장되는 이유 3가지는? (힌트: final, 순환 참조 감지, 테스트 용이성)

🎓 종합 자기 점검 (5주차 졸업 시험)

Part A: 동시성 마무리

  1. 스레드를 많이 만들수록 항상 빠른가? 그렇지 않은 이유 3가지는?
  2. 가시성과 원자성의 차이를 예시로 설명하라
  3. synchronized / volatile / Atomic의 해결 범위와 성능 비교는?
  4. CAS 알고리즘이 동작하는 4단계는?
  5. CAS의 ABA 문제란?

Part B: 객체 설계의 진화

  1. DAO와 비즈니스 로직을 분리하는 이유는?
  2. "관심사의 분리"의 정의는?
  3. 같은 코드가 템플릿 메소드 패턴이면서 동시에 팩토리 메소드 패턴인 이유는?
  4. 상속 기반 분리의 한계 3가지는?
  5. 인터페이스 도입이 OCP를 어떻게 달성하는가?

Part B: 디자인 원칙과 패턴

  1. OCP의 정의를 자기 말로 설명하라
  2. 전략 패턴의 3가지 구성 요소는?
  3. 전략 패턴과 템플릿 메소드 패턴의 차이는?

Part B: IoC와 DI

  1. IoC에서 무엇이 무엇으로 역전되는가?
  2. 프레임워크와 라이브러리의 결정적 차이는?
  3. ApplicationContext의 역할 4가지는?
  4. getBean()을 100번 호출해도 객체가 1개인 이유는?
  5. 싱글톤 빈이 stateless여야 하는 이유는? (4주차 동시성과 연결)
  6. 생성자 주입이 권장되는 이유 3가지는?
  7. DI와 IoC의 관계는?

📌 학습 운영 팁

9-섹션 마스터 프롬프트로 깊이 파야 할 Unit

반드시 깊이 파기:

  • Unit 2.4 — Atomic + CAS 알고리즘 (★★★ 면접 단골)
  • Unit 4.1 ~ 4.3 — 관심사 분리의 진화 (Spring 이해의 출발점)
  • Unit 6.2 — OCP (모든 디자인 패턴의 뿌리)
  • Unit 7.1 — IoC 개념 (Spring의 정신)
  • Unit 8.3 — 싱글톤 레지스트리 (실무 동시성 직결)
  • Unit 8.4 — DI (Spring의 핵심)

Phase별 진도 체크리스트

[ ] Phase 1 — 스레드 풀의 필요성 재정리 (Unit 1.1~1.3)
[ ] Phase 2 — 동시성 안전 도구 3종 비교 (Unit 2.1~2.4)
[ ] Phase 3 — 전통 DAO의 문제 (Unit 3.1~3.3)
[ ] Phase 4 — 관심사의 분리 (Unit 4.1~4.3)
[ ] Phase 5 — 디자인 패턴 적용 (Unit 5.1~5.3)
[ ] Phase 6 — OCP & 전략 패턴 (Unit 6.1~6.3)
[ ] Phase 7 — 제어의 역전 (Unit 7.1~7.3)
[ ] Phase 8 — Spring 컨테이너 (Unit 8.1~8.4)
[ ] 종합 자기 점검 20문항 통과

5주차의 두 흐름 연결 포인트

동시성 (Part A)Spring (Part B)
스레드 풀 = "스레드를 누가 관리하는가"IoC 컨테이너 = "객체를 누가 관리하는가"
Atomic/synchronized = "공유 자원 보호"싱글톤 빈 = "공유되는 객체" → stateless 필요
ExecutorService = 스레드 추상화ApplicationContext = 객체 추상화

두 흐름의 본질은 "관리 책임의 위임" 이라는 동일한 사상.


1~5주차 통합 흐름

  • 1~3주차: 자바 언어 자체 정복 (OOP·JVM·컬렉션·함수형)
  • 4주차: 멀티스레드와 동시성
  • 5주차 (지금): Atomic 마무리 + Spring IoC/DI 입문 ← 자바 → Spring 다리
profile
Software Developer

0개의 댓글