Skip to content
Merged
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
5 changes: 0 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ jobs:
java-version: "17"
cache: gradle

- name: Copy application.yml into runner
run: |
mkdir -p src/main/resources
echo "${{ secrets.APPLICATION_YML }}" > src/main/resources/application.yml

- name: Build + Test(Gradle)
if: ${{ hashFiles('**/build.gradle*') != '' }}
run: |
Expand Down
49 changes: 0 additions & 49 deletions .github/workflows/pr_upload_notify.yml

This file was deleted.

12 changes: 6 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

//security
implementation 'org.springframework.boot:spring-boot-starter-security'
Expand All @@ -45,24 +46,23 @@ dependencies {
// database
runtimeOnly 'com.mysql:mysql-connector-j'

// redis
implementation('org.springframework.boot:spring-boot-starter-data-redis')

// swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.13'

// OAuth
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

// aws secrets manager
implementation 'io.awspring.cloud:spring-cloud-aws-starter-secrets-manager:3.1.0'

// test
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'com.h2database:h2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

//lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
// sms
implementation 'com.solapi:sdk:1.0.3'
}

tasks.named('test') {
Expand Down
32 changes: 0 additions & 32 deletions db-compose.yml

This file was deleted.

11 changes: 11 additions & 0 deletions docker/docker-compose.common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ services:
networks:
- tinybite-network

redis:
container_name: redis
image: redis:7.2.4
ports:
- "6379:6379"
volumes:
- redis_data:/data
Comment on lines +19 to +22
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸ  Major

Redis ํฌํŠธ๊ฐ€ ์™ธ๋ถ€์— ๋…ธ์ถœ๋˜์–ด ์žˆ๊ณ  ์ธ์ฆ์ด ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

6379:6379๋กœ ํ˜ธ์ŠคํŠธ์— ํฌํŠธ๊ฐ€ ๋ฐ”์ธ๋”ฉ๋˜์–ด ์™ธ๋ถ€์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋ณด์•ˆ์ƒ ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ถŒ์žฅ ์กฐ์น˜:

  1. ๋‚ด๋ถ€ ๋„คํŠธ์›Œํฌ์—์„œ๋งŒ ์ ‘๊ทผํ•˜๋„๋ก ํฌํŠธ ๋…ธ์ถœ ์ œ๊ฑฐ ๋˜๋Š” localhost ๋ฐ”์ธ๋”ฉ
  2. Redis ๋น„๋ฐ€๋ฒˆํ˜ธ ์„ค์ • ์ถ”๊ฐ€
   redis:
     container_name: redis
     image: redis:7.2.4
-    ports:
-      - "6379:6379"
+    # ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ์—์„œ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋„๋ก ports ๋…ธ์ถœ ์ œ๊ฑฐ
+    # ๋˜๋Š” ๋กœ์ปฌ ์ ‘๊ทผ๋งŒ ํ—ˆ์šฉ: "127.0.0.1:6379:6379"
+    command: redis-server --requirepass ${REDIS_PASSWORD}
     volumes:
       - redis_data:/data

Committable suggestion skipped: line range outside the PR's diff.

๐Ÿค– Prompt for AI Agents
In docker/docker-compose.common.yml around lines 19โ€“22 the Redis service exposes
port 6379 to the host (ports: "6379:6379") and has no authentication configured;
remove the host binding or bind it to localhost to prevent external access
(e.g., remove the ports stanza or change to 127.0.0.1:6379:6379) and add a Redis
password by supplying an environment variable or mounting a redis.conf that sets
requirepass/ACLs (e.g., set REDIS_PASSWORD and ensure the container starts Redis
with that config or pass the --requirepass flag); alternatively, restrict access
by placing Redis on an internal Docker network with no published ports and
configure services that need Redis to connect via that internal network.

restart: always
networks:
- tinybite-network

certbot:
container_name: certbot
image: certbot/certbot
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ita.tinybite.domain.auth.service;

import ita.tinybite.domain.user.entity.User;
import ita.tinybite.domain.user.repository.UserRepository;
import ita.tinybite.global.exception.BusinessException;
import ita.tinybite.global.exception.errorcode.UserErrorCode;
import ita.tinybite.global.exception.errorcode.CommonErrorCode;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

@Component
public class SecurityProvider {

private final UserRepository userRepository;

public SecurityProvider(UserRepository userRepository) {
this.userRepository = userRepository;
}

public User getCurrentUser() {
return getUserFromContext();
}

private User getUserFromContext() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication instanceof UsernamePasswordAuthenticationToken auth)) {
throw BusinessException.of(CommonErrorCode.UNAUTHORIZED);
}

