묻고 답해요
169만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 핵심 원리 - 기본편
Member 클래스와 HashMap에 관하여 질문 있습니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예[질문 내용]안녕하세요. 스프링 강의를 잘 듣고 있는 사람입니다. 회원 만들기 예제1을 따라 만들던 도중 궁금한 점이 생겨 문의 드립니다. 문의 사항은 아래와 같습니다.Member 클래스를 만들때 Member를 Entity라고 표현을 하시고 클래스 다이어그램에선 Member에 대한 내용이 없어서 이 부분이 궁금합니다. 각 클래스마다 Member를 따로 객체로 생성하지 않고 main문에서 member 객체를 생성하기에 클래스 다이어그램에 들어가진 않은거 같은데, 이 Member 클래스를 왜 Entity라고 표현하시는지 궁금합니다. MemberRepository를 구현하는 MemoryMemberRepository의 해쉬맵의 put을 보면 Long 타입 하나와 Member 하나를 저장할 수 있는 해쉬맵인데요, 근데 Member엔 이미 ID를 저장할 수 있는 private Long id가 있고 main문에서 객체를 생성할때 값을 집어 넣어주는데, 굳이 Member.getId()를 통해 Id 값을 저장해주었는지가 궁금합니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
OrderRepositoryTest에서 Product 객체를 생성하는 것을 생략하고 테스트 해도 괜찮나요?
OrderRepository에서 startDateTime, endDateTime, orderStatus를 파라미터로 받아 List<Order>를 반환하는 findOrdersBy 쿼리메소드를 테스트하려고합니다.OrderRepositoryTest 내부에서 해당 테스트를 작성하던 중 given절에서 Product 객체를 생성하는 과정을 생략하고 Order 객체를 생성할때 비어있는 리스트를 이용하여 생성하도록 하였습니다. @ActiveProfiles("test") @SpringBootTest class OrderRepositoryTest { @Autowired private OrderRepository orderRepository; @DisplayName("원하는 기간과 원하는 주문상태의 주문들을 조회한다.") @Test void findOrdersBy() { // given LocalDate registeredTime = LocalDate.of(2024, 10, 24); Order order1 = Order.builder() .products(List.of()) .orderStatus(PAYMENT_COMPLETED) .registeredDateTime(registeredTime.atStartOfDay()) .build(); Order order2 = Order.builder() .products(List.of()) .orderStatus(PAYMENT_COMPLETED) .registeredDateTime(registeredTime.plusDays(1).atStartOfDay()) .build(); orderRepository.saveAll(List.of(order1, order2)); // when List<Order> orders = orderRepository.findOrdersBy( registeredTime.atStartOfDay(), registeredTime.plusDays(1).atStartOfDay(), PAYMENT_COMPLETED); // then assertThat(orders).hasSize(1) .extracting("orderStatus", "registeredDateTime") .contains( tuple(PAYMENT_COMPLETED, registeredTime.atStartOfDay()) ); }이는 테스트하려는 목적이 Order 객체 내부에 적절한 List<OrderProduct> 값을 가지고 있는지를 검증하려는 것이 아니고 findOrdersBy 쿼리메소드가 적절한 Order객체를 가져오는지를 테스트하는 것이라고 생각하였습니다.위와 같이 실제 객체를 생성하는 것 대신 비어있는 리스트 값을 활용하는 것도 괜찮은지 궁금합니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
stub, mock 개념차이
// stubbing when(mailSendClient.sendEmail(any(String.class), any(String.class), any(String.class), any(String.class))) .thenReturn(true);안녕하세요.어떤 기능을 요청해서 어떤 결과를 반환하니 행위검증용도의 목킹이 아닌가요?강의에서는 스터빙이라고 설명하고 있는데, 상태검증보단 행위검증인거같아서요
-
미해결실전! 스프링 데이터 JPA
@Transactional에 대해서 궁금합니다.
이전에 공부할 때 엔티티매니저에서 트랜잭션을 가져야 로직이 수행된다는 것을 알고 있었습니다. 그런데 이전에 JPA활용2편에 @Transactional을 따로 붙혀주지 않았는데 로직이 실행된걸로 기억하는데 @Service나 @Repository에 의해서 자동으로 트랜잭션이 걸리는 건가요?
-
미해결Practical Testing: 실용적인 테스트 가이드
안녕하세요 레포지토리 관련 질문이 있습니다.
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요 선생님 강의중 하나 궁금증이 생겼습니다. 제가 알기로 Jpa Repository 인터페이스를 생성할 때 @Repository 어노테이션을 사용하지 않아도 최상위 구현체인 Repository 클래스를 구현받고 있기 때문에스프링 컨테이너에서 빈을 주입해준다? 라고 알고있는데@Repository public interface ProductRepository extends JpaRepository<Product, Long> { 어노테이션을 없애고 테스트를 돌려봐도 문제없이 돌아갔고위 어노테이션을 없이 인터페이스를 사용해도 문제없이 실행이 잘 됩니다. 혹시 선생님이 @Repository 어노테이션을 생성해서 개발하시는 이유가 따로 있으신지 궁금합니다.
-
미해결스프링부트 시큐리티 & JWT 강의
이전 강의 참고하라는 말씀
안녕하세요! 최주호 강사님의 수준높은 강의를 통해 시큐리티를 배우고 있는 중입니다. 강의 중간중간에 동작 원리는 이전 강의 올려둔 거 참고하라고 말씀하셨는데 유튜브를 다 찾아보아도 없더라구요... 혹시 어디서 볼 수 있는지 알 수 있을까요?
-
해결됨스프링 핵심 원리 - 고급편
JDK 동적 프록시 호출 메서드 감지?
1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]proxy의 call을 호출한 후 어떻게 InvocationHandler.invoke() 를 호출하는 걸까요?
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
트랜잭션 질문
public class OrderApiController { @GetMapping("/api/v1/orders") public List<Order> orderV1() { List<Order> all = orderRepository.findAllByString(new OrderSearch()); for (Order order : all) { order.getMember().getName(); order.getDelivery().getAddress(); List<OrderItem> orderItems = order.getOrderItems(); orderItems.forEach(o -> o.getItem().getName()); } return all; } } public class OrderRepository{ public List<Order> findAllByString(OrderSearch orderSearch) { String jpql = "select o from Order o join o.member m"; boolean isFirstCondition = true; //주문 상태 검색 if (orderSearch.getOrderStatus() != null) { if (isFirstCondition) { jpql += " where"; isFirstCondition = false; } else { jpql += " and"; } jpql += " o.status = :status"; } ...트랜잭션을 따로 붙히지 않았는데 상관없는건가요?List<Order> all = orderRepository.findAllByString(new OrderSearch()); 이 때 연관관계매핑되어 있는 객체들은 지연로딩에 의해 프록시로 존재하고 for (Order order : all) { order.getMember().getName(); order.getDelivery().getAddress(); List<OrderItem> orderItems = order.getOrderItems(); orderItems.forEach(o -> o.getItem().getName()); } 이 때 강제호출 되어서 쿼리가 나가는 게 맞나요?orderRepository.findAllByString에서 repository에서 작업이 마쳐서 트랜잭션이 커밋되어서 영속성 컨텍스트에는 아무값이 없을 거 같은데 컨트롤러에서 리턴하기 전까지 하나의 트랜잭션 안에서 작동이 이뤄지는 건가요?트랜잭션이 언제 시작하고 언제 종료되는 지 궁금합니다
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
new HashMap 관련한 import 문제
[질문 내용]코드에서 private static Map<Long, Member> store = new HashMap<>(); 부분이 있는데요.. 중간에 코딩시에 HashMap 부분에 빨간줄이 그어져있어서뭔가 문제지 했는데나중에 코드를 보니까import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Optional;처음 작성시엔 위의 코드로 import 가 되어있었는데동영상 후반에 보니까 아래 코드로 변경되어져 있었습니다.import java.util.*;위 import 부분을 강의영상에서 변경된 부분을 못찾았는데어떠한 이유로 그렇게 변경된건지 알고 싶습니다.
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
findAllByString() 실행 시 총 쿼리 7번 날아갑니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]이전 질문 내역에서 하이버네이트6 최적화 문제라는 답변을 봤는데.. 아직 패치가 안된건지 2024 년에도 총 7번 쿼리날아가네요. 디버깅 해보니address = order.getDelivery().getAddress(); // LAZY 초기화이 부분에서select d1_0.delivery_id, d1_0.city, d1_0.street, d1_0.zipcode, d1_0.status from delivery d1_0 where d1_0.delivery_id=? 2024-10-22T14:07:35.134+09:00 DEBUG 6578 --- [nio-8080-exec-1] org.hibernate.SQL : select o1_0.order_id, o1_0.delivery_id, o1_0.member_id, o1_0.order_date, o1_0.status from orders o1_0 where o1_0.delivery_id=?이렇게 두번 쿼리가 실행되네요..그래서 List<Order> all = orderRepository.findAllByString(new OrderSearch());여기서 쿼리 한번 name = order.getMember().getName(); // LAZY 초기화여기서 쿼리 한번 address = order.getDelivery().getAddress(); // LAZY 초기화여기서 쿼리 두번 주문 리스트가 2개 있으므로1 + 2 * (1 + 2) = 7 번 실행됩니다.궁금한 점은 select o1_0.order_id, o1_0.delivery_id, o1_0.member_id, o1_0.order_date, o1_0.status from orders o1_0 where o1_0.delivery_id=?이 쿼리는 왜 추가적으로 실행되는지 모르겠습니다.
-
미해결스프링 핵심 원리 - 기본편
조회되는 빈이 2개 이상이더라도 문제가 없는 이유
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]AllBeanTest에서 DiscountService에 의존 관계를 주입할 때, Map과 List를 사용했기 때문에, RateDiscountPolicy, FixDiscountPolicy 두 가지 빈이 등록되어 있어도 문제가 없는 건가요??
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
매핑이란
개념적인걸 다시 복습중인데요청정보를 매핑, 매핑정보를 저장, 핸들러매핑 등등매핑이 자주 나오는데스프링빈 이름으로 컨트롤러를 찾는것이 매핑인가요?
-
미해결Practical Testing: 실용적인 테스트 가이드
Presentation Layer 테스트 관련 질문 있습니다!
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 현재 Presentation Layer 테스트에서 create할때에는 httpstatus만 확인하는데 보통 Presentation Layer 테스트의 경우 상태값만 확인하고 실제로 db에 저장되어 있는지 확인하지는 않을까요? 만약 확인한다면 통합테스트가 필요할 것 같은데 약간 다른 결의 질문이지만 통합테스트시에 spring Security 인증을 포함해서 해야할까요 아니면 제외하고 해야할까요?만약 제외하고 해야한다면 통합테스트시 spring Security를어떻게 제외해야 하는지도 여쭤보고 싶습니다
-
미해결스프링 핵심 원리 - 기본편
관심사의 분리 테스트 코드 수정 - BeforeEach 사용 이유
1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]관심사의 분리 강의 24분 20초대에 MemberServiceTest 테스트 코드 수정 부분입니다. 강사님께서 AppCofig를 바로 사용하시는게 애매하다고 말씀하시고 "BeforeEach"를 통하여, 각 테스트 진행 전 memberService를 새롭게 정의하는 방식으로 알려주셨습니다궁금한점이, 생성된 memberService 인스턴스가 일부 테스트 함수에서, 멤버 변수로 값을 대입 받는다거나 그런 로직이 있는 경우들 때문에 애매하다고 말씀을 해주신 것일까요? (좀 더 상세하게 알려주시면 감사드리겠습니다)현재 강의에서 사용되는 MemberServiceImpl 클래스에서 정의되어있는 메서드들은 재활용 되어도 별 문제 없다는 생각이 들어, MemberServiceTest-테스트 클래스 상단에 AppConfig 정의해주고 memberService도 초기화하지 않은 이유에 대해 좀 더 상세하게 알고 싶어 질문 드리게 되었습니다
-
해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
@Transactional(readOnly = true) 의 트레이드 오프
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]안녕하세요 영한님.이 강의를 보고 질문이 생겨 남기게 되었습니다.이전의 강의에서 @Transactional(readOnly = true)가 성능에서 최적화 해주는 부분이 있다해서 조회용 Service 레이어의 모든 조회용 메서드에 @Transactional(readOnly = true)를 붙였습니다.OSIV 라는 개념을 공부하면서 커넥션 풀이 마르지 않게 비활성화 해야된다는것을 보고제 방식대로라면 OSIV 를 비활성화 하더라도 모든 서비스 layer의 메소드가 커넥션을 점유해야 돼서 (CUD api 에서 부르는 서비스 메소드는 @Transactional, R 에서는 @Transactional(readOnly = true)가 붙을테니) 마르지 않을까 하는 고민이 생겼습니다.그렇다고 최소한으로 커넥션을 점유하기 위해 OSIV를 false 로 가져가면서 Repository의 조회 메소드 단위로만 @Transactional(readOnly = true)을 붙이면영속성 컨텍스트의 범위도 그만큼만 가져가서 1차캐시나 지연로딩으로 batch size만큼 가져오는것도 사용을 못할테니영속성 컨텍스트의 사용이 필요할때만 붙이는게 맞을지 아니면 Service layer의 조회용 메서드에 붙여도 될지 잘 모르겠습니다.
-
해결됨서버개발자 과제전형 완벽가이드 - 1편
모의과제 소개
모의과제 소개 영상에서 보여주시는 모의과제 요구사항 pdf 파일은 업로드가 안 되어있는 걸까요?
-
미해결견고한 결제 시스템 구축
멱등키에 request를 넘기는 것
uuid만을 사용해도 충분히 유니크할 것 같은데 request 자체를 넘겨서 어떻게 사용하는 건가요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
준영속 상태 질문
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]준영속 상태란 persist context 안에서 한번이라도 관리된 적이 있는 entity의 상태를 의미한다고 알고 있습니다.하지만 찾아본 바에 의하면 jpa가 '한번이라도 관리된 적이 있는지' 여부를 추적하는 메커니즘을 가지고 있는 것 같지는 않고, 단순히 식별자 여부로 판단하는 것 같은데그렇다면Member memberA = em.find(Member.class, 1L);Member memberB = new Member("B", memberA.getId());memberB도 준영속 상태라고 보는 것이 맞나요?memberB가 준영속 상태가 아니라면 사실상 준영속 상태를 만드는 방법은 detach()를 호출하는 방법밖에 없는 건가요?감사합니다.
-
해결됨스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
(해결) 각 테스트가 상태를 공유하지 않습니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]"회원 리포지토리 테스트 케이스 작성" 강의에서 MemoryMemberRepositoryTest를 작성하시며 @AfterEach를 통해 각 테스트 케이스가 끝날 때 마다 repository 필드의 상태를 초기화해야 한다고 말씀하셨습니다.그런데 저는 별 다른 오류가 나타나진 않아서 다음과 같이 작성해봤습니다.@AfterEach void afterEach() { System.out.println(repository.hashCode()); }그랬더니 각 repository의 해쉬가 서로 다르더라구요. MemoryMemberRepository 구현 내부에서 상태를 출력하게 해보면, 매 테스트 케이스마다 새로운 상태가 되는 것으로 보입니다.제가 잘못 작성한 부분이 있는 걸까요? 아니면 스프링, 라이브러리 버전의 문제인가요? 전체 코드는 다음과 같습니다. 읽어주셔서 감사합니다.// MemoryMemberRepository.javapackage hello.hello_spring.repository; import hello.hello_spring.domain.Member; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; public final class MemoryMemberRepository implements MemberRepository { private final Map<Long, Member> store = new HashMap<>(); private long sequence = 0; @Override public Member save(Member member) { member.setId(++sequence); store.put(member.getId(), member); return member; } @Override public Optional<Member> findById(Long id) { return Optional.ofNullable(store.get(id)); } @Override public Optional<Member> findByName(String name) { return store.values() .stream() .filter(member -> member.getName().equals(name)) .findAny(); } @Override public List<Member> findAll() { return store.values() .stream() .toList(); } public void clearStore() { store.clear(); } }// MemoryMemberRepositoryTest.javapackage hello.hello_spring.repository; import hello.hello_spring.domain.Member; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.*; class MemoryMemberRepositoryTest { MemoryMemberRepository repository = new MemoryMemberRepository(); @AfterEach void afterEach() { System.out.println(repository.hashCode()); } @Test void save() { var member = new Member(); member.setName("spring1"); repository.save(member); var result = repository.findById(member.getId()).get(); assertThat(member).isEqualTo(result); } @Test void findByName() { Member member1 = new Member(); member1.setName("spring1"); repository.save(member1); Member member2 = new Member(); member2.setName("spring2"); repository.save(member2); var result = repository.findByName("spring1").get(); assertThat(result).isEqualTo(member1); } @Test void findAll() { Member member1 = new Member(); member1.setName("spring1"); repository.save(member1); Member member2 = new Member(); member2.setName("spring2"); repository.save(member2); var result = repository.findAll(); assertThat(result).hasSize(2); } }
-
미해결Practical Testing: 실용적인 테스트 가이드
영속성 계층과 E2E 테스트에 대해 질문이 있습니다.
안녕하세요! 소프트웨어의 안정성과 테스트에 대해서 많은 고민을 가지고 있는 주니어 백엔드 개발자입니다.우빈님의 강의로 실용적인 테스팅 방식에 대해서 기반을 다졌습니다. 덕분에 면접 질문에서도 우빈님의 의견과 저의 의견이 합쳐져서 좋은 답변을 할 수 있었어요!취업 이후에도 여러가지 테스트 서적을 읽으면서 다른 관점도 많이 바라보고 있는데요. 이 과정에서 영속성 계층에서의 테스트와 E2E 테스트 부분에서 해소되지 않은 고민이 있어서 조언을 얻고자 찾아왔습니다.먼저 영속성 테스트 관련 질문부터 드리고자 합니다.취업을 하기 전에 취준을 하는 상황에서는 H2 DB로만 해소 할 수 있는 상황이 많았던 것 같습니다.하지만 실무에 들어오니 생각보다 Native Function을 사용하는 경우가 있고, 버전 문제로 각 DB에 있는 연산자가 제대로 동작하지 않는 일 (Dialect 이슈) 도 적지 않게 볼 수 있었습니다.이전에 답변 주신 https://www.inflearn.com/community/questions/1408867/classicist-vs-mockist해당 내용처럼 저 또한 동일하게 영속성 계층에서의 테스트를 DB 관점에서 그냥 동작하겠거니 하고 안일하게 생각하여 제대로 동작하지 않는 케이스를 봤기에 할 필요가 있다고 생각을 하는데요.아직까지는 제 경험에서는 Test Container를 사용하여 실 상황과 유사한 DB를 사용하는 것이 그나마 합리적인 방법으로 생각을 하고 있습니다. 하지만, 또 컨테이너가 뜨다보니 테스트하는데 걸리는 시간이 상당한 것도 단점으로 다가오기는 하더라구요.명확한 답은 없겠지만 우빈님은 위와 같은 비슷한 상황에서 어떤 방식을 택하고 계시는지 더 좋은 방법은 없을지하여 질문을 먼저 드리게 되었습니다.이어서, E2E 테스트 관련 질문입니다.비즈니스 계층에서의 통합 테스트가 작성이 되었다면 아직까지는 우빈님의 생각과 동일하게 프레젠테이션 영역에서는 통합 테스트를 하지 않아도 괜찮지 않을까? 라는 생각을 가지고 있는데요.하지만, 종종 테스트 관련 여러 서적이나 토론등을 보면 E2E 테스트는 중요하다는 관점을 가지고 있는 글이나 영상을 종종 찾아 볼 수 있었고, 무엇보다 저희 팀원분들중에서도 "E2E 테스트를 하는게 아니라면 프레젠테이션 레이어를 테스트 할 필요가 있어?" 라는 질문을 받았을 때 다음과 같은 생각이 들었습니다."그러네.. 지금까지는 거의 문서화를 목적으로 작성을 했었는데, 문서화를 RestDocs, RestDocs to Swagger(OpenApi Spec) 를 하는게 아니라면 작성 할 필요가 있을까?" 라는 의문이 떠올랐습니다. 혹시 이 부분에 대해서 어떻게 생각하시는지 우빈님의 소견을 듣고 싶어서 긴 글로 질문을 드리게 되었습니다.항상 좋은 강의 좋은 인사이트 제공 해주셔서 늘 감사드립니다.