🧩 학습 배경

3단계에서는 테이블의 구조가 다음과 같이 변경된다.
테이블 추가:
CREATE TABLE reservation_time (
id BIGINT NOT NULL AUTO_INCREMENT,
start_at VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
테이블 구조 변경:
time VARCHAR → reservation_time id 외래키 참조
CREATE TABLE reservation (
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
date VARCHAR(255) NOT NULL,
time_id BIGINT, -- time VARCHAR(255) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (time_id) REFERENCES reservation_time (id)
);
이로 인해 자바 코드도 불가피하게 변경이 돼야 한다.
- `Reservation` 클래스의 time 필드를 `String` → `ReservationTime` 객체로 변경
- 예약 추가 요청 본문: `time` → `timeId`
- 예약 조회 응답: `time`을 객체로 `({id, startAt})`
🎯 학습 목적
테이블 구조가 변경되면서, 자바 코드를 불가피하게 수정해야 했는데 그냥 아무 생각없이 컴파일러에만 의존한채 수정하다보니 복잡하고 헷갈렸다. 어찌저찌해서 돌아가게는 했는데, 만약 다음번에 테이블 구조 변경이 더 넓은 범위에서 생기면 쉽지 않을 것 같다는 생각이 들었다. 그래서 이거를 헷갈리지 않게 차근차근 하는 방법은 없을까 하는 생각이 들어서 한번 탐구해보기로 했다.
🪜 단계 나누기
🤔 테이블 의존관계가 변경됐을 때 수정을 효율적으로 할 수 있는 방법은 무엇일까?
👉 변경 범위를 먼저 파악하고 단계를 세운다음 그 순서대로 수정하자.
변경된 부분을 먼저 추가 한뒤, 하위계층부터 순차적으로 수정.
- 1단계: 변경된 데이터 모델 파악
- 새로 추가된 테이블은 무엇인가?
- 기존 테이블의 컬럼/외래키는 어떻게 바뀌었는가?
- 2단계: 새 개념을 코드에 먼저 추가
- 새 테이블에 대응되는 Domain 추가
- 새 Repository 추가
- 기본 CRUD 또는 조회 기능 구현 및 테스트
- 3단계: 기존 도메인과 새 도메인의 관계 연결
- 영향을 받는 도메인 파악
- 기존 도메인의 필드 수정
- 필요한 생성자, getter, 검증 로직 수정
- 관련 테스트 수정
- 4단계: Repository 매핑 수정
- CRUD 로직 수정
- 테스트 수정
- 5단계: Service 흐름 수정
- 관련 도메인을 사용하는 비즈니스 로직 수정
- 테스트 수정
- 6단계: Cotroller 수정
- 요청 DTO 변경
- 응답 DTO 변경
- 테스트 수정
🚀 적용하기
코드:
GitHub - jhk01007/spring-roomescape-admin at feat1_가설증명
우테코 레벨2. Contribute to jhk01007/spring-roomescape-admin development by creating an account on GitHub.
github.com
정의한 단계를 실험해보기 위해 브랜치를 새로파서 테이블 의존관계가 바뀌기 전으로 리셋하였다.

1️⃣ 1단계: 변경된 데이터 모델 파악
테이블 추가:
CREATE TABLE reservation_time (
id BIGINT NOT NULL AUTO_INCREMENT,
start_at VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
테이블 구조 변경:
time VARCHAR → reservation_time id 외래키 참조
CREATE TABLE reservation (
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
date VARCHAR(255) NOT NULL,
time_id BIGINT, // time VARCHAR(255) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (time_id) REFERENCES reservation_time (id)
);
2️⃣ 2단계: 새 개념을 코드에 먼저 추가

3️⃣ 3단계: 기존 도메인과 새 도메인의 관계 연결
변경할 도메인:
`LocalTime` 타입에서 `ReservationTime`으로 변경한다.
public class Reservation {
private Long id;
private String name;
private LocalDate date;
private ReservationTime reservationTime; // LocalTime time
}
도메인의 필드가 수정되면 해당 도메인을 사용하던 Repository나 Service에서 컴파일 오류가 발생하기 때문에 도메인 테스트가 정상동작하는지 실행해볼 수가 없다. 그렇다고 컴파일이 안나도록 하나하나 수정하는 것도 오래 걸리고 귀찮은 작업이다. 따라서 이때는 Codex를 활용했다.
프롬프트:
@<테스트 클래스>
- 지정된 테스트 클래스만 기준으로 판단하라
- 해당 테스트에서 실제로 호출되는 클래스와 메서드만 추적해서 분석하라
- 테스트 실행 흐름에 포함되지 않는 다른 클래스는 모두 무시하라
- 프로젝트의 다른 파일에서 발생하는 컴파일 오류는 전부 무시하라
이 테스트는 독립적으로 실행된다고 가정한다.
작업:
1. 이 테스트가 실제로 실행된다면 pass 할지 판단하라
2. 테스트 내부에서 호출되는 실제 클래스 로직까지 따라가서 분석하라
3. 실패한다면 어떤 로직에서 왜 실패하는지 구체적으로 설명하라
절대 하지 말 것:
- 프로젝트 전체 컴파일 기준으로 판단
- 테스트와 무관한 클래스 오류 언급
- 단순히 "컴파일 안됨"으로 결론 내리기
사용 예:

물론 어디까지나 이건 임시방편으로, 추후 수정이 완료됐을 때 다시 테스트를 실행해봐야 한다.
4️⃣ 4단계: Repository 매핑 수정
`save()`:
Reservation테이블에선 String이던 time 컬럼이 ReservationTime의 기본키를 외래키 참조하도록 바꼈으므로 Long으로 변경한다.
사실 save()는 JdbcTemplate 같은 SQL Mapper가 아니라 JPA같은 ORM을 사용하면 수정이 필요가 없어진다. (ORM 짱)

`findAll()`:
테이블로 부터 Reservation 데이터를 조회해서 Reservation 객체로 만들려면 ReservationTime 데이터가 필요하기 때문에 join해서 갖고 와야 한다.

`delete()`: 수정 X
Repository 테스트 수정:
이제 Reservation 테스트 픽스처를 만들 때 ReservationTime도 같이 만들어야 한다.

codex를 이용한 테스트 실행:
테스트가 실패했다. *로 컬럼을 지정했기 때문에 조인한 각 테이블의 id를 가져올 때 문제가 생긴것이다.

오류를 수정하고 다시 실행을 하니 정상적으로 통과했다.

5️⃣ 5단계: Service 흐름 수정
`addReservation`(예약 추가) 서비스 로직:
time을 LocalTime이 아닌 ReservationTime 객체를 넣어줘야 하므로 조회하는 로직을 추가했다.

6️⃣ 6단계: Cotroller 수정
요청 DTO에서 `LocalTime time`이 `Long timeId`로 변경된다.

응답 DTO에서도 `LocalTime`이 `ReservationTimeResponse`로 변경된다.

public record ReservationTimeResponse(
Long id,
LocalTime startAt
) {
}
🆚 그냥 했을 때 vs 단계 별로 수정했을 때
📝 커밋 히스토리 차이

`ReservationTime` 관련 API를 추가하는 과정 부분까지는 커밋 히스토리 차이가 없지만, 그 이후 `Reservation`을 변경했을 때 부터는 그냥 했을 때의 커밋은 하나의 커밋이 너무 많은 변경사항을 반영하고 있는 반면, 단계 별로 접근했을 때는 계층 별로 변경사항이 잘 드러난다.
⚠️ 실수 가능성
그냥 했을 때는 그냥 단순히 의식의 흐름대로 리팩토링했다. 그러다보니 하다가도 내가 다음에는 ‘어떤걸 해야하지?’ 싶은 순간들이 많았고 실제로 DTO를 수정하는 것을 깜빡하기도 했었다.
반면 단계별로 접근했을 때는 가이드라인이 있다보니 다음에 해야할 것이 명확하게 보였다.
📦 최종 정리
데이터베이스의 테이블 구조가 변경됐을 때 자바 코드 수정을 효율적으로 하려면 변경 범위를 먼저 파악하고, 단계를 세운 다음 순서대로 수정해야 한다.
물론 이렇게 단계를 세우는 것도 중요하지만, 그보다 더 중요한 것은 각 단계를 적절한 계층으로 나누는 것이다.
controller / service / repository / domain과 같은 계층 구조로 분리하면, 한 부분이 수정되더라도 그 영향 범위를 보다 쉽게 예측할 수 있다.
물론 다른 아키텍처를 사용한다면 이 가이드라인을 그대로 재사용할 수는 없다. 하지만 이 학습의 핵심은 ‘고정된 가이드라인을 만드는 것’이 아니라, ‘수정 시 단계적으로 접근하는 사고 습관을 기르는 것’이다. 이러한 습관이 자리 잡는다면, 아무리 복잡한 아키텍처라도 보다 수월하게 수정할 수 있을 것이라 기대한다.
'우테코 8기 > 본과정 탐구 일지' 카테고리의 다른 글
| [레벨2 - 방탈출 사용자] 삭제할 리소스가 없을 때도 204 No Content를 내려도 될까? (0) | 2026.05.10 |
|---|---|
| [레벨2 - 방탈출 사용자] 201 Created 응답에서 Location 헤더는 꼭 필요할까? (0) | 2026.05.10 |
| [레벨 1 장기] 안 좋은 코드습관 고치기 (1) | 2026.04.12 |
| [레벨1 선택미션] 《객체지향의 사실과 오해》 읽고 장기 도메인 모델 설계하기 (0) | 2026.03.22 |
| [레벨1 블랙잭] Service 클래스에 대한 고찰 (0) | 2026.03.14 |