Skip to content

Latest commit

Β 

History

History
404 lines (231 loc) Β· 13.4 KB

File metadata and controls

404 lines (231 loc) Β· 13.4 KB

Untitled (19)

ν”Όμ²˜ ν”Œλž˜κΉ… μ†”λ£¨μ…˜ : Light Switch

κΈ°κ°„ : 2024.04.08 ~. 2024.05.20 / 7μ£Ό

κΈ°κ΄€ : SSAFY 10κΈ° 2ν•™κΈ° 자율 ν”„λ‘œμ νŠΈ / 6인

Github : https://github.com/LightSwitch-S202/LightSwitch

μ„±κ³Ό: SSAFY 10κΈ° 2ν•™κΈ° 자율 ν”„λ‘œμ νŠΈ μš°μˆ˜μƒ


ν”Όμ²˜ν”Œλž˜κ·Έ (Feature Flag)

μ†Œν”„νŠΈμ›¨μ–΄ κ°œλ°œμ—μ„œ νŠΉμ • κΈ°λŠ₯μ΄λ‚˜ μ½”λ“œλ₯Ό 쑰건적으둜 ν™œμ„±ν™”ν•˜κ±°λ‚˜ λΉ„ν™œμ„±ν™”ν•  수 있게 ν•΄μ£ΌλŠ” 기술

ν”Όμ²˜ ν”Œλž˜κ·Έ, ν”Όμ²˜ ν† κΈ€, κΈ°λŠ₯ ν† κΈ€ λ“± λ‹€μ–‘ν•œ μ΄λ¦„μœΌλ‘œ 뢈리우며, μƒˆλ‘œμš΄ μ½”λ“œλ₯Ό λ°°ν¬ν•˜μ§€ μ•Šκ³  λŸ°νƒ€μž„μ— νŠΉμ • κΈ°λŠ₯을 ν‚€κ±°λ‚˜ 끌 수 μžˆλ‹€.

이λ₯Ό ν™œμš©ν•˜λ©΄ μ†μ‰½κ²Œ 였λ₯˜μ— λŒ€μ²˜ν•˜κ±°λ‚˜, λ‘€λ°±, A/B ν…ŒμŠ€νŠΈ, μΉ΄λ¦¬λ‚˜ 배포 등이 κ°€λŠ₯ν•˜λ‹€.


ν”Όμ²˜ν”Œλž˜κΉ… μ†”λ£¨μ…˜ : Light Switch

Light SwitchλŠ” μ˜€ν”ˆμ†ŒμŠ€ ν”Όμ³ν”Œλž˜κΉ… μ†”λ£¨μ…˜μœΌλ‘œ Docker Image ν˜•νƒœλ‘œ λ°°ν¬λ˜μ–΄ 있으며 MIT λΌμ΄μ„ΌμŠ€μ— 따라 μ‚¬μš©μž λ§žμΆ€ν˜• 개발이 κ°€λŠ₯ν•˜λ‹€.

νŠΉμ • κΈ°λŠ₯을 ν‚€κ³  끌 수 μžˆλŠ” κΈ°λŠ₯ ν† κΈ€, μ‹€μ‚¬μš©μžλ₯Ό λŒ€μ‘°κ΅°κ³Ό μ‹€ν—˜κ΅°μœΌλ‘œ λ‚˜λˆ„μ–΄ μ–΄λ–€ κΈ°λŠ₯이 더 νš¨μœ¨μ μΈμ§€ ν…ŒμŠ€νŠΈ ν•  수 μžˆλŠ” A/B Test, νŠΉμ •ν•œ μ‚¬μš©μžλ§Œ νƒ€κ²ŸνŒ…μ΄ κ°€λŠ₯ν•œ Target Testλ₯Ό μ§€μ›ν•œλ‹€.

λ˜ν•œ, ν™œμš©μ— 따라 였λ₯˜μ— μ‰½κ²Œ λŒ€μ²˜ν•  수 있고, κΈ°λŠ₯ λ‘€λ°±, μΉ΄λ¦¬λ‚˜ 배포λ₯Ό μˆ˜ν–‰ν•  수 μžˆλ‹€.


