[Sequelize] Join (sequelize-typescript)

[์›๋ณธ ๋งํฌ]

์‹œํ€„๋ผ์ด์ฆˆ์˜ ORM ๊ธฐ๋Šฅ์„ ํ†ตํ•ด join์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฒœ์ฒœํžˆ ๋‹ค๋ค„๋ณด๊ฒ ๋‹ค.
ORM์€ ๋‹จ์ˆœ CRUD ์ž‘์—…์—์„œ ํŠน์ถœ๋‚œ ์ƒ์‚ฐ์„ฑ์„ ๋ณด์ด์ง€๋งŒ, ๋‹จ์ˆœํ•œ ํ˜•ํƒœ์˜ Join ๋˜ํ•œ ์ต์ˆ™ํ•˜๋‹ค๋Š” ์ „์ œํ•˜์—์„œ ๊น”๋”ํ•œ ์ฝ”๋“œ์™€ ๊ดœ์ฐฎ์€ ์ƒ์‚ฐ์„ฑ์„ ๋ณด์—ฌ์ค€๋‹ค,

์ผ๋‹จ ์‚ฌ์šฉ์ž๋ฅผ ๋œปํ•˜๋Š” "User" ์—”ํ‹ฐํ‹ฐ์™€

์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์„ฑํ•œ ๊ฒŒ์‹œ๊ธ€์„ ๋‚˜ํƒ€๋‚ด๋Š” "Post" ์—”ํ‹ฐํ‹ฐ 2๊ฐœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ•œ๋ฒˆ ํ•ด๋ณด๊ฒ ๋‹ค.




@BelongsTo ๊ด€๊ณ„

์ €๊ธฐ์„œ ๋งŒ์•ฝ ๊ฒŒ์‹œ๊ธ€์„ ๊ฐ€์ ธ์˜ค๋˜, ๊ทธ ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ•œ ์‚ฌ์šฉ์ž๊นŒ์ง€ ํ•จ๊ป˜ ๊ฐ€์ ธ์˜ค๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

๊ด€๊ณ„์ ์œผ๋กœ ์ƒ๊ฐํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ–ˆ์œผ๋‹ˆ ๊ฒŒ์‹œ๊ธ€์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ์†ํ•ด์žˆ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๊ฒŒ์‹œ๊ธ€์€ ์ž‘์„ฑํ•œ ์‚ฌ์šฉ์ž์˜ ๊ณ ์œ ํ‚ค๋ฅผ ์ปฌ๋Ÿผ์œผ๋กœ ๋ณด์œ ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ทธ ์†Œ์†์„ฑ์„ ์ฆ๋ช…ํ•œ๋‹ค.

์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” BelongsTo ๊ด€๊ณ„๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
์™ธ๋ž˜ํ‚ค ์ปฌ๋Ÿผ์— ForeignKey ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ํ•ด๋‹น ์‚ฌ์šฉ์ž ๋ชจ๋ธ์„ ์ฐธ์กฐํ•˜๋Š” ํ‚ค์ž„์„ ๋ช…์‹œํ•ด์ค€๋‹ค.
ํ•ด๋‹น ๋ชจ๋ธ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํด๋กœ์ €๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ปฌ๋Ÿผ์ด ์•„๋‹Œ BelongsTo ํ•„๋“œ๋กœ ์กฐ์ธํ•ด์˜จ ๊ฐ’์„ ๋‹ด์•„๋‘˜ ํ•„๋“œ๋ฅผ ์ง€์ •ํ•ด์ค€๋‹ค.
BelongsTo์—๋Š” ์‚ฌ์šฉ์ž ๋ชจ๋ธ์„ ๋„ฃ์–ด์ฃผ๊ณ , ํ•„๋“œ์˜ ํƒ€์ž…์€ ๋ชจ๋ธํƒ€์ž…์ด๋‚˜ ๊ทธ๊ฑฐ๋ž‘ ๋งคํ•‘๋˜๋Š” ๊ฐ์ฒด ํƒ€์ž…์„ ์•„๋ฌด๊ฑฐ๋‚˜ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

