๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป๐Ÿ“/ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

[241223] AWS S3 ๊ถŒํ•œ ๋ฌธ์ œ ๋ฐ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ, ์ค‘๋ณต ๋ฐ์ดํ„ฐ ์ด์Šˆ

_silver 2024. 12. 23. 20:10

 

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ ์ด๋ฆ„์€ "owner"๋กœ ์ •ํ–ˆ๋‹ค.

Owner ํ”„๋กœ์ ํŠธ๋Š” Owner๋ผ๋ฉด ๋ฐ˜๋“œ์‹œ ์•Œ์•„์•ผ ํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋ผ๋Š” ์ปจ์…‰์œผ๋กœ ์ง„ํ–‰๋˜์—ˆ๋‹ค.

์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ To-Do-List๋ฅผ ํ†ตํ•ด ์ž‘์—… ํ˜„ํ™ฉ์„ ํ•œ๋ˆˆ์— ํŒŒ์•…ํ•˜๊ณ , ์ฐธ์—ฌ ์ธ์› ๊ฐ„์˜ ํ™œ๋ฐœํ•œ ์†Œํ†ต๊ณผ ํšจ๊ณผ์ ์ธ ์ผ์ • ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค!

 

ํ•˜์ง€๋งŒ ๊ฐœ๋ฐœ ๋„์ค‘ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๊ณ  ๊ทธ ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ ๊ณผ์ •์„ ์ •๋ฆฌํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

 

[GitHub ๋งํฌ]

 


AWS S3 ๊ถŒํ•œ ๊ด€๋ จ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

1. ๋ฌธ์ œ ์ƒํ™ฉ

 

๐Ÿ“ ๋ณด๋“œ ์ƒ์„ฑ ์š”์ฒญ ์‹œ, S3์™€ ์—ฐ๋™๋œ backgroundImageUrl์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๋ฌธ์ œ ๋ฐœ์ƒ

  •  S3 URL๋กœ ์ด๋ฏธ์ง€ ์ ‘์†ํ•˜๋ฉด "์ ‘๊ทผ ๊ถŒํ•œ ์—†์Œ" ์—๋Ÿฌ๊ฐ€ ๋ฐ˜ํ™˜๋จ.

๋ณด๋“œ ์ƒ์„ฑ ์‘๋‹ต ๋ฉ”์„ธ์ง€
S3 URL๋กœ ์ด๋ฏธ์ง€์— ์ ‘์† ํ™”๋ฉด

 


 

2. ์›์ธ ๋ถ„์„

 

1) Block Public Access ํ™œ์„ฑํ™”

- S3 Bucket ์„ค์ •์—์„œ Block Public Access ์˜ต์…˜์ด ํ™œ์„ฑํ™”๋˜์–ด ์™ธ๋ถ€์—์„œ ์ ‘๊ทผ์ด ์ฐจ๋‹จ๋œ ์ƒํƒœ์˜€๋‹ค.

 

2) Bucket Policy ๋ฏธ์„ค์ •

- S3 Bucket์— ํ•„์š”ํ•œ ์ •์ฑ…(Bucket Policy)์ด ์„ค์ •๋˜์ง€ ์•Š์•„, ์™ธ๋ถ€ ์š”์ฒญ์ด ์ œ๋Œ€๋กœ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค.

 


 

3. ํ•ด๊ฒฐ๋ฐฉ์•ˆ
1) Block Public Access ์„ค์ • ํ•ด์ œ
- AWS S3 ์ฝ˜์†”์—์„œ Block Public Access ์„ค์ •์„ ํ•ด์ œํ•˜์—ฌ ์™ธ๋ถ€ ์ ‘๊ทผ์„ ํ—ˆ์šฉ ํ–ˆ๋‹ค.

 

