블로그
전체 9#카테고리
- 백엔드
2025. 06. 19.
1
4주차 발자국
1. 학습 회고4주차 키워드: Mock과 테스트를 위한 Tipsday16 - Layered Architecture 마지막 강의, [미션] Layered별 특징과 테스트 방법day17 - Mockday18 - 테스트 작성 조언, [미션] 테스트 어노테이션들과 댓글 서비스 테스트day19 - Spring REST Docsday20 - 중간점검 4주차는 테스트와 관련된 어노테이션들과 테스트 코드를 어떤 식으로 구성하면 좋을지에 대해 학습하는 주였다.개인적으로는 헷갈렸던 여러 어노테이션들을 짚고 넘어가는 주여서 좋았다.1달이 생각보다 금방 지나가서 놀랐는데 다음에는 다른 분야의 워밍업클럽도 참여해보고 싶다. 미션 회고Day 16 미션 Presentation, Business, Persistence 3개 Layer의 특징과 어떻게 테스트하면 좋을지 나만의 언어로 표현강의를 기반으로 Layered별 특징을 요약해서 제출했는데,Presentation/Business/Persistence 각 계층을 어떤 식으로 대하면 좋을지,특히, Besiness에서는 LocalDateTime처럼 예상치 못한 결과를 얻을 수 있거나 테스트하기 어려운 코드는 아닌지Presentation에서는 정책에 대한 검증까지 하는 건 아닌지 등 주의해야 할 점들을 다시 한 번 정리하는 미션이었다. Day 18 미션은 테스트에 사용되는 어노테이션들을 정리하고,제시된 코드를 보고 @BeforeEach, given절, when절에 적절히 배치해보는 미션 18-1. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks 에 대해서는강의내용을 기반으로 간략히 정리를 했다.다시 한 번 정리를 하면, 테스트의 편의를 위해 Mocking을 하며, 어노테이션들을 사용하면 더 편리하게 다룰 수 있다.XXXBean과의 가장 큰 차이점은 XXXBean은 Spring 환경에서 ApplicationContext에서 Bean 으로 관리되어의존성 처리가 편하다는 점.그 외 Spring 이 필요없거나 의존성이 적고, 간단한 테스트들의 경우 @Mock, @InjectMocks을 활용하면 되겠다. 18-2. 주어진 코드는 writeCommet, updateComment, cannotUpdateCommentWhenUserIsIsNotWriter 3개댓글을 생성/수정 등에 대한 검증이므로 확인하고자 하는 행위들을 when 절에,그 외 나머지 것들은 모두 준비단계이므로 given 절에 배치했다.따라서, writeCommet에는 댓글 생성, updateComment에는 댓글 수정, cannotUpdateCommentWhenUserIsIsNotWriter에는 댓글 수정 시도를 when 절에 배치했다. 이제 @BeforeEach 에 대해 고민해 봐야하는데,@BeforeEach는 테스트 실행 전에 수행되는 단계로 모든 테스트에 영향을 미칠 수 있어 주의해야 한다.지금 수행 중인 테스트는 댓글 서비스 테스트이고, 어떠한 경우든 댓글을 작성하기 위해서는사용자와 게시물 생성이 필수일 것이라 생각했다.그리고 앞으로 댓글에 대한 테스트가 추가된다고 해도 사용자/게시글 생성이 선행되어야 댓글이 있을 것이다.따라서, @BeforeEach 에 사용자 생성에 필요한 내용 준비/생성, 게시물 생성에 필요한 준비/생성을 배치했다. 학습 출처인프런 워밍업 클럽 스터디 4기 - 백엔드 클린코드, 테스트 코드수강 강의:Practical Testing: 실용적인 테스트 가이드 - 박우빈
2025. 06. 19.
0
테스트 어노테이션과 댓글 서비스 테스트
1. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks@Mock간편하게 Mock 객체 생성, 스프링 없이 일반 단위테스트에 사용@MockBeanMock 객체를 Bean 으로, 스프링 환경에서 사용@Spy실제 객체의 기능 중 일부만 stubbing 가능, 스프링 없이 일반 단위테스트에 사용 가능@SpyBeanSpy 객체를 Bean 으로, 스프링 환경에서 사용@InjectMocks의존성이 필요한 생성자에 만들어진 Mock 객체 주입, 스프링 없이 일반 단위테스트에 사용 @BeforeEach, given절, when절 @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 검증 }
2025. 06. 18.
0
클린 코드, 테스트 코드 완강 !!
2025. 06. 17.
0
Layered Architecture와 테스트
Layered Architecture는 말 그대로 계층형 구조를 뜻하며 나누는 기준은 관심사이다.계층은 크게 3가지로 역할은 다음과 같다.Presentation Layer: 최전선에서 사용자의 요청/응답과 최소한의 검증Business Layer: 도메인과 관련된 데이터의 검증과 요구사항 처리Persistence Layer: DB 접근 데이터 조회, 변경 계층이 다른 만큼 테스트 방식도 확인해야 할 부분도 조금씩 다르다.Presentation Layer: 다른 계층들은 문제가 없다 가정하고 요청 의도에 맞는 응답을 반환받는지Business Layer: 로직의 흐름과 동작이 정상인지, 테스트하기 어려운 코드는 아닌지Persistence Layer: 의도한 쿼리가 발생하는지 학습 출처인프런 워밍업 클럽 스터디 4기 - 백엔드 클린코드, 테스트 코드수강 강의:Practical Testing: 실용적인 테스트 가이드 - 박우빈
2025. 06. 15.
1
3주차 발자국
1. 학습 회고3주차 키워드: Layer별 테스트day11 - 단위 테스트 작성 미션day12 - Persistence Layerday13,14 - Business Layerday15 - Presentation Layer Persistence Layer: DB 접근 계층, 단일 테스트와 유사함. 단순 DB 조회도 왜 테스트가 필요한지에 대해서도 깨달음.Business: 서비스 로직 계층. persistence layer가 포함된 통합 테스트 작성, Spring 을 통째로 띄워서 테스트.Presentation: 외부 세계의 요청을 받는 계층. 파라미터에 대한 최소한의 검증. Persistence/Busuness Layer는 Mocking 하고 단위 테스트 형태로 진행.Mock 을 쓰는 이유: 테스트를 하는데 의존관계가 걸림돌 -> Mock 으로 해결 테스트 강의도 좋았지만 jpa 에 대해서도 한 번 짚고 넘어가는 강의여서 더 좋았다.처음 발자국 작성한 게 얼마 전 같은데 벌써 3주차가 끝났다.마지막까지 가보자고! 미션 회고day 11 미션은 "Readable Code 강의에서 진행한 프로젝트에 단위 테스트 코드를 작성하기" 이다.이전 리팩토링 미션에서 스터디카페를 했으니, 테스트 코드도 여기에 해보면 좋을 거 같아서 스터디카페 프로젝트에 단위 테스트를 작성해보았다. 미션을 진행하면서 고민한 것들은.. 어떤 경우에 테스트 코드를 작성하면 좋을지, 만들어진 모든 메서드에 대해서 작성해야하나? 아니면 정말 중요한 것들에만 작성해야하나? 하는 것이었다.그 결과, 중요해보이는 녀석들로만 선정을 했는데 다음 고민이 생겼다.검증은 어떤 값을, 어느 정도 수준으로 해야하는지, 너무 뻔한 걸 검증하는 건 아닌지, BDD는 잘 따랐는지 등,,아직은 배우는 단계니까 작성을 해 보는 것에 의의를 뒀다. 먼저 이용권 목록은 파일에서 읽어오는 형태이니, 좌석이용권/사물함이용권의 종류를 확인하면 좋을 것 같아서 테스트 코드를 작성했고, 고정석일때만 사물함을 선택 가능한 것도 중요한 조건인 것 같아서 테스트 코드를 작성했다. 그리고 가장 중요한 금액 계산.할인 이벤트가 기간별로 잘 적용되는지, 사물함 이용권까지 할인이 되지는 않는지에 대한 테스트 코드를 작성하는 것을 마지막으로 미션을 제출했다. 학습 출처인프런 워밍업 클럽 스터디 4기 - 백엔드 클린코드, 테스트 코드수강 강의:Practical Testing: 실용적인 테스트 가이드 - 박우빈
2025. 06. 08.
1
2주차 발자국
1. 학습 및 미션 회고2주차 키워드: 리팩토링day6 - 코드를 다듬는 방법들day7 - 리팩토링 실습 미션day8 - 리팩토링 강의day9 - 테스트 소개day10 - 중간점검 코드리뷰 2주차는 리팩토링 진행이 거의 대부분이여서 학습 회고와 미션 회고를 같이 작성하겠다.먼저 좋은 주석 남기기와 메서드의 자연스러운 순서에 대해 학습한 후, 연습 프로젝트 소개 강의를 보고 day7 미션 스터디 카페 이용권 선택 시스템 리팩토링을 진행했다.소개 강의에서 리팩토링 포인트들로 추상화레벨, 일급컬렉션, 객체지향원칙 등을 꼽았고, 그에 맞춰 진행해보려고 했다.처음에 코드를 봤을 때... 변수명도 헷갈리고 어디서부터 어떻게 손을 대야할 지 막막했다.Pass 라는 개념이 반복되고, 이용권과 사물함 이용권이 비슷한 기능을 수행하고 있어서 이용권을 추상화하고 좌석과 사물함을 구체화했다.그리고 금액도 나오고 할인이벤트 등의 개념이 있어서 주문이나 이벤트 객체도 추가해야 하나 고민을 했지만..스터디 카페만 생각해 봤을 때는 좀 단순해도 되지 않을까란 생각에 별도 객체를 두진 않았다.다만, 이용권을 갖는 일급컬렉션을 두고, 일급컬렉션이 가진 이용권들에게 금액과 할인 금액을 묻는 방식으로 해결했는데 다시 생각해보면 이용권 일급컬렉션이 너무 많은 일을 하고 있었나? 라는 생각도 든다.파일 입출력은 어떻게 손을 대야할 지 어렵기도 했고.. 얘가 변경이 있을까 하고 합리화하고 그대로 두고 제출하는 것으로 day 7 미션을 마무리했다.이후 강사님이 진행한 리팩토링 강의와 중간점검 코드리뷰를 보면서 조금 더 시간을 갖고 고민해볼걸, 왜 저런 부분들은 생각을 못했을까 하는 반성도 했다. 벌써 2주차 발자국이다. 3주차 4주차의 강의들과 미션들도 잘 마무리해보자 학습 출처인프런 워밍업 클럽 스터디 4기 - 백엔드 클린코드, 테스트 코드수강 강의:Readable Code: 읽기 좋은 코드를 작성하는 사고법 - 박우빈
2025. 06. 01.
1
1주차 발자국
1. 학습 회고1주차 키워드: 추상화와 객체 지향day2 - 추상의 개념과 이해를 높이는 다양한 명명 방식day3 - 사고의 자연스러운 흐름으로 이해하기 쉽게 작성하기day4 - SOLID. 친해지고 싶다...day5 - 헷갈렸던 VO의 개념과 equals 정리. OCP를 만족하기 위한 시각으로, enum 에 다형성을 적용해 반복되는 if 를 없앤 것이 놀라웠다. 지난 번에는 1주차도 못하고 포기했었다.이번에는 어찌 마무리는 한 것 같다. 이렇게 3번만 더 하자.다만, 미션과 발자국을 너무 임박해서 제출했는데, 2주차부터는 조금은 여유롭게 제출해보는 것이 목표 2. 미션 회고day2 추상과 구체의 예시미션을 확인하고, 작성하려니 생각보다 글로 옮기는 게 힘들었다.사실 추상과 구체는 주변에 정말 많은데 너무 어렵게 생각했다.제시한 예시를 참조해서 살짝 바꾸는 형태로 제출했고 많이 아쉬웠다. day4는 주문 검증 코드와 SOLID기존 코드는 if 의 depth 가 깊어서, 참인 조건을 반환하는 곳이 어디인지 계속 들어가야 하는 구조였다.depth 를 줄이기 위해 조건문이 거짓인 경우들을 메서드로 추출했고, early return 을 바탕으로 메서드 초반에 조건별로 검증하고 종료하는 형태로 리팩토링해서 제출했다. SOLID 원칙을 수강하고, 이해한 걸 바탕으로 자기만의 언어로 표현하는 미션이었다.강의를 들으면서 정리한 내용과 나만의 예시를 들어 내가 이해한 내용을 작성하여 제출했다. 학습 출처인프런 워밍업 클럽 스터디 4기 - 백엔드 클린코드, 테스트 코드수강 강의: Readable Code: 읽기 좋은 코드를 작성하는 사고법 - 박우빈
2025. 05. 30.
0
코드 리팩토링과 SOLID
주문 검증 코드 리팩토링public boolean validateOrder(Order order) { if (order == null) { log.info("주문이 없습니다."); return false; } if (order.hasNoItems()) { log.info("주문 항목이 없습니다."); return false; } if (order.hasNoCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } if (order.isTotalPriceInvalid()) { log.info("올바르지 않은 총 가격입니다."); return false; } return true; } 내가 이해한 SOLID 견고한(SOLID) 소프트웨어를 만드는 데 도움을 주는 5가지의 원칙 심심찮게 접하는 원칙이지만, 돌아서면 단일책임원칙만 기억나고 나머지 원칙들은 항상 떠오르질 않았다. 이번 기회에 장기 기억으로 가져가 보자. 단일책임원칙: 말그대로 하나의 책임만 가져야 한다. 한 가지 일만 잘 하자. 개방폐쇄원칙: 확장에는 "개방", 변경에는 "폐쇄"를 뜻한다. 진열장에 새로운 굿즈들이 들어오는 것은 환영이지만, 새로운 굿즈가 기존 굿즈들의 조화로움을 해쳐선 안 된다. 리스코프치환원칙: 상속 구조에서 하위 객체가 상위 객체에 영향을 주어선 안 되며, 하위 인스턴스로 상위 인스턴스를 치환할 수도 있어야 한다. 사수의 지시/코드 컨벤션을 따르면서, 유사시 사수의 업무도 해낼 수 있어야 한다. 인터페이스분리원칙: 하나의 인터페이스에 기능이 불필요하게 많거나, 불필요하게 많은 인터페이스를 의존함으로써 사용하지 않는 기능에 까지 의존해선 안 된다. 주방용품인 키친타올이 닦을 수 있다고 해서 화장실용품으로도 사용한다면... 의존역전원칙: 고수준모듈이 저수준모듈을 참조하는 형태는 자연스러워 보이지만, 구체화된 저수준 모듈은 변경이 잦다. 어떤 모듈이 변경되어도 서로에게 영향도가 적도록 고/저수준 모듈 모두 추상화에 의존해야 한다. 이 원칙만큼은 어떻게 표현해야 할 지.. 무슨 말인지는 어렴풋이 알겠는데 아직은 어려운 원칙이다.
2025. 05. 28.
0
추상과 구체의 예시
무언가를 인지하는 과정을 구체 레벨로 표현 빛이 눈의 각막을 통해 들어온다.들어온 빛은 망막의 시세포에 의해 전기 신호로 변환된다.전기 신호는 시신경을 통해 뇌로 전달되어 해석된다. 과정 :인프런 워밍업 클럽 스터디 4기 - 백엔드 클린코드, 테스트 코드 과정인프런 강의 :Readable Code: 읽기 좋은 코드를 작성하는 사고법, 박우빈
백엔드