이세계트럭 메뉴 → 내정보 → </> 컴포넌트 로 이동
컴포넌트 추가 → 기본정보에, 아래 항목 복붙 (이미지 참고) → 컴포넌트 이름: Letter → 표시 이름: 편지 → 설명: 하단의 프롬프트
.png)
</>코드에 아래 항목 복붙 → JSX 코드: 하단의 JSX 코드 복붙 → JSON 가져오기: 하단의 JSON 코드 복붙 후, 적용 → 저장
.png)
해당 컴포넌트 활성화
채팅방 가서 즐기기! → 채팅방 설정에서 </>유저 컴포넌트에 활성화 되어 있는지 볼 수 있어요.
# 편지 컴포넌트 호출 규칙
{{user}}와 {{char}}이 편지를 주고 받을 때 {{char}}가 {{user}}에게 주는 편지를 아래 지침에 따라 <Letter /> 컴포넌트를 호출한다.
## 내용 작성 규칙
- 서사 및 기억 반영: {{user}}와 {{char}}의 현재 관계, 성격, 서사, 유저 노트, 장기기억 등을 철저히 반영하여 편지 내용을 작성한다.
- 캐릭터 100% 동기화: 편지의 어조, 말투는 철저하게 {{char}}의 고유한 성격에 기반한다.
- 🚨 언어 및 번역 포맷 절대 유지: {{char}}가 평소에 [외국어+(한국어 번역)]을 쓴다면, 편지 본문(`paragraphs`)과 추신(`psText`)의 문자열 안에도 **반드시 평소 대화와 똑같이 외국어/기호와 (한국어 번역)을 함께 작성**해야 합니다. 코드 내부라고 해서 임의로 영어로만 적거나 번역을 생략하면 절대 안 됩니다!
## 컴포넌트 출력 규칙
- paperColor, textColor, accentColor: 현재 캐릭터의 기분이나 분위기에 맞는 색상(Hex) 무작위 지정 (네온 컬러 금지)
- fontStyle: "serif", "sans-serif", "cursive", "monospace" 중 캐릭터에 어울리는 것 하나 선택
- paragraphs: 편지의 본문을 "배열(Array)" 형태로 작성.
### [출력 예시]
<Letter
paperColor="#f4f1ea"
textColor="#2c2c2c"
accentColor="#a8d8ea"
fontStyle="serif"
senderName="[캐릭터 이름이나 별명]"
senderInfo="[현재 위치나 상태]"
dateStr="[세계관 날짜]"
paragraphs={[
"첫 번째 문단입니다. (만약 번역 기믹을 쓰는 캐릭터라면, 배열 안의 이 문자열에도 평소처럼 외국어/외계어와 (한국어 번역)을 반드시 같이 적으세요.)",
"두 번째 문단입니다.",
"세 번째 문단입니다."
]}
psText="추신 내용을 여기에 적습니다. (번역 기믹 캐릭터는 번역 포함)"
/>
function Letter({
paperColor = "#fdfbf7",
textColor = "#333333",
fontStyle = "serif",
accentColor = "#ffb6c1",
senderName = "익명",
senderInfo = "",
dateStr = "",
paragraphs = [],
psText = ""
}) {
const rawAccent = accentColor.length >= 7 ? accentColor.substring(0, 7) : accentColor;
const accentVerySoft = rawAccent + "1A"; // P.S. 배경용
// 배열로 들어온 문단 데이터를 필터링
const validParagraphs = Array.isArray(paragraphs)
? paragraphs.filter(text => text && String(text).trim().length > 0)
: [];
return (
<div style={{
position: "relative",
backgroundColor: paperColor,
color: textColor,
fontFamily: fontStyle,
padding: "40px 30px",
width: "100%",
maxWidth: "550px",
margin: "20px auto",
boxSizing: "border-box",
borderRadius: "8px",
boxShadow: "2px 5px 15px rgba(0,0,0,0.08)",
overflow: "hidden",
wordBreak: "keep-all"
}}>
<div style={{ borderBottom: `2px solid ${rawAccent}`, paddingBottom: "12px", marginBottom: "25px", display: "flex", justifyContent: "space-between", alignItems: "flex-end", position: "relative", zIndex: 1 }}>
<div style={{ fontSize: "12px", opacity: 0.7, fontStyle: "italic" }}>{dateStr}</div>
<div style={{ textAlign: "right" }}>
<div style={{ fontSize: "11px", opacity: 0.6 }}>{senderInfo}</div>
<div style={{ fontSize: "16px", fontWeight: "bold" }}>{senderName}</div>
</div>
</div>
<div style={{ fontSize: "15px", minHeight: "100px", lineHeight: "1.8", position: "relative", zIndex: 1 }}>
{validParagraphs.length > 0 ? validParagraphs.map((text, idx) => (
<div key={idx} style={{ marginBottom: "16px" }}>
{text}
</div>
)) : <div style={{opacity: 0.5}}>내용이 비어 있습니다.</div>}
</div>
{psText && (
<div style={{ margin: "30px 0 0 0", padding: "15px", border: `1px dashed ${rawAccent}`, backgroundColor: accentVerySoft, borderRadius: "4px", fontSize: "14px", lineHeight: "1.7", position: "relative", zIndex: 1 }}>
<span style={{ fontWeight: "bold", marginRight: "6px" }}>P.S.</span>
{String(psText).trim()}
</div>
)}
</div>
);
}
{
"paperColor": {
"type": "string",
"description": "편지지 배경색 (Hex 코드)"
},
"textColor": {
"type": "string",
"description": "글자색 (Hex 코드)"
},
"accentColor": {
"type": "string",
"description": "포인트/테두리 색상 (파스텔톤 Hex)"
},
"fontStyle": {
"type": "string",
"description": "폰트 스타일",
"enum": ["serif", "sans-serif", "cursive", "monospace"]
},
"senderName": {
"type": "string",
"description": "발신자 이름"
},
"senderInfo": {
"type": "string",
"description": "이름 앞 수식어 (예: 현재 위치나 상태)"
},
"dateStr": {
"type": "string",
"description": "작성된 세계관 내 날짜나 시간"
},
"paragraphs": {
"type": "array",
"description": "편지 본문 문단 배열"
},
"psText": {
"type": "string",
"description": "추신 내용"
}
}