목차

  1. Software Architect란?
  2. 요구사항 조사
  3. 소프트웨어 아키텍처 설계
  4. 소프트웨어 아키텍처 설계
  5. 개발 프레임워크 설계
  6. 로컬 개발환경 구성
  7. 개발프레임워크 준비
  8. 개발가이드 작성 및 개발자 교육
  9. 개발단계에서의 개발자 지원
  10. 오픈 준비, 오픈, 안정화

 

출처 : https://romainefabula.tistory.com/45

 


Software Architect란?

 

 


나는 소프트웨어 아키텍트(Software Architect. 이하 SWA)가 무엇인지 학문적으로 찾아 보거나 공부한 적이 없다. 2000년대 초반까지만 해도 SWA란 용어는 없고 애플리케이션 아키텍트(Application Architect. 이하 AA)라는 용어만 있었고 내가 AA구나 하면서 살았는데, 후에 사실은 이 역할이 SWA라는 걸 알게 되었다. 하지만, 아직도 여기저기 돌아다니다 보면 똑같은 역할인데도 어디서는 AA라고, 다른 데서는 SWA라고 한다. 아무튼 SWA가 정확한 명칭이라고 하니까 그렇게 불러야 할 것 같다.

소프트웨어 아키텍트는 말 그대로 소프트웨어의 구조(architecture)를 설계하고 구현하고 보수하는 건축가(architect)다. 견고해서 쉽게 무너지지 않고, 처리량이 늘어나거나 다른 소프트웨어를 추가해야 할 경우 쉽게 대응이 가능한 유연한 구조를 만드는 것이 중요하다. 15년 전쯤 개발방법론 같은 걸 배울 때 프로젝트 구성원의 역할이 각각 있었는데 그 중에 아키텍트가 개발프레임웍도 만들고, 개발자 지원도 하고, 소프트웨어적인 문제도 해결하는 다재다능한 사람이어서 다들 아키텍트는 정말 못 하는 게 없고, 힘들기도 하겠다고 했었다. 그런데, 시간이 지나고 보니 그 아키텍트라는 역할을 소프트웨어 아키텍트가 하고 있다는 걸 알게 되었다.

앞에서도 얘기했듯이 나는 SWA에 관한 체계적인 지식은 없다. 다만, 15년여의 기간동안 SWA로 프로젝트에서 수행했던 역할이나 이 일을 대하는 마음가짐 등을 공유하고자 하는 생각에서 글을 쓰기로 마음 먹었다. 물론 최근 들어 글쓰기에 재미를 붙였기 때문이기도 하다. 하지만, 요즘 SI 업계는 한참 일하던 SWA가 많이 빠져 나가 품귀현상이 생기면서 새로운 인력들이 그 자리를 급하게 채웠다. 기존 SWA들이 힘들어서 빠져 나간 자리를 빈틈없이 잘 메꾸려면 누군가 이들을 잘 지도해 줘야 하는데 단시간 내에 원하는 수준까지 올리는 것이 쉽지 않다. 여기서 SWA가 알아야 할 방대한 지식을 모두 설명하는 건 어렵고(누가 원고료를 준다면 생각해 보겠지만) 어떤 흐름으로 프로젝트를 수행하는지와 알아 두면 좋을 팁들을 공유해 보려고 한다.

도입부까지 이렇게 쓰긴 했는데 SWA가 힘들어서 한때 떠났던 입장에서 보면 왜들 이렇게 힘든 걸 하려고 하는지 좀 이해가 안 가긴 한다. 누구나 자신의 진로를 바꿀 때는 뭔가 계기가 있게 마련이다. 참여한 프로젝트에서 어디선가 누군가에 기술적인 문제가 생겼을 때  바지 위에 팬티 입고 등 뒤의 보자기를 펄럭이며 날아오는 슈퍼맨처럼 문제를 해결하는 SWA의 모습에 반해 자신도 그렇게 되고 싶은 사람이 있을 수도 있고, 이력서에 SWA 경력 몇 년만 올리면 몸값이 껑충 뛰고 가고 싶던 직장으로 쉽게 이직할 수 있다는 소문에 별 책임의식 없이 이런 역할을 택하는 사람들도 있을 수 있다. 내가 바라는 건 단 하나, 자신을 SWA라고 말하면 그 말에 책임을 지는 사람이 되었으면 좋겠다.

프로젝트는 납기 내에 고객의 요구사항을 반영하여 오류가 없는 시스템을 구축하는 것이 목표다. 즉, 개발자가 쉽고 빠르게 기능을 구현할 수 있어야 한다는 것이다. 그런 의미에서 실력 있는 SWA의 효용가치는 엄청나다. SWA가 개발자의 작업을 최소화하고 높은 성능을 발휘하는 개발프레임워크를 제공하고, 오류가 발생하지 않는 코드를 만들도록 인스펙션을 해 주고, 개발 중에 문제가 생겼을 때 빠른 시간 내에 해결해 주면 개발속도가 최대한이 될 수 있다. 개발속도가 빨라진다는 얘기는 똑같은 일을 적은 수의 개발자가 해낼 수 있다는 의미도 될 수 있는데, 이러면 프로젝트 개발비용을 절감할 수도 있다는 얘기다. 프로젝트 규모에 따라 몇 명에서 몇십 명까지 인원을 줄일 수도 있고, 납기를 맞춤으로써 페널티를 절약할 수도 있다. 그외에 일반 개발자들이 해결할 수 없는 어려운 문제를 해결함으로써 프로젝트 지연을 방지할 수 있다. 그래서, 프로젝트를 관리하는 입장에서는 아주 소중한 존재이다. 

마지막으로 SWA의 역할을 간단하게 요약해 보면,

1. 소프트웨어 아키텍처에 관한 요구사항 조사
2. 요구사항에 부합하는 소프트웨어 아키텍처 설계(소프트웨어 및 버전까지 결정)
3. 개발 프레임워크 및 공통모듈 개발(개발환경 준비. 개발가이드 작성 및 개발자 교육. 개발서버 및 배포환경 구성)
4. 연계 시스템과의 인터페이스 개발
5. 개발자 지원 및 문제 해결
6. 운영환경 준비/성능테스트 지원/오픈 준비


 

더 간단히 요약해 보면,

1. 코딩의 고수
   - 고난이도의 코딩을 문제가 생기지 않도록 하고, 개발자가 만든 잘못된 코드를 잘 수정한다. 업무프로그램에서의 실수는 그 업무를 수행할 때만 문제가 생기지만, 프레임워크나 공통프로그램에서의 오류는 그 코드를 호출하는 모든 업무에 지장을 초래할 수 있다.

2. 여러 파트의 연결고리
   - 서버, DB, 솔루션 담당자들은 대부분 자신의 영역 외엔 잘 모른다. 이 중간에 SWA가 껴서 연결고리 역할을 해야 한다. 즉, 이 영역을 다 알 수는 없더라도 어느 정도는 알고 있어야 한다.

3. 문제해결의 마지막 보루
   - 프로젝트에서 기술적으로 어려운 문제는 대부분 SWA에게 넘어 온다. 이때 문제를 해결하거나, 해결 불가능한 문제라면 왜 불가능한지 근거를 찾아서 제시해야 한다.


 

정말 부담스럽지 않은가? 프로젝트에서 회의를 하다가 누군가 어려운 문제에 대해 질문을 했을 때 거기에 있는 사람들이 일제히 고개를 돌려 나를 바라본다면. 하필 그것이 잘 모르는 문제라면 등에는 식은땀이 흐르고 손은 떨리고 입은 어버버버.


 

이런 부담감을 이겨낼 준비가 된 사람만 다음 글을 읽으시길.

 

 

요구사항 조사

 

 


중요한 시작점이 요구사항 조사다. 고객이 원하는 시스템이 어떤 것인지 잘 듣고 정리해야 한다. 그래서, 불가능한 요구가 있다면 어째서 불가능한지 설명을 해야 하고, 서로 상충되어 도저히 만족할 수 없는 요구사항이 있다면 하나를 포기하도록 설득해야 한다. 이를 위해서 설득의 기술이 많이 필요하다. 자신이 설득력이 부족하다고 생각된다면 '설득의 심리학'이라는 책을 읽는 것도 좋다. 참고로 가장 잘 먹히는 설득방법은, '대부분 프로젝트에서는 이렇게 합니다' 또는 '지난 프로젝트에서 이렇게 해서 지금까지 잘 운영되고 있습니다'이다. 결국 열심히 공부하고, 사례를 찾아 보고, 경험을 쌓는 것이 최선이다.

뭔가 프로젝트에서 방법론에 따라 하는 걸 설명한다면 요구사항 추적 매트릭스를 작성해서 정리를 해 나가야겠지만, 나는 50년 후에 SWA가 되고 싶은 사람도 참고할 수 있는 글을 지향하기 때문에 특정 방법론이나 기술에 얽매이지 않는 글을 쓰려고 한다. 돈 드는 것도 아닌데 꿈을 크게 갖는 것도 나쁘지 않다고 생각한다.