๊ทธ๋Ÿผ ์ด์ œ ์ด๋Ÿฐ์‹์œผ๋กœ Join ์ˆ˜ํ–‰์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.
join์€ ๊ธฐ๋ณธ์ ์œผ๋กœ find ๋ฉ”์„œ๋“œ๋“ค์˜ include ์˜ต์…˜์„ ํ†ตํ•ด ์ˆ˜ํ–‰ํ•˜๋Š”๋ฐ, model์— User๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

๊ทธ๋Ÿผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ฟผ๋ฆฌ๊ฐ€ ๋ฝ‘ํ˜€์„œ ์‹คํ–‰๋  ๊ฒƒ์ด๋‹ค.

๋ณด๊ธฐ ํž˜๋“œ๋‹ˆ ์ •๋ ฌํ•ด์„œ ๋ณด์ž

 select
	"Post"."id",
	"Post"."userId",
	"Post"."title",
	"Post"."content",
	"Post"."useYn",
	"Post"."createdAt",
	"Post"."updatedAt",
	"user"."id" as "user.id",
	"user"."email" as "user.email",
	"user"."password" as "user.password",
	"user"."passwordSalt" as "user.passwordSalt",
	"user"."name" as "user.name",
	"user"."userType" as "user.userType",
	"user"."userStatus" as "user.userStatus",
	"user"."createdAt" as "user.createdAt",
	"user"."updatedAt" as "user.updatedAt"
from
	"Posts" as "Post"
left outer join "Users" as "user" on
	"Post"."userId" = "user"."id"
where
	"Post"."useYn" = true;

left ์กฐ์ธ์— User์˜ ๊ณ ์œ ํ‚ค๋กœ ์กฐ๊ฑด์„ ๊ฑธ์–ด์„œ ์ž˜ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.




๋‚ด๋ถ€&์™ธ๋ถ€์กฐ์ธ ์„ค์ •

์œ„์˜ BelongsTo๋กœ ๋Œ๋ฆฐ ์ฟผ๋ฆฌ์˜ ๊ฒฝ์šฐ์—๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Left ์™ธ๋ถ€์กฐ์ธ์„ ์ˆ˜ํ–‰ํ–ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๋‚ด๋ถ€์กฐ์ธ์œผ๋กœ ๋Œ๋ฆฌ๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์ง€ ์•Š๊ฒ ๋Š”๊ฐ€?
์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” required ์˜ต์…˜๊ฐ’์„ true๋กœ ์ฃผ๋ฉด ๋‚ด๋ถ€์กฐ์ธ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
๋ฐ˜๋Œ€๋กœ false๋ฅผ ์ฃผ๋ฉด ์™ธ๋ถ€์กฐ์ธ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

select
	"Post"."id",
	"Post"."userId",
	"Post"."title",
	"Post"."content",
	"Post"."useYn",
	"Post"."createdAt",
	"Post"."updatedAt",
	"user"."id" as "user.id",
	"user"."email" as "user.email",
	"user"."password" as "user.password",
	"user"."passwordSalt" as "user.passwordSalt",
	"user"."name" as "user.name",
	"user"."userType" as "user.userType",
	"user"."userStatus" as "user.userStatus",
	"user"."createdAt" as "user.createdAt",
	"user"."updatedAt" as "user.updatedAt"
from
	"Posts" as "Post"
inner join "Users" as "user" on
	"Post"."userId" = "user"."id"
where
	"Post"."useYn" = true
order by
	"Post"."createdAt" desc
limit 10 offset 0;


On ์ ˆ ์„ค์ •

