0130 ~ 0205
# 0130 ~ 0205
# 0201 - API Gateway
# [ API Gateway ๋? ]
์๋น์ค๋ก ์ ๋ฌ๋๋ ๋ชจ๋ API ์์ฒญ์ ๊ด๋ฌธ ์ญํ ์ ํ๋ ์๋ฒ. ์์คํ ์ ์ํคํ ์ฒ๋ฅผ ๋ด๋ถ๋ก ์จ๊ธฐ๊ณ ์ธ๋ถ์ ์์ฒญ์ ๋ํ ์๋ต๋ง์ ์ ์ ํ ํํ๋ก ์๋ต (ํ๋ก์ ์ญํ )
API Gateway๋ ๋ชจ๋ ์๋ฒ๋ก์ ์์ฒญ์ ๋จ์ผ์ง์ ์ ๊ฑฐ์ณ์ ์ฒ๋ฆฌํ๋๋ก ํ๋ค. ์ด๋ฅผ ํตํด ๊ณตํต๋ ๋ก์ง ์ฒ๋ฆฌ๋ ์ธ์ฆ ๋ฐ ์ธ๊ฐ ์ฒ๋ฆฌ, ๋ผ์ฐํ ์ฒ๋ฆฌ๋ฑ์ ํ ์ ์๋ค.
# [ ์ธ์ฆ/์ธ๊ฐ์ ๊ด๋ จ๋ ๊ธฐ๋ฅ ]
- ์๋ํฌ์ธํธ๋ณ API ํธ์ถ ์ธ์ฆ
- ์๋ํฌ์ธํธ๋ณ API ์์ฒญ ์ธ๊ฐ
# [ ๋ผ์ฐํ ]
- ๋ก๋๋ฐธ๋ฐ์ฑ
- ์๋น์ค ๋ฐ ํด๋ผ์ด์ธํธ ๋ณ ์๋ํฌ์ธํธ ์ ๊ณต
- ๋ฉ์์ง ๋๋ ํค๋๊ธฐ๋ฐ ๋ผ์ฐํ
# [ ๊ณตํต ๋ก์ง ์ฒ๋ฆฌ ]
# [ Mediation(๋ฉ๋์์ด์ ) ]
๋ฉ๋์์ด์ ์ด๋ '์ค์ฌ' ๋๋ '์กฐ์ '์ด๋ผ๋ ์๋ฏธ๋ฅผ ๊ฐ์ง๋๋ฐ API ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ๊ฐ ์ํ๋ API ํํ์ ๋ค๋ฅผ๋ API ๊ฒ์ดํธ์จ์ด๊ฐ ์ด๋ฅผ ๋ณ๊ฒฝํด์ฃผ๋ ๊ธฐ๋ฅ์ ์ด์ผ๊ธฐํ๋ค.
- ๋ฉ์์ง ํฌ๋งท ๋ณํ
- ํ๋กํ ์ฝ ๋ณํ
- ๋ฉ์์ง ํธ์ถ ํจํด ๋ณํ
- Aggregation(์ด๊ทธ๋ ๊ฒ์ด์ ) : API๋ฅผ ๋ฌถ์ด์ ํ๋์ API ์ฒ๋ผ ์ฒ๋ฆฌํ๊ฒ ๋ณด์ด๋ ๋์
# [ ๋ก๊น ๋ฐ ๋ฏธํฐ๋ง ]
- API ํธ์ถ ๋ก๊น
- API Metering & Charing (๋ฏธํฐ๋ง & ์ฐจ์ง) : API ๋ฏธํฐ๋ง๊ณผ ์ฐจ์ง์ ์ ๋ฃ API ์๋น์ค๋ฅผ ์ํ ๊ธฐ๋ฅ์ผ๋ก ์ธก์ ํ ์ ์๋ ์งํ๋ค์ ๊ธฐ๋กํ๋ ์๋น์ค
# [ QoS ์กฐ์ (Quality of service) ]
Qos ์กฐ์ ๊ธฐ๋ฅ์ด๋ API ์๋น์ค๋ฅผ ํด๋ผ์ด์ธํธ ๋์์ ๋ฐ๋ผ์ ์๋น์ค ๋ ๋ฒจ์ ์กฐ์ ํ๋ ๊ธฐ๋ฅ์ด๋ค.
ํธ์ถํ์๋ฅผ ์ ํ ํ๋ค๊ฑฐ๋, ์ ์ก ์ฉ๋์ด๋, ๋ค์ดํธ์ํฌ ๋์ญํญ์ ์ ๋ฃ/๋ฌด๋ฃ ์ฌ์ฉ์์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ์ ์ฉํ๋ ๊ฒ๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ QoS ๊ธฐ๋ฅ์ด๋ผ๊ณ ํ๋ค.
# 0202 - jasypt
Jasypt is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works.
๊ณต๊ฐ๋ ํ๋ก์ ํธ์ private ์ ๋ณด์ ๋ํ ๋ณด์์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค. ๊ทธ ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ๊ฐ๋ฐ์ ๋ณด๋ฅผ ์ํธํ ํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํ๋ค.
[ ์ฌ์ฉ๋ฒ ]
- ์์กด์ฑ ์ถ๊ฐ
dependencies {
implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter'
}
2
3
Encrypt Key ์์ฑ
https://www.devglan.com/online-tools/jasypt-online-encryption-decryption
jasypt ๊ด๋ จ ์ค์ ์ password๋ฅผ ์ค์ ํ๋ ๋ถ๋ถ์ด ์๋ค. ํด๋น password๋ฅผ ์ํธํํ๊ธฐ ์ํด ํด๋น ์ฌ์ดํธ์์ ์ํธํConfiguration ์์ฑ
@Configuration
@EnableEncryptableProperties
public class JasyptConfig {
@Bean(name = "encryptorBean")
public StringEncryptor stringEncryptor(SimpleStringPBEConfig simpleStringPBEConfig) {
PooledPBEStringEncryptor stringEncryptor = new PooledPBEStringEncryptor();
stringEncryptor.setConfig(simpleStringPBEConfig);
return stringEncryptor;
}
@Bean
@ConfigurationProperties("config.encrypt")
public SimpleStringPBEConfig simpleStringPBEConfig() {
return new SimpleStringPBEConfig();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- properties ์ค์ ์ถ๊ฐ
jasypt:
encryptor:
bean: {๋น์ด๋ฆ}
config:
encrypt:
password: {์ํธํ๋ ํจ์ค์๋}
algorithm: PBEWithMD5AndDES
provider-name: SunJCE
pool-size: 1
key-obtention-iterations: 1000
string-output-type: base64
2
3
4
5
6
7
8
9
10
11
- ์ํธํ
@SpringBootTest
class JasyptConfigTest {
@Autowired
@Qualifier("encryptorBean")
private StringEncryptor stringEncryptor;
@Test
public void generatePassword() {
String encrypt = stringEncryptor.encrypt("password");
System.out.println(encrypt);
String decrypt = stringEncryptor.decrypt(encrypt);
System.out.println(decrypt);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
- ์ ์ฉ
ENC("์ํธํ password")
ย ํ์์ผ๋ก ์ํธํ๋ ๊ฐ ์ ์ฉ
spring:
datasource:
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://localhost:3306
username: dbuser
password: ENC(WHXxOvGjJa7qXjALhA7ghdoYksJjabL/)
2
3
4
5
6
# 0205 - ThreadLocal
# [ Thread Local์ด๋? ]
- ์ผ์ข ์ ์ฐ๋ ๋ ์ง์ญ๋ณ์ใ ก ์ค์ง ํ๋์ ์ฐ๋ ๋์ ์ํด ์ฝ๊ณ ์ธ ์ ์๋ ๋ณ์๋ก์, ๋ค๋ฅธ ๊ฐ๊ฐ์ ์ฐ๋ ๋๊ฐ ํ๋์ ThreadLocal์ ํธ์ถํด๋ ์๋ก ๋ค๋ฅธ ๊ฐ์ ๋ฐ๋ผ๋ณธ๋ค.
- Thread์ ์ ๋ณด๋ฅผ Key๋ก ํ๋ Map ํ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํด๋๊ณ ์ฌ์ฉํ๋ ์๋ฃ๊ตฌ์กฐ.
- ThreadPool ์ฌ์ฉํ์ฌ Thread ์ฌํ์ฉ ์ ์ด์ ์ ์ ์ฅ๋ ThreadLocal์ ํธ์ถํ๊ฒ ๋๋ฏ๋ก ๋ชจ๋ ThreadLocal ์ฌ์ฉ ํ remove ํ์
# [ ํ์ฉ ]
- ์ฌ์ฉ์ ์ธ์ฆ์ ๋ณด - Spring Sercurity์์ ์ฌ์ฉ์๋ง๋ค ๋ค๋ฅธ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด ์ธ์ ์ ์ฌ์ฉํ ๋.
- ํธ๋์ญ์ ์ปจํ ์คํธ - ํธ๋์ญ์ ๋งค๋์ ๊ฐ ํธ๋์ญ์ ์ปจํ ์คํธ๋ฅผ ์ ํํ ๋.
- MDC(Mapped Diagnostic Context) - logback์์ log์ ๋ฉํ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ ๋.
# [ ์ฌ์ฉ๋ฒ ]
- ๊ฐ์ฒด ์์ฑ
ThreadLocal<String> threadLocalGeneric = new ThreadLocal<>();
- ์ด๊ธฐ๊ฐ ์ค์ ๋ฐฉ๋ฒ
ThreadLocal<String> subThreadLocal = new ThreadLocal<String>() {
@Override
protected String initialValue() {
return "Init Value";
}
};
2
3
4
5
6
7
- ๊ฐ ์ ์ฅ
ThreadLocal<String> threadLocalGeneric = new ThreadLocal<>();
threadLocalGeneric.set("TEMP");
2
- ๊ฐ ๋ถ๋ฌ์ค๊ธฐ
ThreadLocal<String> threadLocalGeneric = new ThreadLocal<>();
String result = threadLocalGeneric.get();
2
- ๊ฐ ์ญ์
ThreadLocal<String> threadLocalGeneric = new ThreadLocal<>();
threadLocalGeneric.set("TEMP");
System.out.println(threadLocalGeneric.get());
// OUTPUT: TEMP
threadLocalGeneric.remove();
System.out.println(threadLocalGeneric.get());
// OUTPUT: null
2
3
4
5
6
7
8
# [ ์ฌ์ฉ ์์ ]
- Runnable ์ธํฐํ์ด์ค ๊ตฌํ(MyRunnable) -> threadLocal์ ๋๋ค ๊ฐ ์ ์ฅ
public static class MyRunnable implements Runnable {
private ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
@Override
public void run() {
threadLocal.set( (int) (Math.random() * 100D) );
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
System.out.println(threadLocal.get());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- ํ๋์ Runnable ๊ฐ์ฒด๋ฅผ 2๊ฐ์ ์ฐ๋ ๋์ ๋ด๊ธฐ
MyRunnable runnable = new MyRunnable();
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
2
3
- ๊ฐ ์ฐ๋ ๋ run ์ ๋ ์ฐ๋ ๋์ ๋ค๋ฅธ ๊ฐ์ด ๋ด๊ธฐ๋์ง ํ์ธ(์ฐ๋ ๋ ๋ณ ThreadLocal์ ๋๋ค ๊ฐ์ด ๋ด๊ธฐ๊ธฐ ๋๋ฌธ์ ๋ค๋ฅด๋ค.)
System.out.print("thread1 get ๊ฒฐ๊ณผ :: ");
thread1.start();
// OUTPUT: thread1 get ๊ฒฐ๊ณผ :: 19
Thread.sleep(200);
System.out.print("thread2 get ๊ฒฐ๊ณผ :: ");
thread2.start();
// OUTPUT: thread2 get ๊ฒฐ๊ณผ :: 65
Thread.sleep(200);
2
3
4
5
6
7
8
9
10
# [ InheritableThreadLocal์ด๋? ]
- ๋ถ๋ชจ ์ฐ๋ ๋์์ ์์ฑ๋ ThreadLocal์ ์์ ์ฐ๋ ๋์์๋ ๋์ผํ ๊ฐ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ThreadLocal Class.
ThreadLocal<String> threadLocal = new ThreadLocal<>();
InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();
Thread thread1 = new Thread(() -> {
System.out.println("========== [" + Thread.currentThread().getName() + "] START ==========");
threadLocal.set("[" + Thread.currentThread().getName() + "] ThreadLocal Value");
inheritableThreadLocal.set("[" + Thread.currentThread().getName() + "] InheritableThreadLocal Value");
System.out.println("threadLocal get :: " + threadLocal.get());
System.out.println("inheritableThreadLocal get :: " + inheritableThreadLocal.get());
Thread childThread = new Thread( () -> {
System.out.println("========== [" + Thread.currentThread().getName() + " - ChildThread] START ==========");
System.out.println("threadLocal get :: " + threadLocal.get());
System.out.println("inheritableThreadLocal get :: " + inheritableThreadLocal.get());
});
childThread.start();
});
thread1.start();
Thread thread2 = new Thread(() -> {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("========== [" + Thread.currentThread().getName() + "] START ==========");
System.out.println("threadLocal get :: " + threadLocal.get());
System.out.println("inheritableThreadLocal get :: " + inheritableThreadLocal.get());
System.out.println("------------------------------------------------------------------------------");
});
thread2.start();
/* OUTPUT
*
========== [Thread-2] START ==========
threadLocal get :: [Thread-2] ThreadLocal Value
inheritableThreadLocal get :: [Thread-2] InheritableThreadLocal Value
========== [Thread-4 - ChildThread] START ==========
threadLocal get :: null
inheritableThreadLocal get :: [Thread-2] InheritableThreadLocal Value
========== [Thread-3] START ==========
threadLocal get :: null
inheritableThreadLocal get :: null
*/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47