์ฝ๋๋ฅผ ์ง๋ค๋ณด๋ฉด ๊ฒ์๊ธ๊ณผ ๊ฐ์ ์ํฐํฐ๋ฅผ ๋ฑ๋กํ ๋ ํ์ผ์ ์ถ๊ฐ๋ก ์ ๋ก๋ํ๋ ๊ฒฝ์ฐ๊ฐ ๋งค์ฐ ๋ง๋ค.
์ด๋ฒ ํ๋ก์ ํธ์์๋ ๊ณต์ฐ ํฌ์คํธ๋ฅผ DB์ ์ ์ฅํ๋ฉด์ ์ธ๋ค์ผ ์ด๋ฏธ์ง์ ๋ด์ฉ์ ๋ค์ด๊ฐ ์ด๋ฏธ์ง ๋ฑ์ด AWS S3์ ํจ๊ป ์ ์ฅ๋์๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ์กฐํํ ๋๋ AWS S3์์ ์กฐํํ๋ ๋ก์ง๊ณผ DB์์ ํฌ์คํธ๋ฅผ ์กฐํํ๋ ๋ก์ง์ด ํจ๊ป ์ํ๋๋ค.
์ด๋ ์ธ๋ถ์์ ๋ฆฌ์์ค๋ฅผ ์กฐํํด์ค๋ ๋ก์ง๊ณผ DB์์ ์กฐํํด์ค๋ ๋ก์ง์ ํ ํธ๋์ญ์ ์ ๋ฌถ์ผ๋ฉด ์ ์ข์ง ์์๊น?? ๋ฌธ๋ ์ด๋ฐ ์๊ฐ์ด ๋ค์๊ณ ๊ตฌ๊ธ๋ง ํด๋ณด๋ ์ญ์๋ ๋ค๋ฅธ ์ฌ๋๋ค๋ ์ด๋ฏธ ๊ณ ๋ฏผํ๋ ํ์ ๋ค์ด ๋ณด์๋ค.
์ ํ ํธ๋์ญ์ ์ ๋ฌถ์ผ๋ฉด ์ข์ง ์์๊น??
ํธ๋์ญ์ ์ ํน์ง์ ์ฃผ๋ชฉํ ํ์๊ฐ ์๋ค.
ํ ํธ๋์ญ์ ์ด ์์๋๋ฉด DB์์ ์ปค๋ฅ์ ์ ๋งบ๊ณ ํธ๋์ญ์ ์ด ๋๋ ๋๊น์ง ์ปค๋ฅ์ ์ ๋์ง ์๋๋ค.
์๋ ์ฝ๋์์ ์ด๋ฅผ ๊ฒ์ฆํ ์ ์์๋ค.
@Service
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
private final MemberResourceService resourceService;
private final DataSource dataSource;
@Transactional
public Member create(CreateMemberRequest request) {
printConnectionStatus();
Member member = new Member(request.getUsername());
memberRepository.save(member);
resourceService.upload(request.getUserImage());
printConnectionStatus();
return member;
}
private void printConnectionStatus() {
final HikariPoolMXBean hikariPoolMXBean = ((HikariDataSource) dataSource).getHikariPoolMXBean();
System.out.println("################################");
System.out.println("ํ์ฌ active์ธ connection์ ์ : " + hikariPoolMXBean.getActiveConnections());
System.out.println("ํ์ฌ idle์ธ connection์ ์ : " + hikariPoolMXBean.getIdleConnections());
System.out.println("################################");
}
}
ํธ๋์ญ์ ์ง์ ์งํ ์ปค๋ฅ์ ํ ์ํฉ๊ณผ ํธ๋์ญ์ ์ข ๋ฃ ์ง์ ์ ์ปค๋ฅ์ ํ ์ํฉ์ ์ถ๋ ฅํ๋ฉด ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
์ฆ, ์ ๋ก๋ํ ํ์ผ์ ํฌ๊ธฐ๊ฐ ํฌ๋ค๋ฉด DB ์ปค๋ฅ์ ์ ๋ถํ์ํ๊ฒ ์ ์ ํ๋ฉด์ ์์์ ํฌ๊ฒ ๋ญ๋นํ๊ฒ ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ช๋ช ๋ฐฉ๋ฒ๋ค์ ๋ดค์ง๋ง ๋๋ ํธ๋์ญ์ ๋ถ๋ฆฌ๋ฅผ ์์ผ ํด๊ฒฐ์ ์๋ํ๋ค.
์๋ 1) ํธ๋์ญ์ ์ ๋ฌ์ง ์์ ๋ฉ์๋์์ ํธ๋์ญ์ ์ ๋จ DB ์ ์ฅ ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ์ ์ฅํ ๋๋ง ํธ๋์ญ์ ์ฌ์ฉ - ์คํจ
๋ด ์ฝ๋๋ ์๋์ง๋ง ๋น์ทํ ์ข์ ์์ ๊ฐ ์์ด์ ๊ฐ์ ธ์๋ค.
public Member create(CreateMemberRequest request) {
printConnectionStatus();
Member member = createEntity(request.getUsername());
resourceService.upload(request.getUserImage());
printConnectionStatus();
return member;
}
@Transactional
public Member createEntity(String username) {
Member member = new Member(username);
memberRepository.save(member);
return member;
}
์ ์ฝ๋์์ @Transactional ์ด๋ ธํ ์ด์ ์ด ์ ์ฉ๋ createEntity ๋ฉ์๋๊ฐ ์ฌ์ค ํธ๋์ญ์ ์ด ์ ์ฉ๋์ง ์๋๋ค.
์ด์ ๋ Spring AOP๋ ํ๋ก์ ํจํด์ ๊ธฐ๋ฐ์ผ๋ก ๋์ํ๊ธฐ ๋๋ฌธ์ด๋ค.
์ฆ, A๋น์์ B๋น์ ํธ์ถํ๊ธฐ ์ ์ B์ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ํธ์ถํ๊ฒ ๋๋ค.
ํ์ง๋ง A ์ธ์คํด์ค์์ ์์ ์ ํธ์ถํ๋ค ํด๋ ํ๋ก์ ๊ฐ์ฒด๋ ํธ์ถ๋์ง ์๊ณ @Transactional๋ ๋์ํ์ง ์๋๋ค.
์๋ 2) ๋ฉ์๋ ๋จ์์ ๋ถ๋ฆฌํ์ง ๋ง๊ณ ๋น์ ๋ถ๋ฆฌํด๋ณด์
์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ์๋น์ค ํด๋์ค๋ฅผ ๋ถ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ด ์๋ค. ๋น์ด ๋ถ๋ฆฌ๋๋ฏ๋ก ํธ๋์ญ์ ์ ์ ์ญ ๋์ ์ํฌ ์ ์๋ ๊ฒ์ด๋ค.
๋ถ๋ฆฌ๋ ์๋น์ค ํด๋์ค๋ค์ Facade ํจํด์ ์ฌ์ฉํด์ ๊ณ์ธต์ ํ๋ ๋ ๋ง๋๋ ๋ฐฉ๋ฒ๋ ์ข์๋ณด์๋ค.
ํผ์ฌ๋ ํจํด(Facade Pattern)์ ๊ตฌ์กฐ ํจํด(Structural Pattern)์ ํ ์ข ๋ฅ๋ก์จ, ๋ณต์กํ ์๋ธ ํด๋์ค๋ค์ ๊ณตํต์ ์ธ ๊ธฐ๋ฅ์ ์ ์ํ๋ ์์ ์์ค์ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ ํจํด์ด๋ค.
์ฌ๋ฌ SubSystem๋ค์ ๊ธฐ๋ฅ์ ํ๋์ Facade Object๋ก ์ ์ํ๊ณ , Client๊ฐ Facade Object๋ฅผ ์ฌ์ฉํ๋ ํํ์ด๋ค.
๋ด ์ํฉ์์ ์ด๋ฏธ์ง ์ ๋ก๋์ DB์ ์ํฐํฐ ์ ์ฅ ๊ธฐ๋ฅ์ ํ๋์ Facade Object๋ก ์ ์ํ๊ณ ์ปจํธ๋กค๋ฌ์์ ์ด๋ฅผ ํธ์ถํ๋ ๊ฒ์ด๋ค. ์ด๋ Facade Object์๋ ํธ๋์ญ์ ์ด ๋น์ฐํ ๋ถ์ง ์์์ผ ํ๊ณ ์ํฐํฐ๋ฅผ ๋ค๋ฃจ๋ ๋ถ๋ถ์๋ง ํธ๋์ญ์ ์ ๋ถ์ฌ ์ฌ์ฉํ๋ฉด ๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ์งง์ ํธ๋์ญ์ ์ ์ ์งํ๋ฉด์ ์ ๊ธฐ๋ฅ์ ํ ์ ์๊ฒ ๊ตฌํ ๊ฐ๋ฅํ๋ค.
ํ์ง๋ง ํ๊ฐ์ง ๋ฌธ์ ์ ์ด ์๋ค.
AWS S3์ ์ด๋ฏธ์ง๋ ์ ๋ก๋ ๋์์ง๋ง ์ํฐํฐ ์ ์ฅ ์ค์ ์๋ฌ๊ฐ ๋์ ๋กค๋ฐฑ์ด ๋์๋ค๋ฉด ์ ๋ก๋๋ ์ด๋ฏธ์ง๋ ์ฐ๋ ๊ธฐ ๊ฐ์ด ๋๋ ๊ฒ์ด๋ค.
์ด ๋ฌธ์ ๋ DB ์ ์ฅ์์ ์คํจํ๋ฉด ์๋ฌ๋ฅผ ๋์ง๊ณ ์ด ์๋ฌ๋ฅผ Facade ์ธ์คํด์ค์์ catch๋ก ์ก์์ ๋ฐ๋ก ํด๋น ์ด๋ฏธ์ง๋ฅผ S3 ์ ์ฅ์์์ ์ญ์ ํ๋ฉด ์ข์ ๊ฒ ๊ฐ์๋ค.