"서버 그대로 AWS에 올리면 되는 거 아닌가요?" — 마이그레이션 현장에서 가장 많이 듣는 말이자, 가장 위험한 착각이다.
🎯 이 글에서 다루는 것
레거시 앱 클라우드 이전 전, 반드시 해야 할 호환성 분석
AWS 마이그레이션 도구(MGN)가 커널 문제를 해결해주지 않는 이유
컨테이너로 해결 가능한 케이스와 구체적인 Dockerfile 예제
KVM이 불가피한 케이스와 AWS Bare Metal 구성 방법
판단 기준을 정리한 최종 의사결정 트리
📌 도입 — "올리는 것"과 "돌아가는 것"은 다르다
레거시 시스템 마이그레이션 프로젝트에서 흔히 벌어지는 일이 있다. AWS MGN(Application Migration Service)으로 서버를 통째로 복제해서 EC2에 올렸는데, 앱이 시작조차 안 되는 상황이다.
이유는 단순하다. 마이그레이션 도구는 이동 수단일 뿐이다. 디스크를 블록 단위로 복제해서 EC2에 붙여주는 역할이 전부다. 커널 2.x, 3.x 시절의 레거시 앱이 가진 호환성 문제는 옮긴 후에도 그대로 남는다.
심지어 MGN은 복제 과정에서 구버전 커널을 감지하면 자동으로 Nitro 호환 커널로 교체해버린다. /boot/vmlinuz-3.x 파일이 복제는 되지만, Nitro 하이퍼바이저가 요구하는 ENA(네트워크), NVMe(스토리지) 드라이버가 구버전 커널에 없기 때문이다. 결국 원본 커널로는 부팅이 불가능하다.
그래서 마이그레이션 전에 반드시 해야 할 작업이 있다. 호환성 분석이다.
🔍 핵심 질문 — "커널 종속"인가, "userspace 종속"인가
현장에서 "이 앱은 커널 3.x에서만 돌아요"라는 말을 들으면, 먼저 의심해야 한다. 실제로 커널 자체에 종속된 케이스는 생각보다 드물다. 대부분은 userspace 영역의 문제다.
"커널 3.x에서만 됩니다"
↓ 실제 원인 분석
┌─────────────────────────────────┐
│ glibc 버전 종속 ← 90% 이 케이스 (userspace)
│ .so 라이브러리 종속 ← userspace
│ 런타임 버전 종속 ← userspace
│ 실제 커널 syscall 종속 ← 진짜 커널 문제 (희귀)
└─────────────────────────────────┘
이걸 구분하는 가장 빠른 방법은 아래 두 명령어다.
# 앱이 사용하는 syscall 목록 추적
strace -c ./legacy-app
# 앱이 링크된 라이브러리와 필요한 glibc 버전 확인
ldd ./legacy-app
objdump -p ./legacy-app | grep GLIBC
ldd 결과에서 GLIBC_2.12, GLIBC_2.17 같은 버전 심볼이 보인다면 userspace 종속이다. 이 경우 컨테이너로 해결 가능하다.
🐳 케이스 1 — userspace(glibc) 종속: 컨테이너로 해결
컨테이너의 핵심 구조를 이해하면 왜 이게 해결되는지 바로 보인다.
┌──────────────────────────────────┐
│ 컨테이너 이미지 내부 │
│ ┌────────────────────────────┐ │
│ │ 레거시 앱 │ │
│ │ glibc 2.12 (구버전) │ │ ← 이미지 안에 격리
│ │ 필요한 .so 라이브러리들 │ │
│ └────────────────────────────┘ │
├──────────────────────────────────┤
│ 호스트 커널 (5.x / 6.x) │ ← glibc와 무관
└──────────────────────────────────┘
컨테이너는 커널만 공유하고, glibc를 포함한 모든 userspace 라이브러리는 이미지 안에 독립적으로 탑재된다. 호스트 커널이 6.x여도 컨테이너 내부의 glibc 2.12는 그대로 동작한다.
# glibc 2.12 환경이 필요한 레거시 앱 컨테이너화
FROM centos:6
# 필요한 의존 라이브러리 설치 (앱에 따라 조정)
RUN yum install -y \
libstdc++ \
libgcc \
openssl \
&& yum clean all
# 앱 바이너리 복사
COPY ./legacy-app /opt/app/legacy-app
RUN chmod +x /opt/app/legacy-app
# 설정 파일이 있다면 함께 복사
COPY ./config /opt/app/config
WORKDIR /opt/app
CMD ["./legacy-app"]
추가 라이브러리가 필요한 경우 — .so 직접 패키징
앱이 특정 .so 파일에 직접 의존하고 패키지 매니저로 설치가 안 된다면, 파일을 직접 복사하는 방법도 있다.
FROM centos:7
# 기존 서버에서 필요한 .so 파일 직접 복사
COPY ./libs/liblegacy.so.1.2.3 /usr/lib64/liblegacy.so.1.2.3
RUN ldconfig # 동적 링커 캐시 갱신
COPY ./legacy-app /opt/app/legacy-app
RUN chmod +x /opt/app/legacy-app
CMD ["/opt/app/legacy-app"]
컨테이너 동작 검증
# 이미지 빌드
docker build -t legacy-app:v1 .
# 컨테이너 내부에서 ldd로 라이브러리 링크 확인
docker run --rm legacy-app:v1 ldd /opt/app/legacy-app
# 실제 실행 테스트
docker run --rm legacy-app:v1
# strace로 syscall 정상 동작 확인 (디버깅 시)
docker run --rm --cap-add SYS_PTRACE legacy-app:v1 \
strace -c /opt/app/legacy-app