๐Ÿš€chaper 3 ) ์ผ์ •๊ด€๋ฆฌ ์•ฑ Develop ๊ณผ์ œ [Level 4] / TIL day 31

ํ•˜๋ฆฌ๋น„ยท2025๋…„ 4์›” 4์ผ
1

๐Ÿ“ TIL

๋ชฉ๋ก ๋ณด๊ธฐ
9/11
post-thumbnail

๐Ÿ“ ๊ณผ์ œ ๊ฐœ์š”


โœ”๏ธ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ

  • Java: 17
  • JDK: 17.0.1
  • IDE: IntelliJ
  • Spring Frame Work : 3.4.4
  • API ํ…Œ์ŠคํŠธ ๋„๊ตฌ : postman

๐Ÿ“Œ ๊ณตํ†ต ์กฐ๊ฑด

  • ๋ชจ๋“  ํ…Œ์ด๋ธ”์€ ๊ณ ์œ  ์‹๋ณ„์ž(ID)๋ฅผ ๊ฐ€์ง
  • 3 Layer Architecture์— ๋”ฐ๋ผ ๊ฐ ๊ณ„์ธต์˜ ์—ญํ• ์— ๋งž์ถฐ ๊ฐœ๋ฐœ
  • ๋ชจ๋“  CRUD ๊ธฐ๋Šฅ์€ JPA ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„
  • ์ธ์ฆ/์ธ๊ฐ€ ์ ˆ์ฐจ๋Š” Cookie/Session ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌ
  • JPA ์—ฐ๊ด€๊ด€๊ณ„๋Š” ๊ธฐ๋ณธ ๋‹จ๋ฐฉํ–ฅ, ๊ผญ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์–‘๋ฐฉํ–ฅ ์„ค์ •

๐Ÿ”‘ ํ‚ค์›Œ๋“œ (CRUD ๊ด€๋ จ ์–ด๋…ธํ…Œ์ด์…˜)

  • @Entity : ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘๋˜๋Š” ํด๋ž˜์Šค์— ์‚ฌ์šฉ
  • @Id : ๊ธฐ๋ณธ ํ‚ค ํ•„๋“œ ์ง€์ •
  • @GeneratedValue : ๊ธฐ๋ณธ ํ‚ค ์ž๋™ ์ƒ์„ฑ ์ „๋žต ์„ค์ •
  • @Repository : DAO ํด๋ž˜์Šค์ž„์„ ๋ช…์‹œ
  • @ManyToOne / @OneToMany : ํ…Œ์ด๋ธ” ๊ฐ„ ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •
  • @JoinColumn : join ๋Œ€์ƒ ์ปฌ๋Ÿผ ์ง€์ •


๐ŸŽจ ๊ตฌํ˜„ํ•œ ๋‚ด์šฉ


๐ŸŒŸ Git Hub ๋งํฌ & ReadMe / API ๋ช…์„ธ์„œ

ํ•„์ˆ˜๊ธฐ๋Šฅ๋‹จ๊ณ„๋ณ„์š”๊ตฌ์‚ฌํ•ญ
โœ…Level 0API ๋ช…์„ธ์„œ ์ž‘์„ฑํ•˜๊ธฐ
ERD ์ž‘์„ฑํ•˜๊ธฐ
SQL ์ž‘์„ฑํ•˜๊ธฐ
โœ…Level 1์ผ์ • ์ƒ์„ฑ (์ž‘์„ฑ์ž๋ช…, ์ œ๋ชฉ, ๋‚ด์šฉ, ์ž‘์„ฑ์ผ, ์ˆ˜์ •์ผ)
์ „์ฒด ์ผ์ • ์กฐํšŒ
์ผ์ • ์ˆ˜์ •
์ผ์ • ์‚ญ์ œ
โœ…Level 2์œ ์ € ์ƒ์„ฑ (์œ ์ €๋ช…, ์ด๋ฉ”์ผ, ์ž‘์„ฑ์ผ, ์ˆ˜์ •์ผ)
์œ ์ € ์กฐํšŒ
์œ ์ € ์ˆ˜์ •
์œ ์ € ์‚ญ์ œ
์ผ์ •์— ์œ ์ € ์‹๋ณ„์ž๋กœ ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •
โœ…Level 3ํšŒ์›๊ฐ€์ž…์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ ํ•„๋“œ ์ถ”๊ฐ€
โœ…Level 4๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ ๊ตฌํ˜„ (Cookie/Session ํ™œ์šฉ)
๋กœ๊ทธ์ธ ํ•„ํ„ฐ ๋“ฑ๋ก, ํ•„ํ„ฐ๋กœ ์ธ์ฆ
ํšŒ์›๊ฐ€์ž…/๋กœ๊ทธ์ธ์€ ์ธ์ฆ ์ œ์™ธ
๋กœ๊ทธ์ธ ์‹คํŒจ ์‹œ HTTP 401 ์‘๋‹ต, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ


