모든 이야기

정적 타입과 동적 타입은 언제 무엇을 확인할까

정적 타입과 동적 타입의 차이는 타입이 있느냐 없느냐보다 타입에 관한 검사를 언제, 어떤 정보로 수행하느냐에 있다. 정적 타입 시스템은 실행 전에 코드의 타입 관계를 분석한다. 동적 타입 언어는 실행 중 실제 값의 종류를 보고 연산의 허용 여부를 판단한다. 동적 언어의 값에도 숫자나 문자열 같은 타입이 있으며, 정적 언어에서도 실행 중 검사가 필요한 경우가 있다.

정적 타입 검사는 실행 전 코드 분석 단계에, 동적 타입 검사는 실행 중 실제 값 확인 단계에 표시한 두 흐름

정적 검사는 실행 전 타입 관계를 분석하고, 동적 검사는 실행 도중 실제 값에 맞춰 확인한다.

실행 전의 추론과 실행 중의 확인

정적으로 검사하는 함수가 정수 인자를 요구한다면 문자열을 넘기는 호출은 실행 전 오류로 표시될 수 있다. 이때 타입을 모든 변수 옆에 적어야 하는 것은 아니다. 초기값이나 사용 위치에서 타입을 추론하는 언어도 있다. 따라서 선언문에 타입 이름이 보이는지 여부만으로 언어를 분류할 수 없다. 핵심은 코드 전체의 관계에 대해 어느 시점에 어떤 보장을 제공하는가다.

동적 언어에서는 같은 함수가 실행되는 동안 실제 입력을 사용해 연산한다. 숫자끼리 더하는 경로는 성공하고, 지원되지 않는 값의 조합을 만나는 경로는 그 시점에 오류를 낼 수 있다. 실행되지 않은 분기 안의 타입 문제는 테스트가 그 경로를 지나지 않으면 드러나지 않을 수 있다. 대신 값의 형태가 유연하게 달라지는 코드를 쉽게 표현하는 장점이 있다.

주석을 적었다고 자동으로 검사되지는 않는다

Python의 함수 인자에 x: int를 적어도 일반적인 실행기가 모든 호출에서 정수인지 자동으로 확인하는 것은 아니다. Python typing 공식 문서는 함수와 변수의 타입 주석이 실행 중 강제되지 않으며 외부 검사기나 개발 도구가 활용할 수 있다고 명시한다. 정적 검사기 사용과 런타임 입력 검증은 별도로 설정해야 한다.

예를 들어 def twice(x: int) -> int: return x * 2에 문자열을 주면 Python의 문자열 반복 연산이 수행될 수 있다. 정적 검사기는 주석과 호출을 보고 잘못된 사용을 지적할 수 있지만, 주석만 적고 검사기를 실행하지 않으면 같은 보장을 받지 못한다. API에서 들어오는 JSON의 값도 신뢰할 수 없으므로 경계에서 실제 검증이 필요하다.

다른 기준을 섞지 않는 것이 중요하다

강한 타입과 약한 타입이라는 표현은 자료마다 정의가 달라 정적·동적과 일대일로 대응하지 않는다. 자동 형 변환이 얼마나 허용되는지, 서로 다른 표현을 강제로 해석할 수 있는지 같은 별도 문제를 가리키는 경우가 많다. 동적 언어가 모든 연산에서 아무 값이나 섞게 허용한다거나, 정적 언어가 모든 잘못된 변환을 막는다고 설명하면 실제 동작을 놓친다.

정적 검사는 실행하지 않은 경로에서도 일부 오류를 발견하고 코드 변경의 영향을 추적하는 데 유용하다. 그러나 분석 범위를 벗어나는 외부 데이터나 타입 탈출구가 있으면 보장은 제한된다. 동적 검사는 실제 값에 맞춰 유연하게 동작하지만 오류가 발생하는 경로를 충분히 실행해야 한다. 어느 쪽도 네트워크 실패나 요구사항의 잘못된 해석까지 자동으로 해결하지는 않는다.

현대 개발 환경은 두 접근을 섞기도 한다. 동적 언어에 타입 주석과 검사기를 더하거나, 정적 언어에서 동적 데이터와 런타임 반사를 사용한다. 선택할 때는 언어 이름만 보지 말고 프로젝트의 검사 설정, 입력 경계, 팀의 변경 빈도와 테스트 전략을 함께 봐야 한다. 타입 검사의 시점은 개발 경험과 오류 발견 위치를 바꾸며, 실제 신뢰 수준은 도구를 어떻게 사용하는지에 달려 있다.

참고 자료

정적 타입과 동적 타입은 언제 무엇을 확인할까 · ariser