Light SwitchλŠ” Java, JavaScript, Python μ–Έμ–΄μ˜ SDKλ₯Ό μ§€μ›ν•˜λ©°, ν”Œλž˜κ·Έλ₯Ό 관리할 수 μžˆλŠ” μ›Ή λŒ€μ‹œλ³΄λ“œλ₯Ό μ€‘μ‹¬μœΌλ‘œ κΈ°λŠ₯만 λΉ λ₯΄κ²Œ ν† κΈ€ν•  수 μžˆλŠ” IOS, Android μ•± λŒ€μ‹œλ³΄λ“œλ₯Ό μ§€μ›ν•œλ‹€.




μ£Όμš” λ‹΄λ‹Ή 기술

  • Back-end
    • Spring Boot, Kotlin, Spring AOP, SpringJPA, QueryDSL
  • JavaSDK
    • Java11, SSE(Server-Sent-Event)

λ‹΄λ‹Ή μš”μ•½ :

  • JAVA SDK μ œμž‘
    • Flag 값을 μΊμ‹œλ₯Ό 톡해 λ°˜ν™˜ν•˜μ—¬ 응닡속도 κ°œμ„ 
    • HttpURLConnection을 μ΄μš©ν•œ Get, Post μ„œλ²„ 톡신
    • HttpURLConnection을 μ΄μš©ν•œ SSE(Server-Sent-Event) κ΅¬ν˜„μœΌλ‘œ μ‹€μ‹œκ°„ Flag μ—…λ°μ΄νŠΈ 정보 반영
    • Maven Central Repository에 Artifacts 배포
  • Back-end(Kotlin)
    • Spring AOPλ₯Ό μ΄μš©ν•˜μ—¬ Flag의 기둝 μ €μž₯
  • Front-end
    • Tag UI/κΈ°λŠ₯ κ΅¬ν˜„
  • INFRA
    • Blue/Green 무쀑단 배포 슀크립트 μž‘μ„±





μ‹œμŠ€ν…œ 아킀텍쳐

μ‹€μ§ˆμ μœΌλ‘œ LightSwitch ν”Όμ²˜ν”Œλž˜κΉ… μ†”λ£¨μ…˜μ„ μ œκ³΅λ°›λŠ” μ‚¬μš©μžλŠ” SDKλ₯Ό μ‚¬μš©ν•˜λŠ” 개발자인 Clinet Developer이닀.
Clinet DeveloperλŠ” Light Switch SDKλ₯Ό μ΄μš©ν•˜μ—¬ 개발 μ‹œμ— λ©”μ„œλ“œλ‘œ μ†μ‰½κ²Œ ν”Όμ²˜ ν”Œλž˜κ·Έλ₯Ό μ„€μ •ν•˜κ³  관리할 수 μžˆλ‹€.

Untitled (20)



Java SDK, Maven Central Repository 배포

Java SDKλ₯Ό Maven Central Repository에 λ°°ν¬ν•˜μ—¬ μ‰¬μš΄ 접근성을 μœ μ§€ν•˜μ˜€λ‹€.

https://central.sonatype.com/artifact/kr.lightswitch.www/lightswitch

Untitled (22) Untitled (23)




μ‚¬μš© 방법

μ£Όμš” μ‚¬μš© λ°©λ²•μ—μ„œλŠ” λŒ€ν‘œμ μΈ 언어인 Java SDKλ₯Ό κΈ°μ€€μœΌλ‘œ μ„€λͺ…ν•˜λ©°, 각 언어에 λŒ€ν•œ μ„€λͺ…은 언어별 SDK μ €μž₯μ†Œμ˜ README.mdμ—μ„œ 읽을 수 μžˆλ‹€.

LightSwitch Java SDK μ˜μ‘΄μ„± μ„€μ •

build.gradle

implementation 'kr.lightswitch.www:lightswitch:1.0.1'

build.gradle.kt

implementation("kr.lightswitch.www:lightswitch:1.0.0")

pom.xml

<dependency>
    <groupId>kr.lightswitch.www</groupId>
    <artifactId>lightswitch</artifactId>
    <version>1.0.0</version>
</dependency>

μ˜μ‘΄μ„±μ„ μΆ”κ°€ν•˜λ©΄ ν•΄λ‹Ή SDKλ₯Ό μ΄μš©ν•˜μ—¬ ν”Όμ²˜ν”Œλž˜κ·Έμ— κ΄€λ ¨ν•œ λ©”μ„œλ“œ 호좜이 κ°€λŠ₯ν•˜λ‹€.