IT업계생활을 하면서 가장 일을 잘 하는 사람이 있다면 대부분 기술적으로 뛰어나서 무슨 일이든 척척 해결하는 사람이라고 생각할지 모른다. 하지만, 난 이런 사람은 두번째로 일을 잘 하는 사람이라고 생각한다. 가장 일을 잘 하는 사람은 말로 잘 설명해서 일을 줄이는 사람이다. 고객은 SWA만큼 기술적으로 뛰어나지 않기 때문에 자신이 아는 방법으로 원하는 내용을 서술하게 마련이다. 기술적으로 간단하게 구현할 수 있는 기능을 어렵게 설명할 수도 있고, 기술적으로 불가능한 요구를 할 수도 있다. 이런 요구사항을 들고 가서 머리를 쥐어 뜯으면서, 말도 안 되는 걸 요구한다며 속으로 욕을 하면서 고생하면서 해결하는 건 하수다. 그건 이렇게 하면 더 나을 것 같은데 어떠신가요? 그건 구현할 수가 없는데, 이런 형태로 구현하면 어떨까요? 하는 식으로 설득하면 일도 크게 줄고 시간도 절약하니 가장 효율적인 방법이다. 문제는 이렇게 하려면 다양한 구현방법을 알고 있고, 각각의 방법이 갖고 있는 장단점까지 모두 알고 있어야 한다. 그러니까, 열심히 공부합시다. SWA의 길은 멀고도 험하니까.

내가 지금까지 봤던 시스템의 90% 이상은 웹시스템이었다. 요즘 식으로 구성한다면 화면은 JSP에 JQuery 정도로 구성(요구사항 조사 때 지원해야 할 사용자 PC의 OS버전과 웹브라우저 종류와 버전, 해상도까지 조사해야 한다)하고, 서버는 스프링프레임워크와 MyBatis로 구성하면 될 것이다. (말은 이렇게 쉽게 하지만, 사실은 스프링의 방대한 기능을 이용하도록 설정도 해야 하고 화면도 그냥 JSP만 있는 게 아니고 Bootstrap이니 HTML5니 하면서 신경 쓸 것이 많다.) 하지만, 대부분의 시스템이 이 기능 외에 조금씩 다른 기능들이 들어간다. 대량 데이터를 처리하는 배치프로그램이나, 외부와의 인터페이스를 위한 웹서비스나 ESB도 있고, 소켓통신도 있고, 파일을 전송하는 FTP도 있다. SWA는 이런 요구사항도 받아서 프레임워크에 자연스럽게 녹여서 이질감 없게 돌아가게 해야 하고, 사용하기 어려운 코드를 공통모듈에 숨겨서 개발자가 쉽게 사용할 수 있도록 해야 한다.

여기서 노하우를 하나 전수하자면, 보통 요구사항 조사는 프로젝트에 투입되어 처음으로 하는 일 중에 하나다. 그리고, SWA가 프로젝트에서 아주 중요한 인물 중에 한 사람이기 때문에 PM(Project Manager)을 비롯한 프로젝트 구성원들이 기대하는 바도 크다. 그래서, 처음에 만나 현재 프로젝트 진행상황을 듣거나 요구사항 조사를 할 때 유능하다는 인상을 주는 것이 중요하다. 내공이 쌓이다 보면 웬만한 내용은 알기 때문에 얘기하다가 잘 모르는 내용이 있어도 쉽게 질문을 한다. 그러나, 경력이 많지 않으면 모르는 것이 많기 때문에 이런 질문을 하면 무시당하지 않을까 하는 두려움에 질문을 해야 할지 참아야 할지 고민을 하게 된다. 이럴 땐 일단 눈치로 이 프로젝트 안에서만 사용하는 용어가 확실하다고 느낄 때만 질문을 하고 되도록 과묵하게 있는 것이 좋다.

가만히 있으면 중간 간다는 말이 있다. 하지만, 가만히 있는 사람이 전문가라고 간주되는 사람이라면 중간보다 훨씬 위로 간다. 단지 고개를 끄덕이는 것만으로 모두 이해하는 것으로 판단하게 된다. 모르는 내용은 일단 잘 적어 뒀다가 구글에서 검색해 확인해 보고 그래도 안 나오는 것만 물어 봐도 괜찮다. 모두들 부정하고 싶어하지만 첫인상이라는 것이 너무나 임팩트가 강해서 처음에 신뢰를 잃으면 회복하기 위해 수많은 성공을 보여 줘야 하기 때문이다. 요약하면, 처음엔 일단 못 하는 것은 숨기고 잘 하는 것만 보여 주자. 처음은 요구사항만 조사하는 시간이 아니라 신뢰를 쌓는 시간이기도 하니까.

 

 

소프트웨어 아키텍처 설계

 

 


소프트웨어 아키텍처 관련 요구사항에 대한 조사가 끝났으면 이를 만족하는 아키텍처를 설계해야 한다. 아키텍처는 요구사항에 따라서 매번 바뀌기 때문에 결국은 좋은 아키텍처를 많이 보고 자신이 오랫동안 고민하면서 설계해 봐야 실력이 는다. 그래서, 여기서는 반드시 주의해야 하는 사항만을 얘기할까 한다.

일반적으로 서버 안에서 돌아가는 개발 프레임워크는 구성방법의 차이가 있어도 문제가 있어서 구현이 불가능한 경우는 없다. 즉, 어떻게든 돌아가게 할 수 있다는 의미다. 하지만, 동일하거나 원격의 서버에서 별도의 프로세스로 돌아가는 프로그램이나 솔루션은 서로 통신하는 프로토콜이 일치하지 않으면 통신을 할 수가 없다. 그러므로, 소프트웨어 아키텍처 설계는 단순히 장표에서 두 프로세스 사이에 화살표를 하나 그린다고 알아서 통신하는 것이 아니고, 두 프로세스가 통신에 사용하는 프로토콜이 일치하는지와 둘 중에 어떤 것이 서버이고 어떤 것이 클라이언트인지도 미리 파악해 두어야 한다. 여기서 클라이언트는 요청을 생성해서 서버로 보내는 역할이고, 서버는 하나의 네트워크 포트를 bind하고 listen하고 있다가 이 포트를 통해 들어오는 요청을 받아서 처리하고 클라이언트쪽으로 응답을 보내는 역할이다.

이 내용을 가장 익숙한 웹시스템에 적용해서 설명해 보면, 사용자의 웹브라우저는 클라이언트이고 웹서버나 WAS서버는 서버의 역할을 하게 된다. 사용자가 웹브라우저에서 링크를 클릭하면 웹브라우저는 요청을 생성해서 링크에 있는 서버로 요청을 보낸다. 만약에 링크의 주소가 http://somedomain:1235/index.html 이라면 somedomain이라는 서버의 1235 포트로 연결요청을 하고 연결이 수락되면 GET 방식으로 /index.html 페이지를 요청한다. 그러면, somedomain 서버에서 1235 포트를 bind하고 listen하던 웹이나 WAS서버는 웹브라우저의 연결요청을 수락한 후에 /index.html 요청을 받고 이 페이지의 내용을 클라이언트로 보내 준다. 참고로, http://somedomain/index.html과 같이 포트를 명시하지 않으면 프로토콜에 따라 default 포트가 사용된다. 여기는 http니까 80 포트를 서버가 listen하는 것이고, https라면 443 포트를 listen하는 것이다.

이렇게 HTTP나 HTTPS, REST, 웹서비스 등 표준 프로토콜을 사용하는 경우는 클라이언트/서버 관계만 정해지면 대부분 별 무리없이 통신에 성공한다. 그 외에 솔루션들 중에는 자신만의 통신 프로토콜을 정의해서 사용하는 경우가 있다. 이럴 때는 서버 역할을 하는 솔루션이나 서버프로그램이 클라이언트 라이브러리를 제공하고, 클라이언트는 이 라이브러리를 이용해서 호출하기만 하면 내부적으로 구현된 프로토콜을 이용해 서버와 통신이 된다. 이런 경우 주의할 점은 솔루션에서 우리가 사용하는 프로그래밍 언어에 대한 클라이언트 라이브러리를 제공하고, 이 프로그래밍 언어의 버전에서 그 라이브러리를 사용할 수 있는지 확인하는 것이다. 보통의 경우 솔루션에서 라이브러리를 사용하기 위한 전제조건을 표시해 놓으니까 솔루션을 선정하거나 라이브러리를 사용하기 전에 반드시 확인해 두는 것이 좋다. JDBC나 ODBC 라이브러리를 통해 DB에 접속하는 경우가 이 통신방식의 대표적인 예가 될 것이다.

시스템에서 사용할 소프트웨어 사이에 통신관계에 따라 선을 잘 그어 놓으면 일단 소프트웨어 아키텍처 설계는 일단 완료되었다. 이제는 WAS서버 안에서 실제로 구동될 개발 프레임워크를 설계하고  구현해서 소프트웨어 아키텍처에서 그렸던 프로세스 간의 통신이 원활하게 이루어지는지 확인을 해야 한다.

 

 

