Repository: Kkrap-team/Backend
Pull request #27: [refactor] 카카오 로그인 AuthController로 변경, 각 URL /v2 삭제
Author: login: whitecy01
Labels: name: refactor
description: 코드 리팩토링 (기능 변경 없음)
Created: 2025-04-08T09:20:45Z | Merged: 2025-04-16T02:15:09Z

카카오 로그인 AuthController 변경하였고 v2 URL 다 삭제해놓았습니다


Diff:
diff --git a/src/main/java/com/Kkrap/Controller/AuthController.java b/src/main/java/com/Kkrap/Controller/AuthController.java
new file mode 100644
index 0000000..2781360
--- /dev/null
+++ b/src/main/java/com/Kkrap/Controller/AuthController.java
@@ -0,0 +1,24 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.Service.AuthService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    AuthService authService;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        return authService.kakaoLogin(request);
+    }
+}
diff --git a/src/main/java/com/Kkrap/Controller/FoldersController.java b/src/main/java/com/Kkrap/Controller/FoldersController.java
index 0dd4707..2f0e454 100644
--- a/src/main/java/com/Kkrap/Controller/FoldersController.java
+++ b/src/main/java/com/Kkrap/Controller/FoldersController.java
@@ -3,8 +3,8 @@
 import com.Kkrap.RequestDTO.FoldersCreateRequest;
 
 import com.Kkrap.RequestDTO.FoldersDeleteRequest;
+import com.Kkrap.ResponseDto.FoldersResponse;
 import com.Kkrap.ResponseDto.FoldersLinksAllResponse;
-import com.Kkrap.ResponseDto.MessageResponse;
 import com.Kkrap.Service.FoldersService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
@@ -15,7 +15,7 @@
 
 @Controller
 @RestController
