Continuous Integration의 장점 1

황당한 사태가 벌어져도 당황할 필요 없다.

불과 몇 초전에 발생했던 황당한 사태 입니다.

사용자 삽입 이미지오늘 하루도 정말 열심히 일했고 할 만큼 했다는 생각이 들어서 최종적으로 커밋을 깔끔하게 집에 갈 생각이었습니다. 그런데 왠 걸.. FAILED 메시지가 구글톡에 전해졌습니다. 아 놔~~ 집에 가고 싶은데.. ㅠ.ㅠ

대나무(Bamboo) 숲으로 들어가서 고장난 빌드 로그를 살펴봤습니다. 이런!! 테스트가 죄다(는 아니지만 상당히 많이) 깨졌군요.

사용자 삽입 이미지
헐.. 60개가 넘는 테스트가 한 방에… 그것도 바로 전까지 모두 Success 였는데.. 흠~ 예전 같으면 갑자기 어깨가 굳고 눈동자가 커지면서 조급해졌을텐데, 이젠 좀 CI랑 친해졌는지 더이상 두려워지지 않고 차근 차근 로그를 보고 깨진 테스트를 로컬(이클립스와 콘솔에서 메이븐으로)에서 실행해 봅니다.

그리고 문제의 원인을 발견합니다. 문제의 원인은 분명 이전에 커밋한 코드와 방금 커밋하기 전 코드 사이에서 생겨난 겁니다. 왜냐면 바로 전 단계의 빌드는 Success였기 때문이죠.

문제의 원인은 간단했습니다. 스프링 XML 설정파일에서 빈 이름을 잘못 설정했기 때문입니다. 그래서 모든 통합테스트들이 깨졌고, 단위테스트들은 살아남았던 겁니다. 이걸 계기로 통합테스트가 총 몇 갠지도 덤으로 알 수 있게 됐네요. ㅋㅋ

어쨋거나 중요한 건 CI가 주는 장점 한 가지. 바로 버그 발생 원인 탐사 범위를 좁혀준다는 거… 매우 귿입니다.

이젠 그만 집으로 ㄱㄱㄱ

Maven을 쓴다고 해서 종속성을 안중에서 Out 시킬 수 있느냐?

그런데 요즘, Maven과 JIA, Confluence, Bamboo, Clover, FishEye를 사용해서 Continuous Integration을 하면서 매우 재밌는 일들(주로 Maven과 관련된)이 많이 발생하고 있습니다. 그 중 방금전에 있었던 Maven과 관련된 매우 따끈따끈한 이슈 하나를 소개해 드리고자 합니다.

프로젝트 라이브러리들 간의 종속성을 “Out of 안중”까지는 아니더라도.. 아~주 편하게 쓰려고 Maven을 공부하기 시작했었습니다. 그런데…

잘~ 돌던 빌드가 실패했다는 이메일이 저에게 날아왔습니다. 구글토크를 항상 켜두는 저는 Bamboo에서 빌드 결과를 매번 메일로 보내도록 설정해 두었기 때문에, 금방 알 수 있었습니다. 그리고 누가 작업을 한 것인지가 바로 이메일 제목에 나와있습니다. 정말 사용자가 원하는 정보를 원하는 위치에 보여주는 Atlasian의 Considerable Email(이런 용어 없습니다. 그냥 제가 붙인겁니다.)에 놀라지 않을 수가 없었습니다.

Anyway, 왜 빌드에 실패했는지 보기 위해 로그를 봤습니다. 빌드 과정을 Bamboo가 그대로 로깅 해두고, 보여주기 때문에 에러 메시지를 금방 확인할 수 있었습니다.

빌드 실패의 원인은 컴파일 실패. 컴파일 실패시 발생한 에러는

cannot find symbol: ClassUtils.

ClassUtils는 스프링에서 제공하는 수 많은 유틸성 클래스들(언제 한 번 싹다 정리하려고 합니다.) 중에 하나입니다.

ClassNotFound도 아니고..이게 무슨 에러인가 생각해보면서, 자바 기초가 이리도 없는가 하는 생각에 잠기기 시작하면서 구글에서 저 에러 메시지로 검색해서 어떤 상황에 발생할 수 있는지도 대강 살펴봤지만.. 그리.. 도움이 되는 메시지는 못봤습니다.

이 빌드 전에는 빌드가 성공했는데, 이번 빌드가 실패했다.

그럼 문제는 이번에 어떤 수정 사항으로 인한 것인데, 어떤 수정이 있었는지도 Bamboo에서 확인할 수 있습니다. (글을 쓰다보니 이게 Maven 이슈 글인지, Bamboo 마케팅 글인지 점점 햇갈리네요.) 암튼 거길 보니까 pom.xml밖에 없습니다.

pom.xml을 보니까, spring-security 라이브러리가 추가되었습니다. 그래.. 문제는 여기 있을꺼다. 라고 거의 확신을 하고, 이전에도 Maven 종속성 출동 문제 때문에, 일일히 라이브러리르 뒤져본적이 있었기 때문에, 이번에는 그나마 좀 수월하게, spring-security의 pom.xml 파일을 찾을 수 있었습니다.

그 파일을 열어보니, spring을 모듈별로 가져와서 사용하고 있는데, 버전도 명시가 되어 있지 않고, 이미 이 프로젝트에 추가되어 있는 라이브러리들도 중복해서 가져오고 있었습니다. 그것만 보고는 100% 확신할 수는 없었지만. 대략 정리가 되었습니다.

ClassUtils가 이미 있는데, spring-secutiry가 또 가져오고(spring-support 모듈에서), 그래서 두 개의 다른 버전의 클래스가 존재하는데 이 둘 중에 뭘 써야 할지 모르니까. Cannot find symbol 이군..

그래서 현 프로젝트의 pom.xml을 수정해서 spring-security를 가져올 때, 이미 프로젝트에 존재하는 라이브러리들은 가져오지 않도록 설정을 해주었습니다. 비록 이 작업이 한 문장으로 표현이 되긴 하지만, 결코 엘레강트한 작업은 아닙니다.

1. 일일히 어떤 라이브러리들을 가져오는지 pom.xml에서 확인하고, 현재 프로젝트의 pom.xml에 존재한 녀석인지 확인하고, 있으면 빼줍니다. exclunsion 엘리먼트를 사용합니다.

2. 현 프로젝트의 pom.xml에 없는 라이브러리인데, spring의 pom.xml에 optional로 등록되어 있다. 그럼 그 중에 버전이 높은 녀석을 등록해줍니다.

3. 현 프로젝트의 pom.xml에 없는 라이브러리이고, spring의 pom.xml에 optional로도 등록되어 있지 않다. 그러면 추가합니다. 추가할 때는 별도의 코드를 적을 필요는 없습니다. 다만 주석으로 어떤 라이브러리가 추가되는지 적어두면 나중에 용이하겠죠.

자.. 이 정도되면, 제목에 대한 답은 안해도 되겠죠?