개발 프레임워크 설계

 

 


소프트웨어 아키텍처에 대한 설계가 끝나면 WAS에서 수행될 업무프로그램 개발의 기본이 되는 개발프레임워크를 구성해야 한다. 일반 웹이라면 Spring과 MyBatis를 사용하면 되겠고, 배치라면 Spring Batch 등을 이용해서 구성하게 된다. 중요한 것은 소프트웨어 아키텍처 요구사항에 만족하도록 해야 하는 것이다. 그러므로, 웹이라고 무조건 Spring MVC 기반으로 하는 것이 아니고 요구사항에 부합하는 최적의 조합을 찾아야 하는 것이다.

일단 요구사항이 나오면 그에 적합한 여러가지 솔루션이나 라이브러리를 조사한다. 그중 기능, 성능, 가격, 개발편의성 등에 따라 한 가지를 선정하는 과정을 거친다. 별도 프로젝트로 실제로 프로그램을 만들어서 BMT를 수행하면서 비교해 볼 수도 있지만, 실제 개발프로젝트를 이미 시작한 경우는 그렇게 시간이 많지 않아서 프레임워크 비교 사이트에 올라온 정보 등을 이용해 하나를 선정하거나 두 개 정도를 선정한 후 실제로 개발해서 비교할 수도 있다.

개발프레임워크를 Spring으로 구성하게 되면 Spring MVC, Spring, MyBatis 정도의 조합이 될 것이다. 그런데, 여기에는 추가적으로 버전 선택의 문제가 남아 있다. 현재 Spring 다운로드 사이트에 가 보면 3.2, 4.3. 5.0 등 다양한 버전이 존재한다. 일단 이 중에서 하나를 선택해야 한다. 일단 선택의 첫번째 기준은 필요한 기능이 모두 제공되는 버전인가 확인하는 것이다. 그 다음은 안정된 버전인가이다.

국제 표준으로 버전 번호를 붙이는 데 대한 정의가 나와 있진 않다. 사실 버전은 만드는 사람이 마음대로 붙이게 되어 있다. 다만, 거의 표준처럼 사용하는 기준은 {major_version}.{minor_version}.{bug_patch} 또는 {major_version}.{minor_version}_{bug_patch} 형태이다. Major version은 소프트웨어의 구조나 기능적으로 대대적인 변화가 있을 때 1이나 그 이상을 올린다. Minor version은 기능적으로 일부 기능에 대한 변경이 발생했을 때 올린다. 마지막으로 bug patch는 이전 버전에서 발견된 버그(기능적 오류)에 대해 수정된 버전을 의미한다. 그리고, 추가적으로 버전 뒤에 붙은 것이 GA, Stable, SNAPSHOT, Nightly Build 등이 있다. GA나 Stable은 개발팀이나 업체에서 안정적으로 구현되었으니 믿고 사용해도 된다는 의미이고, SNAPHOT이나 Nightly Build는 수시로 계속 바뀌고 언제든지 개발팀에서 클래스나 메소드명까지 바꿀 수 있는 버전이다. 나도 예전에 SNAPSHOT 버전의 라이브러리를 참조해서 사용하다가 라이브러리 개발자가 갑자기 참조하는 라이브러리와 코드를 바꿔 버리는 바람에 대대적으로 코드를 수정한 적이 있다. 그러므로, SNAPHOT이나 Nightly Build는 되도록 사용하지 않는 것이 좋다.

위 버전에 대한 설명을 보면 대강 어떤 버전을 선택할지 감이 올 것이다. 현재 Spring에서 다운로드 받을 수 있는 버전은 5.0.4 SNAPSHOT, 5.0.3 GA, 4.3.15 SNAPSHOT, 4.3.14 GA, 3.2.18 GA가 있다. 일단 SNAPSHOT 버전을 제외하면 GA 버전으로 5.0.3, 4.3.14, 3.2.18이 남는다. 여기서, 세 버전 모두 필요한 기능을 모두 만족한다고 하면 일단 높은 버전의 5.0.3이나 4.3.14가 남게 된다. 여기서부터는 Bug patch 버전을 기준으로 선정한다. 어떤 프로그램이나 많이 수정하거나 새로 만든다면 보이지 않는 많은 버그가 존재할 수 있다. 이런 것이 발견될 때마다 Bug patch 버전이 올라간다. 그러므로, Bug patch 버전이 올라갈수록 보다 안정적일 가능성이 높다. (물론, bug patch를 하다가 새로운 bug가 생길 수가 있긴 하지만, 대체적으로 그렇다는 얘기다.) Bug patch 버전을 보면 5.0은 3 밖에 안 되기 때문에 불안정할 가능성이 높고 4.3.14가 안정적일 것 같다.

이렇게 해서 나라면 4.3.14를 사용할 것 같다. 하지만, 여기서도 SWA 개인의 취향이 존재한다. 어떤 사람들은 보다 최신버전을 설치해서 최신 기능을 누리는 것을 좋아하는 사람이 있고, 나처럼 보수적인 기준을 갖고 최대한 안정적으로 구성하는 것을 좋아하는 사람도 있다. 최신버전을 좋아한다면 수시로 최신 bug patch 버전을 검색해서 적용하면서 프로젝트에 적용해야 하고, 보수적인 기준을 가진 사람은 문제가 생기기 전까진 버전에 관해 의심할 일이 거의 없다. 단, 오해하지 말았으면 하는 것은 소프트웨어 버전을 보수적으로 선택한다고 정치적으로 보수적인 성향을 가진다는 의미는 아니라는 것이다.

이렇게 Spring의 버전을 선택했다면 다음으로 여기에 연관되는 라이브러리와 버전을 선택해야 한다. 보통 Spring의 pom 등에 참조하는 라이브러리에 대한 정보가 있으니, Maven 등을 적용하면 알아서 Spring 개발시 사용된 라이브러리와 참조 버전까지 알아서 가져 오므로 고민할 필요가 거의 없다. (Maven은 이런 점은 참 편리한데 꼬이기 시작하면 정말 피곤하게 만드는 일이 많다.) 가끔씩 A와 B라는 라이브러리를 넣는데 여기서 공통적으로 C라는 라이브러리를 참조하는 경우가 있다. 그런데, 하필 같은 C라는 라이브러리 중에 A가 참조하는 버전과 B가 참조하는 버전이 다른 경우는 문제의 소지가 있다. 이런 경우 Maven은 자동으로 높은 버전을 참조하는 것 같긴 한데, 두 버전이 버그패치 정도면 문제가 없겠지만 높은 버전이 되면서 일부 클래스나 메소드가 빠지거나 이름이 바뀌면 낮은 버전을 참조하던 곳에서 클래스나 메소드가 없다는 에러가 발생할 수 있다. 그렇다고 두 버전 다 넣으면 같은 이름의 클래스 중에 어떤 게 사용될지 예측하기도 어렵다. 이 문제에 대해선 명쾌한 해결책을 주기가 참 어렵다. 그냥 높은 버전만 넣고 돌려서 문제 없으면 다행이고, 클래스나 메소드가 없다고 하면 두 버전 다 넣고 해서 문제가 없어지길 바라는 방법 뿐이다. 이래도 안 되면 A, B 라이브러리의 버전을 조정해서 C의 같은 버전을 참조하도록 한다거나... (이래서 SWA가 피곤하다. 흰머리가 안 날 수가 없다.) 가장 확실한 방법은 구성해 놓고 필요한 모든 기능을 테스트해서 문제가 발생하지 않는 라이브러리 세트를 구성하는 것이다.

이렇게 프레임워크의 주가 되는 Spring(또는 다른 무언가) 버전까지 결정이 되었으니, 주변 기능에 대한 설계를 해야 한다.

화면이 그냥 JSP면 보통 방식으로 하지만 그래도 화면에서 AJAX 방식을 구현한다면 Controller에선 JSP로 넘기는 방식과 JSON 송수신 기능도 필요하다. 화면 솔루션을 사용한다면 그 송수신 방식에 맞게 요청을 해석하고 응답을 구성하는 기능도 준비해야 한다. REST 방식으로 통신하는 화면 솔루션이라면 Controller도 RESTful로 설계한다. 송수신 메시지 형식에 따라 Message Converter도 필요하다.