join๋ฌธ์˜ on ์ ˆ์— ์ถ”๊ฐ€ ์กฐ๊ฑด์ ˆ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด where ์˜ต์…˜๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค.
๊ทธ๋Ÿฌ๋ฉด ๊ธฐ๋ณธ on ์ ˆ์— ๋”ํ•ด์„œ ์กฐ๊ฑด์„ ๋”ํ•ด์ค„ ๊ฒƒ์ด๋‹ค.

์ด๋ ‡๊ฒŒ

select
	"Post"."id",
	"Post"."userId",
	"Post"."title",
	"Post"."content",
	"Post"."useYn",
	"Post"."createdAt",
	"Post"."updatedAt",
	"user"."id" as "user.id",
	"user"."email" as "user.email",
	"user"."password" as "user.password",
	"user"."passwordSalt" as "user.passwordSalt",
	"user"."name" as "user.name",
	"user"."userType" as "user.userType",
	"user"."userStatus" as "user.userStatus",
	"user"."createdAt" as "user.createdAt",
	"user"."updatedAt" as "user.updatedAt"
from
	"Posts" as "Post"
inner join "Users" as "user" on
	"Post"."userId" = "user"."id"
	and "user"."userStatus" = 0
where
	"Post"."useYn" = true
order by
	"Post"."createdAt" desc
limit 10 offset 0;

๊ทธ๋Ÿฐ๋ฐ ์ €๋Ÿฐ ์ž๋™ ๋งคํ•‘์ด ์ง€๊ฒจ์›Œ์ ธ์„œ join ์กฐ๊ฑด์„ ์ง์ ‘ ๋‹ค ์ง€์ •ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ๋‹ค.
๊ทธ๋Ÿด ๋•Œ๋Š” on ์˜ต์…˜์œผ๋กœ ์กฐ๊ฑด์„ ์ง€์ •ํ•˜๋ฉด ๋œ๋‹ค.
์ด๊ฑธ ์“ฐ๋ฉด ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” on ์ ˆ์ด ์ œ๊ฑฐ๋˜๊ณ  ์šฐ๋ฆฌ๊ฐ€ ๋„ฃ์€ ๊ฒƒ๋งŒ ์กฐ๊ฑด์œผ๋กœ ๋“ค์–ด๊ฐ„๋‹ค.

select
	"Post"."id",
	"Post"."userId",
	"Post"."title",
	"Post"."content",
	"Post"."useYn",
	"Post"."createdAt",
	"Post"."updatedAt",
	"user"."id" as "user.id",
	"user"."email" as "user.email",
	"user"."password" as "user.password",
	"user"."passwordSalt" as "user.passwordSalt",
	"user"."name" as "user.name",
	"user"."userType" as "user.userType",
	"user"."userStatus" as "user.userStatus",
	"user"."createdAt" as "user.createdAt",
	"user"."updatedAt" as "user.updatedAt"
from
	"Posts" as "Post"
left outer join "Users" as "user" on
	"user"."id" = "Post"."userId"
	and "user"."userStatus" = 0
where
	"Post"."useYn" = true
order by
	"Post"."createdAt" desc
limit 10 offset 0;



Join ์ค‘์ฒฉ

๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์€ ํ•œ๋ฒˆ ์กฐ์ธํ–ˆ๋Š”๋ฐ, ์กฐ์ธํ•œ ํ…Œ์ด๋ธ”์—์„œ ๋˜ ์กฐ์ธ์„ ํ•ด์˜ค๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋Ÿด ๋•Œ๋Š” ํ•ด๋‹น include ์ ˆ์— ๋˜ include๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ์ •์˜ํ•˜๋ฉด ๋œ๋‹ค.




HasOne ๊ด€๊ณ„

์ด๋ฒˆ์—” ์‚ฌ์šฉ์ž์˜ ๊ด€์ ์œผ๋กœ ๋Œ์•„๊ฐ€๋ณด์ž.
์ผ๋ฐ˜์ ์ด์ง€๋Š” ์•Š์ง€๋งŒ, ์‚ฌ์šฉ์ž๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์†Œ์œ ํ•œ ํ•˜๋‚˜์˜ ๊ฒŒ์‹œ๊ธ€์„ ๊ฐ€์ ธ์˜ค๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ฒ ๋‹ค.

