출제기준 세세항목: 개발환경 구축 · 서버 개발 프레임워크
요리를 하려면 재료만큼이나 부엌이 중요합니다. 칼과 도마, 불, 냉장고가 갖춰져 있어야 레시피대로 만들 수 있지요. 소프트웨어도 마찬가지로, 코드를 쓰고 실행하고 시험해 볼 장비와 프로그램이 먼저 갖춰져 있어야 합니다. 이렇게 개발에 필요한 하드웨어와 소프트웨어를 골라 설치하고 설정하는 일을 개발환경 구축이라고 합니다.
개발환경은 크게 하드웨어 환경과 소프트웨어 환경으로 나눠 봅니다. 하드웨어 환경은 사용자가 쓰는 클라이언트(PC, 스마트폰)와 서비스를 제공하는 서버로 이뤄집니다. 서버는 다시 정적인 파일을 돌려주는 웹 서버, 요청마다 다른 결과를 만들어 내는 웹 애플리케이션 서버(WAS), 데이터를 저장하는 DB 서버, 파일을 보관하는 파일 서버처럼 맡은 일에 따라 나뉩니다.
소프트웨어 환경에는 운영체제, 자바 가상 머신(JVM) 같은 실행 환경, 미들웨어, DBMS가 들어가고, 여기에 개발자가 직접 쓰는 개발 도구가 더해집니다. 개발 도구는 쓰임에 따라 구현 도구, 빌드 도구, 테스트 도구, 형상관리 도구 네 가지로 나누는 것이 기본이고, 그 밖에 요구사항 관리 도구와 설계·모델링 도구를 더해 기억하면 정리가 쉽습니다.
구현 도구는 코드를 실제로 작성하는 도구입니다. 대표가 IDE(Integrated Development Environment, 통합 개발 환경)인데, 예전에는 편집기, 컴파일러, 디버거를 따로따로 실행해야 했던 것을 한 화면에 모아 둔 프로그램입니다. 코드를 치는 동안 문법 오류를 표시해 주고, 함수 이름을 자동으로 완성해 주며, 버튼 하나로 실행과 디버깅까지 할 수 있습니다.
많이 쓰는 IDE로는 자바 개발에 널리 쓰이는 이클립스(Eclipse)와 IntelliJ IDEA, 마이크로소프트의 Visual Studio, 안드로이드 앱용 Android Studio, 애플 기기용 Xcode가 있습니다. 가벼운 편집기에 확장 기능을 붙여 IDE처럼 쓰는 Visual Studio Code도 흔히 씁니다. IDE는 플러그인으로 형상관리 도구나 데이터베이스와도 연결할 수 있습니다.
테스트 도구는 만든 코드가 제대로 동작하는지 자동으로 확인해 줍니다. 자바의 단위 테스트에는 JUnit, 파이썬에는 unittest나 pytest가 많이 쓰입니다. JUnit처럼 언어마다 같은 틀로 만들어진 단위 테스트 도구(JUnit, NUnit, 파이썬의 unittest 등)를 묶어 xUnit 계열이라고 부르며, pytest는 이 계열과는 다른 방식의 도구입니다. 웹 화면 조작을 자동으로 시험하는 Selenium, 많은 사용자가 동시에 접속하는 상황을 흉내 내 성능을 재는 JMeter 같은 도구도 있습니다.
빌드는 사람이 쓴 소스 코드를 컴퓨터가 실행할 수 있는 형태로 만드는 전체 과정입니다. 단순히 컴파일만 하는 것이 아니라, 필요한 라이브러리를 내려받고, 테스트를 돌리고, 결과물을 하나의 파일(자바라면 JAR나 WAR)로 묶는 일까지 포함합니다. 이 과정을 매번 손으로 하면 실수가 생기기 때문에 빌드 도구로 자동화합니다.
Ant는 아파치 재단이 만든 초기 빌드 도구로, build.xml이라는 XML 파일에 '이 폴더를 컴파일하고, 저 폴더로 복사하라'처럼 할 일을 하나하나 직접 적습니다. 자유롭지만 정해진 규칙이 없어 프로젝트마다 구조가 제각각이 되기 쉽습니다. Maven은 이를 보완해 pom.xml에 프로젝트 정보와 필요한 라이브러리(의존성)만 적으면, 정해진 폴더 구조와 빌드 단계(컴파일, 테스트, 패키징, 설치, 배포 등)를 규약대로 따라가며, 라이브러리도 중앙 저장소에서 알아서 내려받아 줍니다.
Gradle은 XML 대신 Groovy(build.gradle)나 Kotlin(build.gradle.kts)으로 된 스크립트로 빌드를 적습니다. 바뀐 부분만 다시 빌드하는 증분 빌드로 속도가 빠르고, 안드로이드 앱의 기본 빌드 도구로 쓰입니다. 세 도구를 구별할 때는 'Ant는 XML로 절차를 자유롭게, Maven은 XML(pom.xml)로 규약과 의존성 관리, Gradle은 스크립트로 유연하고 빠르게'라고 기억해 두면 됩니다. 여러 사람이 올린 코드를 자주 합쳐 자동으로 빌드·테스트하는 지속적 통합(CI)에는 Jenkins 같은 도구를 빌드 도구와 함께 씁니다.
여러 사람이 같은 코드를 고치다 보면 누가 언제 무엇을 바꿨는지 알 수 없게 되고, 잘 되던 버전으로 되돌리기도 어렵습니다. 형상관리 도구는 파일이 바뀔 때마다 그 이력을 저장해, 언제든 이전 상태와 비교하거나 되돌릴 수 있게 해 줍니다. 문서 편집기의 '버전 기록'을 코드 전체에 적용한 것이라고 생각하면 됩니다.
방식은 두 가지입니다. 클라이언트-서버(중앙 집중) 방식은 이력을 중앙 서버 한 곳에 모아 두고, 개발자가 커밋하면 곧바로 서버에 반영됩니다. CVS와 SVN(Subversion)이 여기에 속합니다. 구조가 단순하지만 서버가 멈추면 이력을 보거나 커밋할 수 없습니다.
분산 방식은 개발자마다 전체 이력을 담은 로컬 저장소를 따로 가집니다. 대표가 Git이며, 먼저 내 컴퓨터의 로컬 저장소에 커밋(commit)한 뒤, 푸시(push)로 원격 저장소에 올리고, 다른 사람의 변경은 풀(pull)로 받아옵니다. 네트워크가 끊겨도 로컬에서 작업을 이어 갈 수 있고, 가지(branch)를 나눠 따로 작업한 뒤 병합(merge)하기도 쉽습니다. 원격 저장소는 GitHub, GitLab 같은 서비스에 두는 경우가 많습니다.
프레임워크는 소프트웨어를 만들 때 자주 쓰는 구조와 기능을 미리 만들어 둔 반제품입니다. 아파트의 뼈대와 배관이 이미 지어져 있고 입주자는 인테리어만 하면 되는 것처럼, 개발자는 로그인 처리나 데이터베이스 연결 같은 공통 부분을 새로 짤 필요 없이 업무에 필요한 코드만 채워 넣으면 됩니다.
프레임워크의 특징은 네 가지로 정리합니다. 기능을 잘게 나눠 묶어 두는 모듈화, 이미 만든 구성 요소를 다시 쓰는 재사용성, 정해진 틀 안에서 기능을 늘려 갈 수 있는 확장성, 그리고 제어의 역전(IoC, Inversion of Control)입니다. 제어의 역전은 개발자가 프로그램의 흐름을 직접 이끄는 대신, 프레임워크가 흐름을 쥐고 필요한 순간에 개발자의 코드를 불러 쓰는 것을 말합니다. '우리가 연락할 테니 먼저 연락하지 마세요'라는 말에 빗대기도 합니다.
그래서 라이브러리와 프레임워크는 누가 누구를 부르느냐로 구별합니다. 라이브러리는 개발자 코드가 필요할 때 불러 쓰는 도구 상자이고, 프레임워크는 개발자 코드를 불러 쓰는 틀입니다. 예를 들어 날짜 계산 함수 모음은 라이브러리지만, 웹 요청이 오면 알아서 개발자가 만든 처리 함수를 찾아 실행해 주는 것은 프레임워크입니다.
자바 진영의 대표는 스프링(Spring)입니다. 객체가 필요로 하는 다른 객체를 프레임워크가 만들어 넣어 주는 의존성 주입(DI)과, 로그·트랜잭션처럼 여러 곳에 흩어진 공통 관심사를 따로 떼어 관리하는 관점 지향 프로그래밍(AOP)이 핵심 기능입니다. 설정을 간단하게 만들어 빠르게 시작하도록 돕는 스프링 부트(Spring Boot)도 널리 쓰입니다. 공공 정보화 사업에서는 정부가 스프링을 바탕으로 공통 기능을 더해 내놓은 전자정부 표준프레임워크를 많이 씁니다. 그 밖에 파이썬의 Django와 Flask, Node.js의 Express, 루비의 Ruby on Rails, C#의 ASP.NET이 있습니다.
개발환경은 아무 도구나 깔아서 끝나는 것이 아니라, 프로젝트 요구사항에 맞춰 고르는 것에서 시작합니다. 운영할 서버의 운영체제와 DBMS, 사용할 언어와 프레임워크가 정해지면, 그에 맞는 IDE, 빌드 도구, 형상관리 도구를 고르고 버전을 맞춥니다.
도구를 고를 때는 서로 버전이 맞는지(호환성), 비용과 라이선스 조건이 어떤지, 팀원들이 써 본 경험이 있는지, 문제가 생겼을 때 참고할 자료와 지원이 충분한지를 봅니다. 특히 JDK 버전과 프레임워크 버전이 맞지 않으면 빌드조차 되지 않는 경우가 있어, 처음에 버전 조합을 정해 문서로 남겨 두는 것이 중요합니다.
팀 전체가 같은 환경을 쓰는 것도 핵심입니다. 한 사람 컴퓨터에서는 되는데 다른 사람 컴퓨터에서는 안 되는 일이 생기지 않도록, 빌드 설정 파일과 필요한 라이브러리 목록을 형상관리 도구에 함께 올려 두고, 새로 합류한 사람도 그대로 따라 하면 같은 환경이 만들어지게 합니다.
새로 합류한 개발자가 Git으로 저장소를 내려받은 뒤 Gradle 빌드 명령 한 번을 실행하자, 필요한 라이브러리가 자동으로 내려받아지고 테스트까지 통과했습니다. 빌드 설정과 의존성 목록이 저장소에 함께 있었기 때문에, 반나절 만에 다른 팀원과 같은 환경에서 일을 시작할 수 있었습니다.
금요일 오후에 올린 코드 때문에 결제 화면이 멈췄습니다. 담당자는 형상관리 이력에서 문제가 된 커밋을 찾아 바로 이전 버전으로 되돌려 서비스를 살렸고, 원인은 별도 가지(branch)에서 차분히 고친 뒤 다시 병합했습니다.
공공기관 민원 시스템을 만들면서 전자정부 표준프레임워크를 썼습니다. 로그인, 권한 확인, 로그 기록, DB 연결 같은 공통 기능이 이미 들어 있어서, 팀은 민원 접수와 처리 같은 업무 기능에만 집중할 수 있었습니다.