사용자 인증이 필요하다면 토큰이나 세션정보를 이용하는 인증모듈도 추가해야 한다. 그리고, 인증을 포함해서 서버 프로그램 수행시 오류가 발생했을 때 화면에서 인식할 수 있는 오류정보를 생성해서 화면으로 전달되게 한다. 클라이언트에서 예상하는 방식으로 정확한 형식의 응답을 보내도록 해야 한다는 것이다. 클라이언트가 HTML을 예상한다면 HTML 코드를, JSON을 예상한다면 JSON 포맷의 응답을 보내야 한다. WAS에서 세션방식으로 인증처리를 한다면 세션에 담는 정보를 최소화해야 하고, 세션타임아웃도 최소한으로 설정하도록 해야 한다. 한 사용자의 세션에 저장된 정보에 현재 접속 사용자수를 곱한만큼 힙메모리를 차지하기 때문에, 세션에 저장하는 정보가 많은데 접속사용자가 몰리면 메모리를 많이 사용하게 된다. 그리고, 세션 타임아웃이 길면 접속해서 잠깐 사용하고 로그아웃을 하지 않은 경우, 사용자가 사용하지 않는데도 세션 타임아웃에 도달할 때까지 세션정보는 계속 힙메모리를 차지하고 있게 되므로 결국 이런 불필요하게 유지되는 세션정보들에 의해서도 OutOfMemory가 발생할 수 있는 것이다.

프로그램 처리 결과를 사용자에게 전달하도록 메시지 처리 기능도 준비한다. 한 개 언어에 대한 처리만 필요하다면 단순히 코드와 그에 대한 메시지만 정의하면 된다. 하지만, 사용자가 다양해 여러 언어를 지원해야 하는 경우라면 다국어 처리도 추가해야 한다. 메시지 처리는 어떤 시스템이나 하는 것이지만 다국어 처리는 진짜 필요한지 요구사항 조사 때 반드시 확인해야 한다. 화면에 있는 내용에 대해 다국어 처리를 하려면 최초 개발시에도 하나씩 코드처리를 해야 하지만, 나중에 유지보수할 때에도 내용이 모두 화면소스에 실제 내용 대신 메시지코드만 보이기 때문에 한눈에 내용이 들어오지 않아 수정할 때마다 코드와 내용을 확인해야 하므로 그만큼 시간이 걸리기 때문이다. 다시 말해, 다국어 처리는 꼭 필요하지 않으면 안 하는 게 좋다.

DB를 이용해 데이터를 저장하고 조회해야 한다면 MyBatis, Hibernate 등의 Persistence Layer 처리 라이브러리를 선택하고, 데이터소스 구성과 트랜잭션 처리에 대한 설계도 필요하다. 하나의 DB만 사용하면 그나마 간단하지만, 2개 이상의 DB에 대해 트랜잭션 처리가 필요하면 2PC(Two Phase Commit) 처리까지 해야 되므로 구성이 훨씬 어려워진다.

로그에 대한 설계도 필요하다. 로그 포맷을 어떻게 하고, 종류에 따라 로그파일을 어떻게 분리하고 어떤 주기로 rotate할지도 결정해야 한다. 그리고, DB 쿼리 수행에 대해서는 쿼리만 기록할지, 쿼리 결과까지 기록할지도 정해야 한다.

요구사항에 따라 프레임워크에 Thread Local이나 Interceptor 등의 기능이 필요할 수도 있다. 개발프레임워크에서 중요한 요소 중의 하나가 반복되는 작업을 잘 녹여 넣어서 실제 업무코드에는 업무로직만 보이게 하는 것이다. 그러므로, 반복되는 작업을 잘 선별해서 프레임워크 안에 잘 숨겨 놓으면 개발자들의 개발공수도 줄어 들고, 반복되는 작업에 변경이 필요할 경우에도 모든 코드를 찾아서 고칠 필요 없이 프레임워크 코드 하나만 수정하면 간단하게 해결될 수 있다.

그리고, 중요한 한 가지가 Service나 DAO 맨앞에 Interface 등을 통해 유연성을 제공하느냐 하는 것이다. 이것은 고객의 요구보다는 주로 SWA의 취향에 따라 결정되는데, Interface를 두는 것이 유연성이 좋아 보이긴 한데 나는 최대한 단순한 구조를 좋아하기 때문에 Interface 없는 구조로 설계한다. 이 방식이 실행속도도 빠르고, 가장 중요한 것은 개발속도가 빠르다는 것이다. SWA의 가장 중요한 임무 중에 하나가 개발자가 빠르게 개발하도록 지원하는 것인데 이것 하나 줄이는 것이 개발자의 스트레스를 줄여 주고 그만큼 일도 줄여 주기 때문이다. (SWA 입장에선 interface 하나가 별 게 아닌 것 같지만, 개발자들은 수십, 수백개를 만들어야 하기 때문에 굉장히 싫어한다.) 물론 이 부분도 각자 취향에 맞게 구성하는 것이라 굳이 한다면 말릴 방법은 없다.

개발 프레임워크 설계를 했으니 다음으로 프레임워크를 구현하기 위한 개발환경을 구성하겠다.

 

 

로컬 개발환경 구성

 

 


개발 프레임워크를 구현하기 전에 개발환경을 준비해야 한다. 이 환경은 SWA가 프레임워크를 개발할 때도 사용하겠지만, 이걸 그대로 개발자에게 배포해서 실제 업무프로그램을 개발할 때도 사용해야 하니까 처음부터 가볍고 편리하게 사용할 수 있도록 하는 것이 중요하다. 결국 개발환경이 개발생산성에도 영향을 미친다는 의미다.
 
가장 먼저 선택할 것은 Java 버전이다. Java 버전에 따라 선택할 수 있는 WAS의 버전 선택의 폭이 결정된다. 통합개발환경은 WAS의 Java 버전과 다르게 선택할 수 있긴 하지만 대개 동일한 버전을 선택하기 때문에 영향이 가장 크다.
 
다음으로 통합개발환경(IDE)을 선택해야 하는데 일반적으로는 이클립스를 사용하는 것이 좋다. 물론, IntelliJ 같은 좋은 유료 도구가 있긴 하지만, 통합개발환경 선택에서 가장 먼저 고려해야 할 것은 모든 개발자가 사용해야 한다는 것이다. 모든 사용자가 유료 도구를 사용할 수 있을만큼 프로젝트 비용이 충분하다면 좋겠지만, 아직까지 그런 프로젝트를 본 적이 없기 때문에 보통은 이클립스를 사용한다.
 
일단 이클립스를 선택했지만, 여기서도 다양한 버전이 있기 때문에 어떤 버전을 선택할지 결정해야 한다. 일단, 개발자 윈도우 OS에 따라서 32bit인지 64bit인지를 선택해야 한다. 요즘 대부분이 64bit를 사용하기 때문에 문제는 없을 것이다. 다음으로 개발환경을 설치할 디스크 드라이브를 선택하는 것이다. 이것은 무조건 C드라이브를 추천한다. 개발환경을 구성할 때 각종 관련 프로그램이나 파일의 경로를 절대경로를 입력하게 된다. 그래서, 개발환경을 구성할 때도 모든 개발자에게 예외 없이 적용할 수 있는 디스크 드라이브를 사용해야 한다. 보통은 C드라이브 외에 D드라이브를 사용하지만 가끔씩 D드라이브가 없는 경우도 있고, SSD와 HDD를 같이 사용하는 경우에도 보통은 SSD를 C드라이브로 지정하기 때문에 최적의 선택은 C드라이브이다.
 
통합개발환경(IDE)에 대한 최적화도 필요하다. Spell Check나 각종 Validation이 켜져 있는 경우, 코드를 입력할 때나 개발툴을 시작할 때마다 내용에 대한 각종 체크를 수행하면서 시간을 소모하기 때문에 개발을 바로 하지 못 하고 기다려야 한다. 이런 기능들은 잘 확인해서 꼭 필요한 기능 외에는 모두 꺼 놓는 것이 좋다. 나 같은 경우는 일단 거의 모두 꺼 놓고 개발하다가 문제가 생기면 하나씩 켜는 방식으로 한다.
 
스프링 프레임워크를 사용한다면 이클립스에 스프링 프레임워크 플러그인을 설치해서 사용하는 것보다는 STS(Spring Tool Suite)를 사용하는 것을 추천하고 싶다. 물론 스프링 프레임워크 플러그인도 추천 이클립스 버전을 제시하기 때문에 거의 문제가 발생할 가능성은 적지만, 이클립스가 마이너 업그레이드 등이 되면서 변경이 생겨 플러그인과 문제가 생길 가능성이 있다. 하지만, STS는 이클립스와 스프링 플러그인을 붙여서 나름 최적화시킨 버전이기 때문에 이클립스에 스프링 플러그인을 설치한 것보다 안정적일 가능성이 높다.
 
여기에 또 다른 이클립스 플러그인을 설치할 일이 생길 수도 있다. 화면구현을 JSP가 아닌 별도 화면 클라이언트 툴을 사용할 수도 있다. 이런 툴이 이클립스 플러그인 형태로 개발툴을 제공하는 경우도 있고 별도 개발툴 프로그램을 제공할 수도 있다. 별도 프로그램을 제공하는 경우는 그냥 설치해서 사용하면 되겠지만 이클립스 플러그인 형태일 경우는 서버 개발환경으로 사용하는 이클립스에 설치할지 아니면 그와 별도의 이클립스를 구성해서 사용할지 결정이 필요하다. 일단, 화면 개발툴의 플러그인도 추천하는 이클립스 버전이 있을 것이다. 이렇게 이클립스 플러그인들이 늘어날수록 사용할 수 있는 이클립스 버전에 제약이 늘어나고, 가끔은 모든 플러그인을 만족하는 이클립스 버전이 없을 수도 있다. 그리고, 플러그인이 늘어날수록 이클립스가 무거워지고 플러그인들간의 충돌로 이클립스가 죽을 수도 있다. 그래서, 화면개발툴 플러그인처럼 무거운 것은 업체에서 추천하는 이클립스 버전에 별도의 프로세스로 띄워서 사용하는 것을 추천한다. 요즘은 대부분 개발자가 8GB RAM에 듀얼모니터를 사용하기 때문에 개발툴 2개 띄우고 테스트용 화면까지 보면서 테스트해도 무리는 없을 것이다.
 
