Skip to content

[Refactor] TypeORM 저장소 조회 로직 정리 - #84

Merged
JangDongHo merged 1 commit into
devfrom
refactor/typeorm-repositories
Jun 11, 2026
Merged

JangDongHo merged 1 commit into
devfrom
refactor/typeorm-repositories

Conversation

@JangDongHo

@JangDongHo JangDongHo commented Jun 11, 2026 •

Copy link
Copy Markdown
Member

📌 개요

  • TypeORM 저장소 조회/저장 로직을 정리하고 사용자 프로필 갱신 저장 흐름을 보완했습니다.

✨ 작업 내용

  • 식당, 단과대학, 학과, 공지 카테고리 조회 로직을 TypeORM Repository 메서드 기반으로 정리했습니다.
  • 연관 엔티티 조건으로만 사용하던 외래키 컬럼을 엔티티에 명시해 조회와 저장 시 값을 직접 다룰 수 있도록 했습니다.
  • 사용자 학과 정보 갱신 시 신규 사용자도 저장될 수 있도록 upsert 흐름을 보완했습니다.
  • 학과 목록 조회에서 잘못된 page 값이 들어와도 최소 1페이지 기준으로 처리하도록 보정했습니다.

🔥 변경 이유

  • QueryBuilder로 작성된 단순 조회를 Repository API로 정리해 읽기 쉽고 일관된 저장소 구현으로 맞췄습니다.
  • 사용자 프로필 갱신 과정에서 기존 사용자 조회 결과에 의존하면 신규 사용자 저장이 실패할 수 있어, 저장 대상 값을 명시적으로 구성하도록 개선했습니다.
  • FK 값을 엔티티에서 직접 참조할 수 있게 해 필터링과 저장 결과 반환을 안정적으로 처리하기 위함입니다.

🧪 테스트

  • 정상 동작 확인
  • 예외 케이스 확인
  • pnpm --dir services/api/app test users.service.spec.ts -- --runInBand
  • pnpm --dir services/api/app lint:check
  • pnpm --dir services/api/app test -- --runInBand

🔗 관련 이슈

  • 해당 없음

Summary by CodeRabbit

릴리스 노트

  • Refactor

    • 데이터 조회 로직 표준화로 쿼리 성능 및 일관성 개선
    • 학생, 캠퍼스, 단과대 관련 저장소 메서드 최적화
  • Bug Fixes

    • 페이지 번호 입력값 검증 강화
    • 사용자 조회 시 데이터 부재에 따른 null 처리 개선
  • Tests

    • 사용자 테스트 케이스 필드 업데이트

@coderabbitai

coderabbitai Bot commented Jun 11, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

이 PR은 엔티티에 denormalized 외래키 필드를 도입하고, TypeORM QueryBuilder 기반 조회를 Repository 메서드 기반으로 통일하며, 입력 검증을 추가합니다. Cafeterias, Departments, Users 엔티티에 FK 필드를 추가하고, 여러 저장소에서 QueryBuilder를 Repository.find/findOne으로 리팩토링합니다.

Changes

엔티티 스키마 및 저장소 쿼리 리팩토링

