โ 1. ํ๋ก์(Proxy) ๋?
- ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ํ ์ ๊ทผ์ ์ ์ดํ๋ ๊ฐ์ฒด๋ก ๋์์ธ ํจํด์ ํ๋ก์ ํจํด๊ณผ ์ผ์นํ๋ ๊ฐ๋ ์ด๋ค.
- ํ๋ก์์ ์ฃผ์ ๋ชฉ์ ์ ์ ๊ทผ ์ ์ด, ๋ก๊น /๊ฐ์, ์ง์ฐ ๋ก๋ฉ, ๋ณด์ ์ฒ๋ฆฌ, ํธ๋์ญ์ ์ฒ๋ฆฌ ๋ฑ์ด ์๋ค.
โ 2. ํ๋ก์ํจํด(Proxy Pattern) ์ด๋?
interface Subject {
void request();
}
class RealSubject implements Subject {
public void request() {
System.out.println("์ค์ ์์
์ํ");
}
}
class Proxy implements Subject {
private RealSubject realSubject;
public void request() {
if (realSubject == null) {
realSubject = new RealSubject(); // ์ง์ฐ ์ด๊ธฐํ
}
System.out.println("ํ๋ก์: ์ ๊ทผ ์ ์ด ๋๋ ๋ก๊น
");
realSubject.request(); // ์ค์ ๊ฐ์ฒด์ ์์ฒญ ์ ๋ฌ
}
}
- ํ๋ก์ ๊ฐ๋ ์ ์ด์ฉํด ๊ฐ์ฒด๋ฅผ ํตํด ๋ค๋ฅธ ๊ฐ์ฒด์ ์ ๊ทผํ๋๋ก ๋ง๋๋ ์ค๊ณ ํจํด์ ์๋ฏธํ๋ค.
- GoF(Gang of Four)์ ๋์์ธ ํจํด ์ค ํ๋์ด๋ฉฐ, ๊ตฌ์กฐ ํจํด์ ์ํ๊ฒ ๋๋ค.
- ๋ณดํต ํ๋ก์ ํจํด์์๋ ์ ๊ทผ์ ์ ์ดํ๊ฑฐ๋ ๋ถ๊ฐ์ ์ธ ์์ (๋ก๊น , ์ธ์ฆ, ์บ์ฑ ๋ฑ)์ ํ๊ฒ ๋๋ค.
- ์ ๋ฆฌํ๋ฉด, ํ๋ก์ ํจํด์ ๊ตฌํ ๊ฐ์ฒด๋ฅผ ์ง์ ํธ์ถํ์ง ์๊ณ ๊ฐ์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ํตํด ํ์ํ ๋ถ๊ฐ ๋ก์ง(๋ก๊น , ์ธ์ฆ, ์บ์ฑ, ํธ๋์ญ์ ๋ฑ)์ ๋จผ์ ์ํํ ํ ์ง์ง ๊ตฌํ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๋ฐฉ์์ด๋ค.
- Spring ์์ AOP ๋ฅผ ํ์ฉ ํ๋ฉด ๋น์ฆ๋์ค ๋ก์ง์ ๋ถ๊ฐ ๊ธฐ๋ฅ์ ๋ฃ์ ์ ์๋๋ฐ, ์ด๋ AOP๋ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ํ ํ ๋ค ์ค์ ๋ก์ง์ ์คํ์ ์์ผ์ค๋ค. ์ด๋ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฐ์๊ฐ ์ง์ ๋ง๋ค์ง ์์๋ Spring ์ AOP ์ค์ ์ ๋ณด๊ณ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๋ฐํ์์ ๋์ ์ผ๋ก ์์ฑํด์ ๋น์ผ๋ก ๋ฑ๋ก์ ํด์ค๋ค. ์ฆ, ๊ฐ๋ฐ์๋ ๋น์ฆ๋์ค ๋ก์ง๋ง ์์ฑ์ ํ๋ฉด ๋๋ค. ์ด ์ฒ๋ผ ํ๋ก์๊ฐ์ฒด๋ฅผ ๋ฐํ์์ ๋ง๋ค์ด ์ฃผ๋ ๋ฐฉ์์ ๋์ ํ๋ก์(Dynamic Proxy) ๋ผ๊ณ ํ๋ค.
- ๋ฐ๋๋ก ๊ฐ๋ฐ์๊ฐ ์ง์ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ ์ํ๋ ๊ฒ์ ์ ์ ํ๋ก์(Static Proxy) ๋ผ๊ณ ๋ถ๋ฅธ๋ค. ( ํ๋ก์ ํจํด ํ์ฉ )
โ 3. ๋์ ํ๋ก์(Dynamic Proxy) ๋?
๊ตฌ๋ถ | ์ ์ ํ๋ก์ | ๋์ ํ๋ก์ |
์์ฑ ์์ | ์ปดํ์ผ ํ์ | ๋ฐํ์ |
๊ตฌํ ๋ฐฉ์ | ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ตฌํ | ํ๋ ์์ํฌ๊ฐ ์๋ ์์ฑ |
๊ธฐ๋ฐ | ์ธํฐํ์ด์ค or ํด๋์ค | ์ธํฐํ์ด์ค(JDK), ํด๋์ค(CGLIB) |
์ ์ฐ์ฑ | ๋ฎ์ | ๋์ |
์ฌ์ฉ ์ | ํ๋ก์ ํจํด ์ง์ ๊ตฌํ | Spring AOP, Feign, JPA ๋ฑ |
- ๋ฐํ์์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ ๊ธฐ๋ฅ์ ์๋ฏธํ๋ค.
- ์ฝ๊ฒ๋งํด, ์ธํฐํ์ด์ค๋ง ์์ผ๋ฉด ๊ตฌํ์ฒด ์์ด๋ ๊ทธ ๋์์ ๊ฐ๋ก์ฑ๊ฑฐ๋ ์กฐ์ํ๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ค ์ ์๋ ๊ธฐ๋ฅ์ ๋๋ค.
- ๋ฐํ์ ์์ ์ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๋์ ์ผ๋ก ์์ฑํ๋ ๊ธฐ๋ฒ(๊ธฐ์ )์ ์๋ฏธํ๋ค.
- ์ฆ, ๋ด๋ถ์ ์ผ๋ก ํ๋ก์ ํจํด์ ๋์ ์ผ๋ก ๊ตฌํํ๋ ๊ธฐ์ ์ด๊ธฐ ๋๋ฌธ์ ํจํด์ด ์๋ ๋์ ์ผ๋ก ๊ตฌํํ๋ ๊ธฐ์ ์ ์ธ ์๋จ์.
- Java ์์๋ java.lang.reflect.Proxy ์ InvocationHandler ๋ฅผ ์ด์ฉํด์ ๋์ ํ๋ก์๋ฅผ ๊ตฌํํ๊ฒ ๋จ.
(1) JDK ๋์ ํ๋ก์ - ์ธํฐํ์ด์ค ๊ธฐ๋ฐ
- ์ธํฐํ์ด์ค๊ฐ ๋ฐ๋์ ์กด์ฌํด์ผ ํ๋ฉฐ, ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ์ต๋ช ํด๋์ค(ํ๋ก์ ๊ฐ์ฒด)๋ฅผ ๋ฐํ์์ ์์ฑ์ ํ๋ ๋ฐฉ์์ด๋ค.
- ์ธํฐํ์ด์ค ํ์ ์ผ๋ก ๋ฐํ์ด ๋๋ฉฐ, ์ค์ ๊ตฌํ์ฒด ์์ด๋ ์ธํฐํ์ด์ค์ ์ ์ธ๋ ๋ฉ์๋๋ฅผ ๊ฐ๋ก์ฑ์ ๋ถ๊ฐ ๋ก์ง ์ํ์ด ๊ฐ๋ฅํจ.
- ๋ํ์ ์ธ ์์๋ก๋ @FeignClient , Spring Data JPA ์ Repository, @Transactional ๋ฑ์ด ์๋ค.
- ์ฆ, ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค๋ฉด ํด๋น ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๋ด๋ถ์ ์ผ๋ก ๋ง๋ ๋ค๋ ์๋ฏธ์. ๋ด๋ถ ๊ตฌํ
- JDK(Java Development Kit) ์์ ๊ธฐ๋ณธ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ด๋ฉฐ,java.lang.reflect.Proxy ํด๋์ค๋ฅผ ์ด์ฉํด์ ๋ฐํ์์ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. ์ฆ, ์๋ฐ JDK ์์ฒด์ ์๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํด์ ์ธํฐํ์ด์ค ๊ธฐ๋ฐ์ผ๋ก ๋ฐํ์(๋์ )์ ํ๋ก์๋ฅผ ๋ง๋๋ ๋ฐฉ์์ด๋ผ JDK ๋์ ํ๋ก์๋ผ ๋ถ๋ฆ ( ์ฐธ๊ณ : ๋ฐ๋์ ์ธํฐํ์ด์ค๊ฐ ์์ด์ผ ํจ )
(2) CGLIB ํ๋ก์ - ํด๋์ค ๊ธฐ๋ฐ
- ๊ธฐ์กด ๊ตฌํ ํด๋์ค์ ๋ณต์ฌ๋ณธ(์๋ธํด๋์ค)์ ๋ง๋ค์ด ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ด๋ค.
- ๊ธฐ์กด ํด๋์ค์ ์๋ธํด๋์ค(์์)๋ฅผ ์์ฑํด์, ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ ๊ฐ๋ก์ฑ๋ ๋ฐฉ์์ด๋ค.
- ์๋ณธ ํด๋์ค์ ํ์ ํด๋์ค์ด๋ฉฐ, ์๋ณธ ํด๋์ค์ ๋์ผํ ๊ธฐ๋ฅ์ ํ๋ฉด์ ์ถ๊ฐ ๊ธฐ๋ฅ์ ์ฝ์ ํ๋ค.
- ์ด ๋ฐฉ์์ SpringBoot ์ @Service, @Component ๊ฐ์ด ๋น์ผ๋ก ๋ฑ๋ก๋ ๊ตฌํ ํด๋์ค์ ์ง์ AOP๊ฐ ์ ์ฉ๋ ๋ ์ฌ์ฉํจ.
- ์ฝ๊ฒ๋งํด, ํด๋น ๋น์ AOP(๋ถ๊ฐ ๊ธฐ๋ฅ)๋ฅผ ์ ์ฉํ ๋ ์ฌ์ฉ๋๋ ๊ธฐ์ ์ ์๋ฏธํ๋ค.
- CGLIB ์ Code Generaion Library ์ ์ฝ์๋ก ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ํ๋ก์๋ฅผ ์๋ฏธํ๋ค. ์ธ๋ถ ๋ฐ์ดํธ์ฝ๋ ์กฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์, ๋ฐ์ดํธ์ฝ๋๋ฅผ ์ง์ ์์ฑํด์, ์๋ณธ ํด๋์ค์ ์๋ธํด๋์ค(์์ ํด๋์ค)๋ฅผ ๋ง๋ค์ด ๋์ผ๋ก์จ ํด๋์ค ๊ธฐ๋ฐ ํ๋ก์๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ CGLIB ํ๋ก์๋ผ๊ณ ๋ถ๋ฅด๋ ๊ฒ์ด๋ค. ์คํ๋ง์์๋ ๊ฐ๋ฅํ๋ฉด JDK ํ๋ก์๋ฅผ ์ฐ์ ์ฌ์ฉํ๊ณ , ํ์ ํ ๋๋ง CGLIB ์ผ๋ก fallback ์ ํ๊ฒ ๋๋ค. ( ๊ฑ ์ง์ง ์ง์ ์ง์ฃผ๋ ๋๋์ด๋ผ ์๊ฐํ๋ฉด ๋จ. )
โ 4. ๋ํ์ ์ธ ๋์ ํ๋ก์(Dynamic Proxy) ์์
(1) Spring AOP
@Service
public class OrderService {
@Transactional
public void placeOrder() {
// ํต์ฌ ๋ก์ง
}
}
- ํธ๋์ญ์ , ๋ก๊น , ๋ณด์, ์ฑ๋ฅ ์ธก์ ๋ฑ ๋ถ๊ฐ ๊ธฐ๋ฅ์ ๋น์ฆ๋์ค ๋ก์ง๊ณผ ๋ถ๋ฆฌํด์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์ฉ๋
(2) Spring Data JPA
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
- JpaRepository ๊ฐ์ ์ธํฐํ์ด์ค๋ง ์ ์ํ๋ฉด ์๋์ผ๋ก ๊ตฌํ์ฒด๊ฐ ์์ฑ์ด ๋๋ฉฐ, ๋ด๋ถ์ ์ผ๋ก ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
(3) FeignClient - Spring Cloud OpenFeign
@FeignClient(name = "user-service", url = "http://localhost:8080")
public interface UserClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable Long id);
}
- HTTP API ํธ์ถ์ Java ์ธํฐํ์ด์ค์ฒ๋ผ ์ฌ์ฉ์ ํ๋ค. ๋ด๋ถ์ ์ผ๋ก ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
(4) Spring Security
- FilterChainProxy, MethodSecurityInterceptor ๋ฑ์์ ์ธ์ฆ๋ ์ฌ์ฉ์์ ๊ถํ ํ์ธ์ด๋ ์ ๊ทผ ์ ํ ๋ฑ์ ์ฒ๋ฆฌํ ๋ ํ๋ก์ ๊ธฐ๋ฐ ๋ณด์ ํํฐ ์ฒด์ธ์ด ๋์์ ํ๋ค.