๊ฒŒ์‹œ๊ธ€์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์„ฑํ•œ ๊ฒƒ์ด๊ณ  ์‚ฌ์šฉ์ž์—๊ฒŒ ์†ํ•ด์žˆ์œผ๋‹ˆ, ์‚ฌ์šฉ์ž๋Š” ๊ฒŒ์‹œ๊ธ€์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

ํ˜„์žฌ ์ค‘์‹ฌ์ด ๋  ์‚ฌ์šฉ์ž๋Š” ๊ฒŒ์‹œ๊ธ€์— ๋Œ€ํ•œ ์ฐธ์กฐ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋Š” ์•Š์ง€๋งŒ, ์†ํ•ด์žˆ๋Š” ๊ฒŒ์‹œ๊ธ€ ์—”ํ‹ฐํ‹ฐ Post๊ฐ€ ์ฐธ์กฐ์†์„ฑ์„ ๊ฐ–๊ณ  ์žˆ๊ธฐ์— ์„ฑ๋ฆฝํ•  ์ˆ˜ ์žˆ๋Š” ๊ด€๊ณ„๋‹ค.

์ด๋ฒˆ์—” ์ด๊ฑธ ์ด์šฉํ•ด์„œ ์‚ฌ์šฉ์ž ์กฐํšŒ์‹œ์— ๊ฒŒ์‹œ๊ธ€๋„ ํ•˜๋‚˜ ๊ฐ€์ ธ์˜ค๋„๋ก ํ•ด๋ณด๊ฒ ๋‹ค.
๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ด€๊ณ„๋ฅผ ๋ช…์‹œํ•ด์ฃผ๊ณ 

include๋งŒ ๋˜‘๋ฐ”๋กœ ์จ์ฃผ๋ฉด ๋œ๋‹ค.

๊ทธ๋Ÿผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ฟผ๋ฆฌ๊ฐ€ ๋ฝ‘ํ˜€์„œ

select
	"User"."id",
	"User"."email",
	"User"."password",
	"User"."passwordSalt",
	"User"."name",
	"User"."userType",
	"User"."userStatus",
	"User"."createdAt",
	"User"."updatedAt",
	"post"."id" as "post.id",
	"post"."userId" as "post.userId",
	"post"."title" as "post.title",
	"post"."content" as "post.content",
	"post"."useYn" as "post.useYn",
	"post"."createdAt" as "post.createdAt",
	"post"."updatedAt" as "post.updatedAt"
from
	"Users" as "User"
left outer join "Posts" as "post" on
	"User"."id" = "post"."userId"
where
	"User"."id" = 1
	and "User"."userStatus" = 0;

์˜ˆ์˜๊ฒŒ ์ž˜ ์ถœ๋ ฅ๋  ๊ฒƒ์ด๋‹ค.




HasMany ๊ด€๊ณ„

์‚ฌ์šฉ์ž์˜ ๊ด€์ ์—์„œ, ์‚ฌ์šฉ์ž๋Š” ์•„๋งˆ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๊ฒŒ์‹œ๊ธ€์„ ์“ธ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.
๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ ๊ฒŒ์‹œ๊ธ€์„ ์†Œ์œ ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

HasOne์—์„œ ๊ทธ๋Œ€๋กœ ๋ณต์ˆ˜ํ˜•๋งŒ ๋œ ๊ฐœ๋…์ด๋‹ค.
์ด๋ฒˆ์—๋Š” ์‚ฌ์šฉ์ž๋ฅผ ๊ฐ€์ ธ์˜ด๊ณผ ๋™์‹œ์— ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ–๊ณ ์žˆ๋Š” ๊ฒŒ์‹œ๊ธ€์„ ์ „๋ถ€ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•ด๋ณด๊ฒ ๋‹ค.
HasMany๋กœ ๋‹ฌ๊ณ , ํ•„๋“œ์˜ ํƒ€์ž…์„ ๋ฐฐ์—ด๋กœ ์„ค์ •ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด์ „๊ณผ ๋™์ผํ•˜๊ฒŒ findOne ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

