Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
e6739f5
feat/SW-38/Back(Infra): PostgreSQL 마이그레이션 및 Docker 환경 구성
jin2304 Feb 4, 2026
4856d7f
feat/SW-38/chore(DB): DB 초기화 및 삭제 스크립트 추가
jin2304 Feb 7, 2026
64cf206
feat/SW-38/chore(DB): BaseEntity 및 의존성 추가
jin2304 Feb 7, 2026
1cd3671
feat/SW-38/refactor(Member): PostgreSQL 마이그레이션에 따른 소셜 Member 도메인 수정
jin2304 Feb 7, 2026
83f1789
feat/SW-38/refactor(Member): PostgreSQL 마이그레이션에 따른 소셜 Member 도메인 수정
jin2304 Feb 7, 2026
fef5873
feat/SW-38/refactor(Bookmark): PostgreSQL 마이그레이션에 따른 Bookmark 도메인 수정
jin2304 Feb 7, 2026
a1ea3ce
feat/SW-38/refactor(Board): PostgreSQL 마이그레이션에 따른 Board 도메인 수정
jin2304 Feb 7, 2026
f17b23e
feat/SW-38/refactor(Comment): PostgreSQL 마이그레이션에 따른 Comment 도메인 수정
jin2304 Feb 7, 2026
f316145
feat/SW-38/refactor(Like): PostgreSQL 마이그레이션에 따른 Like 도메인 수정
jin2304 Feb 7, 2026
21f5792
feat/SW-38/refactor(Main): PostgreSQL 마이그레이션에 따른 Main(웹사이트 목록) 도메인 수정
jin2304 Feb 7, 2026
14d5f74
feat/SW-38/feat(Link): PostgreSQL 마이그레이션에 따른 Link 도메인 추가
jin2304 Feb 7, 2026
4ba6e94
feat/SW-38/refactor(Back): PostgreSQL 마이그레이션에 따른 마이페이지 및 AOP 수정
jin2304 Feb 7, 2026
3916d15
feat/SW-38/refactor(Front): PostgreSQL 마이그레이션에 프론트페이지 수정
jin2304 Feb 7, 2026
f7c3a55
feat/SW-38/chore: 주석 수정
jin2304 Feb 7, 2026
7fd31f3
feat/SW-38/chore: 민감정보 노출 방지를 위한 환경변수 적용
jin2304 Feb 7, 2026
7d66739
feat/SW-38/feat: BaseEntity - MyBatis용 markAsCreated 메서드 추가 (수동 Audit…
jin2304 Feb 10, 2026
76d4b86
feat/SW-38/feat: Bookmark, Link, Member에 @ToString(callSuper = true) 적용
jin2304 Feb 10, 2026
cd740a6
feat/SW-38/refactor: 스키마 표준화 및 제약조건 강화
jin2304 Feb 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

들여쓰기 불일치: 탭 대신 공백이 사용되었습니다.

Line 31은 공백 4칸으로 들여쓰기되어 있지만, 나머지 dependencies 블록은 탭을 사용합니다.

🔧 수정 제안
-    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
+	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
📝 Committable suggestion

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

Suggested change
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
🤖 Prompt for AI Agents
In `@build.gradle` at line 31, The dependency line "implementation
'org.springframework.boot:spring-boot-starter-data-jpa'" in the dependencies
block uses 4 spaces for indentation instead of the tabs used elsewhere; update
the leading whitespace for that line to a single tab so it matches the rest of
the dependencies block formatting (look for the dependencies { ... } block and
the implementation line to correct).

implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'me.paulschwarz:spring-dotenv:4.0.0'

compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'org.postgresql:postgresql'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3'
Expand Down
26 changes: 26 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: '3.8'
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

version 키는 최신 Docker Compose에서 더 이상 사용되지 않습니다.

Docker Compose V2부터 version 필드는 무시되며, 향후 경고가 발생할 수 있습니다. 해당 라인을 제거해도 무방합니다.

🤖 Prompt for AI Agents
In `@docker-compose.yml` at line 1, docker-compose.yml에서 더 이상 사용되지 않는 `version:
'3.8'` 키를 제거하세요; Docker Compose V2는 `version` 필드를 무시하므로 해당 줄(`version: '3.8'`)을
삭제하면 되고 다른 서비스/volume/network 정의에는 영향이 없도록 파일 나머지 구조를 그대로 유지하세요.


services:
postgres:
image: postgres:16
container_name: searchweb-db
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
TZ: Asia/Seoul
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
# - ./src/main/resources/db/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- searchweb-network
restart: always
Comment on lines +3 to +19
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

PostgreSQL 컨테이너에 healthcheck 설정이 누락되었습니다.

애플리케이션이 이 컨테이너에 의존하는 경우, healthcheck 없이는 DB가 준비되기 전에 연결을 시도할 수 있습니다.

♻️ healthcheck 추가 제안
     restart: always
+    healthcheck:
+      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
+      interval: 10s
+      timeout: 5s
+      retries: 5
📝 Committable suggestion

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

Suggested change
services:
postgres:
image: postgres:16
container_name: searchweb-db
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
TZ: Asia/Seoul
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
# - ./src/main/resources/db/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- searchweb-network
restart: always
services:
postgres:
image: postgres:16
container_name: searchweb-db
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
TZ: Asia/Seoul
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
# - ./src/main/resources/db/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- searchweb-network
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
🤖 Prompt for AI Agents
In `@docker-compose.yml` around lines 3 - 19, The postgres service (container_name
searchweb-db) is missing a Docker healthcheck; add a healthcheck section under
the postgres service that runs a sensible readiness probe (e.g., pg_isready or
equivalent) using the container's POSTGRES_USER/POSTGRES_DB, and set interval,
timeout, retries and start_period so other services wait until the DB is ready;
update the docker-compose postgres service to include this healthcheck section
and ensure restart: always stays in place so Docker can manage restarts based on
health status.


networks:
searchweb-network:
driver: bridge

volumes:
postgres_data:
28 changes: 17 additions & 11 deletions src/main/java/com/web/SearchWeb/aop/OwnerCheckAspect.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
import java.util.Arrays;
import java.util.Objects;

/**
* OwnerCheckAspect
*
* 리소스 소유자 검증 AOP
*/
@Aspect
@Slf4j(topic = "[OwnerCheckAspect]")
@Component
Expand All @@ -34,14 +39,14 @@ public class OwnerCheckAspect {
@Before("@annotation(ownerCheck)")
public void validateOwner(JoinPoint joinPoint, OwnerCheck ownerCheck) {
// 접근 검증 대상 리소스의 ID 추출
Integer targetId = extractTargetIdFromParams(joinPoint, ownerCheck.idParam());
Long targetId = extractTargetIdFromParams(joinPoint, ownerCheck.idParam());

// 현재 로그인한 사용자의 memberId 추출
Authentication auth = validateAuthenticatedUser();
Integer currentUserId = extractMemberId(auth);
Long currentUserId = extractMemberId(auth);

// 서비스 이름에 따라 리소스 작성자 memberId 조회
Integer ownerId = findOwnerIdByServiceName(ownerCheck.service(), targetId);
Long ownerId = findOwnerIdByServiceName(ownerCheck.service(), targetId);

// 현재 사용자와 리소스 소유자 검증
if (!Objects.equals(currentUserId, ownerId)) {
Expand All @@ -54,29 +59,30 @@ public void validateOwner(JoinPoint joinPoint, OwnerCheck ownerCheck) {


/**
* 접근 검증 대상이 되는 리소스의 ID를 파라미터 이름(idParam)을 통해 찾아 Integer로 반환
* 접근 검증 대상이 되는 리소스의 ID를 파라미터 이름(idParam)을 통해 찾아 Long으로 반환
* ex) @OwnerCheck(idParam = "boardId", ...) -> 메서드의 boardId 값을 찾아 사용
*
* @param joinPoint 현재 실행된 메서드의 실행 정보
* @param idParam 검증 대상 리소스 ID의 파라미터 이름 (예: "boardId" 문자열)
* @return 접근 검증 대상이 되는 리소스의 ID 값
*/
private Integer extractTargetIdFromParams(JoinPoint joinPoint, String idParam) {
private Long extractTargetIdFromParams(JoinPoint joinPoint, String idParam) {
Object[] args = joinPoint.getArgs(); // 메서드 실제 인자 값 배열
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] paramNames = signature.getParameterNames(); // 메서드 파라미터 이름 배열

for (int i = 0; i < paramNames.length; i++) {
if (paramNames[i].equals(idParam)) {
return Integer.parseInt(args[i].toString());
// Integer나 Long 모두 지원하도록 String으로 변환 후 parse
return Long.parseLong(args[i].toString());
}
}
log.error("{}' 파라미터를 찾을 수 없음. 실제 파라미터: {}", idParam, Arrays.toString(paramNames));
throw new IllegalArgumentException("요청 파라미터에서 ID를 찾을 수 없습니다.");
}
Comment on lines +69 to 82
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

args[i]null일 경우 NullPointerException 발생 가능.

Line 77에서 args[i].toString()을 호출하기 전에 null 체크가 없습니다. 컨트롤러 메서드의 파라미터가 null로 전달될 수 있으며 (예: 선택적 @RequestParam), 이 경우 NPE가 발생합니다.

🛡️ 수정 제안
         for (int i = 0; i < paramNames.length; i++) {
             if (paramNames[i].equals(idParam)) {
-                // Integer나 Long 모두 지원하도록 String으로 변환 후 parse
-                return Long.parseLong(args[i].toString());
+                if (args[i] == null) {
+                    throw new IllegalArgumentException("ID 파라미터 '" + idParam + "'가 null입니다.");
+                }
+                return Long.parseLong(args[i].toString());
             }
         }
🤖 Prompt for AI Agents
In `@src/main/java/com/web/SearchWeb/aop/OwnerCheckAspect.java` around lines 69 -
82, In extractTargetIdFromParams(JoinPoint, String) add a null check for args[i]
before calling toString(): if args[i] is null, log a clear error including
idParam and paramNames and throw IllegalArgumentException (or return a safe
value if desired) instead of letting a NullPointerException propagate; also
guard Long.parseLong with try/catch(NumberFormatException) to convert bad inputs
into a controlled IllegalArgumentException with context so callers see a
descriptive error rather than an NPE or parse crash.



// SecurityContext 에서 인증된 사용자 반한
// SecurityContext 에서 인증된 사용자 반환
private Authentication validateAuthenticatedUser() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null || !auth.isAuthenticated() || "anonymousUser".equals(auth.getPrincipal())) {
Expand All @@ -87,8 +93,8 @@ private Authentication validateAuthenticatedUser() {
}


// 인증 객체에서 현재 로그인한 사용자 memberId 추출
private Integer extractMemberId(Authentication auth) {
// 인증 객체에서 현재 로그인한 사용자 memberId 추출 (Long 반환)
private Long extractMemberId(Authentication auth) {
Object principal = auth.getPrincipal();
if (principal instanceof CustomUserDetails u) return u.getMemberId();
if (principal instanceof CustomOAuth2User u) return u.getMemberId();
Expand All @@ -98,11 +104,11 @@ private Integer extractMemberId(Authentication auth) {


// 서비스 이름에 따라 해당 리소스의 작성자 조회
private Integer findOwnerIdByServiceName(String service, Integer targetId) {
private Long findOwnerIdByServiceName(String service, Long targetId) {
return switch (service) {
case "boardService" -> boardService.findMemberIdByBoardId(targetId);
case "commentService" -> commentService.findMemberIdByCommentId(targetId);
case "memberService" -> targetId;
case "memberService" -> targetId; // memberService의 경우 targetId가 곧 memberId
default -> {
log.error("지원하지 않는 서비스명 '{}'", service);
throw new IllegalArgumentException("지원하지 않는 서비스명입니다.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,9 @@
import java.util.Map;

/**
* 코드 작성자:
* - 서진영(jin2304)
*
* 코드 설명:
* - BoardController는 게시판 및 게시글 관련 기능을 처리하는 컨트롤러
*
* 코드 주요 기능:
* - 게시글 등록, 게시글 목록 조회(검색어, 최신순/인기순), 게시글 단일(상세) 조회, 게시글 수정, 게시글 삭제
* - 게시글 좋아요/북마크 추가 및 취소
*
* 코드 작성일:
* - 2024.08.24 ~ 2024.09.05
* BoardController (Legacy - PostgreSQL)
*
* 게시판 및 게시글 관련 기능을 처리하는 컨트롤러
*/
@Controller
public class BoardController {
Expand All @@ -55,15 +46,6 @@ public BoardController(BoardService boardservice, MemberService memberservice, L
}


/**
* 게시글 생성
*/
@PostMapping("/board/{memberId}/post")
public String insertBoard(@PathVariable int memberId, BoardDto boardDto){
int result = boardservice.insertBoard(memberId, boardDto);
return "redirect:/board";
}



/**
Expand All @@ -76,27 +58,20 @@ public String boardPage() {


/**
* 페이징된 게시글 목록 조회
* - 검색어, 최신순/인기순, 게시글타입
* - 스크롤 방식으로 페이징 지원
* - 클라이언트(JS)에서 스크롤 이벤트 발생 시 요청
* 게시글 생성
*/
@ResponseBody
@GetMapping("api/boards")
public Map<String, Object> getBoards(@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "newest") String sort,
@RequestParam(required = false) String query,
@RequestParam(defaultValue = "all") String postType) {
return boardservice.selectBoardPage(page, size, sort, query, postType);
@PostMapping("/board/{memberId}/post")
public String insertBoard(@PathVariable Long memberId, BoardDto boardDto){
int result = boardservice.insertBoard(memberId, boardDto);
return "redirect:/board";
}


/**
* 게시글 단일 조회
*/
@GetMapping("/board/{boardId}")
public String boardDetail(@PathVariable int boardId,@AuthenticationPrincipal Object currentUser, Model model){
public String boardDetail(@PathVariable Long boardId, @AuthenticationPrincipal Object currentUser, Model model){
Map<String, Object> boardData = boardservice.selectBoard(boardId);
Board board = (Board) boardData.get("board");
String[] hashtagsList = (String[]) boardData.get("hashtagsList");
Expand All @@ -106,7 +81,7 @@ public String boardDetail(@PathVariable int boardId,@AuthenticationPrincipal Obj

// 사용자가 로그인된 상태라면, 좋아요 여부를 확인하여 모델에 추가
if (currentUser != null && !"anonymousUser".equals(currentUser)) {
int memberId;
Long memberId;
if(currentUser instanceof UserDetails) {
// 일반 로그인 사용자 처리
memberId = ((CustomUserDetails) currentUser).getMemberId();
Expand All @@ -129,12 +104,29 @@ else if(currentUser instanceof OAuth2User) {
}


/**
* 페이징된 게시글 목록 조회
* - 검색어, 최신순/인기순, 게시글타입
* - 스크롤 방식으로 페이징 지원
* - 클라이언트(JS)에서 스크롤 이벤트 발생 시 요청
*/
@ResponseBody
@GetMapping("api/boards")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

api/boards 경로에 선행 슬래시(/)가 누락되어 있습니다.

이 컨트롤러의 다른 모든 엔드포인트는 /board, /board/{boardId} 등 선행 슬래시를 사용합니다. 일관성을 위해 /api/boards로 수정하세요.

🔧 수정 제안
-    `@GetMapping`("api/boards")
+    `@GetMapping`("/api/boards")
📝 Committable suggestion

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

Suggested change
@GetMapping("api/boards")
`@GetMapping`("/api/boards")
🤖 Prompt for AI Agents
In `@src/main/java/com/web/SearchWeb/board/controller/BoardController.java` at
line 114, The `@GetMapping` annotation in BoardController (the mapping currently
written as "api/boards") is missing the leading slash; update the mapping value
in the BoardController class (the `@GetMapping` on the method handling boards)
from "api/boards" to "/api/boards" so it matches the other endpoints like
"/board" and "/board/{boardId}" and preserves routing consistency.

public Map<String, Object> getBoards(@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "newest") String sort,
@RequestParam(required = false) String query,
@RequestParam(defaultValue = "all") String postType) {
return boardservice.selectBoardPage(page, size, sort, query, postType);
}


/**
* 게시글 수정
*/
@PostMapping("/board/{boardId}/update")
@OwnerCheck(idParam = "boardId", service = "boardService")
public String updateBoard(@PathVariable int boardId, BoardDto boardDto){
public String updateBoard(@PathVariable Long boardId, BoardDto boardDto){
boardservice.updateBoard(boardId, boardDto);
return "redirect:/board/{boardId}";
}
Expand All @@ -145,7 +137,7 @@ public String updateBoard(@PathVariable int boardId, BoardDto boardDto){
*/
@PostMapping("/board/{boardId}/delete")
@OwnerCheck(idParam = "boardId", service = "boardService")
public String deleteBoard(@PathVariable int boardId) {
public String deleteBoard(@PathVariable Long boardId) {
boardservice.deleteBoard(boardId);
return "redirect:/board";
}
Expand All @@ -156,7 +148,7 @@ public String deleteBoard(@PathVariable int boardId) {
*/
@PostMapping("/board/{boardId}/like")
@ResponseBody
public Map<String, Object> toggleLike(@PathVariable int boardId, @AuthenticationPrincipal Object currentUser) {
public Map<String, Object> toggleLike(@PathVariable Long boardId, @AuthenticationPrincipal Object currentUser) {

Map<String, Object> response = new HashMap<>();

Expand All @@ -168,7 +160,7 @@ public Map<String, Object> toggleLike(@PathVariable int boardId, @Authentication
}

// 로그인 된 경우
int memberId;
Long memberId;
if(currentUser instanceof UserDetails) {
// 일반 로그인 사용자 처리
memberId = ((CustomUserDetails) currentUser).getMemberId();
Expand All @@ -192,8 +184,8 @@ else if(currentUser instanceof OAuth2User) {
*/
@PostMapping(value ="/board/{boardId}/bookmark/{memberId}")
public ResponseEntity<Map<String, Object>> toggleBookmark(
@PathVariable final int boardId,
@PathVariable final int memberId,
@PathVariable final Long boardId,
@PathVariable final Long memberId,
@RequestBody BookmarkDto bookmarkDto,
@AuthenticationPrincipal Object currentUser){
Map<String, Object> response = new HashMap<>();
Expand All @@ -211,7 +203,7 @@ public ResponseEntity<Map<String, Object>> toggleBookmark(

if (bookmarkExists == 0) {
// 북마크가 안 되어 있으면 북마크 추가
bookmarkService.insertBookmarkForBoard(bookmarkDto);
bookmarkService.insertBookmarkForBoard(boardId, bookmarkDto);
boardservice.incrementBookmarkCount(boardId); // 북마크 추가 시 게시글의 북마크 수 증가
response.put("action", "bookmarked");
} else {
Expand Down
24 changes: 12 additions & 12 deletions src/main/java/com/web/SearchWeb/board/dao/BoardDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

public interface BoardDao {
//게시글 생성
public int insertBoard(int memberId, BoardDto boardDto);
public int insertBoard(Long memberId, BoardDto boardDto);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find mapper XML files and implementation
find . -name "*board*mapper*.xml" -o -name "*BoardDao*.java" | head -20

Repository: Searchweb-Dev/Searchweb-Back

Length of output: 239


🏁 Script executed:

#!/bin/bash
# Search for BoardDao.java to inspect the interface
fd "BoardDao.java" -x cat {}

Repository: Searchweb-Dev/Searchweb-Back

Length of output: 4453


🏁 Script executed:

#!/bin/bash
# Search for board-mapper.xml to check parameter binding
fd "board.*mapper.*xml" -x cat {}

Repository: Searchweb-Dev/Searchweb-Back

Length of output: 5530


다중 파라미터 메서드에 @Param 어노테이션이 필수입니다.

insertBoard(Long memberId, BoardDto boardDto), updateBoard, updateBoardProfile, updateBookmarkCount 메서드는 여러 개의 파라미터를 받습니다. board-mapper.xmlparameterType="map"과 함께 #{memberId}, #{boardId}, #{job} 같은 명시적 이름의 매개변수 바인딩을 사용하려면 각 파라미터에 @Param 어노테이션이 필수입니다. 없으면 런타임에 BindingException이 발생합니다.

수정 제안
-    public int insertBoard(Long memberId, BoardDto boardDto);
+    public int insertBoard(`@Param`("memberId") Long memberId, `@Param`("boardDto") BoardDto boardDto);
-    int updateBoard(Long boardId, BoardDto boardDto);
+    int updateBoard(`@Param`("boardId") Long boardId, `@Param`("boardDto") BoardDto boardDto);
-    int updateBoardProfile(Long boardId, String job, String major);
+    int updateBoardProfile(`@Param`("boardId") Long boardId, `@Param`("job") String job, `@Param`("major") String major);
-    int updateBookmarkCount(Long boardId, int bookmarkCount);
+    int updateBookmarkCount(`@Param`("boardId") Long boardId, `@Param`("bookmarkCount") int bookmarkCount);

또한 countBoardList(String query, String postType) 메서드도 마찬가지로 @Param 어노테이션 추가가 필요합니다:

-    int countBoardList(String query, String postType);
+    int countBoardList(`@Param`("query") String query, `@Param`("postType") String postType);
🤖 Prompt for AI Agents
In `@src/main/java/com/web/SearchWeb/board/dao/BoardDao.java` at line 12, BoardDao
인터페이스의 다중 파라미터 메서드들에서 MyBatis 매퍼의 명시적 이름 바인딩(#{memberId}, #{boardId}, #{job},
#{query}, #{postType} 등)을 사용하고 있으므로 각 파라미터에 `@Param` 어노테이션을 추가하세요; 구체적으로
insertBoard(Long memberId, BoardDto boardDto), updateBoard(...),
updateBoardProfile(...), updateBookmarkCount(...), countBoardList(String query,
String postType)의 모든 파라미터에 `@Param을` 붙이고 각 어노테이션의 값은 매퍼에서 사용하는 이름(예: "memberId",
"boardId", "job", "query", "postType")과 동일하게 지정해 BindingException이 발생하지 않도록
수정하세요.


// 페이징된 게시글 목록 조회
List<Board> selectBoardPage(@Param("offset") int offset,
Expand All @@ -22,35 +22,35 @@ List<Board> selectBoardPage(@Param("offset") int offset,
int countBoardList(String query, String postType);

//게시글 목록 조회(회원번호로 조회)
List<Board> selectBoardListByMemberId(int memberId);
List<Board> selectBoardListByMemberId(Long memberId);

//게시글 단일 조회
Board selectBoard(int boardId);
Board selectBoard(Long boardId);

//게시글 수정
int updateBoard(int boardId, BoardDto boardDto);
int updateBoard(Long boardId, BoardDto boardDto);

//게시글 수정(회원정보 수정)
int updateBoardProfile(int boardId, String job, String major);
int updateBoardProfile(Long boardId, String job, String major);

//게시글 삭제
int deleteBoard(int boardId);
int deleteBoard(Long boardId);

//게시글 북마크 수 수정
int updateBookmarkCount(int boardId, int bookmarkCount);
int updateBookmarkCount(Long boardId, int bookmarkCount);

//게시글 조회수 증가
int incrementViewCount(int boardId);
int incrementViewCount(Long boardId);

//게시글 좋아요 증가
int incrementLikeCount(int boardId);
int incrementLikeCount(Long boardId);

//게시글 좋아요 감소
int decrementLikeCount(int boardId);
int decrementLikeCount(Long boardId);

//게시글 댓글 수 증가
int incrementCommentCount(int boardId);
int incrementCommentCount(Long boardId);

//게시글 댓글 수 감소
int decrementCommentCount(int boardId);
int decrementCommentCount(Long boardId);
}
Loading