μΈμŠ€ν„΄μŠ€ μƒμ„±ν•˜κΈ° getInstance()

LightSwitchλŠ” 항상 같은 κ°’μ˜ ν”Œλž˜κ·Έλ₯Ό μ–»μ–΄μ˜€κΈ° μœ„ν•΄, 싱글톀 μΈμŠ€ν„΄μŠ€λ₯Ό μ‚¬μš©ν•œλ‹€. LightSwitch μΈν„°νŽ˜μ΄μŠ€μ˜ getInstance()λ₯Ό ν˜ΈμΆœν•˜μ—¬ 싱글톀 μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μžˆλ‹€.

μ‚¬μš© μ˜ˆμ‹œ :

LightSwitch lightSwitch = LightSwitch.getInstance();



Light Switch μ΄ˆκΈ°ν™” init()

LightSwitch μ„œλ²„μ—μ„œ 초기 ν”Œλž˜κ·Έλ₯Ό SDK λ‚΄λΆ€μ μœΌλ‘œ μΊμ‹±ν•˜κΈ°μœ„ν•΄ ν•„μˆ˜μ μœΌλ‘œ LightSwitch μ„œλΉ„μŠ€λ₯Ό μ΄ˆκΈ°ν™” ν•΄μ•Ό ν•œλ‹€.
init() μˆ˜ν–‰ μ‹œ μž…λ ₯λ°›λŠ” configλŠ” μ•„λž˜μ™€ κ°™λ‹€.

// @param sdkKey    : LightSwitch μ„œλ²„μ—μ„œ λ°œκΈ‰ 받은 sdk Key
// @param serverUrl : μ—°κ²°ν•  LightSwitch μ„œλ²„ URL
void init(String sdkKey, String serverUrl);

μ‚¬μš© μ˜ˆμ‹œ :

lightSwitch.init("your-private-sdk-key","https://lightswitch.kr");



μ‹λ³„μž LSUser.class

ν”Œλž˜κ·Έμ—μ„œ λ°˜ν™˜ 값을 λ°›μ•„μ˜€κΈ° μœ„ν•΄μ„œ ν΄λΌμ΄μ–ΈνŠΈ μœ μ €μ˜ 기본적인 정보λ₯Ό μ œκ³΅ν•˜λŠ” LSUser.classλ₯Ό μ„ μ–Έν•΄μ•Ό ν•œλ‹€.

LSUser.classλŠ” Builder νŒ¨ν„΄λ§Œμ„ μ§€μ›ν•˜λ©°, userIdλŠ” ν•„μˆ˜ κ°’μœΌλ‘œ μ§€μ •ν•΄μ•Ό ν•œλ‹€.
λ˜ν•œ, μœ μ €λ³„λ‘œ 속성을 μ§€μ •ν•˜μ—¬ νŠΉμ • μœ μ €λ§Œμ„ λŒ€μƒμœΌλ‘œ ν•œ νƒ€κ²Ÿ ν…ŒμŠ€νŒ…μ„ μˆ˜ν–‰ν•  수 μžˆλ‹€.

μ‚¬μš© μ˜ˆμ‹œ :

LSUser lsUser = new LSUser.Builder("userId")
	.build();

LSUser lsUser = new LSUser.Builder("123")
	.property("name", "LightSwitch") // 속성 : κ°’
	.property("address", "seoul")   // ν‚€μ›Œλ“œμ— λ§€μΉ­λœλ‹€.
	.build();

image



ν”Œλž˜κ·Έ λ°˜ν™˜ κ°’ getFlag(), get<T>Flag()

ν”Œλž˜κ·Έμ˜ λ°˜ν™˜ 값을 μ–»λŠ” λ©”μ„œλ“œλŠ” νƒ€μž… μ•ˆμ •μ„±μ„ 보μž₯ν•˜λŠ” λ©”μ„œλ“œμ™€ 보μž₯ν•˜μ§€ μ•ŠλŠ” λ©”μ„œλ“œλ‘œ λ‚˜λˆ„μ–΄μ§„λ‹€.

// νƒ€μž…μ„ μ•Œ 수 μ—†μŒ
<T> T getFlag(String key, LSUser LSUser, Object defaultValue);

