Skip to content

feat(user): 사용자 등록/조회 API 구현#1

Open
GaYeongLee0419 wants to merge 2 commits intodevfrom
feat/user
Open

feat(user): 사용자 등록/조회 API 구현#1
GaYeongLee0419 wants to merge 2 commits intodevfrom
feat/user

Conversation

@GaYeongLee0419
Copy link
Owner

📌 작업 내용

  • 사용자 등록/조회 기능 구현
  • User 엔티티 기반으로 CRUD 작업 구성
  • UserRequestDto, UserResponseDto를 활용해 API 응답/요청 명확화

🔍 주요 변경 사항

  • UserController 생성 및 엔드포인트 정의
  • UserService 구현 (등록, 전체 조회, 단일 조회)
  • 응답 객체로 DTO 사용하여 API 안정성 강화

✅ 테스트 결과

  • Postman으로 사용자 등록 및 조회 API 정상 동작 확인
  • Docker MySQL에서 user 테이블 생성 확인됨

📎 기타 참고 사항

  • 추후 로그인 기능을 위한 인증 정보 필드 (password, updatedAt 등) 추가 고려 필요

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Hello @GaYeongLee0419, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

Hello! Gemini or gemini-code-assist here, providing a summary of this pull request. This PR introduces the initial implementation of basic user registration and lookup APIs. It establishes the core components for user management using a standard Spring Boot layered architecture, including a REST controller, service layer, JPA repository, and a User entity. Data transfer objects (UserRequestDto and UserResponseDto) are utilized to clearly define the structure of API requests and responses.

Highlights

  • User API Endpoints: Adds a new UserController (src/main/java/com/remindly/user/controller/UserController.java) defining REST endpoints under /api/users for creating users (POST), fetching all users (GET), and fetching a user by a specific ID (GET /{id}).
  • User Entity Definition: Introduces the User JPA entity (src/main/java/com/remindly/user/domain/User.java) with fields for id, email, name, and createdAt. Includes logic to automatically set the creation timestamp.
  • Service Layer Implementation: Provides the UserServiceImpl (src/main/java/com/remindly/user/service/UserServiceImpl.java) which contains the business logic for creating a user, retrieving all users, and retrieving a user by ID, interacting with the repository.
  • Data Transfer Objects (DTOs): Defines UserRequestDto (src/main/java/com/remindly/user/dto/UserRequestDto.java) for incoming user creation data and UserResponseDto (src/main/java/com/remindly/user/dto/UserResponseDto.java) for outgoing user data, enhancing API contract clarity.
  • JPA Repository Setup: Creates the UserRepository interface (src/main/java/com/remindly/user/respository/UserRepository.java) extending JpaRepository for standard database operations on the User entity, and adds a custom method existsByEmail.

Changelog

Click here to see the changelog
  • src/main/java/com/remindly/user/controller/UserController.java
    • New file added.
    • Introduces @RestController for /api/users.
    • Defines createUser (POST), getAllUsers (GET), and getUserById (GET /{id}) endpoints.
    • Uses UserRequestDto for POST body and returns UserResponseDto.
  • src/main/java/com/remindly/user/domain/User.java
    • New file added.
    • Defines the User JPA @Entity.
    • Includes id, email, name, and createdAt fields.
    • Uses Lombok for boilerplate code (@Getter, @NoArgsConstructor, @AllArgsConstructor, @Builder).
    • Adds @PrePersist method to set createdAt.
  • src/main/java/com/remindly/user/dto/UserRequestDto.java
    • New file added.
    • Defines UserRequestDto with email and name fields.
    • Uses Lombok @Getter and @NoArgsConstructor.
  • src/main/java/com/remindly/user/dto/UserResponseDto.java
    • New file added.
    • Defines UserResponseDto with id, name, and email fields.
    • Includes a constructor to map from a User entity.
  • src/main/java/com/remindly/user/respository/UserRepository.java
    • New file added.
    • Defines UserRepository interface extending JpaRepository<User, Long>.
    • Adds a custom query method existsByEmail(String email).
  • src/main/java/com/remindly/user/service/UserServiceImpl.java
    • New file added.
    • Implements the UserService interface (interface not shown in diff, but implied).
    • Contains createUser, findAllUsers, and findById methods.
    • Uses UserRepository for data access.
    • Maps between User entities and DTOs.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces foundational CRUD functionalities for user management, including user creation and retrieval. The use of DTOs for request/response handling and a clear separation of concerns between controller, service, and repository layers are good practices.

I've identified a few areas for improvement, primarily concerning API response codes, input validation, data integrity, and adherence to common Java/Spring conventions. Addressing these will enhance the robustness and maintainability of the API.

No specific style guide was provided, so my feedback is based on common Java and Spring Boot best practices, such as those implicitly suggested by the Spring framework itself and widely adopted conventions like the Google Java Style Guide where applicable (e.g., naming, general structure).

