블로그
전체 4#카테고리
- 프로그래밍 언어
2024. 10. 27.
0
[인프런 워밍업 클럽 2기 클린코드&테스트코드] 4주차 발자국
출처: Practical Testing: 실용적인 테스트 가이드1. 학습 내용 요약Persistence LayerData Access의 역할비즈니스 가공 로직이 포함되어서는 안됨Data에 대한 CRUD에만 집중한 레이어Business Layer비즈니스 로직을 구현하는 역할Persistence Layer와의 상호작용(Data를 읽고 쓰는 행위)를 통해 비즈니스 로직을 전개 Presentation Layer외부 세계의 요청을 가장 먼저 받는 계층파라미터에 대한 최소한의 검증을 수행MockMvcMock(가짜) 객체를 사용해 스프링 MVC 동작을 재현할 수 있는 테스트 프레임워크트랜잭션에 대한 이야기readOnly = true읽기 전용CRUD에서 CUD 동작 X / only ReadJPA에서 CUD 스냅샷 저장, 변경감지 X → 성능 향상CQRSCommand와 Read의 분리두 동작이 서로 영향을 주지 않게 분리 Stubbing컴포넌트를 MockBean 처리하고 동작에 대한 가짜 행위를 정의하는 것Test Double Dummy아무 것도 하지 않는 깡통 객체Fake단순한 형태로 동일한 기능은 수행하나, 프로덕션에서 쓰기에는 부족한 객체Stub테스트에서 요청한 것에 대해 미리 준비한 결과를 제공하는 객체그 외에는 응답하지 않음SpyStub이면서 호출된 내용을 기록하여 보여줄 수 있는 객체일부는 실제 객체처럼 동작시키고 일부만 Stubbing할 수 있음Mock행위에 대한 기대를 명세하고그에 따라 동작하도록 만들어진 객체 한 문단에 한 주제 논리 구조가 들어가지 않는 형태로 구성하는 것이 좋음Parameterize Test케이스 테스트 코드를 각각 따로 작성완벽하게 제어하기제어할 수 없는 것들은 상위 계층으로 분리해서 테스트 가능하게테스트 환경의 독립성을 보장하자 테스트 간 독립성을 보장하자테스트 간에는 순서가 없어야 함공유 자원을 사용하는 경우 테스트 간 순서가 생길 수 있음한 눈에 들어오는 Test Fixture 구성하기Fixture고정물, 고정되어 있는 물체테스트를 위해 원하는 상태로 고정시킨 일련의 객체 중복으로 세팅하는 경우에는 셋업에서 구성을 하면 어떨까공유 객체를 사용하는 것과 동일한 효과를 가져올 수 있음 테스트와 결합도가 생김코드가 길어지면 의도가 한 눈에 보이지 않을 수 있음 data.sql 같이 셋업을 다른 파일에 옮기면 픽스쳐의 파편화가 일어날 수 있기에 지양빌더를 생성할 땐 파라미터에 테스트에서 필요한 것만 남겨놓자클렌징DeleteAll() Vs. DeleteAllInBatch()DeleteAll()은 각 엔티티를 개별적으로 삭제하며, 삭제 전 select 쿼리를 실행대신 지우는 순서가 상관없어질 수 있음물론 항상 되는 것은 아님DeleteAllInBatch()는 단일 쿼리로 모든 데이터를 삭제하여 더 효율적대량의 데이터를 처리할 때는 DeleteAllInBatch()가 성능상 유리할 수 있음 @DynamicTest어떠한 시나리오를 기반으로 상태를 공유하면서 테스트를 진행할 수 있음테스트 환경 통합테스트 환경을 통합하여 테스트 성능 최적화환경이 다르면 서버가 테스트마다 새로 떠야함 Rest Docs Vs. SwaggerRestDocs장점테스트를 통과해야 문서가 만들어짐 (신뢰도 증가)프로덕션 코드에 비침투적단점코드 양이 많음설정 어려움Swagger장점적용이 쉬움문서에서 바로 API 호출을 수행해볼 수 있음단점프로덕션 코드에 침투적테스트와 무관하기 때문에 신뢰도가 떨어질 수 있음2. 미션 회고Day 15. Layered Architecture 구조의 레이어별 특징을 정리하고, 어떻게 테스트 하면 좋을 지 정리하는 미션이었다. Persistence Layer, Business Layer, Presentation Layer 역할에 대하여 다시 정리해보고, 레이어의 특징에 따른 테스트 코드 예시를 정리해볼 수 있는 기회였다.미션 링크: https://www.notion.so/Day-15-1275cf1d569e8067b43ef2245e1f74ecDay 18. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks의 차이를 정리하고, 주어진 테스트 코드를 리팩토링하는 미션이었다. 강의 시간에 다루었던 어노테이션들에 대해서 자세히 알아볼 수 있었다. 또한, 코드를 리팩토링하며 강의에서 배웠던 내용들을 응용해 볼 수 있었다.미션 링크: https://www.notion.so/Day-18-12a5cf1d569e804e8012f4021394b5bd 3. KPTKeep시험 기간이 겹쳤지만, 과제와 진도를 밀리지 않고 잘 수행하였다. Try 학습했던 내용들을 앞으로 잘 활용하여, 한층 더 성장한 개발자가 되어야겠다.4. 느낀점4주간의 워밍업 클럽 일정이 마무리되었다. 처음 워밍업 클럽을 알게 되었을 때, 테스트에 대해 깊이 있게 학습할 수 있는 좋은 기회라고 생각하여 신청했다. 그러나 클럽 활동을 통해 다양한 지식과 기술을 배울 수 있었을 뿐만 아니라, 다른 참가자들의 코드와 질문들을 보면서 새로운 시각을 갖게 되고, 많은 자극을 받을 수 있었다. 다음 워밍업 클럽이 열린다면, 한번 더 참가하고 싶다.
프로그래밍 언어
2024. 10. 19.
0
[인프런 워밍업 클럽 2기 클린코드&테스트코드] 3주차 발자국
출처: Practical Testing: 실용적인 테스트 가이드1. 학습 내용 요약수동으로 테스트할 경우누락되는 케이스 발생 늦은 피드백유지보수 어려움소프트웨어 신뢰도 낮아짐테스트 코드를 작성하지 않는다면변화가 생기는 매순간마다 발생할 수 있는 모든 Case를 고려해야 함변화가 생기는 매순간마다 모든 팀원이 동일한 고민을 해야 함빠르게 변화하는 소프트웨어의 안정성을 보장할 수 없음테스트 코드가 병목이 된다면프로덕션 코드의 안정성을 제공하기 어려움테스트 코드 자체가 유지보수하기 어려운, 새로운 짐이 되어버림잘못된 검증이 이루어질 가능성이 생김올바른 테스트 코드는자동화 테스트로 비교적 빠른 시간 안에 버그 발견 가능, 수동 테스트에 드는 비용 절약소프트웨어의 빠른 변화 지원 단위 테스트작은 코드 단위(클래스 or 메서드)를 독립적으로 검증하는 테스트검증 속도가 빠르고, 안정적 테스트 케이스 세분화해피 케이스예외 케이스경계값 테스트 → 범위(이상, 이하, 초과, 미만), 구간, 날짜 등테스트하기 어려운 영역을 구분하고 분리하기현재 일시와 같이 테스트가 어려운 코드가 들어오는 경우전체가 테스트하기 어려워질 수 있음테스트가 어려운 부분을 외부로 분리 테스트하기 어려운 영역관측할 때마다 다른 값에 의존하는 코드현재 날짜/시간, 랜덤 값, 전역 변수/함수, 사용자 입력 등외부 세계에 영향을 주는 코드표준 출력, 메시지 발송, 데이터베이스에 기록하기 등테스트하기 좋은 함수순수함수 (pure functions)같은 입력에는 항상 같은 결과외부 세상과 단절된 형태테스트하기 쉬운 코드Test Driven Development프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법론TDD의 3단계Red실패하는 테스트 작성Green테스트 통과최소한의 코딩 Refactor구현코드 개선테스트 통과 유지선 테스트 작성, 후 기능 구현복잡도가 낮은, 테스트 가능한 코드로 구현할 수 있게 해줌쉽게 발견하기 어려운 엣지 케이스를 놓지지 않게 해줌구현에 대한 빠른 피드백 가능과감한 리팩토링 가능 BDD 스타일로 작성Behavior Driven DevelopmentTDD에서 파생된 개발 방법함수 단위의 테스트에 집중하기보다, 시나리오에 기반한 테스트케이스(TC) 자체에 집중하여 테스트 BDD ToolGiven시나리오 진행에 필요한 모든 준비 과정 (객체, 값, 상태 등)When시나리오 행동 진행Then시나리오 진행에 대한 결과 명시, 검증통합 테스트여러 모듈이 협력하는 기능을 통합적으로 검증일반적으로 작은 범위의 단위테스트만으로는 기능 전체의 신뢰성 보장 불가풍부한 단위 테스트 & 큰 기능 단위를 검증하는 통합 테스트2. 미션 회고Day 12. 주어진 코드에 대하여 단위 코드를 작성해보는 미션이었다. 직접 테스트 코드를 작성해보는 건 이번이 처음이었다. 이번 미션에서 어려웠던 부분은 테스트하기 어려운 부분을 통제하는 것이었다. 예를 들어 static으로 클래스 내부에 선언된 Scanner의 경우 입력값을 두 번 이상 넣기가 어려웠다. Scanner를 변수로 빼는 부분도 고려해볼 수 있었지만, 원래 코드의 의도를 테스트때문에 해치는 것 같아 망설이게 되었다. 다행히 강의 뒷편에서 이러한 고민을 다루는 부분이 있는 것 같아 학습 후에 이번 미션에서 고민했던 것들을 확인해 볼 수 있을 것 같다. 3. KPTKeep미션을 해결하고 다른 사람들의 코드들을 보면서 놓쳤던 케이스들을 확인하였다.Problem테스트 환경을 제어하는 부분들 중 어려운 것이 많았다.Try 강의 후반부에서 지금까지 생긴 궁금증들을 많이 다루고 있어서, 나중에도 기억할 수 있도록 정리하면서 들어야겠다.4. 느낀점3주차 테스트 코트 강의가 시작되었다. 워밍업 클럽에 참가한 이유 중에 하나이기도 하다. 이전에 서비스 코드는 작성해 본 적이 있지만 단위 테스트, 통합 테스트는 작성해 본 적이 없었다. 테스트를 작성하지 않았던 이유는 강의 초반에서 강사님이 언급했던 것처럼 '귀찮음'이 가장 컸었다. 그러나 여러 테스트 코드를 작성하고, 전체 테스트를 돌려 모두 성공했을 때의 기쁨은 그 귀찮음을 충분히 보상해 주는 것 같다. 또한, TDD 방식으로 구현을 연습해보았는데, 테스트를 먼저 작성하고 코드를 작성하는 방식이 다소 낯설었다. 그러나 기존의 구현 우선 방식보다 확실히 여러 엣지 케이스를 떠올리기가 쉬웠다. 이 방식을 습관화하여 자연스럽게 활용할 수 있도록 노력해야겠다.
프로그래밍 언어
2024. 10. 13.
0
[인프런 워밍업 클럽 2기 클린코드&테스트코드] 2주차 발자국
출처 : Readable Code: 읽기 좋은 코드를 작성하는 사고법 - 박우빈1. 학습 내용 요약주석의 양면성주석이 많다그만큼 비즈니스 요구사항을 코드에 잘 녹이지 못함코드를 설명하는 주석을 쓰면, 주석에 의존 → 적절하지 않은 추상화 레벨을 갖게 되어 낮은 품질의 코드 생성그럼 언제써야 하나리팩토링 할 때 난관 중 하나는 히스토리를 전혀 알 수 없는 코드후대에 전해야 할 “의사 결정의 히스토리”를 코드로 표현 할 수 없을 때 주석으로 설명모든 표현 방법을 총동원해 코드에 의도를 녹여냈음에도 불구하고 전달해야 할 정보가 남았을 때 사용작성 주의점자주 변하는 정보는 최대한 지양관련 정책이 변하거나 코드가 변경되었다면, 주석도 잊지 않고 함께 업데이트주석이 없는 코드보다, 부정확한 주석이 달린 코드가 더 치명적변수와 메서드 나열 순서변수는 사용하는 순서대로 나열 객체 입장에서도 생각해보자 외부 세계에 내가 어떤 기능을 제공할 수 있는지를 드러냄공개 메서드를 상단에 배치하는 것을 선호물론 정해진 답은 절대 아님!공개 메서드끼리도 기준을 배치, 비공개도 마찬가지상태 변경 >> 판별 ≥ 조회 메서드공통으로 사용하는 메서드인 경우 적당한 곳에 배치패키지문맥으로써의 정보를 제공 가능패키지를 쪼개지 않으면 관리가 어려워짐패키지를 너무 잘게 쪼개도 관리가 어려워짐대규모 패키지 변경은 팀원과의 합의를 이룬 시점에 해야 함오버엔지니어링필요한 적정 수준보다 더 높은 수준의 엔지니어링Ex> 구현체가 하나인 인터페이스, 너무 이른 추상화2. 미션 회고Day 7 미션. 이번 미션은 스터디카페 좌석 예약 시스템 코드를 리팩토링하는 것이었다. 추상화, 일급컬렉션 등 앞선 강의에서 배웠던 개념들을 적용해 볼 수 있었다. 리팩토링 과정에서는 추상화레벨에 대해서 많이 생각하였다. 코드를 처음 보는 사람도 코드가 어떤 구조로 동작하고 있는지 메서드 이름 등으로 최대한 파악할 수 있도록 하였다. 그러나 이전에 경험이 많지 않았기에 추상화를 하는 과정은 쉽지 않았다. 레벨을 높이자니 내용이 날아가는 것 같고 그 반대는 오버엔지니어링이 아닐까하는 고민을 하게 되었다. 그래도 Order와 같은 새로운 도메인 개념 도출, 일급 컬렉션 등 여러 개념들을 십습해 볼 수 있는 기회였다.3. KPTKeep미션을 해결하고 다른 사람들의 코드들을 보면서 여러 관점들을 학습하였다.Problem강의 후반부에서 다루는 개념들은 앞 부분에 비해서 난이도가 조금 더 있었던 것 같다.Try강의를 들으면서 정리해 놓은 내용들을 복습하는 시간을 가져야겠다.앞으로 코드를 짜면서 강의를 통해 배웠던 개념들을 잊지 않고 잘 적용해야겠다.4. 느낀점2주간의 클린코드 강의가 마무리되었다. 강의를 통하여 실습도 해보고, 다른 사람들의 코드도 계속해서 보다 보니 확실히 시작할 때보다 코드를 보는 눈이 생긴 게 체감이 되었다. 강의를 통해 여러 개념들을 공부하면서, 이전에 코드 짜던 사람들이 이러한 구조를 생각해 내는데 얼마나 많은 고민을 했을 까 생각해보게 되는 기회였다. 그리고 이 고민의 결과물들을 강의를 통해 한번에 정리하고 실습도 해볼 수 있어서 좋았다.어느 정도 프로그래밍을 해본 사람들이라면 강의에서 여러 고민의 흔적들을 느낄 수 있을 것이라 생각한다. 또한, 이제 막 코딩을 하고 있는 사람이라면 좋은 습관을 들이는데 좋을 것 같다. 개념을 배웠다고 해서 당장 내일 짜는 코드에서 바로 나타나지는 않듯, 한 번 공부해두면 클린코드를 생각해보는 시간이 모이고 모여 한층 더 성장한 개발자가 될 수 있을 것이다.
프로그래밍 언어
2024. 10. 06.
0
[인프런 워밍업 클럽 2기 클린코드&테스트코드] 1주차 발자국
출처 : Readable Code: 읽기 좋은 코드를 작성하는 사고법 - 박우빈1. 학습 내용 요약이름 짓기추상적 사고를 기반으로 함단수와 복수를 구분이름 줄이지 않기은어/방언 사용하지 않기좋은 코드를 보고 습득하기 메서드 이름메서드 구현에 대한 부분을 추상화해서 중요한 내용을 가지고 있어야 함파라미터와 연결지어 더 풍부한 의미를 전달 할 수 있음 파라미터타입, 개수, 순서를 통해 의미 전달 반환타입메서드 시그니처에 납득이 가는, 적절한 타입의 반환 값void 대신 충분히 반환할 만한 값이 있는지반환 값이 있다면 테스트에 용이 추상화 레벨하나의 세계 안에서는 추상화 레벨이 동등해야 함읽는 사람으로 하여금 자연스럽게 읽히도록 함 Early return일찍 리턴 할 수 있는 경우에는 빠르게 리턴하자! Depth 줄이기무조건 1 depth로 만들어라 → X추상화를 통한 사고 과정의 depth를 줄이는 것이 중요 사용한 변수는 가깝게 선언하기 공백라인복잡한 로직의 의미 단위를 나누어 보여줌으로써 읽는 사람에게 추가적인 정보 전달 부정어! 를 통하여 조건을 뒤집을 경우 사고 과정이 두 번 일어나게 됨한 번에 이해할 수 있게 메서드명 자체에 부정어구를 녹이는 방법을 사용부정어구를 쓰지 않아도 되는 상황인지도 체크 예외 처리예외가 발생할 가능성 낮추기사용자에게 보여줄 예외 vs 개발자가 보고 처리해야 할 예외 새로운 객체를 만들 때 주의할 점1개의 관심사로 명확하게 책임이 정의되었는지생성자, 정적 팩토리 메서드에서 유효성 검증이 가능setter 사용 자제데이터는 불변이 최고만약 변경해야하는 경우 set~ 보다는 update~와 같이 의도를 드러내는 네이밍 이용getter 사용도 자제반드시 필요한 순간에만 생성객체에게 공손하게 물어보자!필드의 수는 적을수록 좋음불필요한 데이터가 많을 수록 복잡도와 대응할 변화가 증가상속보다는 조합을 사용하자상속은 수정이 어렵다 → 부모와 자식의 결합도가 높음조합과 인터페이스를 활용하는 것이 유연한 구조상속을 통한 코드의 중복 제거가 주는 이점보다, 중복이 생기더라도 유연한 구조 설계가 주는 이점이 더 큼 Value Object도메인의 어떤 개념을 추상화하여 표현한 값 객체값으로 취급 받기 위해선 불변성, 동등성, 유효성 검증 등을 보장해야 함 VO vs EntityEntity는 식별자가 존재, 식별자가 아닌 필드의 값이 달라도, 식별자가 같으면 동등한 객체로 취급VO는 식별자 없이, 내부이 모든 값이 다 같아야 동등한 객체로 취급 일급 컬렉션필드가 반드시 하나!컬렉션을 추상화하며 의미를 담을 수 있고, 가공 로직의 보금자리가 생김getter로 컬렉션을 반환할 일이 생긴다면, 외부 조작을 피하기 위해 꼭 새로운 컬렉션으로 만들어서 반환 Enum상수의 집합, 상수와 관련된 로직을 담을 수 있는 공간특정 도메인 개념에 대해 종류와 개념을 명시적으로 표현 가능 2. 미션 회고미션 1. 추상과 구체의 예시를 적어보는 과제였다. 나는 '호흡'이라는 추상 개념을 구체화 해보기로 했다. 우리 몸이 구체적으로 어떻게 호흡이라는 과정이 일어나는 지 서술해보았다. 미션을 통해 추상화 레벨에 대해 생각해보고, 추상화가 얼마나 중요한지 느끼게 되는 계기가 되었다.미션2. 섹션 3에서 배운 내용을 기반으로 읽기 좋은 코드로 리팩토링하는 과제였다. 강의 이전에 문제 코드를 미리 봤었는데, 강의를 보고 문제 코드를 다시 보니 처음에 캐치하지 못했던 개선점들이 보이는 게 신기했다. 문제는 문제점을 우선 파악하고, 개선 방안을 생각해본 뒤, 코드로 직접 수정하며 해결하였다.미션 풀이 과정은 노션에 따로 정리하였다 https://www.notion.so/Day-4-1145cf1d569e80139747c0781f448f433. KPTKeep코드를 보고 이번에는 어떤 방식으로 리팩토링을 해야 할지 고민하면서 강의를 들었다Problem강의가 조금 밀리니 미션을 해결하는 과정에서 고민할 시간을 많이 가지지 못했다.Try강의를 마감일자에 맞추어서 급하게 듣는 것이 아닌 조금 여유를 가지고 듣는 것이 좋겠다.다른 분들이 제출한 코드들을 내 코드와 비교하는 시간을 가져야겠다.4. 느낀점 이번 주는 잘못 들이고 있던 습관들을 고칠 수 있었다. 부정어, 줄임말 등 정말 많은 곳에서 실수를 하고 있었다. 예를 들어, 무언가 객체를 만들면 거의 조건 반사적으로 @Getter, @Setter를 적곤 했다. 이전에 Setter는 조심해서 사용해야 한다는 글을 본 적이 있어서 이제는 잘 사용하지 않지만 Getter는 거리낌 없이 사용했다. 강의를 보고 나니 Getter도 정말 최후에 생성해야하고, 객체에서 Getter로 변수를 꺼내다 쓰는 것이 아닌 요청하는 습관이 바람직 하다는 것을 알게 되었다. 돌아보면 당장 눈앞에 보이는 코드 짜기에 급급했지, 후대에 다른 개발자가 내 코드를 볼 것이라고 생각하고 코드를 짰던 기억은 정말 손에 꼽았던 것 같다. 이번 워밍업 클럽을 통해 Readable한 코드에 대해 항상 고민하는 개발자가 되었으면 좋겠다.
프로그래밍 언어