Java 보안 개요 — 심층 방어와 보안 3대 목표

Java 애플리케이션 보안의 전체 지형을 조망합니다. JVM 플랫폼 보안, JCA 암호화, 입력·데이터 보안, 인증·인가 계층으로 이어지는 심층 방어 구조와 기밀성·무결성·가용성(CIA) 3대 목표, 그리고 앞으로 다룰 주제를 정리합니다.

· 9 min read · PALDYN Team

지난 글에서 gRPC로 서비스 간 통신을 구축하는 방법을 다뤘다. 통신이 열리는 순간부터 보안은 선택이 아니라 전제가 된다. 이번 글부터 여러 글에 걸쳐 Java 애플리케이션 보안을 다룬다. 이번 글에서는 개별 기술로 들어가기 전에 전체 지형을 먼저 그린다. Java 보안이 어떤 계층으로 구성되는지, 우리가 지키려는 목표가 무엇인지 이해해야 각 기술이 왜 존재하는지 납득할 수 있기 때문이다.

보안은 하나의 기능이 아니라 계층이다

보안을 “로그인 기능”이나 “HTTPS 설정” 같은 단일 항목으로 생각하면 반드시 구멍이 생긴다. 현대 보안 설계의 핵심 원칙은 심층 방어(Defense in Depth) 다. 하나의 방어선이 뚫려도 다음 방어선이 공격을 저지하도록, 독립적인 보안 계층을 여러 겹으로 쌓는 것이다.

Java 애플리케이션에서 이 계층은 대략 아래 네 단계로 나눌 수 있다.

Java 보안 계층 — 심층 방어

가장 아래 플랫폼 계층은 개발자가 코드를 한 줄도 쓰지 않아도 JVM이 제공하는 보안이다. 바이트코드 검증기는 클래스 로딩 시 스택 오버/언더플로, 잘못된 타입 캐스팅 같은 위험한 바이트코드를 거부한다. 클래스 로더는 이름 공간을 격리하고, 자동 메모리 관리는 C/C++에서 악명 높은 버퍼 오버플로와 use-after-free 계열 취약점 상당수를 원천 차단한다.

그 위 암호화 계층은 JCA(Java Cryptography Architecture)와 JSSE(Java Secure Socket Extension)가 담당한다. 해시, 대칭·비대칭 암호, 전자서명, TLS, 키 저장소(KeyStore)가 여기에 속한다. 다음 몇 편에서 집중적으로 다룰 영역이다.

입력·데이터 계층은 신뢰할 수 없는 외부 입력을 다루는 지점이다. 입력 검증, SQL 파라미터 바인딩, 역직렬화 필터링, 출력 인코딩이 여기에 있다. 실무에서 발생하는 침해 사고의 대부분은 이 계층의 실수에서 비롯된다. 마지막 애플리케이션 계층은 인증·인가·세션 관리처럼 도메인 규칙과 맞닿은 부분이다.

우리가 지키려는 것: CIA 3대 목표

어떤 보안 기술을 도입할지 결정하려면 먼저 “무엇을 지키는가”를 명확히 해야 한다. 정보보안의 고전적 프레임워크가 CIA 3대 목표 다.

보안 3대 목표(CIA)와 Java 대응 기술

  • 기밀성(Confidentiality): 허가된 대상만 데이터에 접근한다. 암호화(AES, RSA)와 전송 구간 보호(TLS), 접근 제어가 수단이다.
  • 무결성(Integrity): 데이터가 중간에 변조되지 않았음을 보장한다. 해시(SHA-256), HMAC, 전자서명으로 검증한다.
  • 가용성(Availability): 정당한 사용자가 필요할 때 서비스를 이용할 수 있어야 한다. 입력 검증, 요청 제한, 타임아웃, 리소스 격리로 DoS를 방어한다.

세 목표는 종종 서로 상충한다. 강력한 암호화는 성능(가용성)을 갉아먹고, 지나친 접근 제한은 사용성을 해친다. 보안 아키텍처란 결국 이 균형점을 요구사항에 맞게 설계하는 일이다.

코드로 보는 보안 마인드셋

구체적인 기술은 다음 글부터지만, 관점의 차이를 코드로 미리 감각해보자. 아래는 “보안을 나중에 붙이는” 코드와 “설계에 내재한” 코드의 대비다.

// ❌ 보안을 나중에 생각한 코드
public User login(String username, String password) {
    // 평문 비교, SQL 문자열 조립, 예외 메시지에 내부 정보 노출
    String sql = "SELECT * FROM users WHERE name = '" + username +
                 "' AND pw = '" + password + "'";
    return jdbc.queryForObject(sql, ...); // SQL 인젝션 + 평문 저장
}

// ✅ 보안이 설계에 내재한 코드
public Optional<User> login(String username, String password) {
    // 파라미터 바인딩으로 인젝션 차단
    User user = repository.findByName(username).orElse(null);
    if (user == null) {
        // 존재 여부를 노출하지 않도록 동일한 실패 경로
        passwordEncoder.matches(password, DUMMY_HASH); // 타이밍 공격 완화
        return Optional.empty();
    }
    // 저장된 것은 솔트 적용된 해시. 평문 비교 아님
    if (!passwordEncoder.matches(password, user.passwordHash())) {
        return Optional.empty();
    }
    return Optional.of(user);
}

첫 번째 코드는 SQL 인젝션, 평문 비밀번호, 사용자 존재 여부 노출, 타이밍 공격까지 네 가지 문제를 동시에 안고 있다. 두 번째 코드는 각 문제에 대응하는 방어를 설계에 녹였다. 보안은 마지막에 추가하는 기능이 아니라, 코드를 쓰는 방식 그 자체라는 것이 핵심이다.

공격자처럼 생각하기

방어 코드를 잘 짜려면 공격자의 사고를 이해해야 한다. OWASP Top 10은 웹 애플리케이션에서 가장 흔한 취약점을 정리한 목록으로, Java 개발자에게 특히 관련 깊은 항목은 다음과 같다.

취약점Java에서의 대표적 원인앞으로 다룰 글
인젝션SQL 문자열 조립, 검증 없는 입력입력 검증
암호화 실패약한 알고리즘, 하드코딩된 키JCA 암호화, TLS/KeyStore
안전하지 않은 역직렬화신뢰 못 할 데이터 readObject역직렬화 취약점
인증·세션 관리 결함취약한 토큰, 만료 미검증JWT
취약한 구성요소오래된 라이브러리(예: Log4Shell)마이그레이션·의존성 관리

이 목록이 곧 앞으로 다룰 글들의 로드맵이다. 다음 글에서는 이 모든 것의 기반이 되는 JCA — Java 암호화 아키텍처 를 다루며, 해시·대칭 암호·비대칭 암호를 실제 코드로 구현해본다.

정리

  • 보안은 단일 기능이 아니라 플랫폼·암호화·입력·애플리케이션으로 이어지는 심층 방어 계층이다.
  • 지키려는 목표는 기밀성·무결성·가용성(CIA) 이며, 세 목표는 상충하므로 균형 설계가 필요하다.
  • 보안은 나중에 붙이는 기능이 아니라 코드를 작성하는 방식이다.
  • OWASP Top 10은 Java 개발자가 우선 대응할 취약점의 실전 로드맵을 제공한다.

지난 글: Java와 Kotlin 상호운용

다음 글: JCA — Java 암호화 아키텍처


읽어주셔서 감사합니다. 😊