Summary of Findings

  • API HTTP Status Codes: The createUser endpoint returns HTTP 200 OK instead of the more appropriate HTTP 201 Created. Also, getUserById might return HTTP 500 for non-existent users instead of HTTP 404 Not Found.
  • Input Validation: UserRequestDto lacks input validation annotations (e.g., @NotBlank, @Email).
  • Data Integrity: The createUser service method does not check for pre-existing emails, potentially leading to errors or duplicate data.
  • Package Naming Convention: There's a typo in the package name com.remindly.user.respository (should be repository).
  • Transaction Management: The createUser service method is missing the @Transactional annotation.
  • Testing: The PR description mentions manual testing, but no automated unit or integration tests are included in the changes. Adding these would improve long-term maintainability and reliability. (Not commented due to review settings)
  • File Formatting: Some files are missing a newline character at the end of the file (User.java, UserRequestDto.java, UserRepository.java). UserServiceImpl.java has an extra trailing newline. These are minor stylistic points. (Not commented due to review settings)

Merge Readiness

The pull request lays a good foundation for user management. However, there are several high and medium severity issues identified, particularly around API correctness (HTTP status codes, error handling), data integrity (email uniqueness check), and standard practices (input validation, transaction management, package naming).

I recommend addressing these issues before merging to ensure a more robust, maintainable, and conventional API. As I am an AI assistant, I am not authorized to approve pull requests; please ensure further review and approval by team members once the suggested changes are made.

Comment on lines +32 to +33
public ResponseEntity<UserResponseDto> getUserById(@PathVariable Long id) {
return ResponseEntity.ok(userService.findById(id));

Choose a reason for hiding this comment

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

high

When userService.findById(id) throws an IllegalArgumentException (e.g., if the user is not found), this will likely result in a generic 500 Internal Server Error response. For a 'resource not found' scenario, an HTTP 404 Not Found status code is more appropriate.

Consider adding an @ExceptionHandler method within this controller or a global @ControllerAdvice to handle IllegalArgumentException (or a more specific custom exception like UserNotFoundException) and return a ResponseEntity with a 404 status. How do you feel about implementing a more specific exception handling mechanism here?

Comment on lines +19 to +27
public UserResponseDto createUser(UserRequestDto requestDto) {
User user = User.builder()
.name(requestDto.getName())
.email(requestDto.getEmail())
.build();

User savedUser = userRepository.save(user);
return new UserResponseDto(savedUser);
}

Choose a reason for hiding this comment

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

high

The createUser method currently doesn't check if a user with the given email already exists before attempting to save. This could lead to DataIntegrityViolationException if the email column has a unique constraint in the database, or duplicate user entries if not.
It's good practice to check for existence first using the userRepository.existsByEmail() method.

Additionally, service methods performing write operations should typically be annotated with @Transactional to ensure atomicity.

How about we add an email existence check and the @Transactional annotation?

    @Override
    @org.springframework.transaction.annotation.Transactional // Add import if not present
    public UserResponseDto createUser(UserRequestDto requestDto) {
        if (userRepository.existsByEmail(requestDto.getEmail())) {
            throw new IllegalArgumentException("Email already in use: " + requestDto.getEmail()); // Or a custom exception
        }

        User user = User.builder()
                .name(requestDto.getName())
                .email(requestDto.getEmail())
                .build();

        User savedUser = userRepository.save(user);
        return new UserResponseDto(savedUser);
    }

Comment on lines +21 to +23
public ResponseEntity<UserResponseDto> createUser(@RequestBody UserRequestDto requestDto) {
UserResponseDto createdUser = userService.createUser(requestDto);
return ResponseEntity.ok(createdUser);

Choose a reason for hiding this comment

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

medium

For resource creation, it's a common REST best practice to return an HTTP 201 Created status code instead of 200 OK. Additionally, the response should ideally include a Location header pointing to the URI of the newly created resource.

Could we change this to return ResponseEntity.created()? You'll need to construct a URI for the new resource.

        UserResponseDto createdUser = userService.createUser(requestDto);
        // Assuming the new user's ID is accessible via createdUser.getId()
        // and your GET endpoint for a single user is /api/users/{id}
        java.net.URI location = java.net.URI.create(String.format("/api/users/%d", createdUser.getId()));
        return ResponseEntity.created(location).body(createdUser);

Comment on lines +8 to +10
public class UserRequestDto {
private String email;
private String name;

Choose a reason for hiding this comment

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

medium

The fields email and name in the request DTO currently lack validation. It's good practice to validate incoming data at the controller level using annotations like @NotBlank, @Email, @Size, etc., from jakarta.validation.constraints. This helps ensure data integrity before it reaches the service layer.

Could we add validation annotations here? For example:

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
// ...
public class UserRequestDto {
    @NotBlank(message = "Email cannot be blank")
    @Email(message = "Email should be valid")
    private String email;

    @NotBlank(message = "Name cannot be blank")
    private String name;
}

Remember to also add @Valid to the @RequestBody parameter in UserController#createUser.

@@ -0,0 +1,8 @@
package com.remindly.user.respository;

Choose a reason for hiding this comment

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

medium

There seems to be a typo in the package name: com.remindly.user.respository should likely be com.remindly.user.repository.

Correcting this would improve consistency and adhere to common naming conventions. Would you be able to update the package name and all relevant import statements?

Suggested change
package com.remindly.user.respository;
package com.remindly.user.repository;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants