블로그
전체 8#카테고리
- 백엔드
#태그
- 워밍업클럽
- 백엔드
- 소프트웨어_테스트
- junit5
- Spring
- JPA
- Mockito
- clean-code
- 객체지향
- 리팩토링
2025. 06. 22.
1
[인프런 워밍업 클럽 4기 - BE 클린 코드 & 테스트 코드] 4주차 발자국 👣
👣 4주차 발자국 💻 강의 수강👩🏻💻 학습 내용 요약Test DoubleDummy, Fake, Stub, Spy, MockMockito, BDDMockito@Mock, @MockBean, @Spy, @SpyBean, @InjectMockTest FixtureParameterized Test, Dynamic Test테스트 환경 통합private 메서드의 테스트, 테스트에서만 필요한 메소드 🤔 학습 회고이번 주 또한 저번 주처럼 해커톤과 이력서 작성으로 강의를 나중에 몰아서 듣게 되어 아쉬운 한 주였습니다..완강을 하긴 했지만 무조건 복습해야 체화할 수 있겠다는 생각이 드는 미션과 중간 점검이었습니다. 🎯 다음 주 학습 목표중간 점검에서 말씀해 주신 부분을 체크하면서 미션 다시 해보기 ✉ 미션💭 미션 해결 과정Day 16 미션Layered Architecture 구조에서 레이어마다 어떤 특징이 있는지, 어떻게 테스트하면 좋을지 저만의 언어로 정리해보기 위해서 강의 내용을 복습하면서 진행하였습니다. Day 18 미션@Mock, @MockBean, @Spy, @SpyBean, @InjectMocks 의 차이를 정리하기 위해서 강의를 복습하고, 복습하면서 궁금해진 내용도 찾아가며 진행하였습니다. 🤔 미션 회고역시 늘 느끼는 건데 강의를 듣고 저만의 언어로 정리하는 것이 생각보다 쉽지 않습니다. 그건 제가 강의를 체화하지 못했다는 의미 같기도 해서 복습으로 이해해야겠다고 느끼게 됩니다.2차 중간 점검에서 Day 18 미션의 핵심은 중복 제거가 아닌 '도메인'이라고 하셨습니다. 도메인에 대해서 다시 한 번 생각해보았습니다. 테스트하려는 목적 대상이 무엇인지 항상 생각하면서 진행해야겠습니다. 👨🏻💻 강의 출처Practical Testing: 실용적인 테스트 가이드
워밍업클럽
・
백엔드
・
소프트웨어_테스트
・
junit5
・
Spring
・
JPA
・
Mockito
2025. 06. 21.
0
[워밍업 클럽 4기 - BE 클린 코드 & 테스트 코드] Day 18 미션
🎯 Day 18 미션 1⃣번 미션@Mock단위 테스트에서 사용할 가짜 객체를 직접 생성한다.@MockBean mock 객체를 생성하고, 스프링 컨텍스트에 직접 등록한다.@Spy실제 객체를 기반으로, 일부를 stub 할 수 있다.@SpyBeanspy 객체를 생성하고, 스프링 컨텍스트에 직접 등록한다.@InjectMocks 테스트 클래스에 mock이나 spy 객체들을 의존성 주입해준다. 2⃣번 미션댓글 작성과 수정에 대해 테스트할 때, 사용자와 게시물은 무조건 필요하므로 @BeforEach에 넣어주었습니다.@BeforeEach void setUp() { 1-1. 2-1. 3-1. 사용자1 생성에 필요한 내용 준비 1-2. 2-2. 3-2. 사용자1 생성 1-3. 2-3. 3-5. 사용자1의 게시물 생성에 필요한 내용 준비 1-4. 2-4. 3-6. 사용자1의 게시물 생성 } @DisplayName(""사용자가 댓글을 작성할 수 있다."") @Test void writeComment() { // given 1-5. 댓글 생성에 필요한 내용 준비 // when 1-6. 댓글 생성 // then 검증 } @DisplayName(""사용자가 댓글을 수정할 수 있다."") @Test void updateComment() { // given 2-5. 댓글 생성에 필요한 내용 준비 2-6. 댓글 생성 // when 2-7. 댓글 수정 // then 검증 } @DisplayName(""자신이 작성한 댓글이 아니면 수정할 수 없다."") @Test void cannotUpdateCommentWhenUserIsNotWriter() { // given 3-3. 사용자2 생성에 필요한 내용 준비 3-4. 사용자2 생성 3-7. 사용자1의 댓글 생성에 필요한 내용 준비 3-8. 사용자1의 댓글 생성 // when 3-9. 사용자2가 사용자1의 댓글 수정 시도 // then 검증 } 👨🏻💻 강의 출처Practical Testing: 실용적인 테스트 가이드
백엔드
・
워밍업클럽
・
백엔드
・
소프트웨어_테스트
・
junit5
・
Spring
・
JPA
・
Mockito
2025. 06. 20.
0
[인프런 워밍업 클럽 4기 - BE 클린 코드 & 테스트 코드] 3주차 발자국 👣
👣 3주차 발자국 💻 강의 수강👩🏻💻 학습 내용 요약Layered Architecture -> 관심사의 분리라이브러리 vs 프레임워크Persistence Layer: Data Access 역할Business Layer : 비즈니스 로직 구현, Persistence와 상호 작용, 트랜잭션 보장, 동시성 고민Presentation Layer: 외부 요청, Mocking, MockMvc @SpringBoot vs @ DataJpaTest 🤔 학습 회고최근 테스트 코드를 작성할 일이 많았지만, 명확한 기준 없이 작성하고 있었습니다. 강의를 통해 테스트 작성의 기준이 점차 명확해지고 있어서 도움이 많이 됩니다! 이번 주는 직무 과제와 이력서 작성으로 인해 너무 바빠서 강의가 밀렸습니다.. 아쉬운 한 주였습니다.. 🎯 다음 주 학습 목표라이브 세션 듣고 미션 다시 진행해 보기 ✉ 미션💭 미션 해결 과정Day 11 미션문서를 작성한다는 생각으로 다양한 엣지 케이스에 대한 테스트 코드를 작성하려고 노력했습니다. 🤔 미션 회고강의를 들을 때는 할 만 하겠다고 생각했지만, 막상 직접 과제를 진행해 보니 생각보다 쉽지 않았습니다.테스트 코드를 문서로 접근하니 어디까지 작성해야 할지에 대한 범위 설정이 고민되었습니다.과제를 진행하면서 이 정도까지 테스트를 진행해야 하는가에 대한 의문이 많이 들었습니다. 👨🏻💻 강의 출처Practical Testing: 실용적인 테스트 가이드
백엔드
・
워밍업클럽
・
백엔드
・
소프트웨어_테스트
・
junit5
・
Spring
・
JPA
・
Mockito
2025. 06. 20.
0
[워밍업 클럽 4기 - BE 클린 코드 & 테스트 코드] Day 16 미션
🎯 Day 16 미션 📝 나의 답변Persistence Layer비즈니스 가공 로직 XData에 대한 CRUD에만 집중빠른 테스트는 @DataJpaTest 이용 테스트용 DB를 따로 두어 테스트하기 Business Layer비즈니스 로직 구현Persistence Layer와 상호 작용트랜잭션 보장 및 동시성실패 케이스도 중요경계값 테스트 Presentation Layer파라미터에 대한 최소한의 검증 수행Controller만 띄우고, Service나 Repository는 Mock 처리@WebMvcTest을 이용하여 웹 관련 Bean만 주입@MockBean을 이용하여 실제 로직을 호출하지 않은 격리된 테스트 👨🏻💻 강의 출처Practical Testing: 실용적인 테스트 가이드
백엔드
・
워밍업클럽
・
백엔드
・
소프트웨어_테스트
・
junit5
・
Spring
・
JPA
・
Mockito
2025. 06. 08.
1
[인프런 워밍업 클럽 4기 - BE 클린 코드 & 테스트 코드] 2주차 발자국 👣
👣 2주차 발자국 💻 강의 수강👩🏻💻 학습 내용 요약주석에는 코드로 표현할 수 없는 우리의 의사 결정 과정과 도메인 로직을 작성하자.주석도 관리해 줘야 하는 문서다. 업데이트를 잊지 말자.변수는 사용하는 순서대로 배치하자.메서드 순서: 상태 변경 >> 판별 >= 조회패키지도 정보를 제공할 수 있으므로, 적당하게 쪼개서 관리해야 한다.코드를 읽는 것은 도메인 지식을 늘리는 것이 목표다.은탄환은 없다. 유연한 사람이 되자.잘 작성한 테스트 코드는 팀 내 공유 자원으로 좋은 자산이 된다. 🤔 학습 회고Readable Code 강의는 듣고 이해하는 것만으로도 어려워서 시간이 오래 소요되었다...평소 테스트 코드에 대해 궁금해서 그런지, Practical Testing 강의가 재밌다~리팩토링 미션이 너무 어려웠다... 🎯 다음 주 학습 목표Readable Code 강의 복습!! ✉ 미션💭 미션 해결 과정Day 7 미션중복된 부분이 많은 것 같아서 중복 제거를 진행하였다.추상화 레벨을 맞추기 위해서 추상화를 진행하였다.강의 시간에 알려주신 포인트를 최대한 반영해 보았다. 🤔 미션 회고완성도가 낮다고 생각은 했지만, 강의와 중간 점검을 듣고 나니 부족한 점이 많이 보였다.깔끔하지 않은 순서로 리팩토링했던 것 같다.어떻게 진행해야 할지 모르겠어서 코드를 계속 바라봤다... 👨🏻💻 강의 출처Readable Code: 읽기 좋은 코드를 작성하는 사고법 Practical Testing: 실용적인 테스트 가이드
백엔드
・
워밍업클럽
・
백엔드
・
clean-code
・
객체지향
・
리팩토링
・
소프트웨어_테스트
・
junit5
2025. 06. 01.
1
[인프런 워밍업 클럽 4기 - BE 클린 코드 & 테스트 코드] 1주차 발자국 👣
👣 1주차 발자국 💻 강의 수강👩🏻💻 학습 내용 요약잘 읽히는, 이해할 수 있는 코드를 작성하자.추상화는 구체적인 정보들로터 중요한 정보들만 남기는 것이다. 추상화에서 도메인의 문맥이 중요하다.이름을 짓는 행위도 추상화의 일종으로, 단어만으로 읽는 이에게 정보를 쉽게 전달할 수 있어야 한다.메서드의 주제는 반드시 하나여야 한다. 포괄적인 의미를 담아야 하며, 작은 단위의 메서드로 쪼갤 수 있다.상수와 줄 바꿈으로도 가독성을 높일 수 있다.코드를 읽는 이가 너무 많이 고민하지 않게, 기억해야 하는 정보가 많지 않게 읽을 수 있게 하자.Early return, 사고 과정의 depth 줄이기, 부정어 대체하기 등예외가 발생할 가능성을 낮추자. 의도한 예외와 예상하지 못한 예외를 구분하자.Java에서 null로 인한 예외를 주의하자. Optional 사용 고민해 보자. 🤔 학습 내용 회고강의를 듣고 이해하며 미션을 수행하는데 시간이 빠듯했다.하나하나 기록하며 강의를 듣는 편인데 이러한 방식은 시간이 오래 걸려서 비효율적인 것 같다. 어떻게 해야 적은 시간 내에 강의 수강 및 이해, 미션 수행이 가능할 지 학습 방법에 대해서 고민해봐야겠다. 🎯 다음 주 학습 목표효율적인 학습 방법을 알아내서 적용해보자!! ✉ 미션💭 미션 해결 과정Day 2 미션마라톤 기록 측정 과정에 대해서 구체화해보았다. Day 4 미션1번 내용)강의에서 언급한 논리, 사고의 흐름에 따라서 읽기 좋은 코드가 되도록 리팩토링하였다.2번 내용)SOLID 원칙에 대해서 나만의 언어로 작성하였다. 🤔 미션 해결 회고미션을 잘 한 건지 모르겠다.. 👨🏻💻 강의 출처Readable Code: 읽기 좋은 코드를 작성하는 사고법
백엔드
・
워밍업클럽
・
백엔드
・
clean-code
・
객체지향
・
리팩토링
2025. 05. 30.
0
[워밍업 클럽 4기 - BE 클린 코드 & 테스트 코드] Day 4 미션
🎯 Day 4 미션 1⃣번 미션Step 0) 분석 및 이해하기 & 리팩토링 대상/범위 확인키워드 : 논리, 사고의 흐름 , 읽기 좋은 코드, 리팩토링코드와 설명을 통해, 해당 도메인에 대해서 이해합니다.⇒ 주문에 대한 비즈니스 측면의 유효성 검사가 아닌 사용자가 생성한 주문 객체에 대한 유효성 검사는 Order 객체에서 진행한다고 가정하겠습니다.// 사용자가 생성한 '주문'이 유효한지를 검증하는 메서드 public boolean validateOrder(Order order) { // a. 주문 항목이 있는지 확인 if (order.getItems().size() == 0) { // a-1. 주문 항목이 없음 log.info("주문 항목이 없습니다."); return false; } else { // a-2. 주문 항목이 있음 // b. 주문 총액이 올바른지 확인 (0원 초과) if (order.getTotalPrice() > 0) { // b-1. 주문 총액이 0원 초과 // c. 주문한 사용자 정보가 있는지 확인 if (!order.hasCustomerInfo()) { // c-1. 사용자 정보가 없음 log.info("사용자 정보가 없습니다."); return false; } else { // c-2. 사용자 정보가 있음 return true; } } else if (!(order.getTotalPrice() > 0)) { // b-2. 주문 총액이 0원 이하 log.info("올바르지 않은 총 가격입니다."); return false; } } // 모든 조건을 통과하여 유효한 주문인 경우 return true; } Step 1) 리팩토링 1. 주문 항목이 있는지 확인 (a)if (order.getItems().size() == 0)if 조건에서 주문 항목이 없으면 false를 반환하고, 주문 항목이 있다면 그 이후의 else로 자연스럽게 넘어가게 됩니다. 따라서, 주문 항목이 없는 경우에만 false를 반환하고, 그 외의 주문 항목이 존재하는 경우에는 계속해서 다음 조건을 검사하게 되므로 else를 제거해도 문제가 없습니다.⇒ 뇌 메모리 적게 쓰기 (인지적 경제성)public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } 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; } 2. 주문 총액이 올바른지 확인 (b)(b-2)의 !(order.getTotalPrice() > 0) 를 부정의 의미를 담지 않은 order.getTotalPrice() 로 표현할 수 있습니다.public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (order.getTotalPrice() 주문 총액이 0원 이하(b-2)인 경우를 먼저 확인하게 하면 이 조건을 만족하면 바로 false를 반환합니다. 이후, 주문 총액이 0원을 초과(b-1)하는 경우에만 사용자 정보를 확인하는 로직으로 넘어가게 됩니다. 이렇게 조건문의 순서 변경을 통해, 불필요한 else if를 제거할 수 있습니다.public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } if (order.getTotalPrice() 3. 주문한 사용자 정보가 있는지 확인 (c)(c-2)의 경우는 모든 조건을 통과한 경우로, else를 제거해도 됩니다.공백 라인으로 모든 조건을 만족한 경우를 다른 조건과 분리해줍니다.public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } if (order.getTotalPrice() 2⃣번 미션SRP (Single Responsibility Principle; 단일 책임의 원칙)하나의 클래스는 하나의 책임/관심사를 가진다.→ 변경하는 이유는 하나여야 한다. → 높은 응집도 & 낮은 결합도OCP (Open-Closed Principle; 개방-폐쇄의 원칙)확장에는 열려 있고, 수정에는 닫혀 있어야 한다. → 기존 코드 변경 없이 기능 확장 가능해야 한다.LSP (Liskov substitution Priciple; 리스코프 치환 원칙)부모 클래스의 인스턴스는 자식 클래스의 인스턴스로 치환할 수 있어야 한다. → 자식 클래스는 부모 클래스를 변경시키지 않아야 한다.ISP (Interface Segregation Principle; 인터페이스 분리 원칙)인터페이스에는 필요한 기능만 선언한다.DIP (Dependecy Inversion Principle; 의존성 역전의 법칙)구체화된 것보다 추상화된 스펙에 의존해야 한다. 👨🏻💻 강의 출처Readable Code: 읽기 좋은 코드를 작성하는 사고법
백엔드
・
워밍업클럽
・
백엔드
・
clean-code
2025. 05. 28.
0
[워밍업 클럽 4기 - BE 클린 코드 & 테스트 코드] Day 2 미션
🎯 Day 2 미션 📝 나의 답변2⃣번 미션[추상]마라톤 기록이 측정된다. [구체]러너가 몸에 마라톤 칩(BibTag)을 부착한 채 출발 지점을 지난다.출발 지점에 설치된 BibTag 인식용 전자 매트가 러너의 칩을 인식한다.칩이 인식된 시점이 러너의 출발 시간으로 기록된다.인식된 데이터는 전자 매트와 케이블로 연결된 컴퓨터로 전송되어 저장 및 처리된다.중간 지점과 골인 지점에도 동일한 방식의 전자 매트가 깔려 있어, 러너가 각 지점을 통과할 때마다 1~4번 과정이 반복한다. 👨🏻💻 강의 출처Readable Code: 읽기 좋은 코드를 작성하는 사고법
백엔드
・
워밍업클럽
・
백엔드
・
clean-code