Schema Compare 사용해보기

이건선·2026년 2월 14일

해결

목록 보기
60/63

배경

데이터베이스 B의 스키마를 A로 동기화해야 하는 상황이 생겼다. DB를 직접 건드리기 전에 Docker로 MSSQL 환경을 구성하고, 'visual studio', 'vs code'에서 Schema Compare 기능을 테스트해보기로 했다.


Docker MSSQL 환경 구성

docker-compose.yml

version: '3.8'
services:
  mssql-a:
    image: mcr.microsoft.com/mssql/server:2022-latest
    container_name: mssql-a
    environment:
      ACCEPT_EULA: "Y"
      MSSQL_SA_PASSWORD: "YourStrong!Pass123"
    ports:
      - "1433:1433"    # Target (동기화 대상)

  mssql-b:
    image: mcr.microsoft.com/mssql/server:2022-latest
    container_name: mssql-b
    environment:
      ACCEPT_EULA: "Y"
      MSSQL_SA_PASSWORD: "YourStrong!Pass123"
    ports:
      - "1434:1433"    # Source (동기화 원본)

두 컨테이너가 올라오면 각각 독립된 MSSQL 서버로 동작한다.

역할컨테이너포트설명
Source (B)mssql-b1434최신 스키마 (동기화 원본)
Target (A)mssql-a1433이전 스키마 (동기화 대상)

테스트 데이터 설계

스키마 비교에서 발생할 수 있는 주요 케이스를 포함하도록 설계했다.

DB-B (Source): 최신 스키마

-- 컬럼이 추가/변경된 테이블
CREATE TABLE Users (
    Id        INT PRIMARY KEY IDENTITY(1,1),
    Name      NVARCHAR(100) NOT NULL,    -- A는 NVARCHAR(50)
    Email     NVARCHAR(200) NOT NULL,
    Phone     NVARCHAR(20) NULL,         -- A에 없음
    Status    NVARCHAR(20) DEFAULT 'ACTIVE',  -- A에 없음
    CreatedAt DATETIME2 DEFAULT GETDATE(),    -- A에 없음
    UpdatedAt DATETIME2 NULL                  -- A에 없음
);

-- B에만 존재하는 신규 테이블
CREATE TABLE Orders ( ... );
CREATE TABLE OrderItems ( ... );
CREATE TABLE AuditLog ( ... );

-- B에만 존재하는 뷰, 프로시저, 인덱스
CREATE VIEW vw_OrderSummary AS ...
CREATE PROCEDURE sp_GetUserOrders AS ...
CREATE INDEX IX_Users_Email ON Users(Email);

DB-A (Target): 이전 스키마

-- 컬럼이 적은 이전 버전
CREATE TABLE Users (
    Id    INT PRIMARY KEY IDENTITY(1,1),
    Name  NVARCHAR(50) NOT NULL,    -- B는 100
    Email NVARCHAR(200) NOT NULL
    -- Phone, Status, CreatedAt, UpdatedAt 없음
);

-- A에만 존재하는 레거시 테이블
CREATE TABLE LegacyConfig (
    Id          INT PRIMARY KEY IDENTITY(1,1),
    ConfigKey   NVARCHAR(100) NOT NULL,
    ConfigValue NVARCHAR(500) NULL
);

의도한 차이점 요약

구분내용비교 결과
Users.NameNVARCHAR(50) → NVARCHAR(100)변경
Users.Phone 외 4개 컬럼A에 없음추가
Orders, OrderItems, AuditLogA에 없음신규 테이블
vw_OrderSummaryA에 없음신규 뷰
sp_GetUserOrdersA에 없음신규 프로시저
인덱스 5개A에 없음신규 인덱스
LegacyConfigB에 없음삭제 대상

SSDT 설치 확인

Schema Compare 기능을 사용하려면 Visual Studio에 SQL Server Data Tools (SSDT)가 설치되어 있어야 한다.

Visual Studio 2022를 실행한다.

상단 메뉴에서 도구(T) 탭을 클릭한다. 여기서 SQL Server 하위 메뉴가 보이지 않는다면 SSDT가 설치되지 않은 것이다.

Visual Studio Installer에서 데이터 스토리지 및 처리 워크로드를 선택하고, 오른쪽 설치 세부 정보에서 SQL Server Data Tools가 체크되어 있는지 확인한다.


Schema Compare 실행

1. 스키마 비교 열기

도구(T) → SQL Server(Q) → 새 스키마 비교(N) 를 선택한다.

2. 원본(Source) 선택

스키마 비교 화면이 열리면 왼쪽의 원본 선택 드롭다운을 클릭하고 원본 선택... 을 클릭한다.

원본 스키마 선택 대화상자에서 데이터베이스(D) 를 선택하고 연결 선택... 버튼을 클릭한다.

3. Source(B) 서버 연결

연결 대화상자에서 다음과 같이 입력한다.

항목
서버 이름localhost,1434
인증SQL Server 인증
사용자 이름sa
암호YourStrong!Pass123
데이터베이스 이름SchemaTestDB
암호화선택 사항(False)
서버 인증서 신뢰True

암호화서버 인증서 신뢰 설정이 필요한 이유:

Docker MSSQL 2022는 자체 서명 인증서(self-signed)를 사용한다. 공인 기관이 발급한 인증서가 아니므로, 기본값(암호화=필수)으로 연결하면 인증서 검증에 실패한다. 로컬 테스트 환경에서는 암호화를 선택 사항(False)로 변경하거나, 서버 인증서 신뢰를 True로 설정하면 된다.

