Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
language: ko-KR

early_access: true
enable_free_tier: true
reviews:
profile: chill
request_changes_workflow: true
high_level_summary: true
high_level_summary_placeholder: '@coderabbitai 요약'
auto_title_placeholder: '@coderabbitai'
poem: true
review_status: true
collapse_walkthrough: false
path_filters:
- "!**/swagger.json"
- "!**/README.md"
path_instructions:
- path: "**/*.sql"
instructions: >
As a team convention, we do not specify FK constraints. Please avoid suggesting adding FK constraints in code reviews.
This file is a TypeScript file, but the SQL statements that modify the table structure are written as strings. For columns used as primary keys (PK) or foreign keys (FK), you must follow the convention of specifying the column type as "bigint".
If a table column name is "id" or ends with "_id", verify that the column type is "bigint". If the SQL is written with a type other than "bigint", issue a warning. This convention is mandatory, so please raise the severity level of the warning. Add the following characters to the beginning of the warning message so that users can easily notice it: 🚨🚨🚨

- path: "**/*Controller*(V[0-9]*)?.ts"
instructions: >
Review the API endpoints based on this guidelines.

### Richardson Maturity Model (RMM)
1. Level 0: Single URI with POST requests for all actions.
2. Level 1: Separate URIs for individual resources.
3. Level 2: Use of HTTP methods (GET, POST, PUT, DELETE) to define operations on resources.
4. Level 3: Hypermedia (HATEOAS) for advanced RESTful APIs.

### API Conventions
- URI Rules:
- Should be intuitive and self-explanatory.
- Should not map 1:1 to database tables.
- Must be stateless, with no session state between requests.
- Include "api" and version in the URI (/api/{version}/resource).
- Use kebab-case for URIs and camelCase for parameters and body contents.
- Resource identifiers should be unique and only one per URI path.

- Design Principles:
- APIs should be designed around resources, which are abstractions rather than direct database tables.
- Stateless APIs facilitate scalability and flexibility.
- Clear separation of frontend and backend via URI structure.
- Versioning in URI paths is preferred for clarity and ease of caching.
- Maintain consistent naming conventions across the API.
- Use plural forms for resource names (/users instead of /user).
- Complex actions can include verbs in the URI (/orders/{orderId}/cancel).