Long userId = (Long) auth.getPrincipal();
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐Ÿ”ด Critical

์•ˆ์ „ํ•˜์ง€ ์•Š์€ ํƒ€์ž… ์บ์ŠคํŒ…์ด ์žˆ์Šต๋‹ˆ๋‹ค.

auth.getPrincipal()์„ ๊ฒ€์ฆ ์—†์ด Long์œผ๋กœ ์บ์ŠคํŒ…ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Principal์ด Long ํƒ€์ž…์ด ์•„๋‹Œ ๊ฒฝ์šฐ ClassCastException์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํƒ€์ž… ๊ฒ€์ฆ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”:

-        Long userId = (Long) auth.getPrincipal();
+        if (!(auth.getPrincipal() instanceof Long userId)) {
+            throw BusinessException.of(CommonErrorCode.UNAUTHORIZED);
+        }
         return userRepository.findById(userId).orElseThrow(() -> BusinessException.of(UserErrorCode.USER_NOT_EXISTS));
๐Ÿ“ 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
Long userId = (Long) auth.getPrincipal();
Object principal = auth.getPrincipal();
if (!(principal instanceof Long userId)) {
throw BusinessException.of(CommonErrorCode.UNAUTHORIZED);
}
return userRepository.findById(userId).orElseThrow(() -> BusinessException.of(UserErrorCode.USER_NOT_EXISTS));
๐Ÿค– Prompt for AI Agents
In src/main/java/ita/tinybite/domain/auth/service/SecurityProvider.java around
line 32, the code unsafely casts auth.getPrincipal() to Long which can throw
ClassCastException; replace the direct cast with an explicit type check: if
auth.getPrincipal() is an instance of Long, assign it; else if it is a String
attempt to parse it to Long with NumberFormatException handling; otherwise fail
fast by throwing a clear Authentication/IllegalState exception (or return a safe
default) so the code never relies on an unchecked cast.

return userRepository.findById(userId).orElseThrow(() -> BusinessException.of(UserErrorCode.USER_NOT_EXISTS));
}
}

This file was deleted.

4 changes: 0 additions & 4 deletions src/main/java/ita/tinybite/domain/user/constant/Location.java

This file was deleted.

5 changes: 0 additions & 5 deletions src/main/java/ita/tinybite/domain/user/constant/Target.java

This file was deleted.

5 changes: 0 additions & 5 deletions src/main/java/ita/tinybite/domain/user/constant/Work.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package ita.tinybite.domain.user.controller;

import ita.tinybite.domain.user.dto.req.UpdateUserReqDto;
import ita.tinybite.domain.user.service.UserService;
import ita.tinybite.global.response.APIResponse;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;

import static ita.tinybite.global.response.APIResponse.success;

