From d0934718100e5199f8405c2bc904fd9101df4fe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=98=EC=84=B1=EC=A4=80?= Date: Fri, 15 May 2026 19:24:51 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=ED=95=98=EC=84=B1=EC=A4=80=20week06=20?= =?UTF-8?q?=EA=B3=BC=EC=A0=9C=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- solution/week06/Problem1.java | 38 +++++++++++++++++---------- solution/week06/Problem2.java | 49 +++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 33 deletions(-) diff --git a/solution/week06/Problem1.java b/solution/week06/Problem1.java index dd56019..27d2917 100644 --- a/solution/week06/Problem1.java +++ b/solution/week06/Problem1.java @@ -73,6 +73,7 @@ interface BookService { // MemoryBookRepository에 @Component를 붙여서 // 컴포넌트 스캔 시 스프링이 자동으로 빈으로 등록하게 하세요. // ────────────────────────────────────────────────────────────────────── + @Component static class MemoryBookRepository implements BookRepository { private final Map store = new HashMap<>(); @@ -99,21 +100,28 @@ public Book findById(Long id) { // 힌트: 생성자가 딱 1개면 @Autowired를 생략해도 자동 주입됩니다. // 하지만 이번엔 명시적으로 붙여봅시다! // ────────────────────────────────────────────────────────────────────── + @Component static class BookServiceImpl implements BookService { // TODO ②: private final BookRepository bookRepository; + private final BookRepository bookRepository; // TODO ③: @Autowired 생성자 작성 + @Autowired + public BookServiceImpl (BookRepository bookRepository) { + this.bookRepository = bookRepository; + } @Override public void register(Book book) { // TODO ④: bookRepository.save(book) 호출 + bookRepository.save(book); } @Override public Book findBook(Long id) { // TODO ④: return bookRepository.findById(id) - return null; + return bookRepository.findById(id); } } @@ -127,6 +135,8 @@ public Book findBook(Long id) { // 참고: @Bean 메서드는 작성하지 않아도 됩니다. // @ComponentScan이 @Component 클래스들을 알아서 찾아 등록해줍니다. // ────────────────────────────────────────────────────────────────────── + @ComponentScan + @Configuration static class AutoAppConfig { // 비어 있어도 괜찮습니다! } @@ -135,18 +145,18 @@ static class AutoAppConfig { // main: TODO를 모두 완성한 후 아래 주석을 해제하고 실행해보세요. // ────────────────────────────────────────────────────────────────────── public static void main(String[] args) { - // AnnotationConfigApplicationContext ac = - // new AnnotationConfigApplicationContext(AutoAppConfig.class); - // BookService bookService = ac.getBean(BookService.class); - // - // Book book = new Book(1L, "스프링 핵심 원리", "김영한"); - // bookService.register(book); - // - // Book found = bookService.findBook(1L); - // System.out.println("등록한 도서: " + book.getTitle()); - // System.out.println("조회한 도서: " + found.getTitle()); - // System.out.println("일치 여부: " + book.getTitle().equals(found.getTitle())); - // - // ac.close(); + AnnotationConfigApplicationContext ac = + new AnnotationConfigApplicationContext(AutoAppConfig.class); + BookService bookService = ac.getBean(BookService.class); + + Book book = new Book(1L, "스프링 핵심 원리", "김영한"); + bookService.register(book); + + Book found = bookService.findBook(1L); + System.out.println("등록한 도서: " + book.getTitle()); + System.out.println("조회한 도서: " + found.getTitle()); + System.out.println("일치 여부: " + book.getTitle().equals(found.getTitle())); + + ac.close(); } } diff --git a/solution/week06/Problem2.java b/solution/week06/Problem2.java index 7889345..9eb14d2 100644 --- a/solution/week06/Problem2.java +++ b/solution/week06/Problem2.java @@ -76,6 +76,7 @@ public void sendOrder(String item) { // 빈 초기화 완료 직후 이 메서드가 자동으로 호출되도록 // @PostConstruct 애노테이션을 붙이세요. // ────────────────────────────────────────────────────────────────── + @PostConstruct public void init() { System.out.println("[init] CafeConnection 초기화"); connect(); @@ -87,6 +88,7 @@ public void init() { // 빈 소멸 직전에 이 메서드가 자동으로 호출되도록 // @PreDestroy 애노테이션을 붙이세요. // ────────────────────────────────────────────────────────────────── + @PreDestroy public void close() { System.out.println("[close] CafeConnection 종료"); disconnect(); @@ -109,6 +111,7 @@ public void close() { // OrderCounter가 스프링 컨테이너에 요청할 때마다 새로 생성되도록 // @Scope("prototype") 을 추가하세요. // ────────────────────────────────────────────────────────────────────── + @Scope("prototype") @Component static class OrderCounter { private int count = 0; @@ -152,14 +155,22 @@ static class CafeOrderService { // ────────────────────────────────────────────────────────────────── // TODO ①: private final ObjectProvider counterProvider; + private final ObjectProvider counterProvider; // TODO ②: @Autowired 생성자 작성 + @Autowired + public CafeOrderService (ObjectProvider counterProvider) { + this.counterProvider = orderCounter; + } public int processOrder(String itemName) { System.out.println("[주문 처리] " + itemName); // TODO ③: counterProvider.getObject()로 새 OrderCounter를 꺼내 // increment() 호출 후 getCount() 반환 - return -1; // 완성 전 임시 반환값 + OrderCounter orderCounter = counterProvider.getObject(); + orderCounter.increment(); + int count = orderCounter.getCount(); + return count; // 완성 전 임시 반환값 } } @@ -174,23 +185,23 @@ static class CafeAppConfig { } // main: TODO를 모두 완성한 후 아래 주석을 해제하고 실행해보세요. // ────────────────────────────────────────────────────────────────────── public static void main(String[] args) { - // AnnotationConfigApplicationContext ac = - // new AnnotationConfigApplicationContext(CafeAppConfig.class); - // - // // ── Part A 확인 ───────────────────────────────────────────────── - // CafeConnection conn = ac.getBean(CafeConnection.class); - // System.out.println("연결 상태: " + conn.isConnected()); // true 여야 함 - // conn.sendOrder("아메리카노"); - // - // // ── Part B 확인 ───────────────────────────────────────────────── - // CafeOrderService orderService = ac.getBean(CafeOrderService.class); - // - // int count1 = orderService.processOrder("카페라떼"); - // int count2 = orderService.processOrder("에스프레소"); - // - // System.out.println("주문 1 카운트: " + count1); // 1 이어야 함 - // System.out.println("주문 2 카운트: " + count2); // 1 이어야 함 (새 프로토타입!) - // - // ac.close(); // @PreDestroy 호출 확인 + AnnotationConfigApplicationContext ac = + new AnnotationConfigApplicationContext(CafeAppConfig.class); + + // ── Part A 확인 ───────────────────────────────────────────────── + CafeConnection conn = ac.getBean(CafeConnection.class); + System.out.println("연결 상태: " + conn.isConnected()); // true 여야 함 + conn.sendOrder("아메리카노"); + + // ── Part B 확인 ───────────────────────────────────────────────── + CafeOrderService orderService = ac.getBean(CafeOrderService.class); + + int count1 = orderService.processOrder("카페라떼"); + int count2 = orderService.processOrder("에스프레소"); + + System.out.println("주문 1 카운트: " + count1); // 1 이어야 함 + System.out.println("주문 2 카운트: " + count2); // 1 이어야 함 (새 프로토타입!) + + ac.close(); // @PreDestroy 호출 확인 } } From bf46b0a7748c5344e94100480cb53f8f98d10c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=98=EC=84=B1=EC=A4=80?= Date: Fri, 15 May 2026 22:34:36 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=ED=95=98=EC=84=B1=EC=A4=80=206=EC=A3=BC?= =?UTF-8?q?=EC=B0=A8=20=EA=B3=BC=EC=A0=9C=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Problem1.java" | 18 +++-- .../Problem2.java" | 69 ++++++++++++------- 2 files changed, 59 insertions(+), 28 deletions(-) diff --git "a/src/week06/\355\225\230\354\204\261\354\244\200/Problem1.java" "b/src/week06/\355\225\230\354\204\261\354\244\200/Problem1.java" index e5c54c5..592fa4d 100644 --- "a/src/week06/\355\225\230\354\204\261\354\244\200/Problem1.java" +++ "b/src/week06/\355\225\230\354\204\261\354\244\200/Problem1.java" @@ -1,4 +1,4 @@ -package week06.하성준; +package week06.solution; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -73,6 +73,7 @@ interface BookService { // MemoryBookRepository에 @Component를 붙여서 // 컴포넌트 스캔 시 스프링이 자동으로 빈으로 등록하게 하세요. // ────────────────────────────────────────────────────────────────────── + @Component static class MemoryBookRepository implements BookRepository { private final Map store = new HashMap<>(); @@ -99,21 +100,28 @@ public Book findById(Long id) { // 힌트: 생성자가 딱 1개면 @Autowired를 생략해도 자동 주입됩니다. // 하지만 이번엔 명시적으로 붙여봅시다! // ────────────────────────────────────────────────────────────────────── + @Component static class BookServiceImpl implements BookService { // TODO ②: private final BookRepository bookRepository; + private final BookRepository bookRepository; // TODO ③: @Autowired 생성자 작성 + @Autowired + public BookServiceImpl (BookRepository bookRepository) { + this.bookRepository = bookRepository; + } @Override public void register(Book book) { // TODO ④: bookRepository.save(book) 호출 + bookRepository.save(book); } @Override public Book findBook(Long id) { // TODO ④: return bookRepository.findById(id) - return null; + return bookRepository.findById(id); } } @@ -127,12 +135,14 @@ public Book findBook(Long id) { // 참고: @Bean 메서드는 작성하지 않아도 됩니다. // @ComponentScan이 @Component 클래스들을 알아서 찾아 등록해줍니다. // ────────────────────────────────────────────────────────────────────── + @ComponentScan + @Configuration static class AutoAppConfig { // 비어 있어도 괜찮습니다! } // ────────────────────────────────────────────────────────────────────── - // main: 먼저 실행해서 오류를 확인한 뒤, TODO를 채워서 고쳐보세요. + // main: TODO를 모두 완성한 후 아래 주석을 해제하고 실행해보세요. // ────────────────────────────────────────────────────────────────────── public static void main(String[] args) { AnnotationConfigApplicationContext ac = @@ -149,4 +159,4 @@ public static void main(String[] args) { ac.close(); } -} +} \ No newline at end of file diff --git "a/src/week06/\355\225\230\354\204\261\354\244\200/Problem2.java" "b/src/week06/\355\225\230\354\204\261\354\244\200/Problem2.java" index be2f0d1..aec004c 100644 --- "a/src/week06/\355\225\230\354\204\261\354\244\200/Problem2.java" +++ "b/src/week06/\355\225\230\354\204\261\354\244\200/Problem2.java" @@ -1,4 +1,4 @@ -package week06.하성준; +package week06.solution; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; @@ -76,6 +76,7 @@ public void sendOrder(String item) { // 빈 초기화 완료 직후 이 메서드가 자동으로 호출되도록 // @PostConstruct 애노테이션을 붙이세요. // ────────────────────────────────────────────────────────────────── + @PostConstruct public void init() { System.out.println("[init] CafeConnection 초기화"); connect(); @@ -87,6 +88,7 @@ public void init() { // 빈 소멸 직전에 이 메서드가 자동으로 호출되도록 // @PreDestroy 애노테이션을 붙이세요. // ────────────────────────────────────────────────────────────────── + @PreDestroy public void close() { System.out.println("[close] CafeConnection 종료"); disconnect(); @@ -109,6 +111,7 @@ public void close() { // OrderCounter가 스프링 컨테이너에 요청할 때마다 새로 생성되도록 // @Scope("prototype") 을 추가하세요. // ────────────────────────────────────────────────────────────────────── + @Scope("prototype") @Component static class OrderCounter { private int count = 0; @@ -137,19 +140,37 @@ static class CafeOrderService { // ────────────────────────────────────────────────────────────────── // TODO B-2 // ────────────────────────────────────────────────────────────────── + // ① ObjectProvider 타입의 필드를 선언하세요. + // (필드명 예시: counterProvider) + // + // ② @Autowired 생성자를 작성해 ObjectProvider를 주입받으세요. + // + // ③ processOrder() 안에서: + // - counterProvider.getObject()로 새 OrderCounter를 꺼내세요. + // - increment()를 호출하세요. + // - getCount()를 반환하세요. + // // 주의: getObject()를 호출할 때마다 새 프로토타입 빈이 생성됩니다. // OrderCounter를 필드에 직접 @Autowired 주입받으면 어떻게 될지 생각해보세요. // ────────────────────────────────────────────────────────────────── - // TODO ① 필드 선언: ObjectProvider 타입의 counterProvider를 선언하세요. + // TODO ①: private final ObjectProvider counterProvider; + private final ObjectProvider counterProvider; - // TODO ② 생성자: @Autowired를 붙인 생성자로 counterProvider를 주입받으세요. + // TODO ②: @Autowired 생성자 작성 + @Autowired + public CafeOrderService (ObjectProvider counterProvider) { + this.counterProvider = orderCounter; + } public int processOrder(String itemName) { System.out.println("[주문 처리] " + itemName); - // TODO ③ 구현: counterProvider.getObject()로 새 OrderCounter를 꺼내 - // increment() 호출 후 getCount()를 반환하세요. - return -1; // TODO 완성 후 이 줄을 지우세요. + // TODO ③: counterProvider.getObject()로 새 OrderCounter를 꺼내 + // increment() 호출 후 getCount() 반환 + OrderCounter orderCounter = counterProvider.getObject(); + orderCounter.increment(); + int count = orderCounter.getCount(); + return count; // 완성 전 임시 반환값 } } @@ -164,23 +185,23 @@ static class CafeAppConfig { } // main: TODO를 모두 완성한 후 아래 주석을 해제하고 실행해보세요. // ────────────────────────────────────────────────────────────────────── public static void main(String[] args) { - // AnnotationConfigApplicationContext ac = - // new AnnotationConfigApplicationContext(CafeAppConfig.class); - // - // // ── Part A 확인 ───────────────────────────────────────────────── - // CafeConnection conn = ac.getBean(CafeConnection.class); - // System.out.println("연결 상태: " + conn.isConnected()); // true 여야 함 - // conn.sendOrder("아메리카노"); - // - // // ── Part B 확인 ───────────────────────────────────────────────── - // CafeOrderService orderService = ac.getBean(CafeOrderService.class); - // - // int count1 = orderService.processOrder("카페라떼"); - // int count2 = orderService.processOrder("에스프레소"); - // - // System.out.println("주문 1 카운트: " + count1); // 1 이어야 함 - // System.out.println("주문 2 카운트: " + count2); // 1 이어야 함 (새 프로토타입!) - // - // ac.close(); // @PreDestroy 호출 확인 + AnnotationConfigApplicationContext ac = + new AnnotationConfigApplicationContext(CafeAppConfig.class); + + // ── Part A 확인 ───────────────────────────────────────────────── + CafeConnection conn = ac.getBean(CafeConnection.class); + System.out.println("연결 상태: " + conn.isConnected()); // true 여야 함 + conn.sendOrder("아메리카노"); + + // ── Part B 확인 ───────────────────────────────────────────────── + CafeOrderService orderService = ac.getBean(CafeOrderService.class); + + int count1 = orderService.processOrder("카페라떼"); + int count2 = orderService.processOrder("에스프레소"); + + System.out.println("주문 1 카운트: " + count1); // 1 이어야 함 + System.out.println("주문 2 카운트: " + count2); // 1 이어야 함 (새 프로토타입!) + + ac.close(); // @PreDestroy 호출 확인 } }