// νƒ€μž… μ•ˆμ •μ„± 보μž₯
Boolean getBooleanFlag(String key, LSUser LSUser, Boolean defaultValue);

Integer getNumberFlag(String key, LSUser LSUser, Integer defaultValue);

String getStringFlag(String key, LSUser LSUser, String defaultValue);

getFlag()λŠ” νƒ€μž… μ•ˆμ •μ„±μ„ 보μž₯ν•˜μ§€ μ•ŠλŠ”λ‹€.
λ§Œμ•½ λ°˜ν™˜ 받은 ν”Œλž˜κ·Έμ˜ λ°˜ν™˜ κ°’ νƒ€μž…μ΄ μΌμΉ˜ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄, Java.lang.ClassCastException μ˜ˆμ™Έλ₯Ό λ˜μ§€κΈ° λ•Œλ¬Έμ— try/catchλ₯Ό 적적히 μˆ˜ν–‰ν•΄μ•Ό ν•œλ‹€.

νƒ€μž… μ•ˆμ •μ„±μ„ 보μž₯ν•˜λŠ” λ©”μ„œλ“œλ‘œ ν”Œλž˜κ·Έλ₯Ό μ–»μ–΄μ˜¬ λ•Œ, ν•΄λ‹Ή ν”Œλž˜κ·Έμ˜ νƒ€μž…κ³Ό λ©”μ„œλ“œ μœ ν˜•μ΄ μΌμΉ˜ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ defaultValueλ₯Ό λ°˜ν™˜ν•œλ‹€.
λ˜ν•œ, ν”Œλž˜κ·Έμ˜ key와 μΌμΉ˜ν•˜λŠ” μ΄λ¦„μ˜ ν”Œλž˜κ·Έκ°€ 없을 κ²½μš°μ—λ„ defaultValueλ₯Ό λ°˜ν™˜ν•œλ‹€.

μ‚¬μš© μ˜ˆμ‹œ :

boolean typeUnsafeFlag = lightswitch.getFlag("flag-name", user, false);
boolean typeSafeFlag = lightswitch.getBooleanFlag("flag-name", user, false);

image



Light Switch μ‚¬μš© ν•΄μ œ destroy()

LightSwitch μ„œλΉ„μŠ€μ™€μ˜ 연결을 λŸ°νƒ€μž„μ— ν•΄μ œν•˜κ³  싢은 경우 destroy()λ₯Ό μ΄μš©ν•˜μ—¬ 연결을 ν•΄μ œν•  수 μžˆλ‹€.
μΊμ‹±λœ λͺ¨λ“  ν”Œλž˜κ·Έλ„ μ΄ˆκΈ°ν™” 됨에 μœ μ˜ν•΄μ•Όν•œλ‹€.

destroy()κ°€ 호좜 될 경우 λ‹€μŒκ³Ό 같은 μž‘μ—…λ“€μ΄ 이루어 μ§„λ‹€.

  • Lightswitch Connection μ—°κ²° ν•΄μ œ
  • Lightswitch SSE μ—°κ²° ν•΄μ œ
  • μΊμ‹±λœ ν”Œλž˜κ·Έ μ΄ˆκΈ°ν™”
void destroy();

μ‚¬μš© μ˜ˆμ‹œ :

lightSwitch.destroy();

LightSwitch ν™œμš©

ν”Œλž˜κ·Έ μ‹€μ‹œκ°„ λ³€κ²½

LightSwitch SDKλŠ” λ‚΄λΆ€μ μœΌλ‘œ SSE(Server Sent Event) 톡신을 톡해 μ„œλ²„λ‘œλΆ€ν„° ν”Œλž˜κ·Έ 변경사항을 μ‹€μ‹œκ°„μœΌλ‘œ κ°μ§€ν•œλ‹€.
λ”°λΌμ„œ, μ‚¬μš©μžλŠ” λ³€κ²½λœ ν”Œλž˜κ·Έλ₯Ό μƒˆλ‘œ λ°›μ•„μ˜€κΈ° μœ„ν•΄μ„œ μ•„λ¬΄λŸ° μž‘μ—…λ„ ν•  ν•„μš”κ°€ μ—†λ‹€.



ν”Œλž˜κ·Έ ν‚€μ›Œλ“œ νƒ€κ²Ÿ ν…ŒμŠ€νŒ…