-@RequestMapping("/v2/folders")
+@RequestMapping("/folders")
 public class FoldersController {
     @Autowired
     private FoldersService foldersService;
@@ -29,14 +29,14 @@ public ResponseEntity<List<FoldersLinksAllResponse>> getFoldersAll(@PathVariable
 
 //    //Create
 //    //1. 폴더를 만드는 api
-    @PostMapping("/{userId}/create")
-    public ResponseEntity<Object> CreateFolder(@PathVariable("userId") Long userId, @RequestBody FoldersCreateRequest foldersCreateRequest) {
+    @PostMapping("/{userId}")
+    public ResponseEntity<FoldersResponse> CreateFolder(@PathVariable("userId") Long userId, @RequestBody FoldersCreateRequest foldersCreateRequest) {
         return foldersService.CreateFolder(userId, foldersCreateRequest);
     }
 
     //Delete
-    @PostMapping("/{userId}/delete")
-    public ResponseEntity<Object> DeleteFolder(@PathVariable("userId") Long userId, @RequestBody FoldersDeleteRequest foldersDeleteRequest)
+    @DeleteMapping("/{userId}")
+    public ResponseEntity<FoldersResponse> DeleteFolder(@PathVariable("userId") Long userId, @RequestBody FoldersDeleteRequest foldersDeleteRequest)
     {
         return foldersService.DeleteFolder(userId, foldersDeleteRequest);
     }
diff --git a/src/main/java/com/Kkrap/Controller/LinksController.java b/src/main/java/com/Kkrap/Controller/LinksController.java
index 5a95d9c..3f673c0 100644
--- a/src/main/java/com/Kkrap/Controller/LinksController.java
+++ b/src/main/java/com/Kkrap/Controller/LinksController.java
@@ -8,7 +8,7 @@
 import org.springframework.web.bind.annotation.*;
 
 @RestController
-@RequestMapping("/v2/links")
+@RequestMapping("/links")
 public class LinksController {
     @Autowired
     private LinksService linksService;
@@ -20,7 +20,7 @@ public class LinksController {
 
     //Create
     //링크 저장
-    @PostMapping("/{userId}/create")
+    @PostMapping("/{userId}")
     @ResponseBody
     public ResponseEntity<Object> createLink(@PathVariable("userId") Long userId, @RequestBody LinksCreateRequest linksCreateRequest){
         return linksService.CreateLink(userId, linksCreateRequest);
@@ -28,7 +28,7 @@ public ResponseEntity<Object> createLink(@PathVariable("userId") Long userId, @R
 
     //Delete
     //링크 삭제
-    @DeleteMapping("/{userId}/delete")
+    @DeleteMapping("/{userId}")
     public ResponseEntity<Object> deleteLink(@PathVariable("userId") Long userId, @RequestBody LinksDeleteRequest linksDeleteRequest){
         return linksService.DeleteLink(userId, linksDeleteRequest);
     }
diff --git a/src/main/java/com/Kkrap/Controller/UsersController.java b/src/main/java/com/Kkrap/Controller/UsersController.java
index d836551..624a2ca 100644
--- a/src/main/java/com/Kkrap/Controller/UsersController.java
+++ b/src/main/java/com/Kkrap/Controller/UsersController.java
@@ -1,26 +1,17 @@
 package com.Kkrap.Controller;
 
-import com.Kkrap.Entity.Folders;
-import com.Kkrap.Entity.Users;
 import com.Kkrap.Repository.FoldersRepository;
 import com.Kkrap.Repository.UsersRepository;
-import com.Kkrap.RequestDTO.KaKaoTokenRequest;
 import com.Kkrap.RequestDTO.NicknameRequest;
-import com.Kkrap.ResponseDto.MessageResponse;
-import com.Kkrap.ResponseDto.UserProfileResponse;
+import com.Kkrap.ResponseDto.UsersProfileResponse;
 import com.Kkrap.Service.UsersService;
-import org.apache.coyote.Response;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.*;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.*;
-import org.springframework.web.client.RestTemplate;
-
-import java.util.Map;
-import java.util.Optional;
 
 @Controller
-@RequestMapping("/v2/users")
+@RequestMapping("/users")
 public class UsersController {
     @Autowired
     UsersService usersService;
@@ -39,95 +30,17 @@ public String login(){
     //users 프로필 조회
     @GetMapping("/{userId}")
     @ResponseBody
-    public ResponseEntity<UserProfileResponse> getUserProfile(@PathVariable("userId") Long userId)
+    public ResponseEntity<UsersProfileResponse> getUserProfile(@PathVariable("userId") Long userId)
     {
-        UserProfileResponse userProfile = usersService.getUserProfile(userId);
-        if (userProfile != null) {
-            return ResponseEntity.ok(userProfile);
-        } else {
-            return ResponseEntity.status(HttpStatus.NOT_FOUND)
-                    .body(null);
-        }
+        return usersService.getUserProfile(userId);
     }
 
     //닉네임 변경
     @PostMapping("/{userId}/nickname")
     @ResponseBody
-    public ResponseEntity<MessageResponse> updateNickname(@PathVariable("userId") Long userId, @RequestBody NicknameRequest request)
+    public ResponseEntity<UsersProfileResponse> updateNickname(@PathVariable("userId") Long userId, @RequestBody NicknameRequest request)
     {
-
-        boolean updated = usersService.updateNickName(userId, request.getNickname());
-        if (updated) {
-            MessageResponse message = new MessageResponse(404,"닉네임 변경 완료");
-            return ResponseEntity.ok(message);
-        } else {
-            return ResponseEntity.status(HttpStatus.NOT_FOUND)
-                    .body(new MessageResponse(404,"해당 ID의 사용자를 찾을 수 없습니다."));
-        }
-    }
-
-    //토큰 관리 방식
-    @PostMapping("/api/auth/kakao-login")
-    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
-        String accessToken = request.getAccesstoken();
-
-
-
-        //1. 카카오 유저 정보 요청
-        HttpHeaders headers = new HttpHeaders();
-        headers.setBearerAuth(accessToken);
-        HttpEntity<?> entity = new HttpEntity<>(headers);
-
-        ResponseEntity<Map> response = new RestTemplate().exchange(
-                "https://kapi.kakao.com/v2/user/me",
-                HttpMethod.GET,
-                entity,
-                Map.class
-        );
-
-
-        Map<String, Object> userInfo = response.getBody();
-        Long kakaoId = Long.valueOf(userInfo.get("id").toString());
-        Map<String, Object> kakaoAccount = (Map<String, Object>) userInfo.get("kakao_account");
-        Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
-
-        String email = kakaoAccount.get("email").toString();
-        String nickname = profile.get("nickname").toString();
-        String profileImage = profile.get("profile_image_url").toString();
-
-//        Users user = usersRepository.findByKaKaoId(kakaoId).orElseGet(() -> {
-//            Users newUser = new Users(email, nickname, profileImage, kakaoId);
-//            usersRepository.save(newUser);
-//            return newUser;
-//        });
-        String userId;
-        Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kakaoId));
-        System.out.println("CheckUser : " + CheckUser);
-        if (CheckUser.isEmpty()){
-            Users newUser = new Users(email, nickname, profileImage, Long.valueOf(kakaoId));
-            usersRepository.save(newUser);
-
-            // 처음 로그인 한 사람은 모든 링크 보기 폴더가 없음 만들어주어야함
-            Folders folder = new Folders(newUser, "모든 링크", "모든 링크가 저장된 폴더입니다.", false);
-            foldersRepository.save(folder);
-
-            UserProfileResponse userProfileResponse = new UserProfileResponse(newUser.getUserId(), newUser.getEmail(), newUser.getNickname(), newUser.getProfile(), newUser.getKakaoId());
-            return ResponseEntity.ok(userProfileResponse);
-        }
-        else
-        {
-            Users existingUser = CheckUser.get();
-            UserProfileResponse userProfileResponse = new UserProfileResponse(existingUser.getUserId(), existingUser.getEmail(), existingUser.getNickname(), existingUser.getProfile(), existingUser.getKakaoId());
-            return ResponseEntity.ok(userProfileResponse);
-        }
-
-
-//        return ResponseEntity.ok(Map.of(
-//                "userId", user.getUserId(),
-//                "nickname", user.getNickname(),
-//                "email", user.getEmail(),
-//                "profile", user.getProfile()
-//        ));
+        return usersService.updateNickName(userId, request.getNickname());
     }
 
 }
diff --git a/src/main/java/com/Kkrap/Entity/Folders.java b/src/main/java/com/Kkrap/Entity/Folders.java
index d162133..ce4eb7c 100644
--- a/src/main/java/com/Kkrap/Entity/Folders.java
+++ b/src/main/java/com/Kkrap/Entity/Folders.java
@@ -1,21 +1,18 @@
 package com.Kkrap.Entity;
 
+import com.Kkrap.RequestDTO.FoldersCreateRequest;
 import jakarta.persistence.*;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
 import org.hibernate.annotations.CreationTimestamp;
 
 import java.time.LocalDateTime;
 import java.util.List;
 
 @Entity
-@Getter
-@Setter
 @Table(name = "folders")
+@Getter
 @AllArgsConstructor
-@NoArgsConstructor
 public class Folders {
 
     @Id
@@ -46,11 +43,20 @@ public class Folders {
     @OneToMany(mappedBy = "folders", cascade = CascadeType.ALL)
     private List<FoldersLinks> foldersLinks;
 
-
     public Folders(Users user, String folderName, String folderDescription, boolean isPublic) {
         this.user = user;
         this.folderName = folderName;
         this.folderDescription = folderDescription;
         this.isPublic = isPublic;
     }
+
+    private Folders() {} //외부에서 new 사용 못하게 보호
+
+    public boolean getIsPublic() {
+        return isPublic;
+    }
+
+    public static Folders of(FoldersCreateRequest foldersCreateRequest, Users user){
+        return new Folders(user, foldersCreateRequest.getFolderName(), foldersCreateRequest.getFolderDescription(), foldersCreateRequest.getisPublic());
+    }
 }
diff --git a/src/main/java/com/Kkrap/Entity/Users.java b/src/main/java/com/Kkrap/Entity/Users.java
index 3e2aa59..1c44c4b 100644
--- a/src/main/java/com/Kkrap/Entity/Users.java
+++ b/src/main/java/com/Kkrap/Entity/Users.java
@@ -1,5 +1,6 @@
 package com.Kkrap.Entity;
 
+import com.Kkrap.RequestDTO.UsersCreateRequest;
 import jakarta.persistence.*;
 import lombok.Builder;
 import lombok.Getter;
@@ -35,15 +36,16 @@ public class Users {
     @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
     private List<Folders> folders;
 
-//    // Links와의 관계 추가
-//    @OneToMany(mappedBy = "users", cascade = CascadeType.ALL)
-////    @JsonIgnore // 순환 참조 방지
-//    private List<Links> links;
 
+    private Users() { } // 외부에서 new 사용 못하게 보호
 
+    //정적 팩토리 메서드
+    public static Users from(UsersCreateRequest usersCreateRequest) {
+        return new Users(usersCreateRequest.getEmail(), usersCreateRequest.getNickname(), usersCreateRequest.getProfileImage(), usersCreateRequest.getKakaoId());
+    }
 
     @Builder
-    public Users(String email, String nickname, String profile, Long kakaoId)
+    private Users(String email, String nickname, String profile, Long kakaoId)
     {
         this.email = email;
         this.nickname = nickname;
@@ -51,7 +53,4 @@ public Users(String email, String nickname, String profile, Long kakaoId)
         this.kakaoId = kakaoId;
     }
 
-    public Users() {
-        // 기본 생성자
-    }
 }
diff --git a/src/main/java/com/Kkrap/Exception/ErrorCode.java b/src/main/java/com/Kkrap/Exception/ErrorCode.java
new file mode 100644
index 0000000..2051336
--- /dev/null
+++ b/src/main/java/com/Kkrap/Exception/ErrorCode.java
@@ -0,0 +1,18 @@
+package com.Kkrap.Exception;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum ErrorCode {
+//    USER_NOT_FOUND(404,"USERS-ERR-404","사용자를 찾을 수 없습니다."),
+//    FOLDERS_NOT_FOUND(404, "FOLDERS-ERR-404", "존재하지 않는 폴더입니다.");
+
+    USER_NOT_FOUND(404,"USERS-ERR-404","USERS NOT FOUND"),
+    FOLDERS_NOT_FOUND(404, "FOLDERS-ERR-404", "FOLDERS NOT FOUND");
+
+    private int code;
+    private String errorCode;
+    private String message;
+}
diff --git a/src/main/java/com/Kkrap/Exception/FoldersNotFoundException.java b/src/main/java/com/Kkrap/Exception/FoldersNotFoundException.java
index 34b1795..366bc95 100644
--- a/src/main/java/com/Kkrap/Exception/FoldersNotFoundException.java
+++ b/src/main/java/com/Kkrap/Exception/FoldersNotFoundException.java
@@ -1,11 +1,17 @@
 package com.Kkrap.Exception;
 
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ResponseStatus;
+import lombok.Getter;
 
-@ResponseStatus(HttpStatus.NOT_FOUND) // 404 Not Found 상태 코드 반환
+@Getter
 public class FoldersNotFoundException extends RuntimeException {
-    public FoldersNotFoundException(String message) {
+    private ErrorCode errorCode;
+
+    public FoldersNotFoundException(String message, ErrorCode errorCode) {
         super(message);
+        this.errorCode = errorCode;
+    }
+    public static FoldersNotFoundException of(String message, ErrorCode errorCode) {
+        return new FoldersNotFoundException(message, errorCode);
     }
+
 }
diff --git a/src/main/java/com/Kkrap/Exception/GlobalExceptionHandler.java b/src/main/java/com/Kkrap/Exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..d6fea72
--- /dev/null
+++ b/src/main/java/com/Kkrap/Exception/GlobalExceptionHandler.java
@@ -0,0 +1,33 @@
+package com.Kkrap.Exception;
+
+import com.Kkrap.ResponseDto.ErrorResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+
+@RestControllerAdvice
+@Slf4j
+public class GlobalExceptionHandler {
+
+    //사용자 예외 처리
+    @ExceptionHandler(UsersNotFoundException.class)
+    public ResponseEntity<ErrorResponse> handleUsersNotFound(UsersNotFoundException ex) {
+        log.error("handleUsersNotFoundException", ex);
+
+        ErrorResponse response =  ErrorResponse.from(ex.getErrorCode());
+        return new ResponseEntity<>(response, HttpStatus.valueOf(ex.getErrorCode().getCode()));
+    }
+
+    @ExceptionHandler(FoldersNotFoundException.class)
+    public ResponseEntity<ErrorResponse> handleFoldersNotFound(FoldersNotFoundException ex){
+        log.error("handleFoldersNotFoundException", ex);
+
+        ErrorResponse response =  ErrorResponse.from(ex.getErrorCode());
+        return new ResponseEntity<>(response, HttpStatus.valueOf(ex.getErrorCode().getCode()));
+
+    }
+
+
+}
diff --git a/src/main/java/com/Kkrap/Exception/UsersNotFoundException.java b/src/main/java/com/Kkrap/Exception/UsersNotFoundException.java
new file mode 100644
index 0000000..27a7f22
--- /dev/null
+++ b/src/main/java/com/Kkrap/Exception/UsersNotFoundException.java
@@ -0,0 +1,19 @@
+package com.Kkrap.Exception;
+
+import com.nimbusds.oauth2.sdk.ErrorResponse;
+import lombok.Getter;
+
+@Getter
+public class UsersNotFoundException extends RuntimeException {
+
+    private ErrorCode errorCode;
+
+    public UsersNotFoundException(String message, ErrorCode errorCode) {
+        super(message);
+        this.errorCode = errorCode;
+    }
+
+    public static UsersNotFoundException of(String message, ErrorCode errorCode) {
+        return new UsersNotFoundException(message, errorCode);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/Kkrap/Repository/UsersRepository.java b/src/main/java/com/Kkrap/Repository/UsersRepository.java
index fc9bb6f..0ca3858 100644
--- a/src/main/java/com/Kkrap/Repository/UsersRepository.java
+++ b/src/main/java/com/Kkrap/Repository/UsersRepository.java
@@ -14,4 +14,6 @@ public interface UsersRepository extends JpaRepository<Users, Long>{
     @Query("SELECT u FROM Users u WHERE u.kakaoId = :kakaoId")
     Optional<Users> findByKaKaoId(@Param("kakaoId") Long kakaoId);
 
+    
+
 }
diff --git a/src/main/java/com/Kkrap/RequestDTO/FoldersCreateRequest.java b/src/main/java/com/Kkrap/RequestDTO/FoldersCreateRequest.java
index 8362957..8a1c69f 100644
--- a/src/main/java/com/Kkrap/RequestDTO/FoldersCreateRequest.java
+++ b/src/main/java/com/Kkrap/RequestDTO/FoldersCreateRequest.java
@@ -22,4 +22,10 @@ public boolean getisPublic(){
         return isPublic;
     }
 
+    public static FoldersCreateRequest of(Long userId, String folderName, String folderDescription, boolean isPublic){
+        return new FoldersCreateRequest(userId, folderName, folderDescription, isPublic);
+
+    }
+
+
 }
diff --git a/src/main/java/com/Kkrap/RequestDTO/FoldersDeleteRequest.java b/src/main/java/com/Kkrap/RequestDTO/FoldersDeleteRequest.java
index 8c0467e..280a96a 100644
--- a/src/main/java/com/Kkrap/RequestDTO/FoldersDeleteRequest.java
+++ b/src/main/java/com/Kkrap/RequestDTO/FoldersDeleteRequest.java
@@ -4,6 +4,5 @@
 
 @Getter
 public class FoldersDeleteRequest {
-    private Long userId;
     private Long folderId;
 }
diff --git a/src/main/java/com/Kkrap/RequestDTO/UsersCreateRequest.java b/src/main/java/com/Kkrap/RequestDTO/UsersCreateRequest.java
new file mode 100644
index 0000000..2f89836
--- /dev/null
+++ b/src/main/java/com/Kkrap/RequestDTO/UsersCreateRequest.java
@@ -0,0 +1,20 @@
+package com.Kkrap.RequestDTO;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+public class UsersCreateRequest {
+    private String email;
+    private String nickname;
+    private String profileImage;
+    private Long kakaoId;
+
+
+    public static UsersCreateRequest of(String email, String nickname, String profileImage, Long kakaoId){
+        return new UsersCreateRequest(email, nickname, profileImage, kakaoId);
+    }
+}
diff --git a/src/main/java/com/Kkrap/ResponseDto/ErrorResponse.java b/src/main/java/com/Kkrap/ResponseDto/ErrorResponse.java
new file mode 100644
index 0000000..1b93595
--- /dev/null
+++ b/src/main/java/com/Kkrap/ResponseDto/ErrorResponse.java
@@ -0,0 +1,23 @@
+package com.Kkrap.ResponseDto;
+
+import com.Kkrap.Exception.ErrorCode;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class ErrorResponse {
+
+    private int code;
+    private String errorCode;
+    private String message;
+
+
+    private ErrorResponse(){}
+
+    public static ErrorResponse from(ErrorCode errorCode){
+        return new ErrorResponse(errorCode.getCode(), errorCode.getErrorCode(), errorCode.getMessage());
+    }
+}
diff --git a/src/main/java/com/Kkrap/ResponseDto/FoldersDeleteResponse.java b/src/main/java/com/Kkrap/ResponseDto/FoldersDeleteResponse.java
deleted file mode 100644
index c7de3dc..0000000
--- a/src/main/java/com/Kkrap/ResponseDto/FoldersDeleteResponse.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.Kkrap.ResponseDto;
-
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-public class FoldersDeleteResponse {
-    private Long folderId;
-    private Long userId;
-    private String folderName;
-    private String folderDescription;
-    private boolean isPublic;
-}
diff --git a/src/main/java/com/Kkrap/ResponseDto/FoldersLinksAllResponse.java b/src/main/java/com/Kkrap/ResponseDto/FoldersLinksAllResponse.java
index bd67487..0b36d4c 100644
--- a/src/main/java/com/Kkrap/ResponseDto/FoldersLinksAllResponse.java
+++ b/src/main/java/com/Kkrap/ResponseDto/FoldersLinksAllResponse.java
@@ -1,6 +1,7 @@
 package com.Kkrap.ResponseDto;
 import com.Kkrap.Entity.Folders;
 import com.Kkrap.Entity.Links;
+import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.Setter;
 import java.time.LocalDateTime;
@@ -9,6 +10,7 @@
 
 @Getter
 @Setter
+@AllArgsConstructor
 public class FoldersLinksAllResponse {
     private Long folderId;
     private String folderName;
@@ -17,14 +19,17 @@ public class FoldersLinksAllResponse {
     private LocalDateTime createTime;
     private List<LinksResponse> links;
 
-    public FoldersLinksAllResponse(Folders folder, List<Links> linksList) {
-        this.folderId = folder.getFolderId();
-        this.folderName = folder.getFolderName();
-        this.folderDescription = folder.getFolderDescription();
-        this.isPublic = folder.isPublic();
-        this.createTime = folder.getCreateTime();
-        this.links = linksList.stream()
+    private FoldersLinksAllResponse(){}
+
+    public static  FoldersLinksAllResponse of(Folders folder, List<Links> linksList) {
+        Long folderId = folder.getFolderId();
+        String folderName = folder.getFolderName();
+        String folderDescription = folder.getFolderDescription();
+        boolean isPublic = folder.getIsPublic();
+        LocalDateTime createTime = folder.getCreateTime();
+        List<LinksResponse> links = linksList.stream()
                 .map(LinksResponse::new)
                 .collect(Collectors.toList());
+        return new FoldersLinksAllResponse(folderId, folderName, folderDescription, isPublic, createTime, links);
     }
 }
diff --git a/src/main/java/com/Kkrap/ResponseDto/FoldersResponse.java b/src/main/java/com/Kkrap/ResponseDto/FoldersResponse.java
index 23fa460..63d8c21 100644
--- a/src/main/java/com/Kkrap/ResponseDto/FoldersResponse.java
+++ b/src/main/java/com/Kkrap/ResponseDto/FoldersResponse.java
@@ -1,5 +1,7 @@
 package com.Kkrap.ResponseDto;
 
+
+import com.Kkrap.Entity.Folders;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.Setter;
@@ -11,14 +13,17 @@
 @AllArgsConstructor
 public class FoldersResponse {
     private Long folderId;
-
     private Long userId;
-
+    private String folderName;
+    private String folderDescription;
     private LocalDateTime createTime;
+    private boolean isPublic;
 
-    private String folderName;
+    private FoldersResponse() {}
 
-    private String folderDescription;
 
-    private boolean isPublic;
+    public static FoldersResponse from(Folders folders){
+        return new FoldersResponse(folders.getFolderId(), folders.getFolderId(), folders.getFolderName(), folders.getFolderDescription(), folders.getCreateTime(), folders.getIsPublic());
+    }
+
 }
diff --git a/src/main/java/com/Kkrap/ResponseDto/MessageResponse.java b/src/main/java/com/Kkrap/ResponseDto/MessageResponse.java
index 919deee..6fd62d0 100644
--- a/src/main/java/com/Kkrap/ResponseDto/MessageResponse.java
+++ b/src/main/java/com/Kkrap/ResponseDto/MessageResponse.java
@@ -1,16 +1,18 @@
 package com.Kkrap.ResponseDto;
 
+import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.Setter;
 
 @Getter
 @Setter
+@AllArgsConstructor
 public class MessageResponse {
     private Integer code;
     private String message;
+    private MessageResponse() { }
 
-    public MessageResponse(Integer code, String message) {
-        this.code = code;
-        this.message = message;
+    public static MessageResponse of(Integer code, String message){
+        return new MessageResponse(code, message);
     }
 }
diff --git a/src/main/java/com/Kkrap/ResponseDto/UserProfileResponse.java b/src/main/java/com/Kkrap/ResponseDto/UserProfileResponse.java
deleted file mode 100644
index f5d175d..0000000
--- a/src/main/java/com/Kkrap/ResponseDto/UserProfileResponse.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.Kkrap.ResponseDto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@Getter
-@Setter
-@AllArgsConstructor
-@NoArgsConstructor
-public class UserProfileResponse {
-    private Long userId;
-
-    private String email;
-
-    private String nickname;
-
-    private String profile;
-
-    private Long KakaoId;
-
-
-//    public UserProfileResponse(Long userId, String email, String nickname, String profile) {
-//    }
-}
diff --git a/src/main/java/com/Kkrap/ResponseDto/UsersProfileResponse.java b/src/main/java/com/Kkrap/ResponseDto/UsersProfileResponse.java
new file mode 100644
index 0000000..18b194c
--- /dev/null
+++ b/src/main/java/com/Kkrap/ResponseDto/UsersProfileResponse.java
@@ -0,0 +1,32 @@
+package com.Kkrap.ResponseDto;
+
+import com.Kkrap.Entity.Users;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.catalina.User;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class UsersProfileResponse {
+    private Long userId;
+
+    private String email;
+
+    private String nickname;
+
+    private String profile;
+
+    private Long KakaoId;
+
+    private UsersProfileResponse(){ } // 외부에서 생성하지 못하게 함
+
+    public static UsersProfileResponse of(Long userId, String email, String nickname, String profile, Long kakaoId){
+        return new UsersProfileResponse(userId, email, nickname, profile, kakaoId);
+    }
+
+    public static UsersProfileResponse from(Users users){
+        return new UsersProfileResponse(users.getUserId(), users.getEmail(), users.getNickname(), users.getProfile(), users.getKakaoId());
+    }
+}
diff --git a/src/main/java/com/Kkrap/Security/SecurityConfig.java b/src/main/java/com/Kkrap/Security/SecurityConfig.java
index 56cae2d..bf96b8d 100644
--- a/src/main/java/com/Kkrap/Security/SecurityConfig.java
+++ b/src/main/java/com/Kkrap/Security/SecurityConfig.java
@@ -4,7 +4,9 @@
 import com.Kkrap.Entity.Users;
 import com.Kkrap.Repository.FoldersRepository;
 import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.UsersCreateRequest;
 import com.Kkrap.Service.CustomOAuth2UserService;
+import com.Kkrap.Service.UsersService;
 import jakarta.servlet.ServletException;
 import jakarta.servlet.http.Cookie;
 import jakarta.servlet.http.HttpServletRequest;
@@ -42,6 +44,9 @@ public class SecurityConfig {
     @Autowired
     private FoldersRepository foldersRepository;
 
+    @Autowired
+    private UsersService usersService;
+
     private final CustomOAuth2UserService oAuth2UserService;
 
     public SecurityConfig(CustomOAuth2UserService oAuth2UserService) {
@@ -102,7 +107,7 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
                     // 카카오 사용자 정보 추출
                     Map<String, Object> attributes = defaultOAuth2User.getAttributes();
 
-                    String kaka_id = attributes.get("id").toString(); // 사용자 ID
+                    String kakao_id = attributes.get("id").toString(); // 사용자 ID
                     Map<String, Object> kakaoAccount = (Map<String, Object>) attributes.get("kakao_account");
                     Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
 
@@ -111,13 +116,13 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
                     String email = kakaoAccount.get("email").toString(); // 이메일
 
                     // 디버그용 로그 출력
-                    System.out.println("카카오 사용자 ID: " + kaka_id);
+                    System.out.println("카카오 사용자 ID: " + kakao_id);
                     System.out.println("카카오 사용자 닉네임: " + nickname);
                     System.out.println("카카오 사용자 이메일: " + email);
                     System.out.println("카카오 사용자 프로필 이미지 URL: " + profileImage);
 
                     // 사용자 정보를 각각 쿠키에 저장
-                    setCookie(response, "kakao_id", kaka_id, 7 * 24 * 60 * 60); // 쿠키 유효기간 7일
+                    setCookie(response, "kakao_id", kakao_id, 7 * 24 * 60 * 60); // 쿠키 유효기간 7일
                     setCookie(response, "nickname", nickname, 7 * 24 * 60 * 60);
                     setCookie(response, "profileImage", profileImage, 7 * 24 * 60 * 60);
                     setCookie(response, "email", email, 7 * 24 * 60 * 60);
@@ -125,11 +130,12 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
 
                     //DB 로직 추가
                     String userId;
-                    Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kaka_id));
+                    Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kakao_id));
                     System.out.println("CheckUser : " + CheckUser);
                     if (CheckUser.isEmpty()){
-                        Users newUser = new Users(email, nickname, profileImage, Long.valueOf(kaka_id));
-                        usersRepository.save(newUser);
+                        UsersCreateRequest usersCreateRequest = UsersCreateRequest.of(email, nickname, profileImage, Long.valueOf(kakao_id));
+                        Users newUser = usersService.save(usersCreateRequest);
+
                         setCookie(response, "userId", String.valueOf(newUser.getUserId()), 7 * 24 * 60 * 60);
                         userId = String.valueOf(newUser.getUserId());
 
@@ -189,7 +195,7 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
                     // 사용자 정보를 URL 인코딩
                     String redirectUrl = String.format(
                             "http://localhost:3000/login/success?kakao_id=%s&nickname=%s&profileImage=%s&email=%s&userId=%s",
-                            URLEncoder.encode(kaka_id, StandardCharsets.UTF_8.toString()),
+                            URLEncoder.encode(kakao_id, StandardCharsets.UTF_8.toString()),
                             URLEncoder.encode(nickname, StandardCharsets.UTF_8.toString()),
                             URLEncoder.encode(profileImage, StandardCharsets.UTF_8.toString()),
                             URLEncoder.encode(email, StandardCharsets.UTF_8.toString()),
diff --git a/src/main/java/com/Kkrap/Service/AuthService.java b/src/main/java/com/Kkrap/Service/AuthService.java
new file mode 100644
index 0000000..723fd8a
--- /dev/null
+++ b/src/main/java/com/Kkrap/Service/AuthService.java
@@ -0,0 +1,86 @@
+package com.Kkrap.Service;
+
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.FoldersCreateRequest;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.RequestDTO.UsersCreateRequest;
+import com.Kkrap.ResponseDto.MessageResponse;
+import com.Kkrap.ResponseDto.UsersProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.*;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@Service
+public class AuthService {
+
+    public static final String KAKAO_USER_INFO_URL = "https://kapi.kakao.com/v2/user/me";
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    UsersService usersService;
+
+    @Autowired
+    FoldersService foldersService;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+        if (accessToken.isEmpty()){
+            return ResponseEntity.status(HttpStatus.NOT_FOUND)
+                    .body(new MessageResponse(404, "토큰 없음"));
+        }
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                KAKAO_USER_INFO_URL,
+                HttpMethod.GET,
+                entity,
+                Map.class
+        );
+
+
+        Map<String, Object> userInfo = response.getBody();
+        Long kakaoId = Long.valueOf(userInfo.get("id").toString());
+        Map<String, Object> kakaoAccount = (Map<String, Object>) userInfo.get("kakao_account");
+        Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
+
+        String email = kakaoAccount.get("email").toString();
+        String nickname = profile.get("nickname").toString();
+        String profileImage = profile.get("profile_image_url").toString();
+
+        Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kakaoId));
+        if (CheckUser.isEmpty()){
+            // 처음 로그인 한 사람 사용자 만들기
+            UsersCreateRequest usersCreateRequest = UsersCreateRequest.of(email, nickname, profileImage, kakaoId);
+            Users newUser = usersService.save(usersCreateRequest);
+            // 처음 로그인 한 사람은 모든 링크 보기 폴더가 없음 만들어주어야함
+            FoldersCreateRequest foldersCreateRequest = FoldersCreateRequest.of(newUser.getUserId(), "모든 링크", "모든 링크가 저장된 폴더입니다.", false);
+            foldersService.save(foldersCreateRequest, newUser);
+            UsersProfileResponse usersProfileResponse = UsersProfileResponse.of(newUser.getUserId(), newUser.getEmail(), newUser.getNickname(), newUser.getProfile(), newUser.getKakaoId());
+            return ResponseEntity.ok(usersProfileResponse);
+        }
+        else
+        {
+            Users existingUser = CheckUser.get();
+            UsersProfileResponse usersProfileResponse = UsersProfileResponse.of(existingUser.getUserId(), existingUser.getEmail(), existingUser.getNickname(), existingUser.getProfile(), existingUser.getKakaoId());
+            return ResponseEntity.ok(usersProfileResponse);
+        }
+    }
+
+
+}
diff --git a/src/main/java/com/Kkrap/Service/FoldersService.java b/src/main/java/com/Kkrap/Service/FoldersService.java
index 5939071..20bf627 100644
--- a/src/main/java/com/Kkrap/Service/FoldersService.java
+++ b/src/main/java/com/Kkrap/Service/FoldersService.java
@@ -4,31 +4,27 @@
 import com.Kkrap.Entity.FoldersLinks;
 import com.Kkrap.Entity.Links;
 import com.Kkrap.Entity.Users;
+import com.Kkrap.Exception.ErrorCode;
+import com.Kkrap.Exception.FoldersNotFoundException;
 import com.Kkrap.Repository.FoldersLinksRepository;
 import com.Kkrap.Repository.FoldersRepository;
 import com.Kkrap.Repository.LinksRepository;
-import com.Kkrap.Repository.UsersRepository;
 import com.Kkrap.RequestDTO.FoldersCreateRequest;
 import com.Kkrap.RequestDTO.FoldersDeleteRequest;
-import com.Kkrap.ResponseDto.FoldersDeleteResponse;
-import com.Kkrap.ResponseDto.LinksDeleteAllResponse;
+import com.Kkrap.ResponseDto.FoldersResponse;
 import com.Kkrap.ResponseDto.FoldersLinksAllResponse;
-import com.Kkrap.ResponseDto.MessageResponse;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.stream.Collectors;
 
 @Service
 public class FoldersService {
     @Autowired
-    private UsersRepository usersRepository;
+    private UsersService usersService;
 
     @Autowired
     private FoldersRepository foldersRepository;
@@ -39,16 +35,12 @@ public class FoldersService {
     @Autowired
     private LinksRepository linksRepository;
 
+
     public ResponseEntity<List<FoldersLinksAllResponse>> getFoldersAll(Long userId){
-        Optional<Users> userOptional = usersRepository.findById(userId);
-        //사용자가 없으면 빈 리스트
-        if (userOptional.isEmpty()) {
-            return ResponseEntity.status(HttpStatus.NOT_FOUND)
-                    .body(Collections.emptyList());
-        }
+        //중간에 있는 사용자 인지 검사
+        usersService.get(userId);
         // userId를 통해 전부 가져오기
-        List<Folders> folders = foldersRepository.findByUserUserId(userId);
-
+        List<Folders> folders = getAllFolders(userId);
         List<FoldersLinksAllResponse> responseList = folders.stream().map(folder -> {
             // 해당 폴더의 FoldersLinks 조회 (folder_id 기준)
             // 특정 폴더(folder_id)에 해당하는 FoldersLinks를 조회
@@ -59,101 +51,70 @@ public ResponseEntity<List<FoldersLinksAllResponse>> getFoldersAll(Long userId){
                     .map(folderLink -> linksRepository.findById(folderLink.getLinks().getLinkId()).orElse(null))
                     .filter(Objects::nonNull) // 존재하는 Links만 리스트에 추가
                     .collect(Collectors.toList());
-
             // Folder + Links 리스트를 Response DTO로 변환
-            return new FoldersLinksAllResponse(folder, linksList);
+            return FoldersLinksAllResponse.of(folder, linksList);
         }).collect(Collectors.toList());
         return ResponseEntity.ok(responseList);
     }
 
 
-//    public List<FolderUrlResponseDTO> SelectedFolderUrl(Long folderId, Long userId){
-//        // folderId로 모든 FolderList 조회
-//        List<FolderList> folderLists = folderListRepository.findByFolderFolderId(folderId);
-//
-//        // folderLists에서 linkId 목록 추출
-//        List<Long> linkIds = folderLists.stream()
-//                .map(folderList -> folderList.getLink().getLinkId())
-//                .collect(Collectors.toList());
-//
-//        // linkId 목록으로 Links 조회
-//        List<Links> links = linksRepository.findByLinkIdIn(linkIds);
-//
-//        List<FolderUrlResponseDTO> responseDTOs = links.stream()
-//                .map(link -> new FolderUrlResponseDTO(link.getLinkId(), link.getLinkUrl(), link.getCreateTime()) )
-//                .collect(Collectors.toList());
-//
-//        return responseDTOs;
-//    }
-
     //Create
     //폴더를 만드는 것
-    public ResponseEntity<Object> CreateFolder(Long userId, FoldersCreateRequest foldersCreateRequest)
+    public ResponseEntity<FoldersResponse> CreateFolder(Long userId, FoldersCreateRequest foldersCreateRequest)
     {
-        Optional<Users> usersOptional = usersRepository.findById(userId);
-        if (usersOptional.isEmpty()){
-            return ResponseEntity.status(HttpStatus.NOT_FOUND)
-                    .body(new MessageResponse(404,"사용자를 찾을 수 없음"));
-        }
-
+        //사용자 조회
+        Users users = usersService.get(userId);
+        Folders folders = save(foldersCreateRequest, users);
 
-        String folderName = foldersCreateRequest.getFolderName();
-
-        String folderDescription = foldersCreateRequest.getFolderDescription();
-        boolean isPublic = foldersCreateRequest.getisPublic();
-
-        Folders folder = new Folders(usersOptional.get(), folderName, folderDescription, isPublic);
-        foldersRepository.save(folder);
-
-        return ResponseEntity.ok(foldersCreateRequest);
+        return ResponseEntity.ok(FoldersResponse.from(folders));
     }
 
     //Delete
     //폴더 삭제
-    public ResponseEntity<Object> DeleteFolder(Long userId,FoldersDeleteRequest foldersDeleteRequest)
+    public ResponseEntity<FoldersResponse> DeleteFolder(Long userId, FoldersDeleteRequest foldersDeleteRequest)
     {
-        Optional<Users> optionalUsers = usersRepository.findById(userId);
-        if (optionalUsers.isEmpty()){
-            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new MessageResponse(404, "사용자를 찾을 수 없음"));
-        }
-        Long folderId = foldersDeleteRequest.getFolderId();
-        Optional<Folders> optionalFolders = foldersRepository.findById(folderId);
-        if (optionalFolders.isEmpty()) {
-            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new MessageResponse(404, "존재하지 않는 폴더"));
-        }
+        //사용자 체크
+        usersService.get(userId);
 
         //FolderLinks에 해당 folderId에 속한 FolderLinks 리스트 조회
-        Folders folder = optionalFolders.get();
-        List<FoldersLinks> folderLinksList = foldersLinksRepository.findByFolders(folder);
-
+        Long folderId = foldersDeleteRequest.getFolderId();
+        Folders folders = get(folderId);
+        List<FoldersLinks> folderLinksList = foldersLinksRepository.findByFolders(folders);
 
-//        List<Long> linkIds = folderLinksList.stream()
-//                .map(folderLink -> folderLink.getLinks().getLinkId())
-//                .distinct()
-//                .collect(Collectors.toList());
+        // FoldersLinks 테이블에서 해당 folderId를 가진 데이터 삭제 ---------------> 이거 해야됨
+        foldersLinksRepository.deleteAll(folderLinksList);
+        // folders 삭제
+        deleteById(folderId);
+        //응답 데이터를 삭제된 링크들까지 포함 시켜서 해주어야함
+        return ResponseEntity.ok(FoldersResponse.from(folders));
+    }
 
-        //응답을 해주기 위한 데이터
-//        List<Links> deletedLinks = linksRepository.findAllById(linkIds);
-//        List<LinksResponse> deletedLinksResponse = deletedLinks.stream()
-//                .map(LinksResponse::new)
-//                .collect(Collectors.toList());
+    //save
+    public Folders save(FoldersCreateRequest foldersCreateRequest, Users users){
+        Folders folders = Folders.of(foldersCreateRequest, users);
+        foldersRepository.save(folders);
+        return folders;
+    }
 
-        // Links 테이블에서 해당 linkId를 가진 링크 삭제
-//        if (!linkIds.isEmpty()){
-//            linksRepository.deleteAllById(linkIds);
-//        }
+    //사용자가 가진 모든 폴더 조회
+    public List<Folders> getAllFolders(Long userId){
+        List<Folders> folders = foldersRepository.findByUserUserId(userId);
+        if (folders.isEmpty()){
+            throw FoldersNotFoundException.of("폴더가 존재하지 않습니다.", ErrorCode.FOLDERS_NOT_FOUND);
+        }
+        return folders;
+    }
 
-        // FoldersLinks 테이블에서 해당 folderId를 가진 데이터 삭제
-        foldersLinksRepository.deleteAll(folderLinksList);
+    //하나 폴더 조회
+    public Folders get(Long folderId){
+        return foldersRepository.findById(folderId).orElseThrow(() -> FoldersNotFoundException.of("폴더가 존재하지 않습니다.", ErrorCode.FOLDERS_NOT_FOUND));
+    }
 
-        // folders 삭제
+    public void deleteById(Long folderId){
         foldersRepository.deleteById(folderId);
+    }
+
+
 
-        //응답 데이터를 삭제된 링크들까지 포함 시켜서 해주어야함
-        FoldersDeleteResponse response = new FoldersDeleteResponse(
-                folderId, userId, folder.getFolderName(), folder.getFolderDescription(), folder.isPublic()
-        );
 
-        return ResponseEntity.ok(response);
-    }
 }
diff --git a/src/main/java/com/Kkrap/Service/UsersService.java b/src/main/java/com/Kkrap/Service/UsersService.java
index 78d13ce..3bf3e68 100644
--- a/src/main/java/com/Kkrap/Service/UsersService.java
+++ b/src/main/java/com/Kkrap/Service/UsersService.java
@@ -1,40 +1,48 @@
 package com.Kkrap.Service;
 
 import com.Kkrap.Entity.Users;
+import com.Kkrap.Exception.ErrorCode;
+import com.Kkrap.Exception.UsersNotFoundException;
 import com.Kkrap.Repository.UsersRepository;
-import com.Kkrap.ResponseDto.UserProfileResponse;
+import com.Kkrap.RequestDTO.UsersCreateRequest;
+import com.Kkrap.ResponseDto.UsersProfileResponse;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 
-import java.util.Optional;
-
 @Service
 public class UsersService {
 
     @Autowired
     private UsersRepository usersRepository;
 
-    public UserProfileResponse getUserProfile(Long userId){
-        Optional<Users> optionalUsers = usersRepository.findById(userId);
+    public ResponseEntity<UsersProfileResponse> getUserProfile(Long userId){
+        Users users = get(userId);
+        return ResponseEntity.ok(UsersProfileResponse.of(users.getUserId(),users.getEmail(), users.getNickname(), users.getProfile(), users.getKakaoId()));
+    }
+
+    public ResponseEntity<UsersProfileResponse> updateNickName(Long userId, String newNickname){
+        Users users = get(userId);
+        users.setNickname(newNickname);
+        save(users);
+        return ResponseEntity.ok(UsersProfileResponse.from(users));
+    }
 
-        if (optionalUsers.isPresent()){
-            Users user = optionalUsers.get();
-            return new UserProfileResponse(user.getUserId(),user.getEmail(), user.getNickname(), user.getProfile(), user.getKakaoId());
-        }
-        else {
-            return  null;
-        }
+    public Users get(Long userId) {
+        return usersRepository.findById(userId)
+                .orElseThrow(() ->UsersNotFoundException.of("해당 사용자를 찾을 수 없습니다.", ErrorCode.USER_NOT_FOUND));
     }
 
-    public boolean updateNickName(Long userId, String newNickname){
-        Optional<Users> optionalUsers = usersRepository.findById(userId);
+    //유저 만들기
+    public Users save(UsersCreateRequest usersCreateRequest){
+        Users users = Users.from(usersCreateRequest);
+        usersRepository.save(users);
+        return users;
+    }
 
-        if (optionalUsers.isPresent()){
-            Users user = optionalUsers.get();
-            user.setNickname(newNickname);
-            usersRepository.save(user);
-            return true;
-        }
-        return false;
+    //유저 이미 있는데 저장
+    public Users save(Users users){
+        return usersRepository.save(users);
     }
+
 }


Reviews:
user: login: amazon7737
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T10:17:46Z
user: login: whitecy01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T10:31:27Z
user: login: whitecy01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T10:38:31Z
user: login: whitecy01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T10:39:21Z
user: login: amazon7737
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T10:52:07Z
user: login: whitecy01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T11:47:27Z
user: login: whitecy01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T11:47:32Z
user: login: whitecy01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T11:55:39Z
user: login: whitecy01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T12:19:52Z
user: login: amazon7737
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T12:53:29Z
user: login: amazon7737
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T12:55:07Z
user: login: whitecy01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T13:00:21Z
user: login: amazon7737
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T13:26:35Z
user: login: whitecy01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T13:33:11Z
user: login: amazon7737
body: 전체적으로 계층구조와 dto, 메서드 패턴들이 잘 작성된것 같습니다 ~
궁금한 부분들 코멘트 달아봤는데, 추가 리뷰 확인 부탁드려요 ^_^
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T15:15:45Z
user: login: amazon7737
body: 변경사항 잘 반영해주셨네요 ! 😄😄

새벽까지 작업하느라 고생하셨어요 👍
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-16T02:11:24Z

Review comments:
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: 내부 로직들을 Service 계층으로 옮길 필요가 있어 보이네요.
created_at: 2025-04-08T10:12:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: Controller 에서는 Repository 를 주입하지 않습니다.

https://tom-collings.medium.com/controller-service-repository-16e29a4684e5

created_at: 2025-04-08T10:13:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
+                HttpMethod.GET,
+                entity,
+                Map.class
+        );
+
+
+        Map<String, Object> userInfo = response.getBody();
+        Long kakaoId = Long.valueOf(userInfo.get("id").toString());
+        Map<String, Object> kakaoAccount = (Map<String, Object>) userInfo.get("kakao_account");
+        Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
+
+        String email = kakaoAccount.get("email").toString();
+        String nickname = profile.get("nickname").toString();
+        String profileImage = profile.get("profile_image_url").toString();
+
+//        Users user = usersRepository.findByKaKaoId(kakaoId).orElseGet(() -> {
+//            Users newUser = new Users(email, nickname, profileImage, kakaoId);
+//            usersRepository.save(newUser);
+//            return newUser;
+//        });
+        String userId;
+        Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kakaoId));
+        System.out.println("CheckUser : " + CheckUser);
+        if (CheckUser.isEmpty()){
+            Users newUser = new Users(email, nickname, profileImage, Long.valueOf(kakaoId));
+            usersRepository.save(newUser);
+
+            // 처음 로그인 한 사람은 모든 링크 보기 폴더가 없음 만들어주어야함
+            Folders folder = new Folders(newUser, "모든 링크", "모든 링크가 저장된 폴더입니다.", false);
+            foldersRepository.save(folder);
+
+            UserProfileResponse userProfileResponse = new UserProfileResponse(newUser.getUserId(), newUser.getEmail(), newUser.getNickname(), newUser.getProfile(), newUser.getKakaoId());
+            return ResponseEntity.ok(userProfileResponse);
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: 나머지 로직들은 Service 계층으로 옮긴이후 차근히 기능들을 분리해둬야 할 것 같네요.
created_at: 2025-04-08T10:14:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: 참조 링크 내용 중 그림 확인 부탁드려요
created_at: 2025-04-08T10:14:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
+                HttpMethod.GET,
+                entity,
+                Map.class
+        );
+
+
+        Map<String, Object> userInfo = response.getBody();
+        Long kakaoId = Long.valueOf(userInfo.get("id").toString());
+        Map<String, Object> kakaoAccount = (Map<String, Object>) userInfo.get("kakao_account");
+        Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
+
+        String email = kakaoAccount.get("email").toString();
+        String nickname = profile.get("nickname").toString();
+        String profileImage = profile.get("profile_image_url").toString();
+
+//        Users user = usersRepository.findByKaKaoId(kakaoId).orElseGet(() -> {
+//            Users newUser = new Users(email, nickname, profileImage, kakaoId);
+//            usersRepository.save(newUser);
+//            return newUser;
+//        });
+        String userId;
+        Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kakaoId));
+        System.out.println("CheckUser : " + CheckUser);
+        if (CheckUser.isEmpty()){
+            Users newUser = new Users(email, nickname, profileImage, Long.valueOf(kakaoId));
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: 디미터 법칙 맞춰서 엔티티 클래스들의 메소드 분리가 필요해보입니다.
created_at: 2025-04-08T10:15:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
+                HttpMethod.GET,
+                entity,
+                Map.class
+        );
+
+
+        Map<String, Object> userInfo = response.getBody();
+        Long kakaoId = Long.valueOf(userInfo.get("id").toString());
+        Map<String, Object> kakaoAccount = (Map<String, Object>) userInfo.get("kakao_account");
+        Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
+
+        String email = kakaoAccount.get("email").toString();
+        String nickname = profile.get("nickname").toString();
+        String profileImage = profile.get("profile_image_url").toString();
+
+//        Users user = usersRepository.findByKaKaoId(kakaoId).orElseGet(() -> {
+//            Users newUser = new Users(email, nickname, profileImage, kakaoId);
+//            usersRepository.save(newUser);
+//            return newUser;
+//        });
+        String userId;
+        Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kakaoId));
+        System.out.println("CheckUser : " + CheckUser);
+        if (CheckUser.isEmpty()){
+            Users newUser = new Users(email, nickname, profileImage, Long.valueOf(kakaoId));
+            usersRepository.save(newUser);
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: User 의 save 기능은 UserService에서 호출하는것이 필요해보입니다.
created_at: 2025-04-08T10:15:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
+                HttpMethod.GET,
+                entity,
+                Map.class
+        );
+
+
+        Map<String, Object> userInfo = response.getBody();
+        Long kakaoId = Long.valueOf(userInfo.get("id").toString());
+        Map<String, Object> kakaoAccount = (Map<String, Object>) userInfo.get("kakao_account");
+        Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
+
+        String email = kakaoAccount.get("email").toString();
+        String nickname = profile.get("nickname").toString();
+        String profileImage = profile.get("profile_image_url").toString();
+
+//        Users user = usersRepository.findByKaKaoId(kakaoId).orElseGet(() -> {
+//            Users newUser = new Users(email, nickname, profileImage, kakaoId);
+//            usersRepository.save(newUser);
+//            return newUser;
+//        });
+        String userId;
+        Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kakaoId));
+        System.out.println("CheckUser : " + CheckUser);
+        if (CheckUser.isEmpty()){
+            Users newUser = new Users(email, nickname, profileImage, Long.valueOf(kakaoId));
+            usersRepository.save(newUser);
+
+            // 처음 로그인 한 사람은 모든 링크 보기 폴더가 없음 만들어주어야함
+            Folders folder = new Folders(newUser, "모든 링크", "모든 링크가 저장된 폴더입니다.", false);
+            foldersRepository.save(folder);
+
+            UserProfileResponse userProfileResponse = new UserProfileResponse(newUser.getUserId(), newUser.getEmail(), newUser.getNickname(), newUser.getProfile(), newUser.getKakaoId());
+            return ResponseEntity.ok(userProfileResponse);
+        }
+        else
+        {
+            Users existingUser = CheckUser.get();
+            UserProfileResponse userProfileResponse = new UserProfileResponse(existingUser.getUserId(), existingUser.getEmail(), existingUser.getNickname(), existingUser.getProfile(), existingUser.getKakaoId());
+            return ResponseEntity.ok(userProfileResponse);
+        }
+
+
+//        return ResponseEntity.ok(Map.of(
+//                "userId", user.getUserId(),
+//                "nickname", user.getNickname(),
+//                "email", user.getEmail(),
+//                "profile", user.getProfile()
+//        ));
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: 필요하지 않는 주석은 제거 부탁드립니다.
created_at: 2025-04-08T10:15:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: 정적 또는 전역 참조 변수로 코드페이지 상위에 등록해두면 좋아보입니다.