๐Ÿ“‹ ์ฐธ๊ณ ํ–ˆ๋˜ ๋งํฌ


1๏ธโƒฃ ์ปค๋ฐ‹ ์ปจ๋ฒค์…˜

https://sungwookoo.tistory.com/1

  • ์ด๋ฒˆ์—๋Š” ์ปค๋ฐ‹ ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ํ•˜๊ณ ์ž ๋…ธ๋ ฅํ–ˆ๋‹ค

2๏ธโƒฃ์ปค์Šคํ…€ ์ต์…‰์…˜

https://dev-allday.tistory.com/77
https://beaniejoy.tistory.com/93

  • ์ง€๋‚œ ๋ฏธ๋‹ˆ์„ธ์…˜์„ ๋“ฃ๊ณ  ์ปค์Šคํ…€ ์ต์…‰์…˜์„ ๊ผญ ํ™œ์šฉํ•ด์•ผ๊ฒ ๋‹ค ์ƒ๊ฐํ–ˆ๋Š”๋ฐ,
    ์ƒ๊ฐ๋ณด๋‹ค ์–ด๋ ค์› ๋‹ค

3๏ธโƒฃ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ ๊ตฌํ˜„

https://congsong.tistory.com/38



๐Ÿ› ๏ธ TroubleShooting


โถ Patch ์š”์ฒญ์‹œ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ๋ฌธ์ œ

๐Ÿ“Œ ๋ฌธ์ œ

  • ์Šค์ผ€์ค„ ์ˆ˜์ • ํ›„ PATCH ์š”์ฒญ์„ ๋ณด๋ƒˆ๋Š”๋ฐ, ์‘๋‹ต์ด ์ž˜ ์™€์„œ ๋ฌธ์ œ๊ฐ€ ์—†๋Š” ์ค„ ์•Œ์•˜๋‹ค!
    ๋‚˜์ค‘์— DB๋ฅผ ๋ณด๋‹ˆ๊นŒ ์‘๋‹ต๊ณผ ๋‹ค๋ฅด๊ฒŒ ๊ธฐ์กด ์Šค์ผ€์ค„์ด ์ˆ˜์ •๋œ ๊ฒŒ ์•„๋‹ˆ๋ผ ์ƒˆ๋กœ์šด ์•„์ด๋””๋กœ ์Šค์ผ€์ค„์ด ์ถ”๊ฐ€๋˜๊ณ  ์žˆ์—ˆ๋‹ค
  • ๋ฌธ์ œ๋Š” Repository์˜ save() ๋•Œ๋ฌธ์ด์—ˆ๋‹ค. insert/update๋ฅผ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์ค„๊ฑฐ๋ผ ์ƒ๊ฐํ–ˆ๋Š”๋ฐ, ๋‚ด ์ฝ”๋“œ์—์„œ๋Š” ์ผ๋ถ€ ์ˆ˜์ •์‹œ ๊ธฐ์กด ์—”ํ„ฐํ‹ฐ๊ฐ€ ์—†๋Š” ๊ฒƒ์œผ๋กœ ํŒ๋‹จํ•ด์„œ์ธ์ง€ INSERT๋งŒ ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค

๐Ÿ’ก ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

โŽ ๋ฌธ์ œ ์ฝ”๋“œ

Schedule schedule = new Schedule(title, description);
Schedule updatedSchedule = scheduleRepository.save(schedule);

โœ… ํ•ด๊ฒฐ ์ฝ”๋“œ

โท Patch ์š”์ฒญ์‹œ ๋ถ€๋ถ„ ์ˆ˜์ •์ด ์•„๋‹Œ ์ „์ฒด ๋ฎ์–ด์”Œ์›Œ์ง(null๊นŒ์ง€)

๐Ÿ“Œ ๋ฌธ์ œ

  • ์Šค์ผ€์ค„ ์ˆ˜์ •์‹œ ์ œ๋ชฉ๋งŒ ๋ฐ”๊พธ๊ณ  ์‹ถ์–ด์„œ ์ œ๋ชฉ๋งŒ ๋„ฃ์–ด์„œ PATCH ํ–ˆ๋”๋‹ˆ,
    ๋‹ค๋ฅธ ๊ฐ’๋“ค์€ null๋กœ ๋‹ค ๋ฎ์–ด์”Œ์›Œ์ง..! ์‹ฌ์ง€์–ด ๊ธฐ์กด์— ์žˆ๋˜ ๊ฐ’๋“ค๋„ null์ด ๋˜์–ด๋ฒ„๋ ธ๋‹ค

๐Ÿ’ก ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

โœ… ํ•ด๊ฒฐ ์ฝ”๋“œ

  • ์กฐ๊ฑด๋ฌธ์œผ๋กœ ๊ธฐ์กด ๋ฐ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ์ฐพ์•„๋‘๊ณ 
    ์ƒˆ๋กœ ๋ฐ›์€ ์š”์ฒญ์ด null์ด๋ฉด ๊ธฐ์กด ๊ฐ’์„ ์œ ์ง€, null์ด ์•„๋‹ˆ๋ฉด ๊ทธ ๊ฐ’์œผ๋กœ ์—…๋ฐ์ดํŠธ ํ•˜๋„๋ก ํ–ˆ๋‹ค


โธ ๋กœ๊ทธ์ธ ํ•„ํ„ฐ white_list ๊ฒฝ๋กœ ์˜ค๋ฅ˜

๐Ÿ“Œ ๋ฌธ์ œ

  • ์˜ˆ์ œ์™€ ๊ฐ™์ด ๋กœ๊ทธ์ธ ํ•„ํ„ฐ์—์„œ ๋กœ๊ทธ์ธ ์—†์ด ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๊ฒฝ๋กœ๋ฅผ whiteList๋กœ ์„ค์ •ํ•ด๋’€๋Š”๋ฐ,
    /user, /login์œผ๋กœ ํ•ด๋‘๊ณ ๋„ ๊ณ„์† ํ•„ํ„ฐ๋ง์ด ์•ˆ ๋๋‹ค
  • ์•Œ๊ณ  ๋ณด๋‹ˆ ์‹ค์ œ ๋‚ด ์ปจํŠธ๋กค๋Ÿฌ ๊ฒฝ๋กœ๋Š” /user/login์ด๋ผ์„œโ€ฆ ๋งค์นญ์ด ์•ˆ ๋๋‹ค๐Ÿ˜‡

๐Ÿ’ก ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

  • WhiteList ๋ฅผ ์‹ค์ œ URI ๊ฒฝ๋กœ์— ๋งž๊ฒŒ ์ˆ˜์ •ํ–ˆ๋‹ค

  • ํ•ญ์ƒ URI๋ฅผ ํ™•์ธํ•˜๊ณ  ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค..!


โน Post ์š”์ฒญ์—์„œ username ์ง์ ‘ ๋ฐ›์ง€ ์•Š๊ณ  ์„ธ์…˜์—์„œ ๊บผ๋‚ด์“ฐ๊ธฐ