LightSwitchλŠ” ν”Œλž˜κ·Έμ˜ ν‚€μ›Œλ“œμ™€ 속성을 톡해 νƒ€κ²Ÿ ν…ŒμŠ€νŒ…μ„ μ§€μ›ν•œλ‹€.

λ¨Όμ €, μ›Ή λŒ€μ‹œλ³΄λ“œλ₯Ό 톡해 ν”Œλž˜κ·Έμ˜ ν‚€μ›Œλ“œλ₯Ό μ„€μ •ν•  수 μžˆλ‹€.
ν•˜λ‚˜μ˜ ν‚€μ›Œλ“œμ—λŠ” ν•˜λ‚˜μ˜ λ°˜ν™˜ 값이 있으며, ν¬ν•¨λœ 속성을 λͺ¨λ‘ λ§Œμ‘±ν•΄μ•Ό ν‚€μ›Œλ“œ 쑰건을 λ§Œμ‘±ν•œ κ²ƒμœΌλ‘œ κ°„μ£Όν•œλ‹€.

ν‚€μ›Œλ“œ 섀정이 μ™„λ£Œ 됐닀면, ν”Œλž˜κ·Έλ₯Ό μ–»μ–΄μ˜¬ λ•Œ LSUser.class의 속성[속성:κ°’]을 μ„€μ •ν•  수 μžˆλ‹€.
LSUser.class의 속성[속성:κ°’]이 ν‚€μ›Œλ“œμ— ν¬ν•¨λœ 속성에 λͺ¨λ‘ ν¬ν•¨λ˜μ–΄ μžˆμ„ 경우, ν‚€μ›Œλ“œ λ°˜ν™˜ 값을 λ°˜ν™˜ν•œλ‹€.
ν‚€μ›Œλ“œμ— ν¬ν•¨λœ 속성을 μΌλΆ€λ§Œ ν¬ν•¨ν•˜κ³  μžˆκ±°λ‚˜ ν¬ν•¨ν•˜μ§€ μ•ŠλŠ” 경우, ν”Œλž˜κ·Έ λ³€μˆ˜ λΉ„μœ¨λ°©λ²•μ— 따라 값을 λ°˜ν™˜ν•œλ‹€.

μ‚¬μš© μ˜ˆμ‹œ :

LSUser lsUser = new LSUser.Builder("123")
	.property("name", "olrlobt")
	.property("age", "27")
	.build();

Boolean flagTest = lightSwitch.getBooleanFlag("FLAG TEST", lsUser, false);

μœ„ μ˜ˆμ‹œμ—μ„œ ν”Œλž˜κ·Έμ˜ ν‚€μ›Œλ“œ 속성이 [name : olrlobt]와 [age : 27]λ₯Ό λͺ¨λ‘ λ§Œμ‘±ν•˜λ©΄ ν‚€μ›Œλ“œ λ°˜ν™˜ 값을 λ°˜ν™˜ν•œλ‹€.
λ˜ν•œ ν”Œλž˜κ·Έμ˜ ν‚€μ›Œλ“œ 속성이 [name : olrlobt]와 [age : 27]λ₯Ό λ‘˜ 쀑 ν•˜λ‚˜λ§Œ λ§Œμ‘±ν•΄λ„ ν‚€μ›Œλ“œ λ°˜ν™˜ 값을 λ°˜ν™˜ν•œλ‹€.\

ν•˜μ§€λ§Œ, ν”Œλž˜κ·Έμ˜ ν‚€μ›Œλ“œ 속성이 [name : olrlobt]와 [age : 27] 외에도 [company : ssafy]λ₯Ό κ°–κ³  μžˆλ‹€λ©΄, ν‚€μ›Œλ“œ λ°˜ν™˜ 값을 λ°˜ν™˜ν•˜μ§€ μ•Šκ³  ν”Œλž˜κ·Έ λ³€μˆ˜ λΉ„μœ¨ 방법에 따라 λ°˜ν™˜ 값을 λ°˜ν™˜ν•œλ‹€.




ν”Œλž˜κ·Έ λ³€μˆ˜ λΉ„μœ¨ A/B ν…ŒμŠ€νŠΈ, μΉ΄λ‚˜λ¦¬ 배포