created_at: 2025-04-08T10:16:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: https://www.scaler.com/topics/global-variable-in-java/

Circle 클래스 예제 코드 참고
created_at: 2025-04-08T10:17:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: whitecy01
body: 넵 알겠습니다!
created_at: 2025-04-09T10:31:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: whitecy01
body: 확인했습니다!
created_at: 2025-04-09T10:38:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
+                HttpMethod.GET,
+                entity,
+                Map.class
+        );
+
+
+        Map<String, Object> userInfo = response.getBody();
+        Long kakaoId = Long.valueOf(userInfo.get("id").toString());
+        Map<String, Object> kakaoAccount = (Map<String, Object>) userInfo.get("kakao_account");
+        Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
+
+        String email = kakaoAccount.get("email").toString();
+        String nickname = profile.get("nickname").toString();
+        String profileImage = profile.get("profile_image_url").toString();
+
+//        Users user = usersRepository.findByKaKaoId(kakaoId).orElseGet(() -> {
+//            Users newUser = new Users(email, nickname, profileImage, kakaoId);
+//            usersRepository.save(newUser);
+//            return newUser;
+//        });
+        String userId;
+        Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kakaoId));
+        System.out.println("CheckUser : " + CheckUser);
+        if (CheckUser.isEmpty()){
+            Users newUser = new Users(email, nickname, profileImage, Long.valueOf(kakaoId));
+            usersRepository.save(newUser);
+
+            // 처음 로그인 한 사람은 모든 링크 보기 폴더가 없음 만들어주어야함
+            Folders folder = new Folders(newUser, "모든 링크", "모든 링크가 저장된 폴더입니다.", false);
+            foldersRepository.save(folder);
+
+            UserProfileResponse userProfileResponse = new UserProfileResponse(newUser.getUserId(), newUser.getEmail(), newUser.getNickname(), newUser.getProfile(), newUser.getKakaoId());
+            return ResponseEntity.ok(userProfileResponse);
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: whitecy01
body: Service 계층에서 만들어진 기능들은 또 따로 나눠야 되나요?
created_at: 2025-04-09T10:39:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
+                HttpMethod.GET,
+                entity,
+                Map.class
+        );
+
+
+        Map<String, Object> userInfo = response.getBody();
+        Long kakaoId = Long.valueOf(userInfo.get("id").toString());
+        Map<String, Object> kakaoAccount = (Map<String, Object>) userInfo.get("kakao_account");
+        Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
+
+        String email = kakaoAccount.get("email").toString();
+        String nickname = profile.get("nickname").toString();
+        String profileImage = profile.get("profile_image_url").toString();
+
+//        Users user = usersRepository.findByKaKaoId(kakaoId).orElseGet(() -> {
+//            Users newUser = new Users(email, nickname, profileImage, kakaoId);
+//            usersRepository.save(newUser);
+//            return newUser;
+//        });
+        String userId;
+        Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kakaoId));
+        System.out.println("CheckUser : " + CheckUser);
+        if (CheckUser.isEmpty()){
+            Users newUser = new Users(email, nickname, profileImage, Long.valueOf(kakaoId));
+            usersRepository.save(newUser);
+
+            // 처음 로그인 한 사람은 모든 링크 보기 폴더가 없음 만들어주어야함
+            Folders folder = new Folders(newUser, "모든 링크", "모든 링크가 저장된 폴더입니다.", false);
+            foldersRepository.save(folder);
+
+            UserProfileResponse userProfileResponse = new UserProfileResponse(newUser.getUserId(), newUser.getEmail(), newUser.getNickname(), newUser.getProfile(), newUser.getKakaoId());
+            return ResponseEntity.ok(userProfileResponse);
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: 네 지금 기능들이 전부 한 메소드로 작성되어서요. 기능 단위로 메소드를 분리하는게 이상적이어 보입니다.
created_at: 2025-04-09T10:52:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
+                HttpMethod.GET,
+                entity,
+                Map.class
+        );
+
+
+        Map<String, Object> userInfo = response.getBody();
+        Long kakaoId = Long.valueOf(userInfo.get("id").toString());
+        Map<String, Object> kakaoAccount = (Map<String, Object>) userInfo.get("kakao_account");
+        Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
+
+        String email = kakaoAccount.get("email").toString();
+        String nickname = profile.get("nickname").toString();
+        String profileImage = profile.get("profile_image_url").toString();
+
+//        Users user = usersRepository.findByKaKaoId(kakaoId).orElseGet(() -> {
+//            Users newUser = new Users(email, nickname, profileImage, kakaoId);
+//            usersRepository.save(newUser);
+//            return newUser;
+//        });
+        String userId;
+        Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kakaoId));
+        System.out.println("CheckUser : " + CheckUser);
+        if (CheckUser.isEmpty()){
+            Users newUser = new Users(email, nickname, profileImage, Long.valueOf(kakaoId));
+            usersRepository.save(newUser);
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: whitecy01
body: 넵 확인했습니다
created_at: 2025-04-09T11:47:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
+                HttpMethod.GET,
+                entity,
+                Map.class
+        );
+
+
+        Map<String, Object> userInfo = response.getBody();
+        Long kakaoId = Long.valueOf(userInfo.get("id").toString());
+        Map<String, Object> kakaoAccount = (Map<String, Object>) userInfo.get("kakao_account");
+        Map<String, Object> profile = (Map<String, Object>) kakaoAccount.get("profile");
+
+        String email = kakaoAccount.get("email").toString();
+        String nickname = profile.get("nickname").toString();
+        String profileImage = profile.get("profile_image_url").toString();
+
+//        Users user = usersRepository.findByKaKaoId(kakaoId).orElseGet(() -> {
+//            Users newUser = new Users(email, nickname, profileImage, kakaoId);
+//            usersRepository.save(newUser);
+//            return newUser;
+//        });
+        String userId;
+        Optional<Users> CheckUser = usersRepository.findByKaKaoId(Long.valueOf(kakaoId));
+        System.out.println("CheckUser : " + CheckUser);
+        if (CheckUser.isEmpty()){
+            Users newUser = new Users(email, nickname, profileImage, Long.valueOf(kakaoId));
+            usersRepository.save(newUser);
+
+            // 처음 로그인 한 사람은 모든 링크 보기 폴더가 없음 만들어주어야함
+            Folders folder = new Folders(newUser, "모든 링크", "모든 링크가 저장된 폴더입니다.", false);
+            foldersRepository.save(folder);
+
+            UserProfileResponse userProfileResponse = new UserProfileResponse(newUser.getUserId(), newUser.getEmail(), newUser.getNickname(), newUser.getProfile(), newUser.getKakaoId());
+            return ResponseEntity.ok(userProfileResponse);
+        }
+        else
+        {
+            Users existingUser = CheckUser.get();
+            UserProfileResponse userProfileResponse = new UserProfileResponse(existingUser.getUserId(), existingUser.getEmail(), existingUser.getNickname(), existingUser.getProfile(), existingUser.getKakaoId());
+            return ResponseEntity.ok(userProfileResponse);
+        }
+
+
+//        return ResponseEntity.ok(Map.of(
+//                "userId", user.getUserId(),
+//                "nickname", user.getNickname(),
+//                "email", user.getEmail(),
+//                "profile", user.getProfile()
+//        ));
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: whitecy01
body: 넵
created_at: 2025-04-09T11:47:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: whitecy01
body: 글을 한 번 읽어보고 생각이 든 건   "https://kapi.kakao.com/v2/user/me"을 정적 변수로 만들어서 위로 뺴는 걸로 생각했는데 접근 방법이 맞을까요?
created_at: 2025-04-09T11:55:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: whitecy01
body: 그리고 질문이 하나 있습니다 보통 C언어나 C++은 Header라는 파일을 만들어서 전역 변수를 한 번에 보기 쉽게 코드드를 작성하는데 AuthController에서만 정적 변수를 하나 작성한다면 다른 소스 파일에서 이 정적 변수에 대한 존재? 같은 게 찾기가 좀 어려울 것 같다는 생각이 들어 좀 찾아보게 되었습니다