- Implementation Details:
- Avoid deeply nested resource paths to ensure maintainability.
- Ensure URIs reflect the data they provide, not the permissions or roles required to access them.
- Keep URIs simple and predictable, aiding both developers and automated systems.
abort_on_close: true
auto_review:
enabled: true
auto_incremental_review: true
ignore_title_keywords: []
labels: []
drafts: false
base_branches: []
tools:
shellcheck:
enabled: true
ruff:
enabled: true
markdownlint:
enabled: true
github-checks:
enabled: true
timeout_ms: 90000
languagetool:
enabled: true
disabled_rules:
- EN_UNPAIRED_BRACKETS
- EN_UNPAIRED_QUOTES
disabled_categories:
- TYPOS
- TYPOGRAPHY
- CASING
enabled_only: false
level: default
enabled_rules: []
enabled_categories: []
biome:
enabled: true
hadolint:
enabled: true
swiftlint:
enabled: true
phpstan:
enabled: true
level: default
golangci-lint:
enabled: true
yamllint:
enabled: true
gitleaks:
enabled: true
checkov:
enabled: true
ast-grep:
packages: []
rule_dirs: []
util_dirs: []
essential_rules: true
chat:
auto_reply: true
knowledge_base:
learnings:
scope: auto
issues:
scope: auto
jira:
project_keys: []
linear:
team_keys: []
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dependencies {
// Workaround for AOT issue (https://github.com/spring-projects/spring-framework/pull/33949) -->
implementation 'io.projectreactor:reactor-core'

compileOnly 'org.projectlombok:lombok'
implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
Expand All @@ -58,6 +59,8 @@ dependencies {
testImplementation 'org.testcontainers:mysql'
checkstyle "io.spring.javaformat:spring-javaformat-checkstyle:${springJavaformatCheckstyleVersion}"
checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}"

annotationProcessor 'org.projectlombok:lombok'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.springframework.samples.petclinic.course;

import org.springframework.data.jpa.repository.JpaRepository;

public interface CouresRepository extends JpaRepository<Course, Integer> {
}
Comment on lines +5 to +6
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

인터페이스 이름에 오타가 있습니다

인터페이스 이름이 CouresRepository로 되어 있는데, 올바른 철자는 CourseRepository입니다. 's'가 빠져있습니다. 이 오타는 다른 클래스에서 이 레포지토리를 참조할 때 혼란을 줄 수 있습니다.

다음과 같이 수정하세요:

-public interface CouresRepository extends JpaRepository<Course, Integer> {
+public interface CourseRepository extends JpaRepository<Course, Integer> {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public interface CouresRepository extends JpaRepository<Course, Integer> {
}
public interface CourseRepository extends JpaRepository<Course, Integer> {
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.springframework.samples.petclinic.course;

import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.vet.Vet;

@Getter
@Setter
@Entity
@Table(name = "courses")
public class Course extends BaseEntity {
private String name;
private String description;
// 예: 초급, 중급, 고급
private String difficulty;

@ManyToOne
@JoinColumn(name = "vet_id")
private Vet instructor;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.springframework.samples.petclinic.course;

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.samples.petclinic.course.dto.CreateCourseRequest;
import org.springframework.samples.petclinic.vet.Vet;
import org.springframework.samples.petclinic.vet.VetRepository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/courses")
public class CourseController {
private final CourseService courseService;


@PostMapping()
public ResponseEntity<Integer> createCourse(@RequestBody CreateCourseRequest request) {
System.out.println(request);

Course course = courseService.createCourse(request.getName(), request.getDescription(), request.getDescription(), request.getVetId());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

createCourse 메서드 매개변수 오류가 있습니다.

courseService.createCourse 호출 시 세 번째 매개변수로 request.getDifficulty() 대신 request.getDescription()이 잘못 전달되고 있습니다.

-		Course course = courseService.createCourse(request.getName(), request.getDescription(), request.getDescription(), request.getVetId());
+		Course course = courseService.createCourse(request.getName(), request.getDescription(), request.getDifficulty(), request.getVetId());
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Course course = courseService.createCourse(request.getName(), request.getDescription(), request.getDescription(), request.getVetId());
Course course = courseService.createCourse(request.getName(), request.getDescription(), request.getDifficulty(), request.getVetId());


return ResponseEntity.ok(course.getId());
}
Comment on lines +23 to +29
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Mar 23, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

예외 처리가 없습니다.

현재 메서드에는 예외 처리 로직이 없습니다. 예를 들어, 존재하지 않는 VetId로 인한 오류나 DB 관련 예외를 처리하는 로직이 필요합니다.

 	@PostMapping()
 	public ResponseEntity<Integer> createCourse(@RequestBody CreateCourseRequest request) {
 		System.out.println(request);
 
-		Course course = courseService.createCourse(request.getName(), request.getDescription(), request.getDescription(), request.getVetId());
-
-		return ResponseEntity.ok(course.getId());
+		try {
+			Course course = courseService.createCourse(request.getName(), request.getDescription(), request.getDifficulty(), request.getVetId());
+			return ResponseEntity.ok(course.getId());
+		} catch (Exception e) {
+			log.error("Course creation failed: {}", e.getMessage(), e);
+			return ResponseEntity.badRequest().build();
+		}
 	}

더 나은 해결책은 예외 유형에 따라 적절한 응답을 반환하는 글로벌 예외 핸들러를 구현하는 것입니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public ResponseEntity<Integer> createCourse(@RequestBody CreateCourseRequest request) {
System.out.println(request);
Course course = courseService.createCourse(request.getName(), request.getDescription(), request.getDescription(), request.getVetId());
return ResponseEntity.ok(course.getId());
}
@PostMapping()
public ResponseEntity<Integer> createCourse(@RequestBody CreateCourseRequest request) {
System.out.println(request);
try {
Course course = courseService.createCourse(request.getName(), request.getDescription(), request.getDifficulty(), request.getVetId());
return ResponseEntity.ok(course.getId());
} catch (Exception e) {
log.error("Course creation failed: {}", e.getMessage(), e);
return ResponseEntity.badRequest().build();
}
}

Copy link
Copy Markdown
Collaborator Author

@yakpoong yakpoong Mar 26, 2025

Choose a reason for hiding this comment

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

API 에서 발생하는 에러를 Controller 마다 catch 절로 처리하지 않고, 공통 관심사로 묶어서 처리하고 싶습니다. 어떻게 하면 API 에서 발생하는 예외들을 공통 관심사의 로직으로 처리할 수 있을까요 ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@yakpoong Spring에서는 @RestControllerAdvice@ExceptionHandler를 사용하여 API 예외를 중앙에서 처리할 수 있습니다. 구현 방법을 보여드리겠습니다:

  1. 먼저 커스텀 예외 클래스를 만듭니다:
package org.springframework.samples.petclinic.exception;

import lombok.Getter;

@Getter
public class ResourceNotFoundException extends RuntimeException {
    private final String resourceName;
    private final String fieldName;
    private final Object fieldValue;

    public ResourceNotFoundException(String resourceName, String fieldName, Object fieldValue) {
        super(String.format("%s not found with %s : '%s'", resourceName, fieldName, fieldValue));
        this.resourceName = resourceName;
        this.fieldName = fieldName;
        this.fieldValue = fieldValue;
    }
}
  1. 다른 비즈니스 예외들도 추가합니다:
package org.springframework.samples.petclinic.exception;

public class BadRequestException extends RuntimeException {
    public BadRequestException(String message) {
        super(message);
    }
}
  1. 글로벌 예외 처리기를 구현합니다:
package org.springframework.samples.petclinic.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;

import java.time.LocalDateTime;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleResourceNotFoundException(
            ResourceNotFoundException ex, WebRequest request) {
        log.error("Resource not found exception: {}", ex.getMessage());
        ErrorResponse errorResponse = new ErrorResponse(
            LocalDateTime.now(),
            HttpStatus.NOT_FOUND.value(),
            "Resource Not Found",
            ex.getMessage(),
            request.getDescription(false)
        );
        return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(BadRequestException.class)
    public ResponseEntity<ErrorResponse> handleBadRequestException(
            BadRequestException ex, WebRequest request) {
        log.error("Bad request exception: {}", ex.getMessage());
        ErrorResponse errorResponse = new ErrorResponse(
            LocalDateTime.now(),
            HttpStatus.BAD_REQUEST.value(),
            "Bad Request",
            ex.getMessage(),
            request.getDescription(false)
        );
        return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGlobalException(
            Exception ex, WebRequest request) {
        log.error("Unhandled exception: {}", ex.getMessage(), ex);
        ErrorResponse errorResponse = new ErrorResponse(
            LocalDateTime.now(),
            HttpStatus.INTERNAL_SERVER_ERROR.value(),
            "Internal Server Error",
            ex.getMessage(),
            request.getDescription(false)
        );
        return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
  1. 에러 응답 DTO를 정의합니다:
package org.springframework.samples.petclinic.exception;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.time.LocalDateTime;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class ErrorResponse {
    private LocalDateTime timestamp;
    private int status;
    private String error;
    private String message;
    private String path;
}
  1. 이제 Controller에서는 try-catch 없이 예외를 발생시키면 됩니다:
@PostMapping()
public ResponseEntity<Integer> createCourse(@RequestBody CreateCourseRequest request) {
    // 유효성 검사
    if (request.getName() == null || request.getName().trim().isEmpty()) {
        throw new BadRequestException("Course name cannot be empty");
    }
    
    // 서비스 호출
    Course course = courseService.createCourse(
        request.getName(), 
        request.getDescription(), 
        request.getDifficulty(), 
        request.getVetId()
    );
    
    return ResponseEntity.ok(course.getId());
}
  1. CourseService도 수정합니다:
public Course createCourse(String name, String description, String difficulty, Integer vetId) {
    // vetRepository.findById()가 빈 Optional을 반환할 경우 예외 발생
    Vet vet = vetRepository.findById(vetId)
        .orElseThrow(() -> new ResourceNotFoundException("Vet", "id", vetId));
    
    Course course = new Course();
    course.setName(name);
    course.setDescription(description);
    course.setDifficulty(difficulty);
    course.setInstructor(vet);
    
    return courseRepository.save(course);
}

이 방식을 사용하면 모든 컨트롤러에서 공통적으로 발생하는 예외 처리 로직을 중앙화할 수 있습니다.

Copy link
Copy Markdown
Collaborator Author

@yakpoong yakpoong Mar 26, 2025

Choose a reason for hiding this comment

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

@coderabbitai 예외 처리 로직 중앙화처리는 별도의 Issue를 통해 해결하고 싶습니다. 이슈를 생성해 주세요.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

@yakpoong 예외 처리 로직 중앙화에 대한 Issue를 생성해드렸습니다. Issue에는 다음 내용이 포함되어 있습니다:

  1. 현재 문제점: 컨트롤러마다 개별적으로 예외 처리
  2. 구현 방안: @RestControllerAdvice@ExceptionHandler 활용
  3. 기대 효과: 코드 중복 제거, 일관된 오류 응답 등
  4. PR 코멘트 참조 링크

해당 Issue는 yakpoong님께 할당되었습니다. 추가적인 요구사항이 있으시면 말씀해주세요.


🏁 Script executed:

#!/bin/bash
# Create a GitHub issue for centralized exception handling
gh issue create \
  --title "예외 처리 로직 중앙화 구현" \
  --body "## 개요
현재 API에서 발생하는 예외들이 각 Controller에서 개별적으로 처리되고 있습니다. 이를 공통 관심사로 분리하여 중앙화된 예외 처리 메커니즘을 구현해야 합니다.

## 구현 방안
- `@RestControllerAdvice`와 `@ExceptionHandler`를 사용한 글로벌 예외 처리기 구현
- 비즈니스 로직에 맞는 커스텀 예외 클래스 정의 (예: ResourceNotFoundException, BadRequestException 등)
- 표준화된 에러 응답 DTO 정의
- Controller에서 try-catch 블록 제거 및 명시적 예외 발생 패턴 적용

## 기대 효과
- 코드 중복 제거
- 일관된 에러 응답 포맷
- Controller 코드의 가독성 향상
- 예외 처리 로직 변경 시 유지보수 용이성 증가

## 참조
- PR #1 코멘트: https://github.com/inflearn/spring-petclinic/pull/1#discussion_r2009014022" \
  --assignee "yakpoong" \
  --repo "inflearn/spring-petclinic"

Length of output: 893


@yakpoong 요청하신 대로 예외 처리 로직 중앙화에 대한 이슈를 성공적으로 생성했습니다! 이슈는 다음 링크에서 확인하실 수 있습니다: #2

이슈는 yakpoong님께 할당되었으며, PR #1의 코멘트를 참조 링크로 포함했습니다.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.springframework.samples.petclinic.course;

import lombok.RequiredArgsConstructor;
import org.springframework.samples.petclinic.vet.Vet;
import org.springframework.samples.petclinic.vet.VetRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;


@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class CourseService {
private final CouresRepository courseRepository;
private final VetRepository vetRepository;
Comment on lines +12 to +17
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Repository 이름에 오타가 있습니다.

코드에 CouresRepository라고 되어 있는데, 이는 CourseRepository의 오타로 보입니다. 이로 인해 애플리케이션 시작 시 Bean 주입 오류가 발생할 수 있습니다.

-	private final CouresRepository courseRepository;
+	private final CourseRepository courseRepository;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class CourseService {
private final CouresRepository courseRepository;
private final VetRepository vetRepository;
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class CourseService {
private final CourseRepository courseRepository;
private final VetRepository vetRepository;



@Transactional()
public Course createCourse(String name, String description, String difficulty, Integer vetId) {
Collection<Vet> all = vetRepository.findAll();

all.forEach(course -> {
System.out.println(course.getId());
});

Comment on lines +20 to +27
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

디버깅 코드를 제거하세요.

프로덕션 코드에 System.out.println과 같은 디버깅 코드가 남아있습니다. 또한, 모든 Vet을 조회하는 코드는 실제 기능에 필요하지 않아 보입니다.

람다 표현식에서 파라미터 이름이 course로 되어 있지만, 실제로는 Vet 객체입니다. 이는 코드 가독성을 저하시킵니다.

-	@Transactional()
+	@Transactional
 	public Course createCourse(String name, String description, String difficulty, Integer vetId) {
-		Collection<Vet> all = vetRepository.findAll();
-
-		all.forEach(course -> {
-			System.out.println(course.getId());
-		});
-
 		Vet instructor = vetRepository.findById(vetId)
 			.orElseThrow(() -> new RuntimeException("Vet not found"));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Transactional()
public Course createCourse(String name, String description, String difficulty, Integer vetId) {
Collection<Vet> all = vetRepository.findAll();
all.forEach(course -> {
System.out.println(course.getId());
});
@Transactional
public Course createCourse(String name, String description, String difficulty, Integer vetId) {
Vet instructor = vetRepository.findById(vetId)
.orElseThrow(() -> new RuntimeException("Vet not found"));

Vet instructor = vetRepository.findById(vetId)
.orElseThrow(() -> new RuntimeException("Vet not found"));

Course course = new Course();
course.setName(name);
course.setDescription(description);
course.setDifficulty(difficulty);
course.setInstructor(instructor);
courseRepository.save(course);

return course;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.springframework.samples.petclinic.course.dto;

import lombok.Getter;

@Getter()
public class CreateCourseRequest {
private String name;
private String description;
private String difficulty;
private Integer vetId;

public CreateCourseRequest() {
}

public CreateCourseRequest(String name, String description, String difficulty, Integer vetId) {
this.name = name;
this.description = description;
this.difficulty = difficulty;
this.vetId = vetId;
}

@Override
public String toString() {
return "CreateCourseRequest{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
", difficulty='" + difficulty + '\'' +
", vetId=" + vetId +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.Optional;

/**
* Repository class for <code>Vet</code> domain objects All method names are compliant
Expand All @@ -37,6 +38,13 @@
*/
public interface VetRepository extends Repository<Vet, Integer> {

/**
* Retrieve a <code>Vet</code> from the data store.
* @return a <code>Optional</code> of <code>Vet</code>
*/
@Transactional(readOnly = true)
Optional<Vet> findById(Integer id) throws DataAccessException;

/**
* Retrieve all <code>Vet</code>s from the data store.
* @return a <code>Collection</code> of <code>Vet</code>s
Expand Down
10 changes: 10 additions & 0 deletions src/main/resources/db/h2/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,13 @@ CREATE TABLE visits (
);
ALTER TABLE visits ADD CONSTRAINT fk_visits_pets FOREIGN KEY (pet_id) REFERENCES pets (id);
CREATE INDEX visits_pet_id ON visits (pet_id);

CREATE TABLE courses (
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name VARCHAR(255),
description VARCHAR(1000),
difficulty VARCHAR(255),
vet_id INTEGER
);
Comment on lines +66 to +72
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

🚨🚨🚨 ID 및 FK 컬럼 타입이 팀 컨벤션을 따르지 않습니다.

idvet_id 컬럼 타입이 팀 컨벤션에 따라 'bigint'가 아닌 'INTEGER'로 정의되어 있습니다. 이는 필수 컨벤션이므로 반드시 수정해야 합니다.

 CREATE TABLE courses (
-  id          INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
+  id          BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
   name        VARCHAR(255),
   description VARCHAR(1000),
   difficulty  VARCHAR(255),
-  vet_id      INTEGER
+  vet_id      BIGINT
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
CREATE TABLE courses (
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name VARCHAR(255),
description VARCHAR(1000),
difficulty VARCHAR(255),
vet_id INTEGER
);
CREATE TABLE courses (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name VARCHAR(255),
description VARCHAR(1000),
difficulty VARCHAR(255),
vet_id BIGINT
);

CREATE INDEX courses_vet_id ON courses (vet_id);