블로그
전체 42025. 06. 22.
1
[워밍업 클럽 4기 BE] 4주차 발자국
강의강의명: [Practical Testing: 실용적인 테스트 가이드]학습 내용: 섹션7. ~ 마무리이번 주는 남은 강의를 마무리하고 워밍업 클럽의 학습 일정에 마침표를 찍는 날이다. Mock 객체와 앞으로 테스트를 작성하는 데 있어서 가져 가면 좋을 마인드 셋을 배울 수 있었다. Mock을 마주하는 자세가장 기본적인 Mock의 사용법부터 왜 사용하는지, 그리고 Mock을 어디까지 다룰 것인지에 관한 전반적인 부분을 얘기한다.외부 서비스의 API를 이용하거나 메일 전송과 같은 외부 네트워크를 타는 일련의 일들은 우리가 개발하는 과정 동안 계속 서비스를 붙여서 테스트하는 것도 비용이 발생하고, 외부 서비스에서 문제가 발생하는 것까지 우리가 제어할 수 없는 부분이다. 잘 작동할 거라는 믿음과 기대를 바탕으로 제어할 수 없는 부분 등을 Mock으로 대체하여 최대한 우리가 제어할 수 있는 부분에서 최선을 다하는 것이 옳다고 생각한다. 더 나은 테스트를 작성하기 위한 구체적인 조언테스트 간 독립성을 보장하자테스트는 별도의 실행 순서가 정해져 있지 않다. 그러므로 테스트 사이에는 순서가 무관하게 성공해야 하고 각각 독립적으로 실행되어야 한다.공유 변수를 통해서 상태를 변경하고 순서가 정해져 있어야 하며, 만약 중간에 테스트가 수정이 발생하면 나머지 모든 테스트에 수정이 발생하게 된다.Q. private 메서드의 테스트는?client 입장에서 공개 API만 알면 된다. 내부 기능까지 알 필요가 없다. 굳이 하지 않아도 공개 API 검증하면서 자연스럽게 검증될 것이기 때문에 할 필요도 없는 것이다.그렇다고 하더라도 테스트에 관한 생각이 자꾸 떠오른다면 이 메서드가 별도의 책임을 갖는 객체로써 분리해야 하는 것인가를 고민해 보자.Appendix학습 테스트잘 모르는 기능, 라이브러리, 프레임워크를 학습하기 위해 작성하는 테스트로 여러 테스트 케이스를 스스로 정의하고 검증하는 과정을 통해 구체적인 동작과 가능함을 학습이 가능하여 관련 문서만 읽는 것보다 재밌게 학습할 수 있다.Spring REST Docs테스트 코트를 통한 API 문서 자동화 도구로 API 명세를 문서로 만들고 외부에 제공함으로써 협업을 원활하게 한다.테스트를 통과해야 문서가 만들어지므로 신뢰도가 높고 프로덕션 코드에 비침투적이라는 장점이 존재하지만, 코드양이 많고, 초기 설정이 어렵다.vs. Swagger적용이 쉽고 문서에서 바로 API 호출을 수행해 볼 수 있다.하지만 프로덕션 코드에 침투적이며 테스트와 무관하므로 신뢰도가 떨어진다.미션마지막 미션은 총 두 개였다.Layered Architecture 구조 레이어별로 어떤 특징이 있고, 어떻게 테스트하면 좋을지 정리하는 미션과 테스트를 작성할 때 Mock에서 자주 사용하는 어노테이션의 차이를 한번 정리하고 테스트 내용을 살펴보고, 각 항목을 어떻게 배치할지 생각해 보는 미션이었다.이번 미션은 전부 '자신의 언어로 다시 한번 표현할 수 있는가?'가 핵심이라고 생각한다. 무언가를 단순히 배우는 것에서 그치는 것이 아닌 스스로 한 번 더 생각해 보면서 학습의 일련의 과정에서 내가 놓친 부분과 부족한 부분을 스스로 다시 돌아보고 채워나가는 과정을 통해 나를 더 단단하게 만들어 나가는 시간이었다. 회고총 4주에 걸쳐 클린 코드를 지칭하는 수많은 원칙과 조언과 테스트에 대한 많은 내용들을 배웠다.그중에서도 가장 기억 남는 두 가지는 아무래도 '왜 지켜야 하는가?'와 '은탄환이 아닌 도구에 불과하다'라는 것이다. 이 모든 것은 적재적소에 알맞게 사용하는 것이 중요하고, 우리는 이런 것들을 지키면서 일을 하는 개발자로 주어진 기한 내에 요구사항을 모두 만족하는 프로덕트를 개발하는 것이 가장 중요한 사항이다. 도구에 매몰되어 우리의 본분을 잊지 말자.그리고 가장 만족도가 높았던 시간은 코드 리뷰 시간이다.선배 개발자에게 직접 모르는 것을 물어보고 나의 코드를 리뷰 받는 기회가 흔치 않고, 다른 사람들의 코드도 보면서 여러 시야를 확인할 수 있었고 많은 것을 배울 수 있을 거로 생각했지만 생각한 것 이상으로 많은 것을 얻어갈 수 있어서 너무 만족했던 시간이다.마지막에는 하나의 프로젝트를 만들어가면서 실제 서비스와 비슷한 구조에서 테스트가 어떤 의미를 가지는지 배울 수 있었다.4주라는 기간 동안 혼자 학습하는 것이 아닌 다른 사람들과 함께 공통의 목표를 향해 달려가면서 중간중간 포기하고 싶어지는 순간에도 열심히 노력하는 주변을 보면서 다시 한번 마음을 다잡을 수 있었고 끝까지 안주할 수 있었다.
2025. 06. 15.
1
[워밍업 클럽 4기 BE] 3주차 발자국
강의강의명: [Practical Testing: 실용적인 테스트 가이드]학습 내용: 섹션6.이번 주는 Spring을 통해 Layered Acrchitecture에서 단위 테스트와 통합 테스트를 어떻게 수행하는지를 확인할 수 있었다.테스트를 작성하는 노하우 이외에도 트랜잭션 설정, CQRS 등 추가적으로 고민해볼 키워드도 많이 배웠다.Persistence LayerData JPA 프레임워크 기반에서 테스트를 진행했다.실제 DB 대신 local in-memory 환경을 활용해서 도메인 객체의 생명주기를 어떻게 다룰지 확인해봤다.Business Layer핵심 비즈니스 로직이 위치한 계층은 단위 테스트보다는 통합 테스트를 어떻게 진행하느냐가 중심이었다.여러 레이어와 의존 관계를 맺고 있는 구조라서, 트랜잭션 전파나 데이터 정합성 같은 문제를 Persistence Layer와 함께 통합 테스트를 할 때 이런 부분들을 신경쓸 수 있었다.미션읽기 좋은 코드 강의를 수강하면서 실습을 따라하거나 이전 미션을 진행할 때마다, 변경사항이 생기면 수동으로 테스트를 해야 해서 불편함이 있었다. 이번 미션을 통해 그 불편함을 해소할 수 있었다.단순히 강의를 듣고 예제를 따라하는 데서 그치는 게 아니라, 직접 내 생각을 코드로 옮겨보고, 그 과정에서 생긴 여러 의문들을 고민하고 해결하면서 즐겁게 미션을 수행할 수 있었다.회고요구사항이 추가되면서 코드에 변경이 생겼고, 그럴 때마다 테스트 코드가 얼마나 든든한지 느꼈다.리팩토링할 때 불안하지 않았고, 테스트가 잘 돌아가는 걸 보면서 안심할 수 있었다.읽기 좋은 코드와 단위 테스트를 지나 단순한 자바 프로젝트가 아니라, 실제 서비스와 비슷한 구조에서 테스트가 어떤 의미를 가지는지 배울 수 있었다.테스트 코드는 단지 정상 작동을 확인하는 게 아니라, 프로덕션 코드가 의도한 대로 동작하는지, 예외 상황에서도 잘 처리하는지를 확인하는 수단이었다.테스트를 “하는 것” 자체보다, 테스트라는 도구가 개발 전체에 어떤 영향을 주는지 생각하게 됐다.이번 미션에서 예제가 두 개 중 하나를 택하여 그중 하나만 테스트를 진행하였는데 미션을 수행하다보니 "조금 더 여유 있게 시작했으면 나머지 예제도 테스트 코드를 작성해봤으면 좋았을텐데" 하는 아쉬움이 남는다.
2025. 06. 08.
1
[워밍업 클럽 4기 BE] 2주차 발자국
강의강의명: [Readable Code: 읽기 좋은 코드를 작성하는 사고법]학습 내용: 섹션6. ~ 섹션9.강의명: [Practical Testing: 실용적인 테스트 가이드]학습 내용: 섹션1. ~ 섹션5.예제로 먼저 실습을 진행하고 이후 강의를 통해 보완할 점을 배우고, 항상 느꼈던 "계속 실행해서 문제없는지 검증하는 거 불편한데"라고 생각하던 부분을 테스트 코드를 통해 자동으로 검증하는 것을 배우는 한 주였다.변수와 메서드의 나열 순서항상 고민이었다."변수는 어떤 순서로 나열하지? 메서드는 어떤 순서로 배치해야 하나?"이에 대해 어느 정도 해답을 얻을 수 있었다.공개 메서드를 먼저, 공통으로 사용하는 비공개 메서드는 마지막 사용 하위에 동일한 공개 범위 내에서는 상태 변경 >> 판별 ≥ 조회 등 다양한 컨벤션을 배울 수 있었다.그러나 역시 가장 중요한 것은 나열 순서로도 의도와 정보를 전달할 수 있다. 라는 사실이다.리팩토링 연습미션을 먼저 수행한 후 강의를 학습했을 때 가장 많은 것을 얻어갈 수 있었던 부분이라고 생각한다.예제에 대해 간단히 설명하면 스터디카페 이용권을 발급하는 시스템으로 이용권은 일일, 주간, 그리고 고정석이 존재하며 고정석만 추가로 사물함 이용권을 구매할 수 있다.if (studyCafePassType == StudyCafePassType.FIXED) { //logic }그래서 추상화 레벨을 높이기 위해 조건을 메서드로 추출하고 "음, 이 정도면 충분하지" 하고 만족했었다.메서드 추출 개선 코드if (studyCafePass.isFixed()) { //logic }그런데 문제는 과연 이 코드를 모두가 이해할 수 있냐는 것이었다.나는 이미 도메인에 대해 이해했기 때문에 "이용권이 고정석인가? -> 사물함 권한이 존재하는가?"이라는 사고방식이 자연스럽게 이어졌기 때문에 이 부분을 놓치게 된 것이다.현재 우리 도메인에 대해 이해관계가 부족한 사람이 이 코드를 읽었을 때는 어떨 것인가?"이용권이 고정석인가? -> 그래서?"아니면 도메인이 확장되어 사물함에 대한 권한이 다른 이용권까지 확장된다면?메서드로 추출하여 추상화 레벨을 높인 것 좋았지만 도메인 관점에서 바라볼 때 아쉬움이 존재했다.고정 좌석 타입이 아닌가? -> 사물함 옵션을 사용할 수 있는 타입이 아닌가?if (studyCafePass.canUseLocker()) { //logic }그렇기에 위 메서드명처럼 고정석인지를 왜 체크했는지를 더 의미있게 표현할 수 있었던 것이다.테스트는 [ ]다.테스트는 내가 작성한 코드의 동작을 보장해 주는 보험이라고만 생각했다.하지만 테스트 코드들이 모여 프로덕션 기능을 설명하는 문서가 될 수 있다는 것이다.다양한 테스트 케이스를 통해 프로덕션 코드를 이해하는 시야를 보완하고 이 것들이 모여 팀 모두의 자산으로까지 이어질 수 있다.미션그동안의 강의 내용을 통해 예제를 직접 리팩토링해 보는 미션이었다.가장 먼저 한 것은 실제 로직이 어떤 식으로 돌아가는지 파악하는 것이었다. 어떤 도메인이지, 어떻게 구성되어 있고 자세히 모르기 때문에 이에 대한 이해가 필요했다.그 후 추상화 레벨을 높이고 중복 코드를 최소화하여 가독성을 높이고 객체로 묶어볼 만한 것을 찾아 객체들이 상호 협력할 수 있도록 노력했다.마지막으로 책임에 따라 응집도 있게 객체가 잘 나뉘어져 있는지에 초점을 맞춰 진행했다.이번 미션은 다른 사람의 코드를 읽고 이해하는 연습뿐만 아니라 다른 누군가가 나의 코드를 읽었을 때 어떻게 하면 읽기 좋게 할 수 있을지를 배울 수 있었다. 또한 어느 부분은 오버 엔지니어링으로 복잡도가 너무 높아졌을 수도 있지만, 이 역시 도구를 사용하는 데 있어 적정 수준을 찾아갈 기회라고 생각해 재밌게 미션을 수행할 수 있었다.회고리팩토링 연습 부분에서 얘기했듯이 추상화 레벨을 높이기 위해 메서드로 추출하고 해당 메서드의 이름을 단순히 동작에만 초점을 맞춰 이름을 지었던 부분을 반성하고 한 번 더 생각할 수 있었던 한 주였다. 앞으로는 "수준 높은 도메인 개념이 무엇일까?"에 집중해 볼 수 있을 것 같다.그리고 가장 만족감이 높았던 것은 코드 리뷰다.공개적인 자리에서 리뷰를 받는다는 부분에서 신청할 때는 걱정도 됐다.그래도 선배 개발자에게 직접 모르는 것을 물어보고 나의 코드를 리뷰 받는 기회가 흔치 않고, 많은 것을 배울 수 있을 거로 생각해서 용기를 내서 지원했고, 너무 만족했던 시간이다.또한 다른 사람들의 코드도 보면서 여러 시야를 배울 수 있었던 한 주였다.
2025. 06. 01.
1
[워밍업 클럽 4기 BE] 1주차 발자국
강의강의명: [Readable Code: 읽기 좋은 코드를 작성하는 사고법]학습 내용: 섹션1. ~ 섹션5클린 코드를 지칭하는 수많은 원칙과 조언들이 존재한다. 강의를 통해서 이러한 원칙과 조언만을 배울 뿐만 아니라 “왜 지켜야 하는가?”를 배울 수 있는 시간이었다. 그중에서도 가장 기억에 남는 부분은 다음과 같다.사고의 depth 줄이기중첩 분기(반복) 문에서 depth를 줄인다는 것이 "무조건 1 depth로 만들어라."가 아닌 추상화를 통한 사고 과정의 depth를 줄이는 것이 목적이라는 것이다. 무작정 depth를 줄이는 것을 주목적으로 삼으면 오히려 복잡도가 높아져 혼선을 줄 수 있다.getter와 setter를 대하는 자세예전에는 나는 객체를 생성하는 동시에 항상 getter와 setter를 만들어 사용했었다. 그저 편하다는 이유 하나만으로이번 강의를 통해서 그동안 나의 방식이 가져올 수 있는 문제점을 배우고 고칠 기회를 얻었다.setter가 필요하다면 set 대신 update처럼 의도를 드러내는 네이밍을 선정getter를 사용하려고 한다면 외부에서 데이터를 왜 필요로 하는지 생각해 보고 객체에 물어볼 수 있지 않을까?SOLID객체 지향을 학습하면서 설계의 5원칙이라고 하면서 그냥 외우던 것을 실제 코드로 어떻게 녹이는지, 어떤 상황에 위배되고 문제가 발생할 수 있는지 학습할 수 있는 이번 주 학습 내용 중 가장 기억에 남는 부분이다.차주 학습 계획중간중간 기록하여 이해되지 않은 부분을 다시 찾아보고 하느라 강의 시간만 보고 계획을 세워 기존 계획보다 많은 시간을 소모하게 된 부분이 아쉬웠다. 실습 부분이 강의를 수강하면서 같이 진행하여 강의를 더욱 재밌게 수강하였다. 하지만 강의 내용을 온전히 나의 것으로 습득했는가에 대한 의문과 아쉬움이 남는 한 주였다. 앞으로 강의 수강 계획을 강의 시간보다 여유 있게 계획하여 일정을 여유 있게 소화하도록 보완해 나갈 계획이다. 또한, 차주부터 실습 부분은 강의 없이 스스로 진행해 보는 시간을 마련해 볼 계획이다.미션이번 주는 총 두 가지 미션을 진행했다. 첫 번째로 우리가 일상에 자연스럽게 녹아있는 추상을 구체화해 보는 미션으로 둘째로 SOLID를 스스로 정리해 보는 시간을 갖는 것과, 예제 코드를 리팩터링하여 추상화하는 미션이었다. 스스로 정리해 보는 시간은 단순히 무언가를 배운다는 것에 그치지 않고 한 번 더 생각하고 정리할 수 있는 시간이 그동안 나에게 얼마나 부족했고 중요한 순간인지를 알려주는 소중한 기회였다. 또한, 리팩터링 미션은 추상화 레벨, 그리고 메서드의 좋은 이름, 도메인 관점에서 바라보는 방식 등 코드를 다양한 시각에서 바라볼 수 있는 미션이었다.