2) Bucket Policy ์ •์žญ ์ถ”๊ฐ€ ์„ค์ •
- ๋ชจ๋“  ์‚ฌ์šฉ์ž(Principal: "*")๊ฐ€ ๊ฐ์ฒด๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก Bucket Policy๋ฅผ ์ถ”๊ฐ€ ํ–ˆ๋‹ค.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::bucket-name/*"
    }
  ]
}

 

 


 

4. ๊ฒฐ๊ณผ

 

๐Ÿ“ S3 URL ์ด๋ฏธ์ง€ ์ ‘๊ทผ์ด ์ •์ƒ์ ์œผ๋กœ ์™„๋ฃŒ ๋˜์—ˆ๋‹ค.

 

โžก๏ธ ํ˜„์žฌ ๋ชจ๋“  ์‚ฌ์šฉ์ž๊ฐ€ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค์ •๋˜์–ด ์žˆ์ง€๋งŒ ํ•„์š”์‹œ ํŠน์ • ์‚ฌ์šฉ์ž๋‚˜ IP๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ •์ฑ…์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง„ํ–‰ํ•˜๊ณ ์ž ํ•œ๋‹ค.

์šฐ๋ฆฌ์ง‘ ํ˜„์ง€ ๊ผฌ์ˆœ๋‚ด ํ˜„์žฅ.jpg


๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ๊ณผ ์ค‘๋ณต ๋ฐ์ดํ„ฐ ๋ฌธ์ œ

1. ๋ฌธ์ œ ์ƒํ™ฉ

 

๐Ÿ“ ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ ์ค‘ IncorrectResultSizeDataAccessException ์—๋Ÿฌ ๋ฐœ์ƒ

  • ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ ์ค‘ findByUserIdAndWorkspaceId ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ, Query did not return a unique result: 2 results were returned ์—๋Ÿฌ ๋ฐœ์ƒ.
  • ๋™์ผํ•œ user_id์™€ workspace_id ์กฐํ•ฉ์œผ๋กœ ์—ฌ๋Ÿฌ ๋ฉค๋ฒ„ ๋ฐ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•˜๋ฉฐ, role ๊ฐ’("BOARD", "READ")์ด ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋“ค์ด ์ค‘๋ณต๋˜์–ด ์ฟผ๋ฆฌ์—์„œ ๋‘ ๊ฐœ ์ด์ƒ์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜.

member Table ์กฐํšŒ ํ™”๋ฉด


2. ์›์ธ ๋ถ„์„

 

1) ์ค‘๋ณต๋œ ๋ฐ์ดํ„ฐ

  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋™์ผํ•œ user_id์™€ workspace_id๋ฅผ ๊ฐ€์ง€๋Š” ๋ฉค๋ฒ„๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์กด์žฌํ–ˆ๋‹ค.
  • role ๊ฐ’("BOARD", "READ")์ด ๋‹ค๋ฅด์ง€๋งŒ ์ฟผ๋ฆฌ๊ฐ€ ์กฐ๊ฑด์„ ๋ช…ํ™•ํžˆ ํ•˜์ง€ ์•Š์•„ ๋‹ค์ˆ˜์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜๋œ ๋“ฏํ•˜๋‹ค.

 

2) ์ฟผ๋ฆฌ ์„ค๊ณ„ ๋ฌธ์ œ

  • findByUserIdAndWorkspaceId ๋ฉ”์„œ๋“œ๊ฐ€ ๋‹จ์ผ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์—์„œ ์กฐ๊ฑด ์—†์ด ์—ฌ๋Ÿฌ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์™”๋‹ค.
  • // ๋ณ€๊ฒฝ ์ „ Optional<Member> findByUserIdAndWorkspaceId(Long userId, Long workspaceId);

 

3) ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ๋ฌธ์ œ

  • user_id์™€ workspace_id์˜ ์กฐํ•ฉ์— ๋Œ€ํ•ด ์œ ์ผ์„ฑ์„ ๋ณด์žฅํ•˜์ง€ ์•Š์•„ ๋ฐ์ดํ„ฐ๊ฐ€ ์ค‘๋ณต ์ €์žฅ๋˜์—ˆ๋‹ค.

 

 


3. ํ•ด๊ฒฐ๋ฐฉ์•ˆ

 

1) ์ฟผ๋ฆฌ ์ˆ˜์ •

- ์ƒˆ๋กœ์šด ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ findByUserIdAndWorkspaceIdAndRole๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ค‘๋ณต ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ํŠน์ • role ๊ฐ’๋งŒ ๋ฐ˜ํ™˜ํ•˜๋„๋ก Query๋ฌธ์œผ๋กœ ์ž‘์„ฑํ–ˆ๋‹ค.

// ๋ณ€๊ฒฝ ํ›„
@Query("SELECT m FROM Member m WHERE m.user.id = :userId AND m.workspace.id = :workspaceId AND m.role = 'BOARD'")
Optional<Member> findByUserIdAndWorkspaceIdAndRole(@Param("userId") Long userId, @Param("workspaceId") Long workspaceId);

** role = 'BOARD'์ธ ๋ฐ์ดํ„ฐ๋งŒ ์กฐํšŒํ•˜๋ฏ€๋กœ, ์ค‘๋ณต๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋”๋ผ๋„ ๋‹จ์ผ ๊ฒฐ๊ณผ('BOARD') ๊ฐ’๋งŒ ๋ฐ˜ํ™˜๋œ๋‹ค.

 

2) List Service ์ฝ”๋“œ ์ˆ˜์ •

- ๊ธฐ์กด findByUserIdAndWorkspaceId ๋ฉ”์„œ๋“œ๋ฅผ findByUserIdAndWorkspaceIdAndRole๋กœ ์ˆ˜์ •ํ•˜์—ฌ, ํŠน์ • role์„ ๊ฐ€์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋„๋ก ์ˆ˜์ •ํ–ˆ๋‹ค.

// ํŠน์ • ๋ฉค๋ฒ„ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
Member findMember = memberRepository.findByUserIdAndWorkspaceIdAndRole(user.getId(),requestDto.getWorkspaceId())
	.orElseThrow(()-> new CustomException(ErrorCode.MEMBER_NOT_FOUND));

//  ํŠน์ • ๋ฉค๋ฒ„ role ๊ถŒํ•œ ํ™•์ธ
if (!findMember.getRole().equals(MemberRole.BOARD)) {
	throw new CustomException(ErrorCode.UNAUTHORIZED_ACCESS);
}

4. ๊ฒฐ๊ณผ

๐Ÿ“ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋™์ผํ•œ user_id์™€ workspace_id๋ฅผ ๊ฐ€์ง€๋Š” ๋ฉค๋ฒ„๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์กด์žฌํ•ด๋„ "BOARD" ๊ถŒํ•œ์„ ๊ฐ€์ง„ ID๋ฅผ ์ถ”์ถœ์ด ๊ฐ€๋Šฅํ•ด์ ธ ์ •์ƒ์ ์œผ๋กœ ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋‹ค.

 

 


 

์„ธ๋ฒˆ์งธ ํŒ€ ํ”„๋กœ์ ํŠธ ์™„๋ฃŒ! ํ–ˆ๋Š”๋ฐ

๋‚ด๋…„(2์ผ๋’ค) ๋งˆ์ง€๋ง‰ ์ตœ์ข… ํ”„๋กœ์ ํŠธ๊ฐ€ ๋‹ค๊ฐ€์˜จ๋‹ค.

๊ธฐ๋Œ€๋˜๋ฉด์„œ ๋–จ๋ฆฐ๋‹ค ๐Ÿฅน

 

[KPT ํšŒ๊ณ ] Owner 5์กฐ์˜ ์‹ฌํ™” ํ”„๋กœ์ ํŠธ