๊ทธ๋Ÿผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฟผ๋ฆฌ๊ฐ€ ๋ฝ‘ํž ๊ฒƒ์ด๊ณ 

select
	"User"."id",
	"User"."email",
	"User"."password",
	"User"."passwordSalt",
	"User"."name",
	"User"."userType",
	"User"."userStatus",
	"User"."createdAt",
	"User"."updatedAt",
	"posts"."id" as "posts.id",
	"posts"."userId" as "posts.userId",
	"posts"."title" as "posts.title",
	"posts"."content" as "posts.content",
	"posts"."useYn" as "posts.useYn",
	"posts"."createdAt" as "posts.createdAt",
	"posts"."updatedAt" as "posts.updatedAt"
from
	"Users" as "User"
left outer join "Posts" as "posts" on
	"User"."id" = "posts"."userId"
where
	"User"."id" = 1
	and "User"."userStatus" = 0;

์ด๋ ‡๊ฒŒ ์˜๋„ํ•œ๋Œ€๋กœ ์ž˜ ๋‚˜์˜ฌ ๊ฒƒ์ด๋‹ค.





๋™์ผ ์—”ํ‹ฐํ‹ฐ ์™ธ๋ž˜ํ‚ค๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ์ผ ๊ฒฝ์šฐ

์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๋ฅผ ์‹ ๊ณ ํ•  ๊ฒฝ์šฐ์˜ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž.
๊ทธ๋Ÿผ ๋Œ€์ถฉ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹ ๊ณ ํ•œ ์‚ฌ๋žŒ๊ณผ, ์‹ ๊ณ ๋‹นํ•œ ์‚ฌ๋žŒ์˜ ์‹๋ณ„์ž๋ฅผ ๊ฐ–๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

์—”ํ‹ฐํ‹ฐ ์ •์˜์™€ ์‚ฌ์šฉ์€ ๋‹จ์ˆœํ•˜๊ฒŒ ์ƒ๊ฐํ•œ๋‹ค๋ฉด ์ด๋Ÿฐ์‹์œผ๋กœ ํ•ด๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿผ ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค.
sendUser์™€ targetUser๋ฅผ ์–ด๋–ค ํ‚ค๋กœ ์กฐ์ธํ•˜๊ณ , alias๋ฅผ ์–ด๋–ป๊ฒŒ ํ• ์ง€ ์•Œ์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด๋Ÿด ๋•Œ๋Š” ๋งคํ•‘๋˜๋Š” ๊ด€๊ณ„ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์— ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค์™€ ํ…Œ์ด๋ธ” alias๋ฅผ ์˜ต์…˜์œผ๋กœ ์ค˜์•ผ ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  findํ• ๋•Œ๋„ ์ง€์ •ํ•œ as๋ฅผ ๋งž์ถฐ์ฃผ๋ฉด ๋์ด๋‹ค.

๊ทธ๋Ÿผ ์ฟผ๋ฆฌ๊ฐ€ ์ด๋ ‡๊ฒŒ ๋ฝ‘ํ˜€์„œ

