[게시판 프로젝트] 트랜잭션 ERD 새롭게 사용자 히스토리(UserHisotires) 테이블이 생성되었습니다. 이 테이블은 사용자의 정보가 변경될 때마다 변경 내역을 로깅(Logging)하기 위해 사용됩니다. 사용자 정보 변경 API를 구현하면서, 이 변경 내역을 사용자 히스토리 테이블에도 함께 데이터를 생성하도록 구현해보겠습니다. 그럼 먼저, 사용자 히스토리 model을 Prisma로 구현해볼까요?[코드스니펫] 사용자 히스토리(UserHistories) model 구현하기
// schema.prisma
model Users {
userId Int @id @default(autoincrement()) @map("userId")
email String @unique @map("email")
password String @map("password")
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
UserInfos UserInfos? // 사용자(Users) 테이블과 사용자 정보(UserInfos) 테이블이 1:1 관계를 맺습니다.
Posts Posts[] // 사용자(Users) 테이블과 게시글(Posts) 테이블이 1:N 관계를 맺습니다.
Comments Comments[] // 사용자(Users) 테이블과 댓글(Comments) 테이블이 1:N 관계를 맺습니다.
UserHistories UserHistories[] // 사용자(Users) 테이블과 사용자 히스토리(UserHistories) 테이블이 1:N 관계를 맺습니다.
@@map("Users")
}
model UserHistories {
userHistoryId String @id @default(uuid()) @map("userHistoryId")
UserId Int @map("UserId") // 사용자(Users) 테이블을 참조하는 외래키
changedField String @map("changedField") // 변경된 필드명
oldValue String? @map("oldValue") // 변경 전 값
newValue String @map("newValue") // 변경 후 값
changedAt DateTime @default(now()) @map("changedAt")
// Users 테이블과 관계를 설정합니다.
User Users @relation(fields: [UserId], references: [userId], onDelete: Cascade)
@@map("UserHistories")
}
[코드스니펫] Prisma db push 명령어
# schema.prisma에 정의된 모델 정보를 DB와 동기화합니다.
npx prisma db push
🧩 SQL과 비교하기
CREATE TABLE Users
(
userId INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(191) UNIQUE NOT NULL,
password VARCHAR(191) NOT NULL,
createdAt DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updatedAt DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE UserInfos
(
userInfoId INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
UserId INTEGER UNIQUE NOT NULL, -- 1:1 관계 이므로 UNIQUE 조건을 삽입합니다.
name VARCHAR(191) NOT NULL,
age INTEGER NOT NULL,
gender VARCHAR(191) NOT NULL,
profileImage VARCHAR(191) NULL,
createdAt DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updatedAt DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE UserInfos
ADD CONSTRAINT FK_UserInfos_Users
FOREIGN KEY (UserId) REFERENCES Users (userId) ON DELETE CASCADE;
CREATE TABLE Posts
(
postId INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
UserId INTEGER NOT NULL,
title VARCHAR(191) NOT NULL,
content VARCHAR(191) NOT NULL,
createdAt DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updatedAt DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE Posts
ADD CONSTRAINT FK_Posts_Users
FOREIGN KEY (UserId) REFERENCES Users (userId) ON DELETE CASCADE;
CREATE TABLE Comments
(
commentId INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
UserId INTEGER NOT NULL,
PostId INTEGER NOT NULL,
content VARCHAR(191) NOT NULL,
createdAt DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updatedAt DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE Comments
ADD CONSTRAINT FK_Comments_Posts
FOREIGN KEY (PostId) REFERENCES Posts (postId) ON DELETE CASCADE;
ALTER TABLE Comments
ADD CONSTRAINT FK_Comments_Users
FOREIGN KEY (UserId) REFERENCES Users (userId) ON DELETE CASCADE;
CREATE TABLE UserHistories
(
userHistoryId VARCHAR(191) NOT NULL DEFAULT (UUID()) PRIMARY KEY,
UserId INTEGER NOT NULL,
changedField VARCHAR(191) NOT NULL,
oldValue VARCHAR(191) NULL,
newValue VARCHAR(191) NOT NULL,
changedAt DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
PRIMARY KEY (`userHistoryId`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE UserHistories
ADD CONSTRAINT FK_UserHistories_Users
FOREIGN KEY (UserId) REFERENCES Users (userId) ON DELETE CASCADE;
❓ UUID(범용 고유 식별자)란 무엇인가요?

<aside>
💡 **[UUID(Universally Unique Identifier, 범용 고유 식별자)](https://ko.wikipedia.org/wiki/%EB%B2%94%EC%9A%A9_%EA%B3%A0%EC%9C%A0_%EC%8B%9D%EB%B3%84%EC%9E%90)**는 총 4개의 정보를 **하이픈(`-`)** 으로 구분하여 순차적으로 저장한 데이터 타입입니다. **시간 정보를 포함**하고 있어 **생성된 순서대로 정렬**이 되는 특징을 가지고 있습니다.
**[→ UUID 디코드 사용해보기](https://www.uuidtools.com/decode)**
</aside>
사용자 히스토리(UserHistories) 테이블은 사용자 정보에 대한 모든 변경 내역을 기록합니다. 추후에 API 호출 히스토리와 같은 추가 정보를 기록하는 다른 히스토리 테이블을 만들면, 더욱 다양한 데이터를 수집할 수 있겠죠?
사용자 히스토리 테이블은 일반적인 다른 테이블과는 조금 다르게 설계해야합니다. **Integer 타입의 기본키나 createdAt, updatedAt과 같은 컬럼을 사용하기보다는, UUID를 사용하여 컬럼 수를 최소화** 하는 것이 로그 테이블에서는 더욱 효율적인 설계가 될 것입니다. ☺️