https://www.baeldung.com/java-constants-good-practices
대규모 전역 상수 클래스에 내용이 있습니다

읽어보니 Constants 또는 Utils라는 이름의 클래스를 만들어서 정적 변수를 관리한다고 합니다

Constansts 클래스 하나 만들어서 정적변수 담아놓겠습니다
created_at: 2025-04-09T12:19:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: 네 링크 확인했는데, Constants 클래스로 관리하는 것도 좋습니다.
다만, 변수로 관리될 데이터가 다수일 경우에 관리하기 좋을 것 같습니다.

Constants 클래스를 만들어서 관리하셔도 좋은 것 같고
제가 의도한것은 정적 변수로 링크를 페이지 상위에 위치하여 관리하는 것을 말하였는데, 레퍼런스 설명이 조금 부족했던것 같습니다.
created_at: 2025-04-09T12:53:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: 다른 소스 파일에서 해당 정적변수를 참조해야할 경우가 혹시 현재 고려중인 부분이 있을까요?

그부분에 대해서는 아직 생각하지 않았는데 변수를 공유자원으로 확장할 의도를 가지고 있다면 Constants 클래스가 좋아보이네요
created_at: 2025-04-09T12:55:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: whitecy01
body: 카카오에 요청할 유저 조회 URL은 AuthController에서만 사용할 것 같습니다. 다음에 토큰 관리 방향에서 처리할 때는 카카오 토큰 조회 API를 사용할 것 같지만 공유자원으로 확장 되지는 않을 것 같아서 그러면 확장할 의도에서 본다면Constansts 클래스 굳이 필요하지 않을 것 같다는 생각이 듭니다
created_at: 2025-04-09T13:00:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: amazon7737
body: 참고하면 좋을 내용 코멘트 드립니다.