SELECT
	"Report"."id",
	"Report"."sendUserId",
	"Report"."targetUserId",
	"Report"."reason",
	"Report"."createdAt",
	"Report"."updatedAt",
	"sendUser"."id" AS "sendUser.id",
	"sendUser"."email" AS "sendUser.email",
	"sendUser"."password" AS "sendUser.password",
	"sendUser"."passwordSalt" AS "sendUser.passwordSalt",
	"sendUser"."name" AS "sendUser.name",
	"sendUser"."userType" AS "sendUser.userType",
	"sendUser"."userStatus" AS "sendUser.userStatus",
	"sendUser"."createdAt" AS "sendUser.createdAt",
	"sendUser"."updatedAt" AS "sendUser.updatedAt",
	"targetUser"."id" AS "targetUser.id",
	"targetUser"."email" AS "targetUser.email",
	"targetUser"."password" AS "targetUser.password",
	"targetUser"."passwordSalt" AS "targetUser.passwordSalt",
	"targetUser"."name" AS "targetUser.name",
	"targetUser"."userType" AS "targetUser.userType",
	"targetUser"."userStatus" AS "targetUser.userStatus",
	"targetUser"."createdAt" AS "targetUser.createdAt",
	"targetUser"."updatedAt" AS "targetUser.updatedAt"
FROM
	"Reports" AS "Report"
LEFT OUTER JOIN "Users" AS "sendUser" ON
	"Report"."sendUserId" = "sendUser"."id"
LEFT OUTER JOIN "Users" AS "targetUser" ON
	"Report"."targetUserId" = "targetUser"."id";

์ž˜ ๊ฐ€์ ธ์˜ฌ ๊ฒƒ์ด๋‹ค.




BelongsToMany ๊ด€๊ณ„: ๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„ ๋งคํ•‘

์—ฌ๊ธฐ์„œ๋Š” ์กฐ๊ธˆ ์–ด๋ ต๊ฒŒ ๋А๋‚„ ์ˆ˜๋„ ์žˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ์‡ผํ•‘๋ชฐ์˜ ๊ตฌ์กฐ๋ฅผ ๊ณ ๋ คํ•ด๋ณธ๋‹ค๋ฉด, ์‚ฌ์šฉ์ž์™€ ์ƒํ’ˆ์ด๋ผ๋Š” ๊ฐ€์žฅ ์ค‘์‹ฌ ๋ชจ๋ธ์ด ์กด์žฌํ•  ๊ฒƒ์ด๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์ƒํ’ˆ์„ ๊ตฌ๋งคํ•˜๋ฉด ๋ญ”๊ฐ€ ๊ด€๊ณ„๋ฅผ ํ†ตํ•ด์„œ ์—ฐ๊ฒฐํ•ด์•ผ ํ•˜์ง€๋งŒ, ์‚ฌ์šฉ์ž๋„ ์ƒํ’ˆ์—๊ฒŒ ์ข…์†์ ์ด์ง€ ์•Š๊ณ  ์ƒํ’ˆ๋„ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ข…์†์ ์ด์ง€ ์•Š๋‹ค.
ํ•œ ์ƒํ’ˆ๋„ ์—ฌ๋Ÿฌ๋ช…์˜ ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ตฌ๋งค๋  ์ˆ˜ ์žˆ๊ณ , ํ•œ ์‚ฌ์šฉ์ž๋„ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ƒํ’ˆ์„ ๊ตฌ๋งคํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ทธ๋ž˜์„œ ์ด๋Ÿฌํ•œ ๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„๋ฅผ ๋งคํ•‘ํ•  ๋•Œ๋Š” "UserProduct" ๊ฐ™์€ ๊ด€๊ณ„์šฉ ๋งคํ•‘ ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉ์ž์™€ ์ƒํ’ˆ์˜ ๊ณ ์œ ํ‚ค๋ฅผ ์—ฎ์–ด ์‚ฌ์šฉํ•˜๊ณค ํ•œ๋‹ค.

ํ•œ๋ฒˆ ์จ๋ณด์ž.
User์— ๋”ํ•ด Product ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ถ”๊ฐ€๋กœ ์ •์˜ํ•˜๊ณ 

๋งคํ•‘์šฉ ํ…Œ์ด๋ธ”์„ ์ •์˜ํ•œ๋‹ค.
๊ฐ ํ…Œ์ด๋ธ”์˜ ์™ธ๋ž˜ํ‚ค๋ฅผ ๊ฐ€์ง€๋„๋ก ํ–ˆ๋‹ค.