로컬 테스트를 위한 이클립스용 WAS 플러그인도 필요하다. WAS 버전이 결정되어 있기 때문에 이 버전에 맞는 플러그인을 설치해서 사용하면 되는데 여기도 보통 추천 이클립스 버전이 있으므로, 여기서도 이클립스 버전에 대한 제약이 생긴다. WAS 플러그인을 설치한 후엔 반드시 debug 모드로 동작이 되는지도 확인해야 한다. WAS의 debug 모드는 프로그램 버그를 찾는 데 있어 정말 위대한 기능이기 때문에 꼭 확인해야 한다. 사실 가끔씩은 프로젝트에서 사용할 WAS와 동일한 플러그인을 사용하지 않을 수도 있다. WAS의 기능이 아주 많아서 한번 기동할 때마다 아주 오래 기다려야 하는 경우도 있을 경우에는 설정에서 사용하지 않는 기능을 비활성화시키는 경우도 있고, 그래도 안 되는 경우는 로컬 개발환경에만 비슷한 기능을 제공하는 가벼운 WAS와 플러그인을 사용하는 경우도 있다. 혹은, WAS 플러그인이 추천하는 이클립스의 버전이 다른 플러그인과 너무 동떨어져 도저히 맞출 수가 없거나, WAS 플러그인이 꼭 필요한 기능을 제공하지 않을 경우에도 다른 WAS의 플러그인으로 대체할 수 있다. 이렇게 로컬 개발환경의 WAS와 서버의 WAS가 다를 경우에는 개발서버에서 면밀한 테스트를 수행해서 혹시 WAS간의 구현 차이에서 발생할 수 있는 오류의 발생을 방지해야 한다.
 
소스형상관리를 위한 플러그인도 필요하다. 이것은 미리 형상관리서버를 설치하고, 플러그인에서 여기에 연결하는 테스트까지 완료해야 한다. 개발자에게 개발환경을 배포할 때는 형상관리 플러그인에 저장된 패스워드를 초기화하거나 테스트 때 사용한 형상관리서버의 계정에 대한 패스워드를 바꿔 놓아야 한다. 배포된 개발환경에서 바로 형상관리서버에 자동으로 로그인이 되면 개발자들은 계정정보를 변경하지 않고 그냥 쓰기 때문에 나중에 소스를 commit한 개발자를 찾기가 어려워진다.
 
프로젝트에서 소스 정적분석에 사용할 툴(PMD 등)도 설치해서 제공한다.
 
이외에 Maven이나 Ant 등의 빌드툴도 필요할 경우 설치하고, Maven을 사용한다면 Local Repository 등도 설정이 필요하다.
 

 
마지막으로 이 모든 것들을 깔끔하게 묶어서 개발자들이 개발환경을 설치할 때 별도의 작업을 최소화하기 위한 작업이 필요하다. 이 방법을 처음 본 것이 2005년이었고 대부분의 프로젝트에서 개발환경을 이렇게 배포하고 있긴 한데 확인차원에서 설명하려고 한다.
 
먼저 JDK는 설치가 필요하기 때문에 사용하기로 한 Java 버전(6, 7, 8, 9 등)의 가장 높은 bug patch 버전을 선택해서 32bit, 64bit 중 선택해서 다운로드하고, 이것을 그냥 설치한다.
 
일단 위에서 추천한 것과 같이 C드라이브를 사용하고, 여기에 DEV라는 폴더를 생성한다. 여기에 앞에서 설치한 Java 경로를 찾아가 JDK 폴더(예를 들면 jdk1.8.0_111 등)를 통째로 복사해서 C:\DEV 아래에 붙여 넣는다. 다음으로 이클립스(또는 STS), WAS, 빌드툴, 이클립스 workspace, Maven Local Repository 등 윈도우 설치형이 아닌 모든 툴과 경로를 C:\DEV 아래에 설치하는데 Java를 포함한 모든 참조경로를 C:\DEV에 있는 경로로 설정한다. 여기서 한 모든 작업이 C:\DEV라는 큰 크림을 완성하기 위한 과정이다.
 
이렇게 준비한 로컬 개발환경을 개발자에게 배포하는 단계는 개발프레임워크의 개발이 끝나고 샘플프로그램까지 만든 뒤에 하겠지만, 어쨌든 그때에는 C:\DEV 폴더를 통째로 압축해서 전달하면 이 압축파일을 C드라이브에 푸는 것만으로 개발환경 준비가 거의 끝나게 될 것이다.
 
이외에 DB 클라이언트 프로그램의 경우는 단순히 압축을 푸는 방식이 아닌 윈도우 설치프로그램이 많기 때문에 별도로 설치해서 사용하면 된다.

 

 

 

개발프레임워크 준비

 

 


개발환경이 준비되었으니 이제부터는 개발프레임워크를 만들어야 한다. 로컬 개발환경 구성까지는 SWA로서 경험이 많지 않아도 차례만 잘 따라서 어느 정도의 시간만 투자하면 얼추 비슷한 결과물이 나올 수 있지만, 이번 과정은 아주 많은 프로그래밍 언어적인 지식과 경험에 의해 정교하고 수준 높은 코딩 능력이 필요하다. 내 경험을 바탕으로 생각해 보면 최소한 4년 정도는 공통모듈이나 프레임워크 프로그램 개발을 해 봐야 어느 정도 수준의 개발프레임워크를 개발할 수 있을 것 같다. 참고로 코딩 능력을 빠르게 향상시키는 첫번째 방법은 잘 만든 코드를 많이 보는 것인데, 그 코드에는 능력 있다고 알려진 선배의 코드를 참조하거나 공개된 오픈소스 라이브러리의 소스코드를 보는 것이다. 이런 면에서 아무래도 SWA는 오타쿠적인 기질이 있어서 뭔가 기능이 궁금한 코드가 있으면 어떻게 구현했는지 소스코드를 찾아 보거나, 소스코드가 없으면 디컴파일을 해서 비슷하게라도 구현하는 방법을 익히는 과정이 필요하다. 코딩 능력을 향상시키는 두번째 방법은 역시 어려운 코드를 많이 만들어 보는 것이다. 아무래도 라이브러리와 우리가 만들고자 하는 코드는 목적이 다르다 보니 기능적으로도 차이가 나서 똑같이 적용하기는 힘들다. 내가 필요한 기능을 구현하기 위해서 어떤 구조가 좋고 메소드가 받은 파라미터에 대해 어떻게 검증하고 처리결과로 어떤 값을 리턴하는 것이 좋은지, 메소드를 호출한 결과에 대해서는 어떻게 검증하고 어떻게 확인하는지에 대해서 많은 고민이 필요하다. 이 두번째 고민을 하는 시간을 빨리 줄이려면 첫번째 방법처럼 좋은 코드를 많이 보면 된다.

필수적으로 맨처음 조사한 요구사항을 모두 만족시키도록 기능을 빠짐없이 구현해야 하며, 개발자들이 빠르게 개발할 수 있도록 쉽게 만들어야 하고, 대량처리시에 높은 성능을 발휘해야 하고, 처리 중에 문제가 발생하지 않도록 안전해야 한다. 업무프로그램은 그 기능을 실행할 때만 호출되기 때문에 코드에 문제가 있더라도 그 기능을 호출하는 경우에만 문제가 있다. 하지만, 개발프레임워크는 어떤 기능을 호출하더라도 매번 호출되기 때문에 한번의 코딩실수가 모든 시스템에 영향을 미칠 수 있다. 그래서, 개발프레임워크를 멋모르고 만들 때는 막 개발하지만, 어느 정도 알게 되면 코딩을 하면서 이 코드가 문제가 있진 않은지 성능상 병목구간이 되진 않을지 항상 고민을 하게 된다. 참을 수 없는 코딩의 무거움이라고 할까? 대개 개발이 끝나고 오픈을 준비할 때 성능테스트를 수행하지만, 개발프레임워크 개발이 끝나고 나서 프레임워크 코드에 문제가 없는지 POC(Proof Of Concept) 개념의 성능테스트를 수행하기도 한다.