Layer / File(s) Summary
엔티티 FK 필드 추가
services/api/app/src/api/public/cafeterias/domain/entities/cafeteria-diet.entity.ts, services/api/app/src/api/public/cafeterias/domain/entities/cafeteria.entity.ts, services/api/app/src/api/public/departments/domain/entities/department.entity.ts, services/api/app/src/api/public/users/domain/entities/users.entity.ts
CafeteriaDiet, Cafeteria, Department, User 엔티티에 각각 cafeteriaId, campusId, collegeId, campusId/departmentId 필드를 @Column 매핑으로 추가하여 관계 필드와 함께 외래키 값을 직접 보유
Cafeterias 저장소 쿼리 변경
services/api/app/src/api/public/cafeterias/infrastructure/cafeterias.repository.ts
findCafeteriasByCampusId 기본값 제거, findCafeteriaById와 findCafeteriaDietsByCafeteriaId 구현을 QueryBuilder에서 Repository.find/findOne으로 변경하고 relations/select 옵션 사용
Departments 서비스 및 저장소 업데이트
services/api/app/src/api/public/departments/application/departments.service.ts, services/api/app/src/api/public/departments/infrastructure/departments.repository.ts
DepartmentsService.findAll에서 page를 최소값 1로 제한(safePage), findByCollegeId를 QueryBuilder에서 Repository.findAndCount로 리팩토링
Colleges 저장소 필터 적용
services/api/app/src/api/public/colleges/infrastructure/colleges.repository.ts
Not 연산자를 import하고 findAll의 QueryBuilder 조건을 where: { name: Not('공통') } 형태로 변경
NoticeCategories 저장소 필터 적용
services/api/app/src/api/public/notices/infrastructure/notice-categories.repository.ts
In 연산자를 import하고 findByDepartmentIdAndCategories의 QueryBuilder 조건을 category: In(categoryNames) 형태로 변경
Users 저장소 및 서비스 리팩토링
services/api/app/src/api/public/users/application/users.service.ts, services/api/app/src/api/public/users/infrastructure/users.repository.ts
Users 저장소의 save(user) 시그니처를 객체 인자로 변경하고 findOne 반환 타입을 User | null로 수정, 서비스 upsert에서 User 인스턴스 생성 후 updateProfile 호출 및 저장 방식 변경
Users 서비스 테스트 업데이트
services/api/app/src/api/public/users/application/users.service.spec.ts
makeUser 헬퍼에 campusId/departmentId 필드 추가, upsert 테스트를 새 저장소 시그니처(expect.objectContaining)와 User 엔티티 구조 기준으로 업데이트

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • GNU-connect/Server-Node#79: CafeteriasRepository.findCafeteriaDietsByCafeteriaId가 새로운 cafeteriaId FK 컬럼 기준으로 조회하도록 변경된 점이, 해당 PR의 식단 조회 및 메뉴그룹화 로직에 직접 사용됨
  • GNU-connect/Server-Node#58: 이 PR의 저장소 쿼리 변경과 FK 필드 추가가 식단 템플릿 생성 입력 데이터 정렬을 지원하고, 해당 PR의 템플릿 캐싱·워밍업 로직과 같은 흐름을 형성
  • GNU-connect/Server-Node#51: 두 PR 모두 Cafeterias 저장소 조회 로직(findCafeteriaById, findCafeteriaDietsByCafeteriaId)과 이를 소비하는 서비스/컨트롤러 흐름에 직접 변경 적용

Suggested labels

Refactor, Cafeteria

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경 내용인 TypeORM 저장소 조회 로직 정리를 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명이 제공된 템플릿의 모든 필수 섹션(개요, 작업 내용, 변경 이유, 테스트, 관련 이슈)을 포함하고 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/typeorm-repositories

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@JangDongHo JangDongHo self-assigned this Jun 11, 2026
@JangDongHo JangDongHo changed the title ♻️ refactor: TypeORM 저장소 조회 로직 정리 [Refactor] TypeORM 저장소 조회 로직 정리 Jun 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
services/api/app/src/api/public/departments/application/departments.service.ts (1)

16-27: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

캐시 키와 실제 쿼리 매개변수 불일치 문제

@CacheKey 데코레이터는 원본 page 값으로 캐시 키를 생성하지만 (line 18), 실제 쿼리에는 safePage를 사용합니다.

예를 들어:

  • page = -1로 요청 시 캐시 키는 departments:college:X:page:-1이 되지만, 실제로는 page=1의 결과가 저장됩니다
  • 이후 page = 1로 요청 시 다른 캐시 키(departments:college:X:page:1)를 사용하므로 캐시 미스가 발생합니다

캐시 키 생성에도 Math.max(page, 1)를 적용해야 합니다.

