๐Ÿ’ป ์ฝ”๋”ฉ ์ผ๊ธฐ : [์Šคํ”„๋ง ๊ฒŒ์‹œํŒ with React] '๊ฒŒ์‹œํŒ, ํšŒ์›์ •๋ณด ๊ถŒํ•œ ์„ค์ •ํ•˜๊ธฐ' ํŽธ

ybkยท2024๋…„ 5์›” 24์ผ

spring

๋ชฉ๋ก ๋ณด๊ธฐ
40/55
post-thumbnail

๐Ÿ”” '๊ฒŒ์‹œํŒ, ํšŒ์›์ •๋ณด ๊ถŒํ•œ ์„ค์ •ํ•˜๊ธฐ'์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž!


๐Ÿ’Ÿ ๊ธ€ ์ž‘์„ฑ ์‹œ ๊ฒŒ์‹œํŒ ๋‹‰๋„ค์ž„์„ ํšŒ์› ๋‹‰๋„ค์ž„์œผ๋กœ ๋ฐ›๊ธฐ


BoardWrite.jsx(React)

export function BoardWrite() {
  const account = useContext(LoginContext);
	~~

  return (
		~~
        </Box>
        <Box>
          <FormControl>
            <FormLabel>์ž‘์„ฑ์ž</FormLabel>
            <Input readOnly value={account.nickName} />
          </FormControl>
        </Box>
        	~~
  );
}
  • ๊ธฐ์กด์—๋Š” ์ž‘์„ฑ์ž๋ฅผ ๋”ฐ๋กœ ๊ธฐ์ž…ํ–ˆ๋Š”๋ฐ ์ž‘์„ฑ์ž๋ฅผ ๋”ฐ๋กœ ๊ธฐ์ž…ํ•˜์ง€ ์•Š๊ณ  LoginProvider์—์„œ ๋‹‰๋„ค์ž„์„ ๋ฐ›์•„์˜ต๋‹ˆ๋‹ค.
  • LoginProvider์—์„œ ๋‹‰๋„ค์ž„์„ ๋ฐ›์•„์˜ค๋Š” ๊ณผ์ •์€ login์„ ํ–ˆ์„ ๋•Œ setNickName์œผ๋กœ nickName์„ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋‹‰๋„ค์ž„์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

DB์—๋„ ๊ฒŒ์‹œํŒ ์ž‘์„ฑ์ž๋ฅผ member์˜ id๋กœ ๋ฐ”๊ฟ”์ค˜์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”๊ฟ”์ฃผ๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

BoardController.java

 @PostMapping("add")
    @PreAuthorize("isAuthenticated()")
    public ResponseEntity add(
            Authentication authentication,
            @RequestBody Board board) {
        if (service.validate(board)) {
            service.add(board, authentication);
            return ResponseEntity.ok().build();
        } else {
            return ResponseEntity.badRequest().build();
        }
    }

@PostMapping("signup")
@PreAuthorize("isAuthenticated()")
public ResponseEntity signup(Authentication authentication, @RequestBody Member member) {
    if (service.validate(member)) {
        service.add(member);
        return ResponseEntity.ok().build();
    } else {
        return ResponseEntity.badRequest().build();
    }
}
  • ๊ธฐ์กด ๊ธ€์“ฐ๊ธฐ ์ฝ”๋“œ์— ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • @PreAuthorize("isAuthenticated()")์„ ์‚ฌ์šฉํ•˜์—ฌ ํ˜„์žฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํ† ํฐ์œผ๋กœ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

BoardService.java

public void add(Board board, Authentication authentication) {
    board.setMemberId(Integer.valueOf(authentication.getName()));
    mapper.insert(board);
}
  • ๊ธฐ์กด์— ์žˆ๋˜ ์ฝ”๋“œ์—์„œ Authentication์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์‚ฌ์šฉ์ž์˜ ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • ํ† ํฐ์„ ์ƒ์„ฑํ•  ๋•Œ subject๋ฅผ DB์— ์žˆ๋Š” member์˜ Id๋กœ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.(MemberService.java)
  • board ๊ฐ์ฒด์˜ memberId ํ•„๋“œ๋ฅผ authentication.getName()์—์„œ ์–ป์€ ๊ฐ’์„ Integer๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

BoardMapper.java

@Insert("""
        INSERT INTO board (title, content, member_id)
        VALUES (#{title}, #{content}, #{memberId})
        """)