서버단의 개발프레임워크를 개발할 때 조심해야 할 것이 몇 가지 있는데, 첫번째는 Singleton 클래스를 사용한다면 synchronized를 아주 조심해서 사용해야 한다.(Java의 경우 객체 단위 lock을 사용하기 때문에 Singleton 방식 객체가 아니면 synchronized가 전혀 작동하지 않는다) synchronized가 걸린 부분에서 오류가 생기거나 시간이 오래 걸리면 그 뒤에 이 코드를 호출하는 프로그램들이 모두 대기상태에 빠져 서버가 hang이 걸릴 수 있다. 두번째는 서버가 Thread 방식으로 동작한다면 반드시 코드가 thread-safe하도록 만들어야 한다. Thread 사이에 공유하는 변수가 있을 때 그것을 잘못 다루면 한 건씩 요청을 처리할 때는 문제가 없지만, 동시에 이 부분을 호출했을 때 각자 다른 요청 사이에서 변수값이 엉키면서 예상치 못한 결과가 나오게 된다. 세번째는 자체적으로 cache 클래스를 만들어서 사용할 때 반드시 사용하지 않는 값을 그때그때 삭제해 줘야 하고, 전체 cache를 refresh할 때도 꼭 이전 값들을 clear한 후 새로운 값을 읽어 들어야 한다. Cache가 처음 시작할 때는 데이터가 많지 않지만 자꾸 여기에 올리는 값들이 늘어나기만 하고 삭제를 하지 않으면 모든 heap을 사용해서 결국에는 OutOfMemory가 발생하게 된다.

개발프레임워크를 만들 때는 보통 이전에 잘 만들어진 예제를 가져다가 필요한 부분만 고쳐서 사용하는 것이 보통인데 앞서 설명한대로 개발프레임워크의 모든 부분 하나하나가 전체 시스템의 성능과 안전성에 영향을 미칠 수 있기 때문에, 가져다 사용하는 코드라도 기능을 모두 확인하면서 어떻게 동작하는지 모두 확인하고 주석을 달아 두는 것이 좋다. 그래야 문제가 생겼을 때 원인을 찾아서 빠르게 수정할 수 있다. 그리고, 가져 온 예제에서 필요없는 기능은 지워 놓는 것이 좋다. 프레임워크는 꼭 필요한 기능만으로 구성되어야 하는데 어떤 기능인지도 모르는 코드가 들어가 있으면 그로 인해 문제가 생겼을 때 원인을 찾기도 어렵고 해결하기는 더 어려워진다. SWA는 자신이 만든 개발프레임워크에 포함된 모든 기능을 완전하게 파악하고 있어야 한다.

사용자 인증, 권한, 요청/응답 데이터처리, 메시지, DB연결 등을 구현하면, 이런 기능들과 개발프레임워크를 테스트하기 위해 기본적인 CRUD를 수행하는 프로그램을 개발하면서 스스로 개발편의성을 검증한다. 여기서 부족한 부분이 있으면 보완하고, 로컬에서 이 샘플프로그램을 이용해 간단한 성능테스트를 수행한다. LoadRunner가 있으면 좋겠지만 없으면 JMeter나 간단한 클라이언트 프로그램을 이용해서 부하를 주고, 서버 프로그램에 대해선 JConsole이나 Java VisualVM 등으로 간단하게 모니터링을 할 수도 있다. 문제가 없으면 좋겠지만 부하를 주다가 Heap이 꽉 차 OutOfMemory가 발생하면 jmap으로 Heap Dump를 생성해서 Eclipse Memory Analyzer 등으로 분석해서 해결한다.

이렇게 검증이 끝나면 개발자들에게 개발환경을 배포해야 한다. 앞서 설명한 대로 C:\DEV 폴더를 통째로 압축해서 전달하기만 하면 되는데, 이 개발환경도 미리 테스트가 필요하다. C:\DEV 외의 디렉토리는 참조하지 않도록 만들긴 했는데 실수로 빠지는 경우가 있을 수 있기 때문에, 새로운 PC에 이 압축파일을 풀어서 개발을 해 보면서 문제가 없는지 마지막으로 확인하는 것이다.

여기서 노하우를 하나 전수하자면, 이렇게 준비된 개발환경을 테스트해 줄 사람이 필요한데 다른 SWA가 있으면 좋지만 그렇지 않은 경우가 있다. 프로젝트를 진행하다 보면 개발환경 뿐만 아니라 공통모듈 등을 수시로 배포해야 한다. 그래서, 프로젝트에 한두명 정도의 개발자와 친하게 지내는 게 좋다. 이런 사람들에게 이런 것을 배포하기 전에 테스트를 요청해서 미리 확인하고, 대신 이 개발자들에게 도움이 필요할 때 열심히 도와 주면서 서로 공생하는 관계로 지내는 것이다.

또 하나 조언을 하자면, 개발환경을 만들어서 압축까지 했는데 나중에 보니까 조금 수정할 것이 생겼다면 바로 새로운 압축파일을 만드는 것이 좋다. 사실 압축파일이 거의 2GB 이상 크기라서 시간도 오래 걸리지만, SWA가 한 번 움직이면 개발자 수명에서 수십명이 움직일 일이 최소 한번씩 줄어든다. 반대로. SWA가 한번 실수하면 많은 개발자가 최소 한번 이상씩 할 일이 늘어난다. 그러니까, SWA는 자신이 할 수 있는 최대한의 최적화와 테스트를 하는 습관을 들여야 한다.

다음으론 개발한 소스를 관리하는 형상관리 시스템을 설치하고 여기에 소스를 올리고 내려 받는 과정을 확인한다. 형상관리에 있는 소스를 자동으로 내려받아 빌드하고 개발서버에 배포하는 시스템(CI)도 구성한다.

개발 준비가 되었으니 이제는 개발가이드를 작성하고 교육을 해야 한다.

 

 

개발가이드 작성 및 개발자 교육

 

 


개발자가 사용할 개발환경에 대한 준비가 끝나면 개발가이드를 작성해야 한다. 개발가이드는 프로젝트에 투입된 개발자들도 참조하지만 시스템을 오픈한 후에 유지보수를 담당하거나 그 후에 인력이 변경될 경우에 인계받은 개발자도 볼 수 있기 때문에 설명을 듣지 않더라도 문서만으로 필요한 내용을 찾을 수 있도록 정보를 빠짐없이 기록해야 한다. 어떤 종류의 가이드나 마찬가지겠지만, 글만으로 설명하는 것보단 그림을 그리거나 샘플코드를 보여 주면서 개발순서에 따라 하나씩 차례로 설명하는 것이 이해도를 높이는 데 도움이 된다.

먼저 소프트웨어 아키텍처에 대한 설명을 한다. 소프트웨어 아키텍처 구성도와 함께 구성요소와 각각의 역할에 대해 간단히 설명한다. 구성요소가 많다면 처음에는 모두를 포함한 큰 구성도를 그리고, 밀접한 관련이 있는 시스템끼리 묶어서 상세하게 작성된 구성도를 차례로 그리고 설명해 나간다.

참고로, 소프트웨어 아키텍처 문서는 여기서 설명하는 개발가이드와 별도로 만드는 것이 좋다. 개발가이드는 개발자에게 필요한 내용만 담고, 소프트웨어 아키텍처 문서는 소프트웨어 아키텍처를 포함한 개발프레임워크의 모든 기능과 그에 대한 설정을 모두 담아서 SWA 자신을 포함해서 후임자나 운영담당자가 참고할 수 있도록 최대한 자세한 내용을 담도록 한다.

다음으로 개발프레임워크에 대해 설명한다. 개발프레임워크에 대한 그림을 그리고, 각 레이어별 역할과 개발이나 수정을 해야 할 담당자(SWA, 개발자 등)를 표시해 개발자가 혼란없이 자신의 역할에 집중할 수 있도록 정리해 준다.

이제 개발환경 설치에 대해 설명한다. 기본적인 개발환경은 압축만 풀면 준비가 되니까 간단하지만, 그 안에 포함된 프로그램과 관계에 대한 설명은 해야 한다. 그리고, 압축파일에 포함시킬 수 없고 인스톨 프로그램을 통해서만 설치되는 프로그램에 대해서는 설치에 대한 설명을 추가한다.

다음은 만들어 놓은 샘플 CRUD 프로그램을 보여 주며 어떤 파일을 어떤 패키지나 디렉토리에 생성해야 하며, 프로그램이나 설정 파일을 어떻게 작성해야 하는지 설명한다. 파일이나 패키지, 클래스, 메소드 등의 명명규칙은 설계자에게 전달되어 그대로 설계에 적용되었을 테니 설계문서대로 개발하면 되겠고, 개발가이드 문서에서는 명명가이드 문서에 대한 정보만 기술해 주면 된다.

기본적인 개발프레임워크를 사용한 프로그램 외에 인터페이스 등 성격이 다른 프로그램을 개발할 필요가 있을 경우에는 하나씩 처음부터 끝까지 개발하는 과정을 차례로 설명하는 방식으로 작성한다.