디미터 법칙 : 다른 객체가 어떤 자료를 가지고 있는지 몰라야 한다

객체가 전달받기 위한 수단은 오직 메시지(메서드) 이어야만한다.

### User 엔티티 자체에서 디미터 법칙을 지키는 방법

```java
public class User {

    private String email;
    private String name;
    private Address address;


    public static User createUser(...) {
      return new User(...);
    }

}


```

#### 자주 사용하는 상황

호출할 메서드에서 받는 값이 그렇게 유연하게 변화하지 않고
엔티티를 빨리생성하고 save 처리를 단순하게 할때는 User의 메서드 역할로도 충분하다

### 정적 팩토리 메서드 패턴을 활용한 생성자 함수 처리 방법


```java
public class User {

    private String email;
    private String name;
    private Address address;

}

public class UserRequest {

    private String name;
    private String email;

    public static User of (String email, String name) {
      return new User(...);
    }

}

```


DTO를 활용하여 of, from의 원칙을 지켜 의도를 분명히 하라.
of 는 파라미터 여러개
from 은 파라미터 1개

dto를 유연하게 활용하고 싶다면 고려해볼 수 있다.

이펙티브 자바에서는 생성자함수보다는 정적 팩토리메서드 를 고려하라는 권장사항도 기재되어있다.
(이펙티브 자바 3판 2장 아이템1 8페이지 참고)

#### 장점

생성 목적에 대한 이름 표현이 가능하다.

인스턴스에 대해 통제 및 관리가 가능하다


추가적인 자료 : https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EC%A0%95%EC%A0%81-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%83%9D%EC%84%B1%EC%9E%90-%EB%8C%80%EC%8B%A0-%EC%82%AC%EC%9A%A9%ED%95%98%EC%9E%90


created_at: 2025-04-09T13:26:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,96 @@
+package com.Kkrap.Controller;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.ResponseDto.UserProfileResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    @Autowired
+    UsersRepository usersRepository;
+
+    @Autowired
+    FoldersRepository foldersRepository;
+
+    //토큰 관리 방식
+    @PostMapping("/kakao-login")
+    public ResponseEntity<?> kakaoLogin(@RequestBody KaKaoTokenRequest request){
+        String accessToken = request.getAccesstoken();
+
+
+
+        //1. 카카오 유저 정보 요청
+        HttpHeaders headers = new HttpHeaders();
+        headers.setBearerAuth(accessToken);
+        HttpEntity<?> entity = new HttpEntity<>(headers);
+
+        ResponseEntity<Map> response = new RestTemplate().exchange(
+                "https://kapi.kakao.com/v2/user/me",
path: src/main/java/com/Kkrap/Controller/AuthController.java
user: login: whitecy01
body: 감사합니다!! 공부하고 다시 코멘트 달겠습니다.
created_at: 2025-04-09T13:33:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -31,15 +31,9 @@ public String login(){
     //users 프로필 조회
     @GetMapping("/{userId}")
     @ResponseBody
-    public ResponseEntity<UserProfileResponse> getUserProfile(@PathVariable("userId") Long userId)
+    public ResponseEntity<Object> getUserProfile(@PathVariable("userId") Long userId)
path: src/main/java/com/Kkrap/Controller/UsersController.java
user: login: amazon7737
body: Object 로 반환중이네요. 혹시 이유가 있을까요? :)
created_at: 2025-04-15T15:04:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -35,23 +36,21 @@ public class Users {
     @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
     private List<Folders> folders;
 
-//    // Links와의 관계 추가
-//    @OneToMany(mappedBy = "users", cascade = CascadeType.ALL)
-////    @JsonIgnore // 순환 참조 방지
-//    private List<Links> links;
 
+    private Users() { } // 외부에서 new 사용 못하게 보호
path: src/main/java/com/Kkrap/Entity/Users.java
user: login: amazon7737
body: Users 생성자 함수를 보호하시는 이유가 있으실까요?
created_at: 2025-04-15T15:05:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -35,23 +36,21 @@ public class Users {
     @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
     private List<Folders> folders;
 
-//    // Links와의 관계 추가
-//    @OneToMany(mappedBy = "users", cascade = CascadeType.ALL)
-////    @JsonIgnore // 순환 참조 방지
-//    private List<Links> links;
 
+    private Users() { } // 외부에서 new 사용 못하게 보호
 
+    //정적 팩토리 메서드
+    public static Users from(UsersCreateRequest usersCreateRequest) {
+        return new Users(usersCreateRequest.getEmail(), usersCreateRequest.getNickname(), usersCreateRequest.getProfileImage(), usersCreateRequest.getKakaoId());
+    }
 
     @Builder
-    public Users(String email, String nickname, String profile, Long kakaoId)
+    private Users(String email, String nickname, String profile, Long kakaoId)
     {
         this.email = email;
         this.nickname = nickname;
         this.profile = profile;
         this.kakaoId = kakaoId;
     }
path: src/main/java/com/Kkrap/Entity/Users.java
user: login: amazon7737
body: Builder 어노테이션을 생성자함수에 추가해두셨는데, 내용은 멤버변수 주입이네요.
Builder 기능이 사용되지 않는 것으로 보입니다.
created_at: 2025-04-15T15:06:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,87 @@
+package com.Kkrap.Service;
+
+import com.Kkrap.Entity.Folders;
+import com.Kkrap.Entity.Users;
+import com.Kkrap.Repository.FoldersRepository;
+import com.Kkrap.Repository.UsersRepository;
+import com.Kkrap.RequestDTO.FoldersCreateRequest;
+import com.Kkrap.RequestDTO.KaKaoTokenRequest;
+import com.Kkrap.RequestDTO.UsersCreateRequest;
+import com.Kkrap.ResponseDto.MessageResponse;
+import com.Kkrap.ResponseDto.UserProfileDefaultFolderResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.*;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+
+@Service
+public class AuthService {
+
+    public static final String KAKAO_USER_INFO_URL = "https://kapi.kakao.com/v2/user/me";
+
+    @Autowired
+    UsersRepository usersRepository;
path: src/main/java/com/Kkrap/Service/AuthService.java
user: login: amazon7737
body: UserRepository 주입
계층 구조 지켜주시기 바래요
created_at: 2025-04-15T15:09:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -46,11 +43,20 @@ public class Folders {
     @OneToMany(mappedBy = "folders", cascade = CascadeType.ALL)
     private List<FoldersLinks> foldersLinks;
 
-
     public Folders(Users user, String folderName, String folderDescription, boolean isPublic) {
         this.user = user;
         this.folderName = folderName;
         this.folderDescription = folderDescription;
         this.isPublic = isPublic;
     }
+
+    private Folders() {} //외부에서 new 사용 못하게 보호
+
+    public boolean getIsPublic() {
+        return isPublic;
+    }
path: src/main/java/com/Kkrap/Entity/Folders.java
user: login: amazon7737
body: get + IsPublic 으로 명시하셨는데
boolean을 반환하는 메소드이니 isPublic 으로 작성하셔도 오해없을것 같습니다!


created_at: 2025-04-15T15:13:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -14,16 +20,12 @@ public class UsersService {
     @Autowired
     private UsersRepository usersRepository;
 
-    public UserProfileResponse getUserProfile(Long userId){
-        Optional<Users> optionalUsers = usersRepository.findById(userId);
-
-        if (optionalUsers.isPresent()){
-            Users user = optionalUsers.get();
-            return new UserProfileResponse(user.getUserId(),user.getEmail(), user.getNickname(), user.getProfile(), user.getKakaoId());
-        }
-        else {
-            return  null;
+    public ResponseEntity<Object> getUserProfile(Long userId){
+        Users users = get(userId);
+        if (users == null){
+            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(MessageResponse.of(404,"사용자를 찾을 수 없음"));
         }
+        return ResponseEntity.ok(UserProfileDefaultFolderResponse.of(users.getUserId(),users.getEmail(), users.getNickname(), users.getProfile(), users.getKakaoId()));
path: src/main/java/com/Kkrap/Service/UsersService.java
user: login: amazon7737
body: 반환타입에 Object 가 아닌 Response dto로 작성이 힘든가요?
created_at: 2025-04-15T15:14:49Z
author_association: CONTRIBUTOR

PR comments:
user: login: whitecy01
created_at: 2025-04-10T09:18:13Z
body: 정적 팩토리 메서드 디미터 법칙 공부하였고 코드 전체를 수정해야될 것 같아서 좀 걸릴 것 같습니다.. commit 올리면 다시 연락드리겠습니다!
author_association: CONTRIBUTOR
user: login: whitecy01
created_at: 2025-04-16T05:59:52Z
body: 넵 감사합니다! 
나중에 Links랑 FoldersLinks 작업도 되면 커밋 올리겠습니다! 😳
author_association: CONTRIBUTOR