๐Ÿ“Œ ๋ฌธ์ œ

  • ์ผ์ • ์ƒ์„ฑ ์š”์ฒญ์—์„œ username์„ request๋กœ ๋ฐ›์•„์„œ ์“ฐ๊ณ  ์žˆ์—ˆ๋Š”๋ฐ,
    ๋กœ๊ทธ์ธ ๊ตฌํ˜„ ํ›„์—๋Š” ์„ธ์…˜์— ์ด๋ฏธ ๋กœ๊ทธ์ธ ์ •๋ณด๊ฐ€ ์žˆ๋Š” ์ƒํƒœ๋‹ˆ๊นŒ
    ๊ตณ์ด ํด๋ผ์ด์–ธํŠธ์—์„œ username์„ ๋˜ ๋ฐ›์„ ํ•„์š”๊ฐ€ ์—†์–ด์กŒ๋‹ค.

๐Ÿ’ก ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

โŽ ๊ธฐ์กด ์ฝ”๋“œ

// 1. ์Šค์ผ€์ค„ ์ƒ์„ฑ
@PostMapping
public ResponseEntity<ScheduleResponseDto> save(
			@RequestBody ScheduleRequestDto requestDto
       ){
       ScheduleResponseDto scheduleResponseDto = scheduleService.save(requestDto.getTitle(), requestDto.getDescription(), requestDto.getUsername());
		return new ResponseEntity<>(scheduleResponseDto, HttpStatus.CREATED);

โœ… ํ•ด๊ฒฐ ์ฝ”๋“œ

  • request.getSession().getAttribute("username") ์ž‘์„ฑ,
    ๊ทธ๋ฆฌ๊ณ  ScheduleResopnseDto ์—์„œ๋Š” username ํ•„๋“œ๋ฅผ ์•„์˜ˆ ์—†์• ๋ฒ„๋ ธ๋‹ค


โบ ์—๋Ÿฌ์ฝ”๋“œ enum ์‚ฌ์šฉ ์ค‘ instance ์˜ค๋ฅ˜

๐Ÿ“Œ ๋ฌธ์ œ

  • enum์œผ๋กœ ์ •์˜ํ•œ errorCode.USER_NOT_FOUND๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ž๊พธ๋งŒ ์ธ์Šคํ„ด์Šค ์˜ค๋ฅ˜ ๋ฐœ์ƒ,,
    enum์„ ์‚ฌ์šฉํ•ด๋ณธ์ ๋„ ์—†๊ณ (ใ…‹ใ…‹) ํ‹€๋ฆฐ ๋ถ€๋ถ„์„ ์ฐพ์„ ์ˆ˜ ์—†์–ด ํ•œ์ฐธ์„ ํ•ด๋งธ๋‹ค

โŽ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€

Static member 'com. example. schedulerproject. exception. ErrorCode. USER_NOT_FOUND' accessed via instance reference

โŽ ์—๋Ÿฌ ์ฝ”๋“œ

public class UserNotFoundException extends CustomException{
    public UserNotFoundException(ErrorCode errorCode) {
        super(errorCode.USER_NOT_FOUND);
    }
}  

๐Ÿ’ก ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

  • ErrorCode์—์„œ enum์˜ static์œผ๋กœ ์„ ์–ธ๋œ ๊ฒƒ๋“ค์„ ์ธ์Šคํ„ด์Šค ์‚ฌ์šฉํ•˜๋“ฏ ์‚ฌ์šฉํ•ด์„œ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค!
    ํด๋ž˜์Šค ์ด๋ฆ„์œผ๋กœ ์ ‘๊ทผํ•ด์•ผํ•œ๋‹ค..!
  • super(ErrorCode.USER_NOT_FOUND); ํ•œ๊ธ€์ž์”ฉ๋งŒ ๋ฐ”๊พธ๋‹ˆ ํ•ด๊ฒฐ๐Ÿ˜‚


๐ŸŒŸ ๋‚˜์˜ ํšŒ๊ณ 


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