4. Target(A) 서버 연결

Source 연결이 완료되면 오른쪽 대상 선택도 동일한 방식으로 설정한다. 서버 이름만 localhost,1433으로 변경하면 된다.

5. 비교 실행

양쪽 연결이 완료되면 상단의 비교 버튼을 클릭한다. 비교 결과가 세 가지 카테고리로 표시된다.

카테고리내용
삭제B에 없고 A에만 있는 객체 (LegacyConfig)
변경양쪽 모두 존재하지만 정의가 다른 객체 (Users)
추가B에 있고 A에 없는 객체 (Orders, AuditLog 등)

하단 패널에서 선택한 객체의 스키마 차이를 좌우로 비교하여 확인할 수 있다.


동기화 스크립트 생성 및 첫 번째 실패

스크립트 생성

비교 결과를 확인한 후 상단의 스크립트 생성 버튼을 클릭하면, SSDT가 B의 스키마를 A에 적용하기 위한 SQL 스크립트를 자동으로 생성한다.

생성된 스크립트에는 다음과 같은 내용이 포함된다:

-- [dbo].[LegacyConfig] 테이블을 삭제하고 있습니다.
-- 테이블에 데이터가 들어 있으면 배포가 중단됩니다.
IF EXISTS (select top 1 1 from [dbo].[LegacyConfig])
    RAISERROR (N'행이 발견되었습니다. 데이터가 손실될 수 있으므로
    스키마 업데이트가 종료됩니다.', 16, 127) WITH NOWAIT

실행 실패

스크립트를 실행하면 즉시 오류가 발생한다.

메시지 50000, 수준 16, 상태 127, 줄 48
행이 발견되었습니다. 데이터가 손실될 수 있으므로 스키마 업데이트가 종료됩니다.
** 일괄 처리를 실행하는 동안 오류가 발생했습니다. 종료하고 있습니다.

실패 원인

SSDT의 안전장치가 작동한 것이다. LegacyConfig 테이블에 데이터(2건)가 존재하는 상태에서 테이블을 삭제하면 데이터가 영구적으로 손실된다. SSDT는 이런 상황을 감지하고 스크립트 실행을 자동으로 중단한다.

이것은 버그가 아니라 의도된 동작이다. 운영 환경에서 실수로 데이터가 있는 테이블을 날리는 사고를 방지해준다.


삭제 대상 제외 후 재실행

삭제 항목 체크박스 해제

Schema Compare 화면으로 돌아가서 삭제 카테고리의 LegacyConfig 테이블 체크박스를 해제한다. 이렇게 하면 해당 테이블은 동기화 대상에서 제외된다.

B에 없다고 A의 테이블을 무조건 삭제하는 것이 아니라, 삭제 여부를 판단해야 한다.

스크립트 재생성 및 실행

체크박스를 해제한 상태에서 다시 스크립트 생성실행하면 성공한다.

하단 메시지 탭에서 실행된 작업을 확인할 수 있다:

테이블 [dbo].[Members]을(를) 변경하는 중...
인덱스 [dbo].[Members].[IX_Members_Grade]을(를) 만드는 중...
인덱스 [dbo].[Members].[IX_Members_LoginId]을(를) 만드는 중...
테이블 [dbo].[Payments]을(를) 변경하는 중...
테이블 [dbo].[Products]을(를) 변경하는 중...
테이블 [dbo].[Users]을(를) 변경하는 중...
인덱스 [dbo].[Users].[IX_Users_Email]을(를) 만드는 중...
테이블 [dbo].[AuditLog]을(를) 만드는 중...
테이블 [dbo].[Orders]을(를) 만드는 중...
...

동기화 결과 확인

다시 비교

동기화가 완료된 후 다시 비교 버튼을 클릭하면 결과가 달라져 있다.

카테고리동기화 전동기화 후
삭제LegacyConfigLegacyConfig (체크 해제 상태 유지)
변경Users없음
추가Orders, OrderItems, AuditLog, 뷰, 프로시저없음

변경추가 항목이 모두 사라졌다. LegacyConfig만 남아있는데 이는 의도적으로 제외한 것이므로 정상이다.


Schema Compare 옵션 권장 설정

스키마 비교 화면에서 톱니바퀴 아이콘을 클릭하면 비교 옵션을 설정할 수 있다.


번외: VS Code에서도 Schema Compare가 된다

Visual Studio 없이도 VS Code만으로 스키마 비교가 가능하다. Microsoft의 공식 SQL Server (mssql) 확장이 Schema Compare를 정식 지원하고 있다.

설치

  1. VS Code에서 Extensions 아이콘을 클릭한다.
  2. SQL Server (mssql) 을 검색하고 Install 한다.

사용 방법

  1. 좌측 Object Explorer에서 데이터베이스를 우클릭하고 Schema Compare를 선택한다. 선택한 데이터베이스가 Source로 설정된다.

  1. Source와 Target의 말줄임표(...)를 클릭하여 비교 대상을 변경할 수 있다.

  1. Options 버튼으로 비교 옵션을 커스터마이징한다.
  2. Compare 버튼을 클릭하면 비교 결과가 표시된다.
  3. 적용할 객체를 선택한 후 변경 사항을 Target에 적용하거나, 스크립트를 생성할 수 있다.
profile
멋지게 기록하자

0개의 댓글