๊ทธ๋Ÿผ ์ด์ œ ์‚ฌ์šฉ์ž๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•ด์„œ ๊ตฌ๋งคํ•œ ์ƒํ’ˆ์„ ๊ฐ€์ ธ์˜ค๋Š” ์ฟผ๋ฆฌ๋ฅผ ๋Œ๋ ค๋ณด๊ฒ ๋‹ค.
BelongsToMany๋กœ Product๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํด๋กœ์ €, ๋งคํ•‘ ํ…Œ์ด๋ธ”์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํด๋กœ์ €๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

๊ทธ๋Ÿผ ์ด๋ ‡๊ฒŒ ๋‹จ์ˆœํ•˜๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

์ฟผ๋ฆฌ๋Š” ์ด๋ ‡๊ฒŒ ๋ฝ‘ํžˆ๊ณ 

select
	"User"."id",
	"User"."email",
	"User"."password",
	"User"."passwordSalt",
	"User"."name",
	"User"."userType",
	"User"."userStatus",
	"User"."createdAt",
	"User"."updatedAt",
	"products"."id" as "products.id",
	"products"."name" as "products.name",
	"products"."price" as "products.price",
	"products"."createdAt" as "products.createdAt",
	"products"."updatedAt" as "products.updatedAt",
	"products->UserProduct"."id" as "products.UserProduct.id",
	"products->UserProduct"."userId" as "products.UserProduct.userId",
	"products->UserProduct"."productId" as "products.UserProduct.productId",
	"products->UserProduct"."createdAt" as "products.UserProduct.createdAt",
	"products->UserProduct"."updatedAt" as "products.UserProduct.updatedAt"
from
	"Users" as "User"
left outer join ( "UserProducts" as "products->UserProduct"
inner join "Products" as "products" on
	"products"."id" = "products->UserProduct"."productId") on
	"User"."id" = "products->UserProduct"."userId";

๊ฐ€์ ธ์˜ค๊ธฐ๋„ ์ž˜ ๊ฐ€์ ธ์˜ฌ ๊ฒƒ์ด๋‹ค.

์ƒํ’ˆ์„ ๊ธฐ์ค€์œผ๋กœ ํ•  ๋•Œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค.
๋ฐ˜๋Œ€๋กœ๋งŒ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

๊ทธ๋Ÿผ ์ด๋ ‡๊ฒŒ ์ž˜ ๊ฐ€์ ธ์˜ฌ ๊ฒƒ์ด๋‹ค.

 select
	"Product"."id",
	"Product"."name",
	"Product"."price",
	"Product"."createdAt",
	"Product"."updatedAt",
	"users"."id" as "users.id",
	"users"."email" as "users.email",
	"users"."password" as "users.password",
	"users"."passwordSalt" as "users.passwordSalt",
	"users"."name" as "users.name",
	"users"."userType" as "users.userType",
	"users"."userStatus" as "users.userStatus",
	"users"."createdAt" as "users.createdAt",
	"users"."updatedAt" as "users.updatedAt",
	"users->UserProduct"."id" as "users.UserProduct.id",
	"users->UserProduct"."userId" as "users.UserProduct.userId",
	"users->UserProduct"."productId" as "users.UserProduct.productId",
	"users->UserProduct"."createdAt" as "users.UserProduct.createdAt",
	"users->UserProduct"."updatedAt" as "users.UserProduct.updatedAt"
from
	"Products" as "Product"
left outer join ( "UserProducts" as "users->UserProduct"
inner join "Users" as "users" on
	"users"."id" = "users->UserProduct"."userId") on
	"Product"."id" = "users->UserProduct"."productId";

๊ทธ๋ ‡๋‹ค.



์ฐธ์กฐ
https://sequelize.org/master/manual/eager-loading.html
https://gist.github.com/zcaceres/83b554ee08726a734088d90d455bc566
https://velog.io/@cadenzah/sequelize-document-4