시큐어코딩으로 개발 단계에서 보안 취약점 줄이기
시큐어코딩의 개념과 CWE 취약점 분류, 공공 정보화 사업 적용 기준, 개발 과정의 보안 통합 방안을 정리합니다.
2026-08-14 · 최초 발행 2025-05-23
코드가 배포되기 전에 취약점을 없애는 일
시큐어코딩(Secure Coding)은 개발 과정에서 코드 수준의 보안 취약점을 미리 제거해 안전성과 신뢰성을 갖춘 소프트웨어를 만드는 기법이다. 개발이 끝난 뒤 취약점을 발견하면 패치 비용이 개발 단계보다 30배 이상 늘어날 수 있다.
사이버 공격의 75% 이상이 애플리케이션 계층을 대상으로 발생한다. 국가 주요 시스템과 개인정보를 다루는 소프트웨어에서 코드 작성 단계의 보안 검토가 필수 프로세스로 자리 잡은 이유다.
공공 정보화 사업에 적용된 기준
정부는 공공부문 소프트웨어의 보안을 강화하기 위해 시큐어코딩 적용을 단계적으로 의무화했다. 2012년 12월에는 개발비 40억 이상 사업에 적용했고, 2014년 1월에는 개발비 20억 이상 사업으로 범위를 넓혔다. 2015년 1월부터는 상용 SW를 제외한 모든 정보화 산업 감리대상에 확대 적용됐다.
감리에서는 SQL 인젝션, XSS(Cross-Site Scripting), 정수 오버플로우 등을 포함한 43개 항목을 중심으로 점검한다.
CWE 분류로 보는 취약점 검토 범위
CWE(Common Weakness Enumeration)는 소프트웨어 보안 취약점을 분류한 목록이다. Pernicious Kingdoms는 이를 7개 주요 영역으로 묶어 개발 과정에서 어떤 결함을 확인해야 하는지 정리한다.
입력값은 허용 범위부터 검증한다
XSS, SQL 삽입, 버퍼 오버플로우, OS 명령어 삽입공격은 외부 입력을 신뢰할 때 발생할 수 있다. 모든 사용자 입력은 화이트리스트(허용 목록) 방식으로 검증하고, 쿼리에는 파라미터화된 쿼리(Prepared Statement)를 사용한다. 특수문자 필터링과 인코딩 처리도 함께 적용한다.
// 취약한 코드
String query = "SELECT * FROM users WHERE username='" + username + "'";
// 안전한 코드
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE username=?");
pstmt.setString(1, username);
인증 정보와 암호화 처리를 코드 밖으로 분리한다
중요정보 평문 저장, 하드코드된 패스워드, 취약한 암호화 알고리즘 사용은 보안기능 영역의 대표적인 문제다. 중요 정보는 암호화해 저장하고 SHA-256 이상의 해시 알고리즘을 사용한다. 패스워드나 API 키를 소스코드에 남기지 않고 안전한 인증 메커니즘을 구현해야 한다.
// 취약한 코드
static final String DB_PASSWORD = "admin123";
// 안전한 코드
String dbPassword = System.getenv("DB_PASSWORD"); // 환경변수에서 로드
동시성과 세션 상태를 통제한다
데드락(DeadLock), 자원에 대한 경쟁 조건(Race Condition), 세션 고착은 시간 및 상태 관리에서 발생한다. 동기화 메커니즘을 적절히 적용하고, 세션 타임아웃과 랜덤 세션 ID 생성·주기적 재생성을 검토한다.
// 취약한 코드 (경쟁 조건 발생 가능)
if (balance > amount) {
balance = balance - amount;
}
// 안전한 코드
synchronized void withdraw(int amount) {
if (balance > amount) {
balance = balance - amount;
}
}
오류 정보가 외부로 새지 않게 처리한다
예외 처리 루틴이 없거나 오류 메시지에 기술적 정보가 그대로 포함되면 공격자에게 내부 정보를 줄 수 있다. 모든 예외 상황을 처리하고, 사용자에게는 필요한 수준의 일반적인 메시지만 제공한다. 오류 로그 정책도 별도로 수립해 관리한다.
// 취약한 코드
try {
// 코드 실행
} catch (Exception e) {
e.printStackTrace(); // 스택 트레이스가 사용자에게 노출될 수 있음
}
// 안전한 코드
try {
// 코드 실행
} catch (Exception e) {
logger.error("오류 발생: " + e.getMessage());
response.sendError(500, "시스템 오류가 발생했습니다."); // 일반적인 메시지만 노출
}
자원과 널 처리는 품질 문제이자 보안 문제다
널 포인터 역참조, 부적절한 자원 해제, 메모리 누수는 코드 품질 영역에서 확인한다. 널 체크를 강화하고, try-with-resources 구문을 활용해 자원 해제를 보장한다. 코드 리뷰와 정적 분석 도구도 이 검토를 지원한다.
// 취약한 코드
FileInputStream fis = new FileInputStream("file.txt");
// 예외 발생 시 자원이 해제되지 않음
// 안전한 코드 (Java 7 이상)
try (FileInputStream fis = new FileInputStream("file.txt")) {
// 코드 실행
} // 자동으로 자원 해제
내부 상태와 직렬화 대상을 감춘다
제거되지 않은 디버거 코드와 시스템 데이터 정보 노출은 캡슐화가 깨졌을 때 발생한다. 프로덕션 코드에서는 디버깅 코드를 완전히 제거하고, 민감한 내부 정보에는 적절한 접근 제어를 적용한다. 객체 직렬화 시에도 민감 정보가 포함되지 않도록 관리해야 한다.
// 취약한 코드
public class User {
public String username;
public String password; // 직렬화 시 노출될 수 있음
}
// 안전한 코드
public class User {
private String username;
private transient String password; // 직렬화에서 제외
// Getter/Setter 메서드로 접근 제어
}
API 호출도 외부 입력처럼 검증한다
DNS Lookup에 의존한 보안 결정이나 취약한 API 호출은 API 악용으로 이어질 수 있다. 안전한 API 사용법을 숙지하고, 최신 보안 패치가 적용된 라이브러리를 사용한다. DNS 스푸핑 공격을 막기 위한 추가 인증 메커니즘도 고려 대상이다.
// 취약한 코드
URLConnection conn = new URL(userInputUrl).openConnection();
conn.connect(); // 검증 없이 사용자 입력으로 URL 연결
// 안전한 코드
if (validateUrl(userInputUrl)) { // URL 검증 로직 추가
URLConnection conn = new URL(userInputUrl).openConnection();
conn.connect();
}
개발 흐름 안에 보안 검증을 넣는 방식
보안 검토는 구현 이후에만 수행하는 별도 절차가 아니다. 요구사항 분석부터 보안 고려사항을 반영하고, 설계·구현·테스트 단계마다 검증 지점을 둔다. 개발자의 지속적인 보안 교육과 인식 제고도 이 흐름에 포함된다.
정적 분석 도구(SAST)로는 Fortify, FindBugs, SonarQube 등을 활용할 수 있고, 동적 분석 도구(DAST)로는 OWASP ZAP, Burp Suite 등이 있다. CI/CD 파이프라인에 보안 테스트를 통합하면 코드 변경마다 검토를 반복할 수 있다.
정기적인 시큐어코딩 교육, 보안 취약점 데이터베이스와 사례 공유, 코드 리뷰용 보안 체크리스트는 개발자 역량을 유지하는 수단이다. 웹 애플리케이션에서는 OWASP Top 10 취약점을 우선 대응 대상으로 두고 인증·접근 제어를 강화하며, 주기적인 취약점 평가와 패치 관리를 이어간다.
비용과 신뢰성에 미치는 영향
시큐어코딩은 단기적으로 개발 비용과 시간이 늘어나는 것처럼 보일 수 있다. 다만 장기적으로는 연평균 보안 사고 대응 비용을 약 60% 절감하는 효과가 있다. 버그 수정 비용 감소와 신뢰성 향상, 개인정보보호법·정보통신망법 등 법적 요구사항 충족, 보안 사고에 따른 기업 이미지 손상 방지도 함께 기대할 수 있다.
도입 결과로 확인된 변화
금융권 코어뱅킹 시스템 리뉴얼에서는 개발 초기부터 시큐어코딩을 적용하고, 모든 개발자를 대상으로 보안 코딩 교육을 실시했다. 자동화된 코드 스캐닝 도구도 함께 활용했으며, 출시 후 1년간 보안 취약점 제로와 2,500만 달러 보안 사고 비용 절감이라는 결과가 제시됐다.
공공기관 대민 서비스 포털은 기존 시스템의 보안 취약점을 분석한 뒤 시큐어코딩 가이드라인을 기반으로 재구축했다. 지속적인 모의해킹과 취약점 점검을 병행한 결과, 이전 시스템 대비 해킹 시도 대응률이 95% 향상되고 시스템 신뢰도가 증가했다.
시큐어코딩은 개발자 보안 의식, 체계적인 가이드라인, 자동화된 취약점 분석 도구, 지속적인 보안 테스트와 모니터링이 함께 갖춰질 때 작동한다. 공공기관 정보화 사업에서는 법적 의무사항이기도 하므로, 감리 기준을 충족하는 개발 과정으로 정착시킬 필요가 있다.