2018.06.21 OKKY “TDD 잘알못을 위한 돌직구 세미나” Review
[OKKY 세미나] TDD 잘알못을 위한 돌직구 세미나
- 2018.06.21 PM 07:00 ~ 09:30 진행된 OKKY - TDD 세미나에 다녀왔다.
- OKKY 세미나 중 가장 빨리 마감된 세미나, 그만큼 많은 사람이 관심을 가지는 주제라고 생각한다.
[발표 1] TDD와 리팩토링. 어떻게 연습할 것인가?, 발표자 - 박재성 (30’)
- SLIPP 커뮤니터 운영, NextStep 1인 교육 사업 시작
- 이 발표에서는 “TDD와 리팩토링을 왜 해야 하는지 알고 있다.”는 가정하에 진행
- 개발 현장을 떠난 지 6년이 되어가고 있어 고려하고 듣자.
TDD와 리팩토링. 나는 어떻게 연습했나?
- 1.2000년대 초반 JUnit과의 만남.
- 2.테스트 주도 개발(TDD) 책과의 만남.
- 3.리팩토링 책과의 만남.
- 1, 2, 3을 거쳤지면서 연습할 때는 잘되나 프로젝트에 적용하려니 안 됨.(간단한 Unit 성격의 메소드만 가능함)
- TDD에 대한 미련을 버리지 못하고 현장 프로젝트에 적용 시도
- 어느 순간 mock 프레임워크를 활용한 테스트가 대부분
- kent beck은 mock 프레임워크 없이 개발한다던데, 이건 뭐지?
- 2009년 ~ 2010년 어느 날. 볼링 점수판과의 만남
- 좀 더 깔끔하게 만들어서 리뷰하는 스터디 (봄싹 스터디에서 미션 과제로 만남)
- step by step 방식으로 mock 프레임워크 없이 진행하는데 재밌었다.
- 너무 재미있어 코드 리뷰 전 3번, 코드 리뷰 후 1번 구현해 봄.
- 접근방식 달리 지우고 작성하고 반복.
- 점진적으로 TDD + 리팩토링
- TDD와 리팩토링도 잘 모른 채 UI DB 의존관계가 있는 프로젝트에 적용하려 하니 잘 안 됬었다.
- TDD와 관련해 7, 8년을 도전한 후에야
- 테스트하기 쉬운 코드와 테스트하기 어려운 코드를 보는 눈이 생김.
- 테스트하기 어려운 코드를 테스트하기 쉬운 코드로 설계하는 감이 생김
- 테스트하기 쉬운 코드 먼저 테스트하고 테스트하기 어려운 코드는 다른 전략을 수립
- 2012년부터 ATDD + TDD 기반으로 SLiPP 개발
- 현장 감을 살리기 위해
- 서비스 자체를 100% 테스트 가능하게 끔 만듬.
- 무슨 짓을 해도 괜찮은 프로젝트이기 때문에 가능.(개발 계기)
- C# -> 자바 -> 스칼라 (테스트 코드가 있어서 점진적으로 바꿀 수 있었음)
- Spring 5 코틀린 지원하므로 코틀린으로 재개발하고 싶다.
- (셀레니움 관심 있으면 참고)
- 2014년 함수형 프로그래밍과의 만남
- 컴퓨터 프로그램의 구조와 해석 (SICP)
- 어렵기로 소문난 책
- 끝까지 못 했지만 얻은 건 많음
- 함수형 프로그래밍 스타일을 자바에 적용해 구현하니 좀 더 테스트하기 쉬운 코드를 구현하는 경험을 하게 됨.
- 기회가 된다면 함수형 언어를 공부하길 추천
- 2012년 ~ 현재
- 학생들 교육 자료, 스터디 하면서 수많은 예제 코드를 TDD로 구현
- 재직자 대상 TDD, 리팩토링 교육하면서 수많은 예제 코드를 TDD로 구현
- 볼링 점수 게시판의 경우 지금까지 10번 이상은 구현
- 할 때마다 다른 인사이트 생김, 계속해서 다른 코드가 나옴
- 반복해서 꾸준히 연습해보길!
- TDD, 리팩토링 멋져 보인다.
- 하지만 생각만큼 연습할 수 있는 녀석이 아니다.
상당한 연습 필요
.- 좋은 글을 쓰는 것과 같다.
- 다양한 책을 읽고, 다양한 방식으로 글을 써봐야 함
프로그래밍도 같음. 많이 읽고 쓰면서 익혀 나가기
추천하는 연습 방법
- 내가 돌아간다면 이렇게 하겠다.
- 처음에는 TDD를 시작하지 않아도 된다고 생각
1단계 xUnit 사용법과 단위 테스트 연습
- 단위테스트의 유용성을 느낀 다음에 TDD 연습을 시작했으면 좋겠다.
- Unit 성격의 메소드에서 시작(유틸성 메소드)
- 알고리즘 연습할 때 적용해도 좋음
- JDK와 같이 누군가 제공하는 API 사용법을 익히기 위한 학습 테스트
2단계 TDD 연습
- 게임과 같이 요구사항이 명확한 프로그램으로 연습
- 의존관계(모바일 UI, 웹 UI, 데이터베이스 등 외부 API와 같은 의존관계)가 없는 여제로 연습
- 적합한 구현에제
- 게임(로또 사다리 타기, 볼링게임, 체스연습, 지뢰 찾기 게임. 단 UI는 콘솔)
3단계 리백토링과 객체지향설계(또는 함수형 프로그래밍) 연습
- 같은 요구사항을 반복해서 연습
- 연습할 때마다 제약사항을 추가해 난이도를 높이면서 연습
- 객체지향 설계 1단계 제약사항
- 규칙 1: 한 메스드에 오직 한 단계의 들여쓰기(인덴트)만 한다.
- 규칙 2: else 예약어를 쓰지 않는다.
- 객체지향 설계 1단계 제약사항
- 2단계 제약사항
- 규칙 3: 모든 원시값과 문자열을 포장한다.
- 규칙 8 일급 컬렉션을 쓴다.
- 리팩토링 제약사항
- 리팩토링 과정에서 컴파일 에러가 발생하지 않도록 한다.
- 이렇게 난이도를 높여가면서 연습한다.
- 똑같은 거 다음 단계 똑같이 짜면 실력이 늘지 않는다.
4단계 - 웹/모바일 프로젝트에 적용
- 앞의 3단계와 병행해 연습
- 장난감 프로젝트로 연습(언제든 포기했다가 다시 도전 가능)
- 처음부터 현장에 적용하려 하면 안 좋다. 레거시 프로젝트에 테스트코드, 리팩토링 하려면 너무 어려운 작업 당연히 포기하게 됨.
5단계 ATDD와 CI 적용
- ATDD(End to End) 를 적용
- 지속적 통합도구를 적용해 지속적인 피드백
TDD, 리팩토링 연습을 위해 필요한 것은?
조급함 대신 마음의 여유
(바로 도입하면 좌절감만 든다.)- 같은 과제를 반복적으로 구현할 수 있는 인내력 (TDD, 리팩토링 어느 시점에 지루해지는데 이겨내는 인내력)
나만의 장난감 프로젝트 (가 필요하다고 생각한다. 반드시!)
- 가장 필요한 것은 가보지 않는 길에 꾸준히 도전할 수 있는 용기
- 재미와 보상이 주어질 것이다.
- 갈 수 있는 회사도 많고
- 자신을 믿고 용기를 내서 TDD와 리팩토링에 대한 즐거움을 느꼇으면 좋겠다.
- 한 번에 너무 많은 리팩토링을 하려고 하면 중간에 일이 들어오면 깨짐.
[발표 2] 테스트하기 쉬운 코드로 개발하기, 발표자 - 정진욱 (30’)
- 10월 24일
- 날짜를 안다는 것 -> 암기
- 자전거 타기 -> 훈련 (균형 감각)
- 학습
- 단순히 암기하는 것도 있지만
- 훈련이 필요한 것도 있을 것
- 테스트, 암기하면 되는가?
- RED, GREEN, REFACTORING 암기하면 되는가?
- 테스트는 암기가 아니라 훈련에 가까움
- 하지만 우리의 욕망은 암기에 있음( 단순히 외우고 잘하길 바람)
- 테스트는 암기가 아니라 훈련이다.
테스트를 잘 할 수 있는 방법은 없을까
- 장애물이 엄청 많다.
- 장애물 없는 길로 다닐 수 없을까요?
- 많은 장애물 중 2개만 치워보자 이 발표에서
- 최근 관심분야 : Property-based testing에 관심 많아서 공부하고 적용 중
테스트하기 쉬운 코드로 개발하기 (장애물 없는 길로 다니기)
- 테스트하기 쉬운 코드란?(테스트의 장애물은?)
- 테스트 장애물 -> 장애물이 없는 경우보다 테스트 비용이 높다.
- 장애물!
- 불확실성(non-deterministic)
- 외부세상에서 값 읽어오기
- 랜덤수/임의시각
- 전역변수 (확신할 수 없음)
- 로컬머신에 존재하는 파일 내용
- 데이터베이스의 특정 레코드
- HTTP-GET
- 외부세상에서 값 읽어오기
- 부수효과(Side-effect)
- 외부세상의 값을 변경
- 전역변수
- 로컬머신에 존재하는 파일 대용
- 데이터베이스의 특정 레코드 (데이터베이스를 타면 테스트하기 어려움)
- HTTP-POST
- 외부세상의 값을 변경
- 불확실성(non-deterministic)
- 순수함수 (PURE FUNCTION) (외부 세상과 단절된 상태)
- 불확실성과 부수효과가 없는 것을 순수함수 ( 같은 INPUT 같은 OUTPUT)
- 장애물이 없다는 것을 의미
- 리턴 타입 별 Testablility (장애물 판별)
- 리턴 타입이 없는 경우
- 외부세상을 변경하는 코드(대부분의 경우)
- 테스트하기 어려움
- 외부세상을 변경하는 코드(대부분의 경우)
- 리턴 타입이 있는 경우
- 외부세상을 변경하는 코드 존재 (ex- print = display, 출력코드)
- 테스트하기 어려움
- 만약 CQS를 지킨다면?
- 테스트하기 쉬운 코드가 됨
- 만약 CQS를 지켜도 외부세상에 의존한다면
- 테스트하기 어려움
- 외부세상을 변경하는 코드 존재 (ex- print = display, 출력코드)
- 리턴 타입이 없는 경우
- 정리
- 테스트하기 쉬운 코드란? 외부 세상에 의존하지 않고 값을 리턴하는 경우
- 외부세상 ex) java = Future
- future 리턴 메소드/함수 = 테스트하기 어렵고 <-> 반대의 경우 테스트하기 쉬움
- 테스트하기 쉬운 코드로 개발하기
- Testable( 대부분 도메인 모델 )과 Non-testable 코드를 최대한 분리한다. (완벽하게 분리)
- testaable 단위 테스트, Non-testable 수동테스트
- Testable과 Non-testable 코드는 Boundary Layer(가장 바깥쪽)에서 만나야 한다.
- Boundary Layer test 테스트 방법을 익힌다.
- Testable( 대부분 도메인 모델 )과 Non-testable 코드를 최대한 분리한다. (완벽하게 분리)
- 요구 사항을 구현하려면 테스트하기 쉬운 코드와 테스트하기 어려운 코드가 만나야 함
- 어디서 만나야 Testable 코드를 최대한 많이 작성할 수 있을까?
- 가장 바깥 쪽일 것 - 내가 작성한 코드가 처음 실행 되는 곳
- Boundary Layer 테스트란? 테스트하기 쉬운 코드가 어려운코드가 만나서 잘 돌아가는지 테스트하는 것.
- Boundary Layer 단위테스트 방법
- 수동테스트
- 인수테스트(전체를 관통)
- 단위테스트(추상화 di를 통해서 등…)
[토론] 테스팅과 디자인, 진행자 - 이규원 (60’)
첫번째 토론 (이규원님이 생각한 질문)
- Q. 디자인, 설계란 무엇이라고 생각하는지
- J(정진욱님) -A. 코드의 정리정돈
- P(박재성님) -A. 추상화
- L(이규원님) -A. 평소에 하는 일
- Q. 프로그래머는 언제 디자인을 하나요?
- P -A. 프로그래밍하는 자체에서 항시 디자인을 해야 한다.
- J -A. 변수 이름 짓는 것부터 항상 디자인을 한다.
- Q. 어떤 프로그래머가 설계자일까요?
- P -A. 코더와 아키텍처를 분리할 수 없다. 설계만 해서는 좋은 설계가 나올 수 없다. 프로그래밍 도메인에 대한 지식이 넓어지면 더 좋은 설계가 나온다. 경력이 많고 적음에 따라 설계를 하고 안 하고 이분법적 생각을 안 했으면 한다. 프로그래머 자신이 설계자 이자 구현자가 되어야 한다고 생각한다.
- Q. 좋은 디자인이 소프트웨어에 어떤 영향을 주는가?
- P -A: 클린코드나 좋은 설계가 중요하다.(책에 나오는 말), 개발자 입장에서보면 깔끔한 코드나 설계가 잘된 코드를 보면 여기에 개발, 기여를 할때 기분좋게 할 수 있다. 확장하기 쉽기 때문에 코딩하는 재미가 있다. 개발자의 동기 부여 측면에서도 중요하다. 전문가로서 살아가는 것에 대한 자부심에도 기여
- J -A: 개발자의 고통을 줄여준다.
- Q. TDD는 테스트 드리븐 디자인이다 에대한 생각
- P-A : 물론 그렇게 볼 수 있다. TDD를 한다 해서 좋은 설계가 나오는 것은 아니지만, Test를 통해 좋은 힌트를 얻을 수 있다.
- J-A : 경험상 디자인과 테스트는 큰 연관 관계가 없지 않나 하는 생각이 든다.
- Q. 좋은 설계란?
- P-A: 현재의 도메인 요구사항에 따라 설계는 달라진다. 정답은 없다.
- Q. 국내 소프트웨어 설게에 대해서 어떤 인식을 가지고 있다고 생각하는가
- P-A : 과거의 SI에 큰 영향이 있다고 생각. (SI 있던 분들이 기득권을 유지하고 있기 떄문에), 왜 중요한지 경험을 해봐야 하는데 경험해보지 못해서 그런 것 같다.
- J-A : 시간적인 여유가 없어서 그렇다고 생각한다.
- Q. 좋은 디자인, 테스팅이 비지니스에는 어떤 영향을 줄까요?
- J -A : 안전감, 자신감, 신뢰감이 생긴다. 비지니스를 할 때 앞으로 나아갈 수 있는 자신감.
- P -A : 예시, 많은 금융회사에서 TDD 코칭 제의가 왔다. 많은 회사들이 한계치가 온것 같다. 장기적으로 비지니스에도 큰 영향을 미칠 것이라고 생각한다.
두번째 토론 (신청자들의 질문)
- Q. 레거시 환경에서 TDD를 어떻게 할지? 여태껏 못했었는데 시작하려면 어떻게 해야 할지 모르겠다.
- P -A: 자신도 TDD 적용하는데 힘든데, 조직의 문화를 바꾼다는 게 힘든 일.
추천하고 싶은 건 나부터 스스로 TDD, 리팩토링 연습을 일정 수준 해야 된다. 나부터 변해야 된다.
내가 만드는 코드에 대해서 단위테스트 등을 하고 누군가 영향을 받아서 전파. 어떤 사람이 좋대 해보자 하면 실패할 것이다. 노력을 하면 나의 성장에 많이! 도움이 된다(근육을 만들어간다는 생각으로).조급해하면 안된다. 천천히 몇년에 걸쳐서.. 평생에 한 번이라도 그런 문화를 가진 조직에서 일해본다라는 생각으로
- J -A: 레거시 코드가 있을떄는 새로운 코드에서만 점진적으로 도입 (레거시는 포기)
- P -A: 자신도 TDD 적용하는데 힘든데, 조직의 문화를 바꾼다는 게 힘든 일.
- Q. 자바에서 TDD는 어떻게 합니까?
- P -A: 강의할 때 말한 내용으로. 프론트앤드, 모바일보다 더 쉽다고 생각한다.
- Q. TDD에 대한 오해에는 어떤 것들이 있는가?
- P -A : 테스트 커버리지가 100% 되야한다. 테스트 코드를 만드는 것도 유지보수 비용이 발생한다. 모든 코드를 테스트코드 작성하면 좋지만 중요하다고 생각하는 부분에 대해서 우선적으로 테스트를 하는 것도 좋다고 생각한다.
정답이 있다고 접근하지 말고 이 코드는 오랫동안 유지보수가 필요하면 테스트를 견고하게 만드는 게 필요하지만 이벤트성 코드는 크게 필요 없다고 생각한다.
- P -A : 테스트 커버리지가 100% 되야한다. 테스트 코드를 만드는 것도 유지보수 비용이 발생한다. 모든 코드를 테스트코드 작성하면 좋지만 중요하다고 생각하는 부분에 대해서 우선적으로 테스트를 하는 것도 좋다고 생각한다.
- TDD 안 한다고 좋고 나쁜 조직 판단을 할 수 없다!
- 관심있는 동료가 없으면 오프라인 커뮤니티를 만들어 (스터디) , 들어가는 것보다 관심 가는 것을 만들어라!
- 사진을 찍지 못해 창천향로님의 글에서 가져왔습니다. 출처 : https://okky.kr/article/476113
발표자료
후기
- Q&A 시간에는 집중하느라 놓친 질문들이 몇개 있는데 창천향로님의 후기를 보면 더 자세하게 나와있다.
- 정말 많은 것을 배울 수 있는 세미나였고 앞으로는 박재성 님이 말한 것처럼 조급해 하지 않고 단위테스트부터 조금씩 연습해 나갈 것이다.