@RestController
@RequestMapping("/api/v1/user/me")
public class UserController {

private final UserService userService;

public UserController(UserService userService) {
this.userService = userService;
}

@GetMapping
public APIResponse<?> getUser() {
return success(userService.getUser());
}

@PatchMapping
public APIResponse<?> updateUser(@Valid @RequestBody UpdateUserReqDto req) {
userService.updateUser(req);
return success();
}

@PatchMapping("/location")
public APIResponse<?> updateLocation(@RequestParam(defaultValue = "37.3623504988728") String latitude,
@RequestParam(defaultValue = "127.117057453619") String longitude) {
userService.updateLocation(latitude, longitude);
return success();
}

@DeleteMapping
public APIResponse<?> deleteUser() {
userService.deleteUser();
return success();
}
Comment on lines +39 to +43
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸ  Major

๐Ÿงฉ Analysis chain

๐Ÿ Script executed:

find . -name "*.java" -type f | grep -E "(User|user)" | head -20

Repository: tinybite-2025/tinybite-server

Length of output: 815


๐Ÿ Script executed:

cat -n ./src/main/java/ita/tinybite/domain/user/entity/User.java

Repository: tinybite-2025/tinybite-server

Length of output: 1669


๐Ÿ Script executed:

cat -n ./src/main/java/ita/tinybite/domain/user/service/UserService.java

Repository: tinybite-2025/tinybite-server

Length of output: 1944


๐Ÿ Script executed:

cat -n ./src/main/java/ita/tinybite/domain/user/constant/UserStatus.java

Repository: tinybite-2025/tinybite-server

Length of output: 209


๐Ÿ Script executed:

cat -n ./src/main/java/ita/tinybite/domain/user/controller/UserController.java

Repository: tinybite-2025/tinybite-server

Length of output: 1657


๐Ÿ Script executed:

cd ./src/main/java && find . -name "*.java" -type f -exec grep -l "@ManyToOne.*User\|@OneToMany.*User" {} \;

Repository: tinybite-2025/tinybite-server

Length of output: 55


๐Ÿ Script executed:

rg "@Entity" --type java -A 20 | head -100

Repository: tinybite-2025/tinybite-server

Length of output: 4308


๐Ÿ Script executed:

rg "private.*User" --type java -B 3 | grep -E "@Entity|@ManyToOne|private.*User"

Repository: tinybite-2025/tinybite-server

Length of output: 1269


๐Ÿ Script executed:

find ./src -name "*.java" -path "*/entity/*" -type f

Repository: tinybite-2025/tinybite-server

Length of output: 325


๐Ÿ Script executed:

cat -n ./src/main/java/ita/tinybite/domain/auth/entity/RefreshToken.java

Repository: tinybite-2025/tinybite-server

Length of output: 1110


๐Ÿ Script executed:

cat -n ./src/main/java/ita/tinybite/domain/auth/entity/JwtTokenProvider.java

Repository: tinybite-2025/tinybite-server

Length of output: 3768


๐Ÿ Script executed:

rg "deleteUser\|delete.*User" --type java -B 2 -A 2

Repository: tinybite-2025/tinybite-server

Length of output: 55


๊ณ„์ • ์‚ญ์ œ ์ž‘์—…์— ์•ˆ์ „์žฅ์น˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ ๊ตฌํ˜„์€ ๋‹จ์ˆœ hard delete๋กœ ์ฆ‰์‹œ ์‚ญ์ œ๋˜๋ฉฐ, ๋ณต๊ตฌ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ ์†์‹ค ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์‚ฌํ•ญ๋“ค์„ ๊ฐœ์„ ํ•˜์„ธ์š”:

  1. ์†Œํ”„ํŠธ ์‚ญ์ œ ๊ตฌํ˜„: UserStatus.WITHDRAW๊ฐ€ ์ด๋ฏธ ์ •์˜๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ, delete() ๋Œ€์‹  ์‚ฌ์šฉ์ž ์ƒํƒœ๋ฅผ WITHDRAW๋กœ ๋ณ€๊ฒฝํ•˜๋„๋ก ์ˆ˜์ •
  2. ์žฌ์ธ์ฆ ์š”๊ตฌ: ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌํ™•์ธ ๋“ฑ ์ถ”๊ฐ€ ์ธ์ฆ ๋‹จ๊ณ„ ์ถ”๊ฐ€ ํ•„์š”
  3. ์‚ญ์ œ ์ „ ํ™•์ธ: ์š”์ฒญ ๋ณธ๋ฌธ์—์„œ ์‚ฌ์šฉ์ž ํ™•์ธ (์˜ˆ: ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ) ํ•„์ˆ˜
  4. RefreshToken ์ •๋ฆฌ: user_id ์™ธ๋ž˜ ํ‚ค๋กœ ์ธํ•œ orphan ๋ฐ์ดํ„ฐ ๋ฐœ์ƒ - ์‚ญ์ œ ์‹œ ์—ฐ๊ด€ RefreshToken๋„ ํ•จ๊ป˜ ์ •๋ฆฌ
  5. ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ: @transactional ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ ๋ณด์žฅ

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package ita.tinybite.domain.user.dto.req;

public record UpdateUserReqDto(
String nickname
) {
}
14 changes: 14 additions & 0 deletions src/main/java/ita/tinybite/domain/user/dto/res/UserResDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ita.tinybite.domain.user.dto.res;

import ita.tinybite.domain.user.entity.User;

public record UserResDto(
Long userId,
String name,
String location
) {

public static UserResDto of(User user) {
return new UserResDto(user.getUserId(), user.getNickname(), user.getLocation());
}
}
11 changes: 10 additions & 1 deletion src/main/java/ita/tinybite/domain/user/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import ita.tinybite.domain.user.constant.LoginType;
import ita.tinybite.domain.user.constant.UserStatus;
import ita.tinybite.domain.user.dto.req.UpdateUserReqDto;
import ita.tinybite.global.entity.BaseEntity;

import jakarta.persistence.*;
Expand All @@ -21,7 +22,7 @@ public class User extends BaseEntity {
@Comment("uid")
private Long userId;

@Column(nullable = false, length = 50)
@Column(nullable = false, length = 50, unique = true)
private String email;

@Column(length = 50)
Expand All @@ -40,4 +41,12 @@ public class User extends BaseEntity {

@Column(nullable = false, length = 100)
private String location;

public void update(UpdateUserReqDto req) {
this.nickname = req.nickname();
}

public void updateLocation(String location) {
this.location = location;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

import ita.tinybite.domain.user.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

Optional<User> findByEmail(String email);

boolean existsByNickname(String nickname);
}

User getUserByUserId(Long userId);
}
46 changes: 46 additions & 0 deletions src/main/java/ita/tinybite/domain/user/service/UserService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package ita.tinybite.domain.user.service;

import ita.tinybite.domain.auth.service.SecurityProvider;
import ita.tinybite.domain.user.dto.req.UpdateUserReqDto;
import ita.tinybite.domain.user.dto.res.UserResDto;
import ita.tinybite.domain.user.entity.User;
import ita.tinybite.domain.user.repository.UserRepository;
import ita.tinybite.global.location.LocationService;
import org.springframework.stereotype.Service;

@Service
public class UserService {

private final SecurityProvider securityProvider;
private final UserRepository userRepository;
private final LocationService locationService;

public UserService(SecurityProvider securityProvider,
UserRepository userRepository,
LocationService locationService) {
this.securityProvider = securityProvider;
this.userRepository = userRepository;
this.locationService = locationService;
}

public UserResDto getUser() {
User user = securityProvider.getCurrentUser();
return UserResDto.of(user);
}

public void updateUser(UpdateUserReqDto req) {
User user = securityProvider.getCurrentUser();
user.update(req);
}
Comment on lines +31 to +34
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐Ÿ”ด Critical

ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

user.update(req) ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์ง€๋งŒ ๋ช…์‹œ์ ์ธ save() ํ˜ธ์ถœ์ด๋‚˜ @Transactional ์–ด๋…ธํ…Œ์ด์…˜์ด ์—†์Šต๋‹ˆ๋‹ค. JPA์˜ dirty checking์ด ๋™์ž‘ํ•˜๋ ค๋ฉด ๋ฉ”์„œ๋“œ๊ฐ€ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์‹คํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ์ƒํƒœ์—์„œ๋Š” ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ˜์˜๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ž˜์Šค ๋˜๋Š” ๋ฉ”์„œ๋“œ์— @Transactional ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”:

+import org.springframework.transaction.annotation.Transactional;
+
 @Service
+@Transactional(readOnly = true)
 public class UserService {
 
     // ... ์ƒ์„ฑ์ž ...
 
+    @Transactional(readOnly = true)
     public UserResDto getUser() {
         User user = securityProvider.getCurrentUser();
         return UserResDto.of(user);
     }
 
+    @Transactional
     public void updateUser(UpdateUserReqDto req) {
         User user = securityProvider.getCurrentUser();
         user.update(req);
     }

Committable suggestion skipped: line range outside the PR's diff.

๐Ÿค– Prompt for AI Agents
In src/main/java/ita/tinybite/domain/user/service/UserService.java around lines
31 to 34, the updateUser method calls user.update(req) but lacks transaction
management so JPA dirty checking may not flush changes; add transaction
boundaries by annotating the method (or the service class) with @Transactional
(from org.springframework.transaction.annotation) or explicitly invoke the
repository save() after modifying the entity to ensure changes are persisted;
ensure the service is a Spring-managed bean and import the annotation.


public void updateLocation(String latitude, String longitude) {
User user = securityProvider.getCurrentUser();
String location = locationService.getLocation(latitude, longitude);
user.updateLocation(location);
}
Comment on lines +36 to +40
Copy link

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐Ÿ”ด Critical

ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

user.updateLocation(location) ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์ง€๋งŒ ๋ช…์‹œ์ ์ธ save() ํ˜ธ์ถœ์ด๋‚˜ @Transactional ์–ด๋…ธํ…Œ์ด์…˜์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ˜์˜๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฉ”์„œ๋“œ์— @Transactional ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”:

+    @Transactional
     public void updateLocation(String latitude, String longitude) {
         User user = securityProvider.getCurrentUser();
         String location = locationService.getLocation(latitude, longitude);
         user.updateLocation(location);
     }
๐Ÿค– Prompt for AI Agents
In src/main/java/ita/tinybite/domain/user/service/UserService.java around lines
36 to 40, the updateLocation method mutates the current user's state but lacks
transaction management so changes may not be persisted; add Spring's
@Transactional annotation to the method (or the class) to ensure the persistence
context is flushed and changes are saved, and import
org.springframework.transaction.annotation.Transactional (ensure the service is
a Spring-managed bean and do not set readOnly=true).


public void deleteUser() {
userRepository.delete(securityProvider.getCurrentUser());
}
Comment on lines +42 to +44
Copy link

Choose a reason for hiding this comment

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

๐Ÿ› ๏ธ Refactor suggestion | ๐ŸŸ  Major

์‚ญ์ œ ์ž‘์—…์—๋„ ํŠธ๋žœ์žญ์…˜์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ช…์‹œ์ ์ธ @Transactional ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜์—ฌ ํŠธ๋žœ์žญ์…˜ ๊ฒฝ๊ณ„๋ฅผ ๋ช…ํ™•ํžˆ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

+    @Transactional
     public void deleteUser() {
         userRepository.delete(securityProvider.getCurrentUser());
     }
๐Ÿค– Prompt for AI Agents
In src/main/java/ita/tinybite/domain/user/service/UserService.java around lines
42 to 44, the deleteUser method performs a repository delete without a
transactional boundary; add an explicit transaction by annotating the method
with @Transactional (importing
org.springframework.transaction.annotation.Transactional if not present) so the
delete executes within a transaction and rollbacks are possible on failure.


}
Loading