LightSwitchλŠ” ν”Œλž˜κ·Έ λ³€μˆ˜ λΉ„μœ¨μ„ μ‹€μ‹œκ°„μœΌλ‘œ μ‘°μ ˆν•˜λ©° λ‹€μ–‘ν•˜κ²Œ ν™œμš©ν•  수 μžˆλ‹€.
λ³€μˆ˜ λΉ„μœ¨μ€ ν”Œλž˜κ·Έλ₯Ό 얻을 λ•Œ μ‚¬μš©ν•˜λŠ” LSUser.class의 ν•„μˆ˜ userId에 따라 ν•΄μ‹œ(MD-5)κ°’ λ°±λΆ„μœ¨μ„ 기반으둜 ν•œλ‹€.

μ‚¬μš© μ˜ˆμ‹œ :

// Flag Variation 1 : True : 50%
// Flag Variation 2 : False : 50%
LSUser lsUser = new LSUser.Builder("000") // User Hash : 54.72%
	.build();

LSUser lsUser2 = new LSUser.Builder("123") // User Hash : 03.17%
	.build();

Boolean flagTest = lightSwitch.getBooleanFlag("FLAG TEST", lsUser, false); // False
Boolean flagTest2 = lightSwitch.getBooleanFlag("FLAG TEST", lsUser2, false); // True

μœ„ μ˜ˆμ‹œμ—μ„œ ν”Œλž˜κ·Έμ˜ λ³€μˆ˜ λΉ„μœ¨μ΄ 50%, 50%의 λΉ„μœ¨λ‘œ 섀정이 λ˜μ–΄ μžˆλ‹€λ©΄, LSUser.class의 userId κ°’μ—μ˜ ν•΄μ‹œκ°’μ— 따라 λ°˜ν™˜ 값이 λ‹¬λΌμ§ˆ 수 μžˆλ‹€.
이λ₯Ό 적절히 ν™œμš©ν•˜μ—¬, A/B ν…ŒμŠ€νŠΈ, μΉ΄λ‚˜λ¦¬ 배포 λ“± μ—¬λŸ¬ 방면으둜 ν™œμš©ν•  수 μžˆλ‹€.




κ΅¬ν˜„ μž‘λ™ ν™”λ©΄

Java SDKλ₯Ό ν¬ν•¨ν•œ μ™ΈλΆ€ ν”„λ‘œμ νŠΈ( 좕ꡬ ν”Œλž«νΌ ν”„λ‘œμ νŠΈ : Kλ¦¬λ²„μŠ€)μ—μ„œ ν”Όμ²˜ν”Œλž˜κΉ… μ†”λ£¨μ…˜μ΄ μ •μƒμ μœΌλ‘œ μž‘λ™ν•˜λŠ”μ§€ ν™•μΈν•˜μ˜€λ‹€.


A/B ν…ŒμŠ€νŒ… : ex) κ΄‘κ³  μˆœμ„œ λ³€κ²½ μ˜ˆμ‹œ

ν”Œλž˜κ·Έμ— μ„€μ •ν•œ λΉ„μœ¨μ„ 기반으둜 값을 λ°˜ν™˜ν•œλ‹€. 이λ₯Ό A/B ν…ŒμŠ€νŒ…μ— ν™œμš©ν•  수 μžˆλ‹€.

  • Hash μ•Œκ³ λ¦¬μ¦˜ MD5(Message Digest Algorithm 5)λ₯Ό μ‚¬μš©ν•˜μ—¬ νšŒμ›μ„ 고유 λ°±λΆ„μœ¨ κ°’μœΌλ‘œ λ‚˜λˆˆλ‹€. 이에 따라 νšŒμ›μ˜ 고유 λ²ˆν˜Έμ— 따라 λΉ„μœ¨μ΄ λ‚˜λ‰˜κ²Œ λœλ‹€.

  • Java, JavaScript, Python λͺ¨λ‘ 같은 λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ν•˜μ—¬ 일관성을 μœ μ§€ν•˜μ˜€λ‹€.

  • SSE 톡신을 ν™œμš©ν•˜μ—¬ Flagκ°€ 생성, μˆ˜μ •, μ‚­μ œ 될 λ•Œ μ‹€μ‹œκ°„μœΌλ‘œ 응닡을 λ°›μ•„ ν”Œλž˜κ·Έλ₯Ό μ μš©ν•œλ‹€.

  • μ‹œμ—°μ— μ‚¬μš©ν•œ μ½”λ“œ