개발하기 전에 형상관리 시스템에서 기본소스를 내려받는 과정과 하나씩 개발을 완료했을 때 형상관리 시스템에 소스를 올리는 과정에 대해서도 설명한다. 개발한 프로그램을 테스트하기 위해 소스를 빌드하고 서버에 배포하는 방법에 대해서도 기술한다. 빌드 및 배포는 보통 개발자 개인이 하지 않고 각 개발팀에서 담당자가 일정주기로 한꺼번에 하는 것이 좋으므로 이에 대해 미리 개발팀과 협의를 통해 수동으로 할지, 스케줄링을 통해 할지도 결정하는 것이 좋다. 개발자 교육을 실시하기 전에 형상관리 시스템에서 개발자별로 사용할 계정을 미리 받아서 생성해 두는 것이 좋다. 그래야 교육 중이나 교육 직후에 개발과정을 바로 따라해 볼 수 있기 때문이다.

개발가이드를 작성했으면 개발단계가 시작되는 시점에 개발자 교육을 실시한다. 가장 좋은 환경은 개발자들이 설명을 들으면서 자신의 컴퓨터를 이용해 직접 개발을 따라해 보는 것이다. 백견이 불여일타라고, 역시 백번 보는 것보다 한번이라도 직접 키보드를 두드려 보고 결과를 확인해 보는 것이 오래 기억에 남는다. 이런 환경이 준비되지 않으면 어쩔 수 없이 내용을 보면서 설명을 해야 한다. 교육 중간이나 종료 후에 질문을 듣고 답변을 하는 시간도 필요하다. 개발자 교육 이후에 개발자들의 질문을 받고 그에 답변을 하며, 개발프레임워크나 공통모듈이 추가/변경되었을 때 이를 공지하는 목적으로 개발자 게시판을 만들어 운영하는 것이 좋다.

드디어 개발이 시작되었다.

 

 

개발단계에서의 개발자 지원

 

 


개발자에게 교육을 했다고 곧바로 개발자가 개발을 원활히 할 수 있는 것은 아니다. 이번 프로젝트에서 사용하는 기술을 모두 사용해 봤고 능숙하게 다룰 수 있는 개발자라면 빠르게 적응할 수 있지만, 이렇게 준비된 개발자는 일부이거나 많아도 절반 정도일 것이다. 준비된 개발자가 많은 상태에서 개발을 시작하려면 개발자를 뽑을 때 준비된 사람만 뽑던가, 현재 SI판에서 보편적으로 사용하는 기술로 개발 프레임워크를 구성하면 된다. 그래서, 나는 최신기술보다는 비교적 신기술이긴 한데 보편적으로 많이 사용하는 기술을 사용하려고 노력하는 편이다.
 
개발자들에게 개발 프레임워크가 손에 익어 최고의 속도로 개발을 할 때까지 시간이 필요하다. 이 과정 때문에 몇 명의 개발자로 얼마의 기간동안 개발을 하는지 정교하게 조정해야 한다. 많은 수의 개발자로 아주 짧은 기간동안 개발한다면 개발속도가 최고로 올라오고 얼마 안 있어서 프로젝트가 끝나 버리게 되므로 전체적인 효율성이 떨어진다. 하지만, 그보다 적은 수의 개발자가 보다 긴 기간동안 개발한다면, 최고의 개발속도로 오랫동안 개발하므로 전체적으로 효율이 높아진다.
 
결국 최고의 개발속도(개발생산성)를 얻으려면 개발자가 빨리 적응하도록 SWA가 열심히 지원해야 한다. 이를 위해 개발초기에 몇 가지 할 일이 있다. 일단 개발자들과 가까이 있으면서 개발하다가 질문이 있거나 잘 안 되는 부분이 있으면 바로 가서 지원해서 적응시간을 줄여 준다. 이렇게 해서 1주일 정도 개발을 하고 나면 개발한 소스를 모두 형상관리에 commit하도록 한 후에, SWA가 이 코드에 대해 코드인스펙션을 실시한다. 그래서, 개발표준에 잘 맞는지, SWA가 개발 프레임워크를 만들 때 의도한대로 적절한 레이어에 프로그램의 기능을 잘 분리해서 넣었는지 확인하다. 그 후에 코드인스펙션에 대한 결과를 회의실에서 개발자들과 공유하면서 각 개발자가 다른 개발자들의 실수를 보면서 나중에 실수할 가능성을 줄여 주는 것이다. 이후에도 가끔씩 SWA가 개발자들의 소스를 보면서 새로운 실수 패턴이 있다면 회의실에서 공유하거나 개발자 게시판에 올려서 새로운 실수가 반복되지 않도록 해야 한다. 무슨 실수든 처음에 고치는 건 간단하지만, 어느 정도 시간이 지난 후엔 너무나 많은 코드에 실수가 반복되면서 고치기가 점점 어려줘지고 시간도 오래 걸린다. 이러한 과정이 몇 번 반복되면 SWA가 직접 코드에 신경 쓸 일은 거의 없어지고, 각 개발 파트나 팀원끼리 모여서 Peer Review 시간을 가지면서 문제를 해결할 수 있는 분위기가 형성된다.
 
코드 인스펙션을 시작한 후에는 SonarQube 등의 툴로 지속적으로 인스펙션을 수행하는 것이 좋다. 그래야 코드 품질을 유지하면서 위험한 코드를 방지할 수 있다. 여기서 또 능력있는 SWA가 필요하다. 이런 코드 인스펙션 툴들은 코드에서 체크해야 하는 룰을 선택해서 인스펙션을 수행하는데, 현재 프로젝트 환경에서 꼭 필요한 룰을 잘 고르면 그 결과도 신뢰할 수 있고 코드 결과물도 훌륭하다. 하지만, 굳이 필요하지 않은 룰을 많이 포함시켜서 인스펙션을 수행하면 개발자들이 스트레스만 받고 코드 결과물도 그다지 좋지 않을 수 있다. 그러므로, 코드 인스펙션 룰을 고를 때는 하나씩 내용을 충분히 살펴 보고 꼭 필요한 것만 골라야 한다.
 
개발자들이 개발을 시작한 후에도 SWA가 개발할 것이 있다. 바로 공통모듈이다. 이것은 SWA가 개발할 수도 있고, 공통모듈을 전담하는 개발자가 개발할 수도 있는데, 중요한 것은 개발 프레임워크 못지 않게 공통모듈도 개발실력이 뛰어난 사람이 개발해야 한다는 것이다. 개발 프레임워크만큼은 아니지만 공통모듈도 아주 빈번하게 호출되기 때문에 잘못된 코드가 아주 큰 영향을 미칠 수 있다. 공통모듈은 기능별로 사용가이드 문서를 만들거나, 사용자 게시판에 게시물을 올려 개발자들이 쉽게 가이드를 보면서 사용할 수 있도록 한다.
 
기본적인 공통모듈 외에도 각종 시스템과의 인터페이스 모듈 개발도 SWA가 담당한다. 솔루션의 호출이라면 대개 솔루션에서 제공하는 API를 이용해서 호출하지만, 이 또한 SWA가 호출방식이나 문제발생 가능성에 대비해 적당한 방법으로 개발프레임워크에 포함시키거나 공통모듈을 만들어야 한다. 이를 이용해 실제로 테스트를 해 보고 문제가 없는지 확인한 후에 개발자에게 사용가이드를 배포한다. 테스트에 간단한 성능테스트도 포함해야 하고, 시스템 오픈하기 전에 실시하는 성능테스트에 포함시키는 것이 좋다.
 
솔루션 외에 표준방식(웹서비스 등)으로 통신하는 외부 시스템과의 인터페이스에 대해서도 모듈을 만들고 테스트를 한 후에 배포해야 한다. 새로운 인터페이스에 대한 개발을 할 경우, 가끔씩 이클립스 등의 개발툴의 다른 기능을 이용할 수도 있고, 새로운 플러그인을 설치해서 이용해야 할 수도 있다. 이런 경우에는 다른 기능을 이용하거나 플러그인을 설치해서 그 기능을 이용하는 과정을 한 화면씩 캡쳐해서 어떤 것을 누르고 이 과정이 무엇인지 간단하게 설명하는 문서를 함께 만들어서 배포한다. 과정이 복잡해서 직접 설명이 필요한 경우도 있겠지만, 웬만한 난이도까지는 잘 만들어진 가이드 문서만으로 충분히 따라할 수 있다. 가이드 문서만으로 설명이 된다면 새로운 개발자가 들어오더라도 매번 설명할 필요가 없어서 좋다.
 