int insert(Board board);
  • board์— writer๋ฅผ ์ง€์šฐ๊ณ  member_id๋กœ ๋ฐ”๊ฟ”์„œ ๊ฒŒ์‹œํŒ์„ ์ถ”๊ฐ€ํ•˜๋Š” ์ฟผ๋ฆฌ๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’Ÿ ์ž‘์„ฑ์ž member์˜ ๋‹‰๋„ค์ž„์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ๊ธฐ


**1. ์ „์ฒด ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ **

BoardMapper.java

@Select("""
        SELECT b.id, b.title , m.nick_name writer
        FROM board b JOIN member m 
        ON b.member_id = m.id 
        ORDER BY b.id DESC
        """)
List<Board> selectAll();
  • ๋ชจ๋“  ๊ฒŒ์‹œ๊ธ€์„ ๋ณด์—ฌ์ค„ ๋•Œ, ๊ฒŒ์‹œํŒ์˜ writer๊ฐ€ ์•„๋‹Œ member์˜ nick_name์„ ๊ฐ€์ ธ์™€ ๋ณด์—ฌ์ค˜์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— board ํ…Œ์ด๋ธ”๊ณผ member ํ…Œ์ด๋ธ”์„ JOIN์„ ํ•ฉ๋‹ˆ๋‹ค.

2. ํ•ด๋‹น id ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ

BoardMapper.java

@Select("""
        SELECT b.id,
               b.title,
               b.content,
               b.inserted,
               m.nick_name writer
        FROM board b JOIN member m ON b.member_id = m.id
        WHERE b.id = #{id}
        """)
Board selectById(Integer id);
  • ํ•ด๋‹น id์˜ ๊ฒŒ์‹œ๊ธ€์— ์ž‘์„ฑ์ž๊ฐ€ writer๊ฐ€ ์•„๋‹Œ member์˜ nick_name์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด board ํ…Œ์ด๋ธ”๊ณผ member ํ…Œ์ด๋ธ”์„ JOIN์„ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’Ÿ ์ž์‹ ์˜ ๊ฒŒ์‹œ๊ธ€๋งŒ ์‚ญ์ œํ•˜๊ธฐ(Delete)


BoardController

@DeleteMapping("{id}")
@PreAuthorize("isAuthenticated()")
public ResponseEntity delete(@PathVariable Integer id,
                             Authentication authentication) {
    if (service.hasAccess(id, authentication)) {
        service.remove(id);
        return ResponseEntity.ok().build();
    }
    return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
  • ๋กœ๊ทธ์ธ์„ ํ–ˆ๋Š”์ง€ @PreAuthorize("isAuthenticated()")๋กœ ํ™•์ธํ•˜๊ณ  ๋งŒ์•ฝ ๋กœ๊ทธ์ธ ํ–ˆ๋‹ค๋ฉด ํ•ด๋‹น id์— ์ ‘๊ทผํ•  ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€ id๊ฐ€ ํ˜„์žฌ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์ด ๋งž๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ๋งž๋‹ค๋ฉด ์„œ๋น„์Šค์—์„œ ํ•ด๋‹น ๊ฒŒ์‹œ๊ธ€์„ ์ œ๊ฑฐํ•ด์ค๋‹ˆ๋‹ค.

BoardService.java

public boolean hasAccess(Integer id, Authentication authentication) {
    Board board = mapper.selectById(id); //๊ฒŒ์‹œ๋ฌผ ๋ฒˆํ˜ธ
    return board.getMemberId().equals(Integer.valueOf(authentication.getName()));
}
  • ๊ฒŒ์‹œ๋ฌผ ๋ฒˆํ˜ธ(board.getMemberId())์™€ ๊ณ„์ •์˜ ์•„์ด๋””(authentication.getName())๊ฐ€ ๊ฐ™๋‹ค๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์•„๋‹ˆ๋ฉด false๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

BoardMapper.java

@Select("""
        SELECT b.id,
               b.title,
               b.content,
               b.inserted,
               m.nick_name writer,
               b.member_id
        FROM board b JOIN member m ON b.member_id = m.id
        WHERE b.id = #{id}
        """)
Board selectById(Integer id);
  • ํšŒ์›์˜ ์•„์ด๋”” ๋ฒˆํ˜ธ๋ฅผ ์•Œ์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— board ํ…Œ์ด๋ธ”์— member_id๋ฅผ ์ถ”๊ฐ€์ค๋‹ˆ๋‹ค.

BoardView.jsx(React)

 axios
      .delete(`/api/board/${id}`, {
        headers: {
          Authorization: `Bearer ${localStorage.getItem("token")}`,
        },
      })
  • DELETE ์š”์ฒญ์„ ํ•  ๋•Œ, Authorization ํ—ค๋”์— Bearer ํ† ํฐ์„ ํฌํ•จ์‹œ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ† ํฐ์ด ์žˆ์–ด์•ผ ์„œ๋ฒ„์—์„œ ์š”์ฒญ์„ ์ธ์ฆํ•˜๊ณ  ๊ถŒํ•œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ํ† ํฐ์„ ๊ฐ™์ด ๋ณด๋‚ด์•ผ๋งŒ ์‚ฌ์šฉ์ž๊ฐ€ ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ถŒํ•œ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์š”์ฒญ์ด ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’Ÿ ์ž์‹ ์˜ ๊ฒŒ์‹œ๊ธ€๋งŒ ์ˆ˜์ •ํ•˜๊ธฐ(Update)


BoardController.java

    @PutMapping("edit")
    @PreAuthorize("isAuthenticated()")
    public ResponseEntity edit(@RequestBody Board board, Authentication authentication) {
        if (!service.hasAccess(board.getId(), authentication)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        if (service.validate(board)) { // ์ œ๋ชฉ, ๋‚ด์šฉ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
            service.edit(board);
            return ResponseEntity.ok().build();
        } else {
            return ResponseEntity.badRequest().build();
        }
    }
  • ๋กœ๊ทธ์ธ์„ ํ–ˆ๋Š”์ง€ @PreAuthorize("isAuthenticated()")๋กœ ํ™•์ธํ•˜๊ณ  ๋งŒ์•ฝ ๋กœ๊ทธ์ธ ํ–ˆ๋‹ค๋ฉด ํ•ด๋‹น board ๊ฐ์ฒด์˜ id์— ์ ‘๊ทผํ•  ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€ board ๊ฐ์ฒด์˜ id๊ฐ€ ํ˜„์žฌ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์ด ๋งž๋Š”์ง€ service์—์„œ ํ™•์ธํ•˜๊ณ  ์•„๋‹ˆ๋ผ๋ฉด FORBIDDEN ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

BoardMapper.java

@Update("""
        UPDATE board SET title=#{title}, content=#{content}
        WHERE id=#{id}
        """)
int update(Board board);
  • UPDATE์—์„œ writer ์ปฌ๋Ÿผ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

BoardEdit.jsx(React)

axios
      .put("/api/board/edit", board, {
        headers: {
          Authorization: `Bearer ${localStorage.getItem("token")}`,
        },
      })
  • PUT ์š”์ฒญ์„ ํ•  ๋•Œ, Authorization ํ—ค๋”์— Bearer ํ† ํฐ์„ ํฌํ•จ์‹œ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ† ํฐ์ด ์žˆ์–ด์•ผ ์„œ๋ฒ„์—์„œ ์š”์ฒญ์„ ์ธ์ฆํ•˜๊ณ  ๊ถŒํ•œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

**BoardView.jsx(React)** ~~~ // BoardView.jsx {account.hasAccess(board.memberId) && ( navigate(`/edit/${board.id}`)} > ์ˆ˜์ • ์‚ญ์ œ )}
- ์ž์‹ ์˜ ๊ฒŒ์‹œ๊ธ€์ด๋ผ๋ฉด, ํ•ด๋‹น ๊ถŒํ•œ์ด ์žˆ๋‹ค๋ฉด ์ˆ˜์ •, ์‚ญ์ œ ๋ฒ„ํŠผ์„ ๋ณด์ด๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

---

### ๐Ÿ’Ÿ **์ž์‹ ์˜ ํšŒ์› ์ •๋ณด๋งŒ ์—ด๋žŒ(READ)**

<br>

**Member.jsx(React)**
```java
axios
      .get(`/api/member/${id}`, {
        headers: {
          Authorization: `Bearer ${localStorage.getItem("token")}`,
        },
      })

if (err.response.status === 403) {
          toast({
            status: "error",
            description: "์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.",
            position: "top-right",
            duration: 1000,
          });
          navigate(-1); //์ด์ „ํ•˜๋ฉด
        }
  • GET ์š”์ฒญ์„ ํ•  ๋•Œ, Authorization ํ—ค๋”์— Bearer ํ† ํฐ์„ ํฌํ•จ์‹œ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ† ํฐ์ด ์žˆ์–ด์•ผ ์„œ๋ฒ„์—์„œ ์š”์ฒญ์„ ์ธ์ฆํ•˜๊ณ  ๊ถŒํ•œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • 404(FOBBDIEN) ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ๋ฐ›์œผ๋ฉด ์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†๋‹ค๋Š” ๋ฉ”์‹œ์ง€๋ฅผ toast๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ณด์ด๊ฒŒ ํ•˜๊ณ  ์ด์ „ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

MemberController.java

@GetMapping("{id}")
@PreAuthorize("isAuthenticated()")
public ResponseEntity get(@PathVariable Integer id, Authentication authentication) {
    if (!service.hasAccess(id, authentication)) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
    }

    Member member = service.get(id);
    if (member == null) {
        return ResponseEntity.notFound().build();
    } else {
        return ResponseEntity.ok().body(member);
    }
}
  • ๋กœ๊ทธ์ธ์„ ํ–ˆ๋Š”์ง€ @PreAuthorize("isAuthenticated()")๋กœ ํ™•์ธํ•˜๊ณ  ๋งŒ์•ฝ ๋กœ๊ทธ์ธ ํ–ˆ๋‹ค๋ฉด ํ•ด๋‹น id์— ์ ‘๊ทผํ•  ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€ id๊ฐ€ ํ˜„์žฌ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์ด ๋งž๋Š”์ง€ ์„œ๋น„์Šค์—์„œ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์•„๋‹ˆ๋ผ๋ฉด FORBIDDEN ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

MemberService.java

    public boolean hasAccess(Integer id, Authentication authentication) {
        return authentication.getName().equals(id.toString());
    }
  • ํ˜„์žฌ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ID(authentication ๊ฐ์ฒด์˜ ์ด๋ฆ„)์™€ ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์ฃผ์–ด์ง„ id๋ฅผ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’Ÿ ์ž์‹ ์˜ ํšŒ์› ์ •๋ณด๋งŒ ์ˆ˜์ •(Update)


MemberController.java

    @PutMapping("modify")
    @PreAuthorize("isAuthenticated()")
    public ResponseEntity modify(@RequestBody Member member, Authentication authentication) {
        if (service.hasAccessModify(member, authentication)) {
            service.modify(member);
            return ResponseEntity.ok().build();
        } else {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
    }
  • ๋กœ๊ทธ์ธ์„ ํ–ˆ๋Š”์ง€ @PreAuthorize("isAuthenticated()")๋กœ ํ™•์ธํ•˜๊ณ  ๋งŒ์•ฝ ๋กœ๊ทธ์ธ ํ–ˆ๋‹ค๋ฉด member ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€ member ๊ฐ์ฒด๊ฐ€ ํ˜„์žฌ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์ด ๋งž๋‹ค๋ฉด ์„œ๋น„์Šค์—์„œ ํ•ด๋‹น member ์ •๋ณด๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

MemberService.java

public boolean hasAccessModify(Member member, Authentication authentication) {
        if (!authentication.getName().equals(member.getId().toString())) {
            return false;
        }
		~~~
}
  • ํ˜„์žฌ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ID์™€ Member ๊ฐ์ฒด์˜ ID๋ฅผ ๋ฌธ์ž๋กค ๋ณ€ํ™˜ํ•˜์—ฌ ๋‘ ๊ฐ’์„ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’Ÿ ์ž์‹ ์˜ ๊ณ„์ •๋งŒ ํšŒ์› ํƒˆํ‡ดํ•˜๊ธฐ(Delete)


MemberController.java

@DeleteMapping("{id}")
@PreAuthorize("isAuthenticated()")
public ResponseEntity delete(@RequestBody Member member,
                             Authentication authentication) {
    if (service.hasAccess(member, authentication)) {
        service.delete(member.getId());
        return ResponseEntity.ok().build();
    }
    return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
  • ๋กœ๊ทธ์ธ์„ ํ–ˆ๋Š”์ง€ @PreAuthorize("isAuthenticated()")๋กœ ํ™•์ธํ•˜๊ณ  ๋งŒ์•ฝ ๋กœ๊ทธ์ธ ํ–ˆ๋‹ค๋ฉด ํ•ด๋‹น member์— ์ ‘๊ทผํ•  ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€ member๊ฐ€ ํ˜„์žฌ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์ด ๋งž๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ๋งž๋‹ค๋ฉด ์„œ๋น„์Šค์—์„œ ์ž์‹ ์˜ ๊ณ„์ •์„ ํƒˆํ‡ดํ•ฉ๋‹ˆ๋‹ค.

MemberService.java

public boolean hasAccess(Member member, Authentication authentication) {
    if (!member.getId().toString().equals(authentication.getName())) {
        return false;
    }
    Member dbMember = mapper.selectById(member.getId());
    if (dbMember == null) {
        return false;
    }

    return passwordEncoder.matches(member.getPassword(), dbMember.getPassword());
}
  • authentication.getName()(์‚ฌ์šฉ์ž์˜ ID)์™€ member ๊ฐ์ฒด์˜ ID๊ฐ€ ๋‹ค๋ฅด๋ฉด ์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Œ false๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ  DB์— ํ•ด๋‹น ๋ฉค๋ฒ„์˜ ID๊ฐ€ ์กฐํšŒ๋˜์ง€ ์•Š์•„๋„ false๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์กฐํšŒ๋˜์–ด ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋น„๋ฐ€๋ฒˆํ˜ธํ™” DB์— ์กฐํšŒ๋œ ๋ฉค๋ฒ„์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด false๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ๊ถŒํ•œ์ด ์—†์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

MemberView.jsx(React)

const account = useContext(LoginContext);

function handleDeleteClick() {
  setIsLoading(true);
  axios
    .delete(`/api/member/${id}`, {
      headers: {
        Authorization: `Bearer ${localStorage.getItem("token")}`,
      },
      data: { id, password },
    })
    .then((res) => {
      toast({
        status: "success",
        description: `${member.id}๋‹˜์ด ํƒˆํ‡ดํ•˜์˜€์Šต๋‹ˆ๋‹ค. `,
        position: "top-right",
        duration: 1000,
      });
      account.logout();
      navigate("/");
    })
    .catch((err) => {
      toast({
        status: "error",
        description: `์˜ฌ๋ฐ”๋ฅธ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.`,
        position: "top-right",
        duration: 1000,
      });
    })
    .finally(() => {
      setIsLoading(false);
      setPassword("");
      onClose();
    });
}
  • account.logout() : ํƒˆํ‡ด์‹œ ๋กœ๊ทธ์•„์›ƒ ๋˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿฅน ํšŒ์› ์‚ญ์ œ ์‹œ, ์ด๋ฏธ ๊ฒŒ์‹œ๊ธ€์ด ์žˆ๋Š” ํšŒ์›์€ ์‚ญ์ œ๊ฐ€ ์•ˆ๋จ...


MemberService.java

public void delete(Integer id) {
    // board ํ…Œ์ด๋ธ”์—์„œ ์ž‘์„ฑํ•œ ๊ธ€ ์ง€์šฐ๊ธฐ
    boardMapper.deleteByMemberId(id);

    // board ์ง€์šด ํ›„ member ํ…Œ์ด๋ธ” ์ง€์šฐ๊ธฐ
    mapper.deleteById(id);
}
  • ํšŒ์› ํƒˆํ‡ด ์‹œ, ํ•ด๋‹น ํšŒ์›์˜ ๊ฒŒ์‹œ๋ฌผ์„ ์ง€์›Œ์ง€๊ณ  ํƒˆํ‡ด๊ฐ€ ๋˜์–ด์„œ ์ˆœ์„œ๋Œ€๋กœ ๋กœ์ง์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • board์—์„œ board์˜ id๋ฅผ ์‚ญ์ œ์‹œํ‚ค๊ณ  member์˜ id๋ฅผ ์‚ญ์ œ์‹œ์ผœ ํšŒ์›์„ ํƒˆํ‡ด์‹œํ‚ต๋‹ˆ๋‹ค.

BoardMapper.java

    @Delete("""
            DELETE FROM board
            WHERE member_id=#{memberId}
            """)
    int deleteByMemberId(Integer memberId);
  • ์‚ญ์ œํ•˜๊ณ  ์‹ถ์€ member ํ…Œ์ด๋ธ”์˜ id๋ฅผ board ํ…Œ์ด๋ธ”์—์„œ memberId๋ฅผ ์‚ญ์ œ์‹œํ‚ต๋‹ˆ๋‹ค.

axios ํ† ํฐ์„ ๊ณ„์†ํ•ด์„œ ์ถ”๊ฐ€์‹œ์ผœ์ค˜์•ผ ํ•˜๋‹ˆ ๋ฒˆ๊ฑฐ๋กœ์›Œ App.jsx ํŒŒ์ผ์— axios interceptor ์„ค์ •์„ ํ•ด์ฃผ์—ˆ๋‹ค.

// axios interceptor ์„ค์ •
axios.interceptors.request.use((config) => {
  const token = localStorage.getItem("token");
  if (token) {
    config.headers.authorization = `Bearer ${token}`;
  }
  return config;
});
  • ํ† ํฐ์ด ์กด์žฌํ•  ๋•Œ(null์ด ์•„๋‹ ๋•Œ)๋งŒ ์ถ”๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค.
profile
๊ฐœ๋ฐœ์ž ์ค€๋น„์ƒ~

0๊ฐœ์˜ ๋Œ“๊ธ€