LSUser lsUser = new LSUser.Builder(userId)
            .build();

if (lightSwitch.getBooleanFlag("Event κ΄‘κ³  ν”Œλž˜κ·Έ", lsUser, false)) {
      eventResDtos.sort(Comparator.comparing(CheckEventResDto::getEnd_date));
}

ezgif com-resize

첫 ν™”λ©΄μ—μ„œλŠ” μœ μ €λ³„λ‘œ κ΄‘κ³  λ°°λ„ˆμ˜ μˆœμ„œκ°€ μ‹œμž‘μΌ 순으둜 λ™μΌν•˜μ§€λ§Œ, ν”Œλž˜κ·Έκ°€ ν™œμ„±ν™” 되고 λ‚˜λ©΄ 쒌츑 νšŒμ›μ˜ κ΄‘κ³ μˆœμ„œκ°€ 마감일 순으둜 λ°”λ€ŒλŠ” 것을 확인할 수 μžˆλ‹€.

User의 고유 아이디에 따라 λΉ„μœ¨μ΄ κ³„μ‚°λ˜κ³ , 50% λΉ„μœ¨μ— μ†ν•˜λŠ” μœ μ €λ“€μ€ 마감일 순으둜 κ΄‘κ³ λ₯Ό μ œκ³΅λ°›λŠ”λ‹€.



ν‚€μ›Œλ“œ 기반 νƒ€κ²Ÿ ν…ŒμŠ€νŒ… : ex) 섀문쑰사 λ°°λ„ˆ μƒλ‹¨μœΌλ‘œ 이동 μ˜ˆμ‹œ

ν”Œλž˜κ·Έμ— μ„€μ •ν•œ νŠΉμ • ν‚€μ›Œλ“œλ₯Ό 기반으둜 값을 λ°˜ν™˜ν•œλ‹€. ν”Œλž˜κ·Έλ₯Ό μ‚¬μš©ν•  λ•Œ, User의 고유 속성듀을 μ„€μ •ν•  수 있으며, 이 것이 ν‚€μ›Œλ“œμ™€ μΌμΉ˜ν•œλ‹€λ©΄ 값을 λ°˜ν™˜ν•œλ‹€. νŠΉμ • μœ μ € νƒ€κ²ŸνŒ… ν…ŒμŠ€νŠΈμ— ν™œμš©ν•  수 μžˆλ‹€.

  • Builder νŒ¨ν„΄μ„ μ‚¬μš©ν•˜μ—¬ νšŒμ›μ˜ 속성을 κ°„νŽΈν•˜κ²Œ μ§€μ •ν•  μˆ˜μžˆλ‹€.

  • SSE 톡신을 ν™œμš©ν•˜μ—¬ Flagκ°€ 생성, μˆ˜μ •, μ‚­μ œ 될 λ•Œ μ‹€μ‹œκ°„μœΌλ‘œ 응닡을 λ°›μ•„ ν”Œλž˜κ·Έλ₯Ό μ μš©ν•œλ‹€.

  • μ‹œμ—°μ— μ‚¬μš©ν•œ μ½”λ“œ

LSUser lsUser = new LSUser.Builder(userId)
						.property("mainBadge", user.getBadge())
            .build();

ezgif com-crop (16) (1)

User의 Badge의 값을 가져와 μ†μ„±μœΌλ‘œ 섀정을 ν•΄ μ£Όμ—ˆλ‹€. 이 것이 ν”Œλž˜κ·Έμ˜ ν‚€μ›Œλ“œμ™€ λŒ€μ‘°λ˜μ–΄, μ‹œμ—°μ—μ„œ Null이 μ•„λ‹Œ μœ μ €λ“€μ€ 섀문쑰사 λ°°λ„ˆκ°€ μƒλ‹¨μœΌλ‘œ μ΄λ™ν•˜λŠ” 것을 확인할 수 μžˆλ‹€.



λ³€κ²½ 기둝

  • Spring AOPλ₯Ό μ΄μš©ν•˜μ—¬, Flag의 변동사항을 κ°μ§€ν•˜μ—¬ κΈ°λ‘ν•œλ‹€.

recording-1-ezgif com-crop



κ΄€λ ¨ ν¬μŠ€νŒ…

MVNλ ˆνΌμ§€λ°°ν¬

무쀑단배포