🔧 캐시 키 수정 제안
  `@CacheKey`({
    key: ([collegeId, page]) => {
-      return `departments:college:${collegeId}:page:${page}`;
+      const safePage = Math.max(page, 1);
+      return `departments:college:${collegeId}:page:${safePage}`;
    },
  })
  public async findAll(collegeId: number, page: number): Promise<DepartmentListResult> {
    const safePage = Math.max(page, 1);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@services/api/app/src/api/public/departments/application/departments.service.ts`
around lines 16 - 27, The cache key uses the raw page param while the query uses
safePage, causing mismatched cache entries; update the `@CacheKey` callback used
on findAll to compute the same normalized page (Math.max(page, 1)) as safePage
so the cache key and the call to departmentsRepository.findByCollegeId use
identical page values, ensuring keys like
departments:college:{collegeId}:page:{safePage} are generated consistently.
🧹 Nitpick comments (1)
services/api/app/src/api/public/users/application/users.service.ts (1)

30-46: ⚡ Quick win

FK 유효성 검증을 추가하는 것을 권장합니다.

campusId와 departmentId가 실제로 DB에 존재하는지 검증하지 않습니다. 존재하지 않는 ID를 전달하면 DB 외래키 제약 위반으로 런타임 에러가 발생할 수 있습니다. 저장 전에 campus와 department의 존재 여부를 확인하는 것을 고려하세요.

🛡️ 제안: FK 유효성 검증 추가
 public async upsert(
   userId: string,
   campusId: number,
   departmentId: number,
 ): Promise<UpsertDepartmentResult> {
+  // Validate that campusId and departmentId exist in DB
+  // Consider injecting CampusRepository and DepartmentRepository
+  // to check existence before saving
+  
   const user = new User();
   user.updateProfile(userId, campusId, departmentId);
   const userResult = await this.usersRepository.save(user);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/api/app/src/api/public/users/application/users.service.ts` around
lines 30 - 46, The upsert method currently saves a User without verifying
campusId and departmentId exist, causing possible FK violations; update upsert
to first query the Campus and Department stores (e.g., via injected
campusRepository and departmentRepository or corresponding service methods) to
ensure both campusId and departmentId exist, throw a clear validation/error
(e.g., BadRequest or NotFound) if either is missing, and only then call
this.usersRepository.save(user) so that upsert (method name) validates FK
references before persisting.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@services/api/app/src/api/public/colleges/infrastructure/colleges.repository.ts`:
- Around line 14-26: The findAll method can compute a negative skip when page <=
0; clamp the page to a minimum of 1 inside findAll (e.g., compute const safePage
= Math.max(1, page)) before calculating skip, then pass skip: limit * (safePage
- 1) to this.collegesRepository.findAndCount and keep the rest of the logic
unchanged so queries never receive a negative offset.

---

Outside diff comments:
In
`@services/api/app/src/api/public/departments/application/departments.service.ts`:
- Around line 16-27: The cache key uses the raw page param while the query uses
safePage, causing mismatched cache entries; update the `@CacheKey` callback used
on findAll to compute the same normalized page (Math.max(page, 1)) as safePage
so the cache key and the call to departmentsRepository.findByCollegeId use
identical page values, ensuring keys like
departments:college:{collegeId}:page:{safePage} are generated consistently.

---

Nitpick comments:
In `@services/api/app/src/api/public/users/application/users.service.ts`:
- Around line 30-46: The upsert method currently saves a User without verifying
campusId and departmentId exist, causing possible FK violations; update upsert
to first query the Campus and Department stores (e.g., via injected
campusRepository and departmentRepository or corresponding service methods) to
ensure both campusId and departmentId exist, throw a clear validation/error
(e.g., BadRequest or NotFound) if either is missing, and only then call
this.usersRepository.save(user) so that upsert (method name) validates FK
references before persisting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 98af1d0d-03e4-429a-ace1-bafb389ea2bf

📥 Commits

Reviewing files that changed from the base of the PR and between 44fb793 and 0ceb4e7.

📒 Files selected for processing (12)
  • services/api/app/src/api/public/cafeterias/domain/entities/cafeteria-diet.entity.ts
  • services/api/app/src/api/public/cafeterias/domain/entities/cafeteria.entity.ts
  • services/api/app/src/api/public/cafeterias/infrastructure/cafeterias.repository.ts
  • services/api/app/src/api/public/colleges/infrastructure/colleges.repository.ts
  • services/api/app/src/api/public/departments/application/departments.service.ts
  • services/api/app/src/api/public/departments/domain/entities/department.entity.ts
  • services/api/app/src/api/public/departments/infrastructure/departments.repository.ts
  • services/api/app/src/api/public/notices/infrastructure/notice-categories.repository.ts
  • services/api/app/src/api/public/users/application/users.service.spec.ts
  • services/api/app/src/api/public/users/application/users.service.ts
  • services/api/app/src/api/public/users/domain/entities/users.entity.ts
  • services/api/app/src/api/public/users/infrastructure/users.repository.ts

@JangDongHo
JangDongHo merged commit 3845675 into dev Jun 11, 2026
2 checks passed
@JangDongHo
JangDongHo deleted the refactor/typeorm-repositories branch June 11, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant