블로그
전체 82025. 06. 24.
0
[인프런 워밍업클럽] DAY18 미션
1. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks 의 차이를 한번 정리해 봅시다. @Mock가짜 객체(mock)을 생성한다.단위 테스트에서 의존성을 완전히 격리할 수 있다.@MockBean 스프링 컨텍스트에 Mock 객체로 등록할 수 있다.@Spy실제 메서드를 호출하되, 필요한 부분만 stub 처리 가능하다.@SpyBean스프링 컨텍스트에 직접 등록하고 spy 객체를 생성한다.@InjectMocks Mock 객체들을 실제 테스트 대상 객체에 주입한다. 2. 아래 3개의 테스트가 있습니다.내용을 살펴보고, 각 항목을 @BeforeEach, given절, when절에 배치한다면 어떻게 배치하고 싶으신가요?@BeforeEach void setUp() { 1-1. 사용자 생성에 필요한 내용 준비 1-2. 사용자 생성 } @DisplayName("사용자가 댓글을 작성할 수 있다.") @Test void writeComment() { // given 1-3. 게시물 생성에 필요한 내용 준비 1-4. 게시물 생성 1-5. 댓글 생성에 필요한 내용 준비 // when 1-6. 댓글 생성 // then 검증 } @DisplayName("사용자가 댓글을 수정할 수 있다.") @Test void updateComment() { // given 2-3. 게시물 생성에 필요한 내용 준비 2-4. 게시물 생성 2-5. 댓글 생성에 필요한 내용 준비 2-6. 댓글 생성 // when 2-7. 댓글 수정 // then 검증 } @DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.") @Test void cannotUpdateCommentWhenUserIsNotWriter() { // given 3-3. 사용자2 생성에 필요한 내용 준비 3-4. 사용자2 생성 3-5. 사용자1의 게시물 생성에 필요한 내용 준비 3-6. 사용자1의 게시물 생성 3-7. 사용자1의 댓글 생성에 필요한 내용 준비 3-8. 사용자1의 댓글 생성 // when 3-9. 사용자2가 사용자1의 댓글 수정 시도 // then 검증 }출처 : https://inf.run/EBCNE
백엔드
・
인프런워밍업클럽
2025. 06. 22.
1
[워밍업 클럽 4기 백엔드] 4주차 회고
한달간 인프런 워밍업 클럽을 마무리 하며 4주차 회고를 작성해보았습니다.KEEP4주간 두개의 강의를 들으면서 리팩토링과 테스트코드에 대한 잘 몰라서 생기는 막연한 두려움에 도전해본 시간이었다고 생각합니다. 기존에 테스트코드를 작성해볼 때 테스트코드를 위한 코드를 작성하는 시간이 많아서 이게 맞는건가 하는 생각을 많이 했습니다. 리팩토링과 테스트코드의 정답은 없지만 도메인의 관점에서 검증해야 할 부분들에 대해서 분류해보는 것들이 코드레벨보다 비즈니스의 관점에서 코드를 어떻게 바라봐야 할지에 대해서 많이 배웠습니다.PROBLEM많이 배웠지만 여전히 리팩토링과 테스트코드를 작성하는 것은 어려운 것 같습니다. 어려운 이유는 검증을 위한 테스트 코드가 아니라는 새로운 관점을 배웠기 때문이라고 생각합니다. 어떤 도메인 로직에 대해 검증이 필요하고 그 방식에서 단위테스트가 필요한 경우에 사용을 한다는 것을 알게되었습니다. requestdto에서 사용하던 @max 와 같이 검증하는 어노테이션도 하나의 레이어에서 사용하기 보다 어느 레이어에서 검증을 할 건지에 대해서 고민해보면 좋다는 것을 알게되어 비즈니스로직을 작성할때도 많이 도움이 될 것 같습니다.TRY앞으로 제가 작성하는 코드와 로직들이 충분한 검증을 거치고 있는지 테스트코드로 보장하고 싶습니다. 테스트코드가 없던 때 운영으로 나간 코드가 어떤 결과들을 만들어낼지 두려워 했던 기억이 있습니다. 이제 그 부분에서는 벗어나보고 싶다는 마음으로 워밍업 스터디를 통해서 듣게 되었는데, 진도를 못따라 가는 날도 있어서 쉽지만은 않았지만 발자국이라는 의미에 걸맞게 한발자국 내딛은 것 같다는 생각이 듭니다.
백엔드
・
인프런워밍업클럽
・
테스트코드
2025. 06. 17.
0
[인프런 워밍업 클럽 백엔드] Layered Architecture 구조의 테스트 작성법
Presentation Layer - mocking - Business Layer의 Service들을 모킹하여 격리된 테스트Business Layer- 비즈니스 로직을 구현하는 역할- persistence layer 호출을 조합해 비즈니스 로직 구현- Business Layer에서 트랜잭션을 관리하는 이유 - 비즈니스 규칙에 따른 데이터의 일관성이 보장된다Persistence Layer- 비즈니스 가공 로직을 배제하고 data access의 부분만 담당- @DataJpaTest를 사용할 수 있다 - 전체 애플리케이션이 아닌 JPA 관련한 구성요소만 필요한 부분만 로드된다 - 불필요한 빈들을 로드하지 않아 테스트 속도가 향상된다
백엔드
・
인프런워밍업클럽
2025. 06. 15.
1
[워밍업 클럽 4기 - 백엔드] 3주차 회고
인프런 워밍업클럽 백엔드 스터디를 진행하며 3주차 회고를 정리해봤습니다. KEEPPersistence Layer, Business Layer에 대해서 코드를 구현하면서 테스트 코드를 함께 작성하는데 학습을 하면서 그동안 테스트코드를 작성하면서 느꼈던 의문을 많이 해결하는 시간이 되었습니다. 테스트코드에서 어떤 계층을 우선적으로 테스트 해야할지, 어떤 관점에서 테스트코드를 바라봐야 할지, 그리고 서비스로직에 대해서 테스트코드를 작성하면서 테스트를 위해 구축해야 하는 부분들이 어디까지 일지 하는 고민들이 있었는데, 그런 부분에 대해서 강의에서 다뤄주셔서 공감하면서 강의를 수강했습니다. PROBLEM지난주와 비슷한 생각이지만 강사님이 실시간으로 막힘없이 작성하실만큼의 시간들이 아직 저에게는 없기 때문에 여전히 낯선 부분들이 있어서 테스트코드를 중요한 메서드를 선정해서 적용해보는 연습이 필요할 것 같습니다. 그리고 TDD를 연습해봤는데 red-green을 오가면서 하는 부분에 대해서도 작게나마 적용해 보고 싶습니다.TRYAssertJ 를 사용하면서 assertThat, assertEquals만 사용했었는데 새로운 메서드를 많이 알게 되었습니다. 새로운 코드를 작성할때 내가 사용할 수 있을 정도로는 아직 익숙해지지 않아서 더 많이 사용해 보는게 필요하고, 강의에서 말해주신것 처럼 테스트가 가능한 영역과 가능하지 않은 영역을 분리해서 테스트코드를 작성했을때 효과적인 부분들을 분리하는 눈도 더 길러가고 싶습니다.
백엔드
・
인프런워밍업클럽
・
실용적인테스트가이드
2025. 06. 08.
1
[워밍업 클럽 4기 - 백엔드] 2주차 회고
인프런 워밍업클럽 백엔드 스터디를 진행하며 2주차 회고를 정리해봅니다. KEEP스터디를 하면서 가장 좋은 점은 함께 공부하는 커뮤니티가 있다는 점 인것 같습니다. 특히 진도표를 같이 따라갈 동료를 모집해 함께 진행중인데, 비슷한 고민들을 하고 있다는 점들이 큰 위로가 되면서 동기부여가 됩니다.PROBLEM읽기좋은 코드 강의를 진행하면서 가장 어려웠던 부분은, 리팩토링이라는게 커다란 규칙은 있지만 문법같은 규칙은 아니어서 강사님께서 강의에서 경험의 영역이라고 했던 부분이 어떤 말인지 직접 과제를 해보면서 체감이 되었습니다. 코드를 읽어가면서 추상화 레벨이 맞지 않는 부분들을 찾아가는 연습이 계속해서 필요하다는 생각이 들었습니다.TRY강의 진도를 따라가고 학습하는데 가장 큰 목표가 있지만 , 읽기좋은 코드와 테스트코드 작성을 모두 체화하고 싶은 목표를 달성하기 위해서는 더 적극적으로 학습해야 할 것 같습니다. 이번주에 학습하면서 테스트가 가능한 영역과 불가능한 영역들을 분류해보는 눈을 더 키우고 작은 영역부터 테스트코드를 작성해 코드의 안정성을 확보해보는 연습을 해보고 싶습니다.
백엔드
・
인프런워밍업클럽
・
테스트코드
・
박우빈
2025. 06. 01.
1
[워밍업 클럽 4기 - 백엔드] 1주차 발자국
워밍업 클럽에서 한주동안 공부하면서 느낀점을 정리해보았습니다. 읽기좋은코드는 뭘까?백엔드 개발을 공부하면서 테스트코드의 중요성은 누구나 알고 있지만 코드가 돌아가는데는 필수항목은 아니기 때문에 열심히 공부했던 영역은 아니었습니다. 테스트코드가 어렵다고 생각이 들어서 더 가까이 하기 어려운 존재 였습니다. 이전 프로젝트를 같이 한 동료가 워밍업클럽을 추천해줬고 이번 기회를 통해 테스트코드에 대한 두려움을 없애보고자 신청하게 되었습니다.읽기좋은코드 강의를 절반정도 들으면서 그동안 막연하게 생각했던 읽기좋은 코드에 대해서 조금이나마 이런거구나 하고 알게되었습니다. 무조건 라인 수가 짧은 코드가 좋은 코드도 아니고 조건이 많은 로직이 검증을 잘 할 수는 있어도 읽기좋은코드는 아니었다는 것을 알게되었습니다. 기존에 코드를 구현하다가 메서드로 분리하는 기준은 코드가 길어질때 아니면 역할이 다를때 정도였던것 같은데 뇌과학적인 측면에서 읽는 사람의 흐름이라는 새로운 관점을 배울 수 있었습니다.
백엔드
・
인프런워밍업클럽
・
읽기좋은코드를작성하는법
・
박우빈
2025. 05. 30.
0
[인프런워밍업클럽] Day4 미션 - 읽기좋은 코드
https://inf.run/yTUP41. 읽기 좋은 코드로 리팩토링 하기[AS-IS]public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; }[TO-BE]메서드 분리 & Early Return 적용if -else - else-if 문을 각각의 if문으로 분리하고 return 할 수 있도록 수정공백 라인 적용각각의 조건문에서 공백라인을 적용해 분리된 로직을 확인할 수 있도록 수정부정연산자를 긍정형으로 바꿔서 적용!(order.getTotalPrice() > 0) 조건문 내 영역을 메서드를 분리하고 0이거나 0보다 작은 경우를 나타내는 checkTotalPriceAboveZero 로 메서드 이름을 변경!order.hasCustomerInfo() 조건을 사용자 정보를 가지고 있는 의미를 나타내는 checkCustomerInfoExists 메서드로 변경예외 처리각각의 메서드에서 주문항목이 없는 경우, 사용자 정보가 없는 경우 0보다 같거나 작은 경우를 확인 하기 때문에 예외로 처리하면 좋겠다고 생각해 IllegalArgumentException 예외를 던지도록 수정원 메서드인 validateOrder을 try-catch문으로 변경하고 각각의 메서드로 예외를 확인하고 아닌 통과가 되면 true를 반환하도록 수정했다.public boolean validateOrder(Order order) { try { checkOrderItemsExist(order); checkCustomerInfoExists(order); checkTotalPriceAboveZero(order); return true; } catch (IllegalArgumentException e) { log.info(e.getMessage()); return false; } } private static void checkOrderItemsExist(Order order) { if (order.getItems().size() == 0) { throw new IllegalArgumentException("주문 항목이 없습니다."); } } private static void checkCustomerInfoExists(Order order) { if (!order.hasCustomerInfo()) { throw new IllegalArgumentException("사용자 정보가 없습니다."); } } private static void checkTotalPriceAboveZero(Order order) { if (order.getTotalPrice() 2. SOLID에 대하여 자기만의 언어로 정리하기SRP(Single Responsibility Principle)하나의 클래스는 하나의 책임만 가져야 한다는 의미하나의 클래스가 여러 역할을 담당하면 결합도가 높아지기 때문에 유지보수가 어려워 진다. OCP(Open-Closed Principle)확장에는 열려있고, 수정에는 닫혀있어야 한다는 의미새로운 기능을 추가할 때 기존 코드를 수정하지 않고 확장할 수 있어야 한다LIP(Liskov Substitution Principle)부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 대체해도 동일하게 동작해야 한다는 의미상속 관계에서 부모 클래스가 가지고 있는 동작을 자식 클래스가 깨뜨리면 안 된다ISP (Interface Segregation Principle)클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다클라이언트가 필요하지 않은 기능까지 구현하는 것을 지양DIP (Dependency Inversion Principle)구체적인 구현체가 아닌 추상화(인터페이스)에 의존해야 한다는 의미고수준 모듈이 저수준 모듈에 직접 의존하지 않고, 둘 다 추상화에 의존해야 한다
백엔드
・
읽기좋은코드
・
인프런워밍업클럽
2025. 05. 27.
0
워밍업 클럽 4기 - 백엔드 Day 2 추상과 구체
[추상과 구체의 예시]추상: 김밥을 만드는 과정시금치, 당근, 단무지, 우엉과 햄, 김밥김과 밥을 준비한다.밥은 흰쌀밥과 참기름 소금으로 간을 한다.채소는 길게 잘라 볶아둔다.김밥김을 펼치고 밥을 위에 올린다.볶은 채소와 단무지를 흰 밥 위에 올리고 말아준다.잘 말린 김밥에 참기름을 발라주고 칼로 자른다. https://inf.run/pZXb7
백엔드
・
읽기좋은코드를작성하는사고법