-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feat/#18] Button component #19
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
μ‘°κ±΄λΆ μ€νμΌλ§μ΄ λ무 λ§μμ 머리 μν μ λ²λ νλ° μ λ°μνλ€... κ³ μνμ΄ π₯Ί
λ
Όμν΄λ³΄κ³ μΆμ λ΄μ©, κ°μ ν΄λ³Ό μ μμλ§ν λΆλΆλ€μ μ½λ©νΈλ‘ λ¨κ²¨λμΌλ νλ² νμΈν΄μ€!!
<button | ||
className={clsx( | ||
styles.button, | ||
styles[size], | ||
disabled && styles.disabled, | ||
!disabled && variants[variant], | ||
disabled && variant === "outlinePrimary" && styles.disabledOutline | ||
)} | ||
disabled={disabled} | ||
> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3) λ²νΌμ κ²½μ°μ μκ° μ λ§ λ§μμ μ΄λ₯Ό νΈλ¦¬νκ² μ‘°κ±΄λΆλ‘ κ²°ν©νκΈ° μν΄ clsxλ₯Ό μ¬μ©νμ κ² κ°μμ!
μλͺ»λ λ°©λ²μ μ λ μλμ§λ§ @vanilla-extract/recipes μμλ recipe λΌλ ν¨μλ₯Ό μ 곡νμ¬ μ’ λ νΈλ¦¬νκ² λ€μν 쑰건λΆλ₯Ό κ³ λ €νμ¬ μ€νμΌμ λμ μΌλ‘ μ μ©ν μ μλλ‘ λκ³ μλλ°, μκ°μ΄ λλ€λ©΄ recipeλ‘ μ½λλ₯Ό ꡬμ±ν΄λ³΄λ 건 μ΄λ¨κΉμ?
λ§μ½ recipe ν¨μλ₯Ό μ μ©νλ€λ©΄, μμ μ½λλ μλμ κ°μ΄ λ³ν μ μμ΅λλ€!
// css.ts μμ button ν¨μ(recipe)μ import ν΄μμΌν¨, λ°μ λ€λ₯Έ μ½λ©νΈμμ μΆκ° μ€λͺ
μμ
export const Button: React.FC<ButtonProps> = ({
label = "Button",
leftIcon,
rightIcon,
size = "medium",
variant = "solidPrimary",
disabled = false,
}) => {
return (
<button
className={button({ size, variant, disabled })}
disabled={disabled}
>
{leftIcon && <div className={icon}>{leftIcon}</div>}
{label}
{rightIcon && <div className={icon}>{rightIcon}</div>}
</button>
);
};
ν¨μ¬ 보기 νΈνμ§ μλμ?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
κ·Έλμ μ΄κ²μ΄μμ΅λλ€.. μ κ° λ°λΌλ νμμ΄μ
κ°μ¬ν©λλ€ γ
κ΄λͺ
μ°Ύμλ€μ μμ νκ² μ΅λλ€
/** | ||
* Button κ³΅ν΅ μ»΄ν¬λνΈ | ||
* @param label | ||
* @param leftIcon μΌμͺ½ μμ΄μ½ | ||
* @param rightIcon μ€λ₯Έμͺ½ μμ΄μ½ | ||
* @param size λ²νΌ μ¬μ΄μ¦ small | medium | large | ||
* @param variant λ²νΌ μ’ λ₯ solidPrimary | solidNeutral | outlinePrimary | ||
* @param disabled λΉνμ±ν μ¬λΆ | ||
* @constructor minjeoong | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p5) κΉλν μ£Όμ μ’λ€μ! κ΅³μ΄ μ§μ°μ§ μμλ λ κ±° κ°μ΅λλ€ :)
κ·Όλ° νΉμ μ΄λ° μ£Όμμ μΌμΌν νμ΄ννμλ건κ°μ? μλλ©΄ νλ¬κ·ΈμΈ κ°μκ² μλ건κ°μ? (νμμ΄ μ‘ν μλκ±° κ°μμ μ¬μ€λ΄
λλ€)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JSDoc(JavaScript Documentation) μ
λλ€.
Webstorm κΈ°μ€, μ»΄ν¬λνΈ μλ¨μμ "/**" + enter ν€ λλ₯΄λ©΄ μλ μμ±λ©λλ€.
VSCode λ ν΄λΉ μ¬ν κ°λ₯νλ€κ³ μκ³ μμ΅λλ€
import { style, styleVariants } from "@vanilla-extract/css"; | ||
import { color, font } from "@style/styles.css.ts"; | ||
|
||
export const styles = { | ||
button: style([ | ||
font.body01, | ||
{ | ||
display: "flex", | ||
alignItems: "center", | ||
justifyContent: "center", | ||
gap: "0.6rem", | ||
borderRadius: "8px", | ||
border: "none", | ||
cursor: "pointer", | ||
transition: "background-color 0.3s", | ||
":focus": { | ||
outline: "none", | ||
}, | ||
}, | ||
]), | ||
small: style({ | ||
height: "3.2rem", | ||
|
||
padding: "0.6rem 1.4rem", | ||
}), | ||
medium: style({ | ||
height: "3.6rem", | ||
|
||
padding: "0.8rem 2rem", | ||
}), | ||
large: style({ | ||
height: "4.4rem", | ||
padding: "1.2rem 2.8rem", | ||
}), | ||
disabled: style({ | ||
background: color.gray.gray300, | ||
color: color.gray.gray500, | ||
pointerEvents: "none", | ||
}), | ||
disabledOutline: style({ | ||
background: "transparent", | ||
border: `1px solid ${color.gray.gray300}`, | ||
color: color.gray.gray400, | ||
}), | ||
icon: style({ | ||
height: "2rem", | ||
display: "flex", | ||
alignItems: "center", | ||
}), | ||
}; | ||
|
||
export const variants = styleVariants({ | ||
solidPrimary: { | ||
backgroundColor: color.primary.blue600, | ||
color: "#fff", | ||
":hover": { | ||
backgroundColor: color.primary.blue800, | ||
}, | ||
}, | ||
solidNeutral: { | ||
backgroundColor: color.gray.gray100, | ||
color: color.gray.gray700, | ||
":hover": { | ||
backgroundColor: color.gray.gray300, | ||
}, | ||
":active": { | ||
backgroundColor: color.gray.gray400, | ||
}, | ||
}, | ||
outlinePrimary: { | ||
border: `0.1rem solid ${color.primary.blue500}`, | ||
backgroundColor: "transparent", | ||
color: color.gray.gray700, | ||
":hover": { | ||
backgroundColor: color.gray.gray100, | ||
}, | ||
":active": { | ||
backgroundColor: color.primary.blue300, | ||
border: `0.1rem solid ${color.primary.blue500}`, | ||
}, | ||
":focus": { | ||
border: `0.1rem solid ${color.primary.blue500}`, | ||
}, | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3) μμμ μΈκΈν recipeλ₯Ό μ¬μ©νλ€λ©΄, μλμ κ°μ νμμΌλ‘ μ½λκ° λ³ν μ μμ κ² κ°μμ!
(μ κ° μ§μ μμ±ν΄λ³΄κΈ΄ νμ§λ§, λμΉ λΆλΆμ΄ μμ μ μμΌλ μ 체ν¬ν΄μ£ΌμΈμ..!)
import { recipe } from "@vanilla-extract/recipes";
import { color, font } from "@style/styles.css.ts";
export const button = recipe({
base: [
font.body01,
{
display: "flex",
alignItems: "center",
justifyContent: "center",
gap: "0.6rem",
borderRadius: "8px",
border: "none",
cursor: "pointer",
transition: "background-color 0.3s",
":focus": {
outline: "none",
},
},
],
variants: {
size: {
small: {
height: "3.2rem",
padding: "0.6rem 1.4rem",
},
medium: {
height: "3.6rem",
padding: "0.8rem 2rem",
},
large: {
height: "4.4rem",
padding: "1.2rem 2.8rem",
},
},
variant: {
solidPrimary: {
backgroundColor: color.primary.blue600,
color: "#fff",
":hover": {
backgroundColor: color.primary.blue800,
},
},
solidNeutral: {
backgroundColor: color.gray.gray100,
color: color.gray.gray700,
":hover": {
backgroundColor: color.gray.gray300,
},
":active": {
backgroundColor: color.gray.gray400,
},
},
outlinePrimary: {
border: `0.1rem solid ${color.primary.blue500}`,
backgroundColor: "transparent",
color: color.gray.gray700,
":hover": {
backgroundColor: color.gray.gray100,
},
":active": {
backgroundColor: color.primary.blue300,
border: `0.1rem solid ${color.primary.blue500}`,
},
":focus": {
border: `0.1rem solid ${color.primary.blue500}`,
},
},
},
disabled: {
true: {
backgroundColor: color.gray.gray300,
color: color.gray.gray500,
pointerEvents: "none",
},
outlinePrimary: {
backgroundColor: "transparent",
border: `1px solid ${color.gray.gray300}`,
color: color.gray.gray400,
pointerEvents: "none",
},
false: {},
},
},
compoundVariants: [
{
variants: { disabled: true, variant: "outlinePrimary" },
style: {
backgroundColor: "transparent",
border: `1px solid ${color.gray.gray300}`,
color: color.gray.gray400,
},
},
],
defaultVariants: {
size: "medium",
variant: "solidPrimary",
disabled: false,
},
});
export const icon = style({
height: "2rem",
display: "flex",
alignItems: "center",
});
κ°λ¨νκ² μ½λ μ€λͺ λ리면, λ€μκ³Ό κ°μ΅λλ€.
recipeμ μΈμλ‘ λ€μ΄κ°λ κ°μ²΄μ 첫λ²μ§Έ propμΈ baseλ κΈ°λ³Έμ μΌλ‘ μ μ©λ styleλ€μ μ μν΄λ‘λλ€.
λλ²μ§Έ propμΈ variants λ λ€μν propμ λ°λΌ, λ λλ§ν cssλ₯Ό μ μν©λλ€. μ΄ κ²½μ°μλ μ΄ 3κ°μ§μ propμ΄ μ μλμ΄ μμ΅λλ€. (size, variant, disabled) κ·Έλ¦¬κ³ μ΄ 3κ°μ§μ propμ κ°μ§ μ μλ κ°λ€μ΄ κ°κ° μ μλμ΄ μμ΅λλ€. μλ₯Ό λ€μ΄, size propμ κ²½μ°μλ "small", "medium", "large" λ₯Ό κ°μ§ μ μκ³ , μ΄μ λ°λΌ μ μ©λλ cssλ λ¬λΌμ§λλ€.
μ¬κΈ°μ ν΅μ¬μ μΈλ²μ§Έ propμΈ compoundVariants μ λλ€. λ―Όμ λμ΄ κ΅¬νν λ²νΌ μ»΄ν¬λνΈμμλ λ°λμ μ¬μ©ν μ λ°μ μμ΅λλ€. μλνλ©΄ variantsλ€μ prop μ€ disabled: true, variant: "outlinePrimary" μΌ κ²½μ°μλ νΉμ ν cssλ₯Ό μ μ©ν΄μΌνκΈ° λλ¬Έμ λλ€. (μ κ° μ μ΄ν΄νλ€λ©΄, μ 쑰건 2κ°κ° and μ°μ°μΌλ‘ λ¬Άμμ λ μ μ©νλ μ€νμΌμ΄ λ€λ₯Έκ±° κ°λλΌκ΅¬μ)
κ·Έλμ
compoundVariants: [
{
variants: { disabled: true, variant: "outlinePrimary" },
style: {
borderColor: "gray",
backgroundColor: "transparent",
color: "gray",
},
},
],
κ³Ό κ°μ νμμΌλ‘, 쑰건λ€μ μ‘°ν©μ variantsμ λ£κ³ κ·Έλ μ μ©ν cssλ₯Ό styleμ μ μ΄λ£μΌλ©΄ λ©λλ€. (μ½λλ§ λ΄λ μ΄ν΄νμ€κ±°λΌ λ―Ώκ³ λ μμΈν μ€λͺ μ μλ΅νκ² μ΅λλ€)
μ¬νΌ.. μ κ° recipe μ΄μ©ν΄μ μμ±ν΄λ³Έ μ½λμΈλ° νλ² μ΄ν΄λ³΄μκ³ , recipeλ‘ λ³κ²½ν΄λ λμΌνκ² μλνλ€κ³ νλ¨λλ€λ©΄
recipeλ‘ λ³κ²½ν΄λ³΄λ κ²λ μ’μ κ² κ°μμ! (λ°μλ©΄ λμ€μ ν©μλ€)
μ°Έκ³ ) https://vanilla-extract.style/documentation/packages/recipes/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
μ... μ΄λ κ²λ λλκ΅°μ
κ°μ¬ν©λλ€. μμ ν΄μ PUSH νμ΅λλ€ :)
wrapper: style({ | ||
width: "100%", | ||
display: "flex", | ||
justifyContent: "space-between", | ||
gap: "1rem", | ||
alignItems: "center", | ||
padding: "1rem 2rem", | ||
border: `0.1rem solid ${color.gray.gray200}`, | ||
borderRadius: "8px", | ||
}), | ||
input: base, | ||
error: style([base, { border: `0.1rem solid ${color.red.warning_red200}` }]), | ||
disabledWrapper: style({ | ||
background: color.gray.gray300, | ||
pointerEvents: "none", | ||
}), | ||
disabledInput: style([ | ||
base, | ||
{ | ||
background: color.gray.gray300, | ||
color: color.gray.gray500, | ||
}, | ||
]), | ||
icon: style({ | ||
height: "2rem", | ||
alignContent: "center", | ||
}), | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p5) λ¬Έλ λ μκ°μΈλ°, μ λ wrapper, input, error ... λ±λ±μ νλ νλ export const ν λ€,
import * as styles from "./μ΄μ©κ΅¬μ μ©κ΅¬" λ°©μμΌλ‘ κ°μ Έμμ styles.wrapper , styles.input λ±μΌλ‘ μ¬μ©νμλλ°
λ―Όμ μ΄κ° μ¬μ©ν λ°©λ²μ import { styles } from "@common/component/TextField/styles.css.ts";
λ‘ κ°μ Έμ¬ μ μμΌλκΉ μ’ λ λΉ λ₯΄κ³ μ½κ² import ꡬ문μ μμ±ν μ μλ€λ μ₯μ μ΄ μκΈ΄ νλ€!
κ·Όλ° κ°λ
μ± μΈ‘λ©΄μμλ λκ° λ λμμ§ κ°λ¨νκ²λΌλ λ
Όμν΄λ³΄κ³ μΆμλ°, λμ€μ λ΄ PR νμΈν΄λ³΄κ³ μ½λ©νΈ λ¨κ²¨μ€ !
(κ°λ
μ±λ λΉμ·ν΄λ³΄μΈλ€λ©΄, λλ λ―Όμ μ΄ λ°©μλλ‘ νλμ ν° style κ°μ²΄λ₯Ό μ μνλ λ°©μμΌλ‘ νλ €κ³ !)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
κ°λ
μ± μΈ‘λ©΄μμλ μ΄λ κ² λ¬Άλ κ² μ’λ€κ³ μκ°ν΄μ
κ·Όλ° λ무 μκ΄ μμ΄ λ¬Άμ΄λ²λ¦¬λ 건 λ μ μ’μ κ² κ°μμ, λ λ°λ‘ μμ΄μΌ νλ 건 νμν κ² κ°μ΅λλ€
<div | ||
className={clsx( | ||
styles.wrapper, | ||
!active && styles.disabledWrapper, | ||
state === "error" && styles.error | ||
)} | ||
> | ||
<input | ||
type="text" | ||
className={clsx(styles.input, !active && styles.disabledInput)} | ||
placeholder={placeholder} | ||
value={value} | ||
onChange={onChange} | ||
disabled={!active} | ||
/> | ||
{icon && <div className={styles.icon}>{icon}</div>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p4) μμμ μ€μ»· μΈκΈν clsx.. recipeλ‘ κ°μ κ°λ₯νλ€λ©΄ κ°μ ν΄λ³΄λ건 μ΄λ¨κΉμ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
text field λ ν΄λΉ PR λ΄μ μμ ν΄μ μ¬λ¦¬κ² μ΅λλ€
interface TextFieldProps { | ||
label?: string; | ||
leftIcon?: React.ReactNode; | ||
rightIcon?: React.ReactNode; | ||
size?: "small" | "medium" | "large"; | ||
variant?: "solidPrimary" | "solidNeutral" | "outlinePrimary"; | ||
disabled?: boolean; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p1) μ λ€μ보λκΉ μ€ν λ°κ²¬! ButtonPropsλ‘ λ°κΏμΌν κ² κ°μμ!
+) μνλ λμμ΄ μμ μλ μμΌλκΉ onClick ν¨μλ propμΌλ‘ λκ²¨μ€ μ μμ΄μΌ ν κ² κ°μμ!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
μμ ν΄μ μ¬λ Έμ΅λλ€!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
μ½λ¦¬ λ°μ νμΈνμ΅λλ€ ~! μΆ©λλ§ ν΄κ²°νκ³ λ¨Έμ§ν΄μ£ΌμΈμ!
π₯ Related Issues
β μμ 리μ€νΈ
π§ μμ λ΄μ©
[ λ²νΌ variant ]
λ²νΌ μ’ λ₯ μ λλ€. μ§κΈνμ¬ λμμΈμΌλ‘λ 3κ°μ λλ€.
solidPrimary | solidNeutral | outlinePrimary
-> νΌκ·Έλ§ κΈ°μ€ λ€μ΄λ° μ§ννμ΅λλ€.
variant λ‘ μ λ ₯νλ©΄ μ μ© λ©λλ€.
[ λ²νΌ size ]
![αα
³αα
³α
α
΅α«αα
£αΊ 2025-01-12 07 13 37](https://private-user-images.githubusercontent.com/88662427/402294280-12613e05-1c60-43c7-80da-d9aa5777779e.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk1ODg4MjQsIm5iZiI6MTczOTU4ODUyNCwicGF0aCI6Ii84ODY2MjQyNy80MDIyOTQyODAtMTI2MTNlMDUtMWM2MC00M2M3LTgwZGEtZDlhYTU3Nzc3NzllLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE1VDAzMDIwNFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWFiZDE1MThiY2M4ZjVjZTk0NWFkODE5YWVlNDE2OGYxNDE2YjA4ZWM5YTg1ZmI2MTE0ZjU1ODI1ZjJiNjgyZjImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.gfiZVQhlnZoyrXlSJ77lk0wVQ0_k2GHZx66f_nSKrE4)
λ²νΌ μ¬μ΄μ¦ μ΄ 3κ° μ λλ€.
λ§μ°¬κ°μ§λ‘ size props μ£Όλ©΄ μ μ© λ©λλ€. small | medium | large
[ λ²νΌ disabled ]
![αα
³αα
³α
α
΅α«αα
£αΊ 2025-01-12 07 14 32](https://private-user-images.githubusercontent.com/88662427/402294310-41bcae31-ea2f-401a-b1ec-06746b56eecc.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk1ODg4MjQsIm5iZiI6MTczOTU4ODUyNCwicGF0aCI6Ii84ODY2MjQyNy80MDIyOTQzMTAtNDFiY2FlMzEtZWEyZi00MDFhLWIxZWMtMDY3NDZiNTZlZWNjLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE1VDAzMDIwNFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWRhNWVkNzZmZWIzNTFhMTE1OGJlZjQ1OWIzYWJiNTliODVmYTEwNWE4NjZjZDllM2QxM2ZhNzg2YTU3ZTQ4MDYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.bRSuJ6CDrX0GLFFBxI2MFPuIXO4pbelUrosXecS5aK4)
μ΄ 3κ°μ λμμΈμ disabled λ λμμΈμ΄ μ‘°κΈμ© λ€λ¦ λλ€.
κ·Έλμ μ§κΈμΌλ‘μλ disabled μ΄ outline λ§ λμμΈμ΄ λ¬λΌμ
μμΈλ‘ μ μ©νλλ‘ κ΅¬ννλλ°, μΆν λμμΈμ΄ λ μκΈ΄λ€λ©΄ μ½λ λ³λμ΄ νμν μ μμ κ² κ°μμ!
[ λ²νΌ interaction ]
![αα
³αα
³α
α
΅α«αα
£αΊ 2025-01-12 07 15 40](https://private-user-images.githubusercontent.com/88662427/402294346-49407dc1-bb96-484a-81ea-7eeedc6dcbcd.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk1ODg4MjQsIm5iZiI6MTczOTU4ODUyNCwicGF0aCI6Ii84ODY2MjQyNy80MDIyOTQzNDYtNDk0MDdkYzEtYmI5Ni00ODRhLTgxZWEtN2VlZWRjNmRjYmNkLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE1VDAzMDIwNFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWJlMTBlNDRkMzFlOTlkMzIyZTlhMzI2MTFhOTk5NzhjY2NiZDllYjQzZTY0NmRlODMzOWFmZjVhZjdkNjVjNDMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.99jybVbTrwRT8HIeNLY332aKlIrVbS0T3-jN9OaX2pI)
ν΄λΉ λ²νΌλ€ μκΉμ΄ μ λ¨λλΌκ΅¬μ 4κ°κ° μμ΄ λ€λ₯Έλ° λ€ κ°μ₯ λ°μ μμΌλ‘ λμ μμ΄μ
μ°μ μ μ½λ©νΈ λ¬μλμ΅λλ€,,!!
π£ 리뷰μ΄μκ² μ΄λ μ κ°μ?
πΈ μ€ν¬λ¦°μ· / GIF / Link