Skip to content

Commit cf6ab33

Browse files
committed
fix: panel 개선
1 parent deb0233 commit cf6ab33

File tree

6 files changed

+57
-44
lines changed

6 files changed

+57
-44
lines changed

components/Panel.tsx

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { ReactNode } from 'react';
1+
import React, {isValidElement, ReactNode} from 'react';
22
import {
33
Info,
44
AlertTriangle,
@@ -102,58 +102,71 @@ const typeStyles: Record<
102102
},
103103
};
104104

105-
function extractTextFromChildren(children: ReactNode): string {
106-
if (typeof children === 'string') {
107-
return children;
108-
}
109-
if (Array.isArray(children)) {
110-
return children.map(extractTextFromChildren).join('\n');
111-
}
112-
if (typeof children === 'object' && 'props' in children) {
113-
return extractTextFromChildren((children as any).props.children);
114-
}
115-
return '';
116-
}
105+
function extractLines(children: ReactNode): ReactNode[][] {
106+
const result: ReactNode[][] = [];
107+
let line: ReactNode[] = [];
117108

118-
function renderText(type: InfoPanelType, children: ReactNode) {
119-
const text = extractTextFromChildren(children);
120-
const lines = text
121-
.split(/\r?\n/)
122-
.reduce<string[]>((acc, line) => {
123-
const trimmed = line.trim();
124-
if (!trimmed) return acc;
109+
const flush = () => {
110+
if (line.length > 0) {
111+
result.push(line);
112+
line = [];
113+
}
114+
};
125115

126-
const hasHtmlTag = /^<\w+/.test(trimmed); // <a ...>, <code>, <strong> 등
127-
if (hasHtmlTag) {
128-
acc.push(trimmed); // 그대로 넣음
129-
} else if (acc.length > 0 && !/^<\w+/.test(acc[acc.length - 1])) {
130-
acc[acc.length - 1] += ' ' + trimmed; // 이전 줄에 이어붙임
131-
} else {
132-
acc.push(trimmed);
116+
const walk = (node: ReactNode) => {
117+
if (typeof node === 'string') {
118+
node.split(/\r?\n/).forEach((part, i) => {
119+
if (i > 0) {
120+
flush();
133121
}
122+
if (part) {
123+
line.push(part);
124+
}
125+
});
126+
} else if (Array.isArray(node)) {
127+
node.forEach((child) => {
128+
walk(child);
129+
});
130+
} else if (isValidElement(node)) {
131+
const { type, props } = node as any;
132+
if (type === 'a' || type === 'code' || type === 'b') {
133+
line.push(node);
134+
} else {
135+
walk(props.children);
136+
}
137+
} else if (typeof node === 'number') {
138+
line.push(node);
139+
}
140+
};
134141

135-
return acc;
136-
}, []);
142+
walk(children);
143+
flush();
144+
return result;
145+
}
137146

138-
const [title, ...bodyLines] = lines;
139147

148+
function renderText(type: InfoPanelType, children: ReactNode) {
149+
const lines = extractLines(children);
150+
const [title = [], ...rest] = lines;
140151
const style = typeStyles[type];
141152

142153
return (
143154
<>
144-
<div className={`text-mi flex items-center gap-2 mt-2 mb-2 ${style.titleColor}`}>
155+
<div className={`text-mi flex items-center gap-2 mt-2 mb-1 ${style.titleColor}`}>
145156
{React.cloneElement(style.icon, { className: `w-4 h-4 ${style.titleColor}` })}
146157
{title}
147158
</div>
148159
<div className={`space-y-1 text-mi pl-[1.3rem] ${style.titleColor}`}>
149-
{bodyLines.map((line, idx) => (
150-
<div key={idx}>{line}</div>
160+
{rest.map((line, i) => (
161+
<div key={i}>{line}</div>
151162
))}
152163
</div>
153164
</>
154165
);
155166
}
156167

168+
169+
157170
export default function InfoPanel({ type = 'info', children }: InfoPanelProps) {
158171
const style = typeStyles[type];
159172

posts/clean-code/comments.mdx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ description: "Clean Code 관점에서의 Comment(주석) 남기는 방법에 대
88

99

1010
:::info
11-
유용한 정보가 있는 주석이 있는 반면, 의미가 없거나 JavaDoc 처럼 의무적으로 작성하는 주석이 혼재한다. <br />
12-
어떤 주석을 남겨야 좋은 것인지, 어떤 컨벤션을 가져야 할지 고민하는 시기가 온다. <br />
11+
유용한 정보가 있는 주석이 있는 반면, 의미가 없거나 JavaDoc 처럼 의무적으로 작성하는 주석이 혼재한다.
12+
어떤 주석을 남겨야 좋은 것인지, 어떤 컨벤션을 가져야 할지 고민하는 시기가 온다.
1313
Clean Code 관점에서는 주석을 어떻게 남기는 것이 좋은지 정리해보았다.
1414
:::
1515

@@ -576,8 +576,7 @@ this.pngBytes = new byte[((this.width + 1) * this.height * 3) + 200];
576576
## Best practices for writing code comments
577577

578578
:::quote
579-
stackoverflow blog 에서 소개된 코드 주석 작성 모범 사례를 정리한 내용
580-
<a href="https://stackoverflow.blog/2021/12/23/best-practices-for-writing-code-comments/">(보러가기)</a>
579+
stackoverflow blog 에서 소개된 코드 주석 작성 모범 사례를 정리한 내용 <a href="https://stackoverflow.blog/2021/12/23/best-practices-for-writing-code-comments/">(보러가기)</a>
581580
:::
582581

583582
유명한 MIT 교수인 Hal Abelson 은 아래와 같이 말했다.
@@ -813,7 +812,7 @@ public void onMouseMove(Widget sender, int x, int y) { .. }
813812
이러한 규칙을 따르면 시간과 좌절감을 줄일 수 있다.
814813

815814
:::success
816-
💡 <b> 개인적인 생각 & 정리</b> <br />
815+
<b> 개인적인 생각 & 정리</b> <br />
817816
의무적인 Javadoc 은 없어도 된다. <b> (Clean Code Bad Comments 6, 7, 18) </b> <br />
818817
API 중에서 특수한 경우 (parameter 에 대한 주석이 필요할 때) Javadoc 으로 작성하면 가독성이 좋다. <br />
819818
→ (반드시 best practices 를 따를 필요는 없으므로!!) <br />

posts/ddd/ddd-core-concept.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ DDD 의 적용 흐름 사이클은 애자일 방법론과 매우 밀접하게
162162
---
163163

164164
:::success
165-
💡 <b>정리</b><br />
165+
<b>정리</b><br />
166166
DDD 는 복잡한 도메인을 코드로 명확하게 표현하기 위한 사고방식이다. <br />
167167
도메인 모델과 코드 모델의 일관성 유지, 불변식 보장, 행위 중심 모델링이 핵심이며,
168168
패턴을 무조건 따르기보단 <b>상황에 맞는 유연한 적용</b>이 중요하다. <br />

posts/ddd/ddd-fact-misunderstanding.mdx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ description: "도메인 주도 설계(DDD, Domain-Driven Design)의 사실과
2727
### DDD 란 무엇인가?
2828

2929
:::note
30-
<b>도메인 주도 설계(Domain-Driven Design, DDD)</b> 는 <br /> 복잡한 비즈니스 도메인을 효과적으로 다루기 위해 <b>도메인 중심의 사고방식과 설계 원칙을 적용하는 철학적인 관점</b>에 가깝다. <br />
30+
도메인 주도 설계(Domain-Driven Design, DDD)는
31+
복잡한 비즈니스 도메인을 효과적으로 다루기 위해 <b>도메인 중심의 사고방식과 설계 원칙을 적용하는 철학적인 관점</b>에 가깝다. <br />
3132
특정한 방법론이나 아키텍처가 아니라, 순수하게 <b>비즈니스 중심으로 사고하는 방식</b> 이다.
3233
:::
3334

@@ -36,7 +37,7 @@ description: "도메인 주도 설계(DDD, Domain-Driven Design)의 사실과
3637
### DDD 의 철학
3738

3839
:::note
39-
<b> 복잡한 소프트웨어를 효과적으로 관리하고, 비즈니스 문제를 올바르게 모델링하여 해결 하는 것</b>이 핵심 철학이다.
40+
복잡한 소프트웨어를 효과적으로 관리하고, 비즈니스 문제를 올바르게 모델링하여 해결 하는 것이 핵심 철학이다.
4041
:::
4142

4243
단순히 코드를 작성하는 것이 아니라, **도메인 전문가와 개발자가 협력하여 도메인을 깊이 이해하고, 이를 소프트웨어에 반영하는 방식** 을 추구하는 것이고, <br />
@@ -237,7 +238,7 @@ DDD 의 철학은 **소프트웨어가 도메인을 정확하게 반영해야
237238
<br />
238239

239240
:::success
240-
💡 <b>정리</b><br />
241+
<b>정리</b><br />
241242
DDD 의 핵심 철학은 비즈니스 도메인을 깊게 이해하고 소프트웨어에 정확히 반영하는 것이다. <br />
242243
DDD 는 모든 프로젝트에 적용해야만 하는 것은 아니고, 비즈니스 복잡성에 따라 적절히 활용하는 것이다. <br />
243244
핵심 도메인에 집중하고, 변화에 유연하게 대응할 수 있도록 설계하는 것이 철학이라고 볼 수 있다. <br />

posts/java/try-with-resources.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ Closeable : AutoCloseable 의 하위 인터페이스로 주로 I/O 클래스에
181181
<br />
182182

183183
:::success
184-
💡 <b>정리</b><br />
184+
<b>정리</b><br />
185185
try-with-resources 를 이용하면 AutoCloseable 인터페이스를 구현한 자원들은 try() 구문에서 자동으로 close() 된다. <br />
186186
finally 블록 없이 간결한 코드를 작성할 수 있고, 리소스 누출 가능성을 줄일 수 있다. <br />
187187
:::

posts/spring/jpa-determine-entity-is-new.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ Database 에는 해당 ID 가 존재하지 않지만, 신규 Entity 임에도
173173
<br/><br/>
174174

175175
:::success
176-
💡 <b>정리</b><br />
176+
<b>정리</b><br />
177177
Spring Data JPA 는 내부적으로 isNew() 를 통해서 신규 Entity 여부를 판단한다. <br />
178178
ID 는 존재하지만 실제 DB 에 없는 경우 SELECT + UPDATE 후 merge 를 하므로 정합성이 떨어질 수 있고, 비효율적이다. <br />
179179
ID 를 직접 설정했을 경우는 Persistable + isNew() 로 명시하는 것이 필요하다. <br />

0 commit comments

Comments
 (0)