개발을 진행하다 보면 기본적인 개발패턴 외에 다양한 이슈가 발생한다. 위에서 다룬 각종 인터페이스도 있지만, XA를 비롯한 다양한 트랜잭션 처리, 메모리 관리 문제, SSO 등이 있다. 이런 일들 또한 전문적인 지식이 필요하기 때문에 SWA가 해야 하는 일이긴 한데, 단순히 기술만 알고 혼자 해결하는 일들만 있는 것은 아니다. 때로는 다른 시스템의 담당자들과 협의를 해야 할 수도 있고, 누가 해야 하는 일인지 업무분담에 대해 논의해야 할 수도 있다. 이런 회의를 처음 할 때는 프로젝트에 처음 투입될 때와 마찬가지로 첫인상이 중요하다. 일단은 우호적인 자세로 임하되, 기술적으로 밀린다는 인상을 주면 회의에서 주도권을 잃을 수 있기 때문에 모르는 것은 적당히 넘어가고 꼭 필요한 내용이면 다시 물어 보고 확인을 하는 것이 좋다. 업무분담에 대해서는 인력이나 시간적으로 한계를 미리 알고 적당한 선에서 나누는 것이 좋다. 물론, 처음부터 이런 상황에 대한 판단을 하고 최소한 지지 않는 협상을 하는 것이 쉽지는 않다. 거기다가 SI 프로젝트를 돌아다니다 보면 이런 협상에 닳고 닳은 전문가들이 널려 있기 때문에 더 힘들다.
 
어느 정도 개발을 진행하면 소스를 빌드하고 배포한 후에 개발서버에서 테스트를 수행해야 한다. 이때에 필요한 것이 CI(Continuous Integration)툴이다. 보통은 Jenkins를 사용한다. 가장 큰 빌드 단위는 운영 시 하나의 인스턴스에 하나의 웹애플리케이션으로 수행되는 단위로 할 수 있다. 그런데, 이 단위가 너무 크면 여기에 올라가는 하나의 소스에서만 컴파일 에러가 발생해도 그 소스를 포함하는 빌드 단위가 모두 서버에 배포될 수 없는 상황이 발생할 수 있다. 이런 경우를 대비해서 되도록 더 작은 단위로 소스를 빌드해서 그 빌드마다 별도의 인스턴스를 할당해 준다. 그러면, 그 작은 단위에서 빌드에러가 발생할 경우 빨리 개발자를 찾아서 고친 후에 다시 빌드를 수행하고 테스트를 할 수 있다. 여기서 개발빌드/배포 소스범위나 주기는 개발팀의 의견을 반영해서 정하면 된다. 하루에 3번 시간을 정해서 자동으로 배포할 수도 있고, 각 개발팀의 빌드 담당자가 팀별로 정한 시간에 자율적으로 빌드/배포하고 테스트를 수행해도 된다.
 

 
이렇게 개발단계의 개발이 진행되고, SWA는 개발이 원활하게 진행될 수 있도록 지원하고 문제를 해결해 나가야 한다.

 

 

 

오픈 준비, 오픈, 안정화

 

 


개발이 끝나갈 때쯤엔 오픈시기가 다가온다. 기본적으로 운영서버가 들어와야 되고, 거기에 서버담당자가 OS나 기본 소프트웨어를 설치하고, 애플리케이션을 실행할 WAS나 솔루션 등이 설치된다. SWA는 유료 솔루션은 엔지니어에 설치를 요청하고, 무료 소프트웨어는 직접 설치와 설정을 진행한다. 그리고, 기본 설치 소프트웨어가 정상적으로 작동하는지 애플리케이션을 배포하고, DB에 데이터를 올려서 테스트를 진행한다. 여기까지가 운영서버가 들어 온 후 기본적으로 하는 테스트이다.
 
다음으로 가용성 테스트와 성능 테스트를 진행한다.
 
가용성 테스트는 서버나 장비 또는 인스턴스 일부에 장애가 발생했을 때, 전체 서비스가 멈추지 않고 계속 되는지 확인하는 테스트이다. 그래서, 다중화된 웹서버나 WAS, DB 인스턴스나 서버 중 일부를 내리고 서비스가 진행되는지 확인하는 것으로 일반적으로 큰 문제 없이 짧은 시간에 테스트가 완료된다. 여기서 중요한 것은 어떤 부분까지 장애가 발생했을 때 서비스가 가능해야 하는지 내릴 인스턴스나 서버를 정하는 것이다.
 
성능 테스트는 아주 중요하고, 실제로 설계부터 테스트를 진행하는 과정까지 굉장히 길고 어려운 과정을 거친다. 보통은 성능 테스트 담당자가 프로젝트에 투입되어 성능 목표치와 테스트 대상 업무 선정, 스크립트 기록 및 부하까지 진행하기 때문에 SWA는 시키는 일만 잘 준비해 놓고 있다가 WAS가 솔루션을 내렸다가 기동하고 쌓인 로그를 지우는 역할을 주로 한다. 그런데, 성능 테스트하는 동안 네트워크에 부하가 많이 가기 때문에 다른 서비스에 영향을 주지 않기 위해서 주로 새벽시간에 테스트를 진행한다는 것이다. 그리고, 성능 테스트 중에 프레임워크나 업무프로그램 또는 설정에 문제가 있어서 원하는 만큼의 성능이 나오지 않을 때는 SWA가 이 부분을 고쳐야 한다. 성능 테스트도 가용성 테스트와 마찬가지로 개발프레임워크 뿐만 아니라 인터페이스나 기타 솔루션 중 성능테스트가 필요한 부분을 성능 테스트에 포함시키도록 해야 한다.
 
성능 테스트 중에 애플리케이션에서 문제가 발생하면 SWA는 문제를 찾아서 해결해야 한다. 보통 부하를 주기 전에는 잘 돌아가던 프로그램이 성능 테스트 때 문제가 발견되는 경우가 많기 때문에, 일단 개발프레임워크를 만들 때부터 이런 상황이 발생하지 않도록 주의를 기울여야 한다. 성능 테스트 때 문제가 발생하면 로그를 확인하고, jstack이나 jmap 등을 이용해서 문제의 원인을 찾은 후 코드나 설정을 수정해서 문제를 해결해야 한다.
 
업무팀에서는 통합테스트도 진행한다. 핵심 업무에 대해서 처음 접속하는 단계부터 중요한 업무를 마치고 나올 때까지 작업을 한번에 이어서 하는 것인데, 서버구성만 잘 되어 있으면 크게 지원할 것이 없다.
 
이렇게 운영서버 구성부터 설정까지 문제가 없다는 것이 확인되면, 운영서버에 대한 소스 배포를 준비한다. 오픈 때부터 시작해서 오픈 이후에 운영서버에 프로그램을 배포하기 위해서다. 운영서버는 소스코드를 다시 빌드해서 배포하는 경우가 많지 않고, 운영서버 직전의 테스트서버(회사마다 통합테스트서버, 스테이징서버 등으로 불린다)에 배포했던 바이너리 프로그램을 그대로 묶어서 배포하는 방식을 주로 사용한다. 잘 작동하는 바이너리를 그대로 배포함으로써 새로 빌드하면서 발생할 수 있는 문제를 방지하기 위해서이다.
 

 
오픈이 1~2주일 앞으로 다가오면 오픈일의 오픈시간에 맞춰서 할 일을 아주 세세하게 계획한다. 마지막 소스배포부터 WAS 및 프로그램 기동, 기본기능 테스트까지 동작 하나하나를 계획해서 실수로 빠뜨리는 작업이 없도록 하려는 것이다. 오픈일이 되면 견디기 힘든 무거운 분위기가 사무실 전체를 감싼다. 누구 하나라도 실수하면 자신 때문에 오픈을 실패했다는 책임을 질 수 있기 때문에 더욱 긴장하게 된다. 그래서, 이렇게 상세하게 계획을 세우는 것이고, 이 계획만 잘 세우면 오픈도 문제 없이 할 수 있다.
 
개발 및 테스트를 잘 진행하고 오픈 준비까지 완벽하게 했으면 좋겠지만, 완벽한 준비는 신의 영역인지라 언제나 오픈 후에 크고 작은 문제가 발생한다. 오픈 직후에 큰 문제가 발생하면 실패 결정을 내리고 오픈을 연기하게 되고, 작은 문제가 발생해서 어떻게든 오픈을 유지할 수 있으면 문제를 해결하면서 버틴다. 이렇게 오픈 후에 문제를 고쳐 나가는 기간이 안정화 기간이다. 안정화가 잘 되면 별로 할 일이 없지만, 안정화가 아주 많이 필요한 경우에는 수시로 프로그램을 고쳐서 운영서버에 배포를 해대야 한다. 운영서버 배포는 보통 SWA 쪽에서 수행하기 때문에 하루종일 앉아서 배포만 할 수도 있다. 배포 및 재기동 중에 문제만 일으키지 않겠다는 마음으로 차례차례 절차만 잘 지키면서 배포해 주면 된다. 언제나 문제는 서두르다가 절차를 빼먹거나 잘못 수행해서 발생하는 것이다. 조금 더 빨리 배포한다고 SWA에게 득될 것은 없다. 빨리 배포하겠다고 서두르다가 실수해서 문제가 생기면 책임이 생길 수는 있어도.

 

'Architecture' 카테고리의 다른 글

개발방법론  (0) 2020.08.25
Application Architect란?  (0) 2020.08.25
[ 아키 ] Function Point를 활용한 소프트웨어 비용산정  (0) 2015.01.29
[ 아키] 웹기획 이란?  (0) 2011.12.19

+ Recent posts