Skip to content

ATGC 염기서열 입력 검증 및 자동 대문자 변환 기능 추가#46

Merged
7hyunii merged 13 commits intoSeq-Lab:developfrom
cnvxlns:validate
Feb 22, 2026
Merged

ATGC 염기서열 입력 검증 및 자동 대문자 변환 기능 추가#46
7hyunii merged 13 commits intoSeq-Lab:developfrom
cnvxlns:validate

Conversation

@cnvxlns
Copy link
Copy Markdown
Collaborator

@cnvxlns cnvxlns commented Feb 21, 2026

변경 사항 (Changes)

  • 입력 검증 및 예외 처리: A, T, G, C 이외의 잘못된 문자 입력 시, 경고 메시지를 노출하고 재입력을 요구하도록 방어 로직을 추가했습니다.
  • 자동 대문자 변환: 편의성을 위해 소문자(a, t, g, c)를 입력하더라도 자동으로 대문자로 치환되도록 적용했습니다.

작업 목적 (Purpose)

  • 잘못된 데이터가 입력되거나 처리되는 것을 사전에 방지하여 데이터 무결성을 확보했습니다.

  • 사용자가 대소문자를 신경 쓰지 않고 입력할 수 있게 하여 전반적인 사용 경험(UX)을 개선했습니다.

    ++ 입력시 ATGC만 대문자로 변환되고, 나머지는 변환되지 않습니다. 이렇게 하면 오히려 이상한 문자가 잘 보여서 잘못 들어갔을 때 수정이 용이할 것 같습니다.

@cnvxlns
Copy link
Copy Markdown
Collaborator Author

cnvxlns commented Feb 21, 2026

pr 쓰면서 떠오른건데 그냥 입력 시 atgc아닌걸 미리 다 지워버리는 방식도 좋을것 같습니다. 서열 길이가 엄청 길어버리면 직접 찾아서 수정하는게 어려울 것 같네요

@7hyunii
Copy link
Copy Markdown
Contributor

7hyunii commented Feb 21, 2026

변경 사항 (Changes)

  • 입력 검증 및 예외 처리: A, T, G, C 이외의 잘못된 문자 입력 시, 경고 메시지를 노출하고 재입력을 요구하도록 방어 로직을 추가했습니다.
  • 자동 대문자 변환: 편의성을 위해 소문자(a, t, g, c)를 입력하더라도 자동으로 대문자로 치환되도록 적용했습니다.

작업 목적 (Purpose)

  • 잘못된 데이터가 입력되거나 처리되는 것을 사전에 방지하여 데이터 무결성을 확보했습니다.
  • 사용자가 대소문자를 신경 쓰지 않고 입력할 수 있게 하여 전반적인 사용 경험(UX)을 개선했습니다.

동작 화면 (Optional)

  • (여기에 경고 메시지가 뜨는 화면이나, 대문자로 자동 변환되는 짧은 GIF를 첨부하면 리뷰어가 보기 좋습니다!)

  • 입력시 ATGC만 대문자로 변환되고, 나머지는 변환되지 않습니다. 이렇게 하면 오히려 이상한 문자가 잘 보여서 잘못 들어갔을 때 수정이 용이할 것 같습니다.

맨 밑에 동작 화면 부분은 뭔가요.. 여러 번 말씀드리지만 좀 컨펌하고 올려주세요

@7hyunii 7hyunii closed this Feb 21, 2026
@7hyunii 7hyunii reopened this Feb 21, 2026
@7hyunii
Copy link
Copy Markdown
Contributor

7hyunii commented Feb 21, 2026

pr 쓰면서 떠오른건데 그냥 입력 시 atgc아닌걸 미리 다 지워버리는 방식도 좋을것 같습니다. 서열 길이가 엄청 길어버리면 직접 찾아서 수정하는게 어려울 것 같네요

미리 다 지워버린다는게 무슨 말인지 잘 모르겠습니다. 입력을 했을 때 A,T,G,C가 아닌 부분을 없애주는 기능을 추가한다는 말인가요?

@cnvxlns
Copy link
Copy Markdown
Collaborator Author

cnvxlns commented Feb 21, 2026

pr 쓰면서 떠오른건데 그냥 입력 시 atgc아닌걸 미리 다 지워버리는 방식도 좋을것 같습니다. 서열 길이가 엄청 길어버리면 직접 찾아서 수정하는게 어려울 것 같네요

미리 다 지워버린다는게 무슨 말인지 잘 모르겠습니다. 입력을 했을 때 A,T,G,C가 아닌 부분을 없애주는 기능을 추가한다는 말인가요?


입력할때 ATGC외의 문자가 들어오면 지워버리는 로직을 짜봤는데, 백스페이스가 여러 번 들어가서 문제가 발생할 소지가 있어서, 파일로 업로드한(또는 paste한) 문자열에 대해서만 삭제하는 로직을 구현해서 커밋했습니다. 어차피 키보드로 친 서열은 그렇게 길지 않아서 눈으로 보고 제거하는게 어렵지 않을 것 같아서 사용자 경험 상 큰 에러가 없을 것 같습니다.

@cnvxlns
Copy link
Copy Markdown
Collaborator Author

cnvxlns commented Feb 21, 2026

혹시 github copilot으로 request 한번 해주실수 있나요

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

이 PR은 ATGC 염기서열 입력에 대한 검증 및 자동 변환 기능을 추가하여 데이터 무결성을 강화하고 사용자 경험을 개선합니다. 새로운 파서 모듈을 통해 입력값을 sanitize하고, UI에서 실시간으로 검증 메시지를 표시합니다.

Changes:

  • ATGC 염기서열 파싱 및 검증을 위한 새로운 유틸리티 함수 추가 (src/lib/parsers/step1TemplateSequence.ts)
  • 텍스트 입력 시 실시간 sanitization을 위한 onBeforeInput 이벤트 핸들러 구현
  • Step 전환 시 및 API 호출 전 다단계 검증 로직 추가

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 7 comments.

File Description
src/lib/parsers/step1TemplateSequence.ts ATGC 염기서열 검증, sanitization, 정규화를 위한 유틸리티 함수 모음 추가
components/steps/Step1TemplateEssential.tsx 입력 필드에 실시간 sanitization 및 검증 메시지 표시 기능 통합
app/page.tsx Step 전환 및 API 호출 시점의 검증 로직 추가 및 경고 메시지 처리
Comments suppressed due to low confidence (1)

components/steps/Step1TemplateEssential.tsx:218

  • handleTextareaChange가 사용자가 직접 입력한 내용을 sanitization 없이 그대로 저장합니다. onBeforeInput 핸들러가 모든 입력을 가로채려고 하지만, 특정 브라우저나 입력 방식(예: IME, 자동완성, 드래그앤드롭)에서는 beforeInput 이벤트가 발생하지 않을 수 있습니다. handleTextareaChange에서도 입력값을 sanitize하도록 수정하세요: updateSequence(sanitizeStep1TemplateSequenceInput(event.currentTarget.value))
    const handleTextareaChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
        if (isLargeSequenceMode || event.currentTarget.readOnly) return;
        updateSequence(event.currentTarget.value);

if (sanitizedChunk === rawChunk) return;

event.preventDefault();
insertSanitizedChunkAtSelection(event.currentTarget, rawChunk);
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 210에서 sanitizedChunk === rawChunk 조건이 역설적입니다. 이 조건이 true일 때 함수가 early return하므로, 실제로는 입력이 이미 유효할 때만 반환하고 무효한 입력만 처리합니다. 그러나 line 209에서 sanitizeStep1TemplateSequenceInput이 FASTA 헤더와 공백도 제거하므로, 유효한 ATGC 입력이더라도 공백이 포함되어 있으면 불필요하게 처리됩니다. 로직을 재검토하세요: 유효한 입력은 그대로 통과시키고, 무효한 입력만 sanitize해야 합니다.

Suggested change
insertSanitizedChunkAtSelection(event.currentTarget, rawChunk);
insertSanitizedChunkAtSelection(event.currentTarget, sanitizedChunk);

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,29 @@
const FASTA_HEADER_PREFIX = ">";
const ATGC_ONLY_PATTERN = /^[ATGC]*$/i;
const UPPERCASE_ATGC_ONLY_PATTERN = /^[ATGC]+$/;
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정규식 패턴이 빈 문자열을 거부합니다. + 수량자는 최소 1개 이상의 문자를 요구하지만, 빈 시퀀스도 유효한 입력으로 처리되어야 합니다. *로 변경하여 빈 문자열도 허용하도록 수정하세요.

Suggested change
const UPPERCASE_ATGC_ONLY_PATTERN = /^[ATGC]+$/;
const UPPERCASE_ATGC_ONLY_PATTERN = /^[ATGC]*$/;

Copilot uses AI. Check for mistakes.
.join("")
.replace(/\s+/g, "");

export const toUpperCaseAtgcOnly = (value: string) =>
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 함수가 export 되어 있지만 코드베이스 어디에서도 사용되지 않습니다. 불필요한 export는 제거하거나, 실제로 사용할 계획이 있다면 해당 위치에서 사용하세요.

Suggested change
export const toUpperCaseAtgcOnly = (value: string) =>
const toUpperCaseAtgcOnly = (value: string) =>

Copilot uses AI. Check for mistakes.
stripFastaHeadersAndWhitespace(rawSequence)
.replace(NON_ATGC_GLOBAL_PATTERN, "")
.toUpperCase();

Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 함수는 단순히 sanitizeStep1TemplateSequenceInput을 호출하는 wrapper입니다. 중복 레이어를 제거하고 직접 sanitizeStep1TemplateSequenceInput을 사용하거나, 이 함수가 향후 다른 로직을 추가할 계획이 있다면 주석으로 명시하세요.

Suggested change
// NOTE: 이 함수는 step1 템플릿 시퀀스에 대한 "정규화(normalize)" 공개 API입니다.
// 현재 구현은 sanitize 로직에만 위임하지만, 향후 추가적인 정규화/검증 단계가
// 필요해질 수 있으므로 별도 함수로 유지합니다.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +29
const FASTA_HEADER_PREFIX = ">";
const ATGC_ONLY_PATTERN = /^[ATGC]*$/i;
const UPPERCASE_ATGC_ONLY_PATTERN = /^[ATGC]+$/;
const NON_ATGC_PATTERN = /[^ATGCatgc]/;
const NON_ATGC_GLOBAL_PATTERN = /[^ATGCatgc]/g;

const stripFastaHeadersAndWhitespace = (rawSequence: string) =>
rawSequence
.split(/\r?\n/)
.filter((line) => !line.trim().startsWith(FASTA_HEADER_PREFIX))
.join("")
.replace(/\s+/g, "");

export const toUpperCaseAtgcOnly = (value: string) =>
ATGC_ONLY_PATTERN.test(value) ? value.toUpperCase() : value;

export const sanitizeStep1TemplateSequenceInput = (rawSequence: string) =>
stripFastaHeadersAndWhitespace(rawSequence)
.replace(NON_ATGC_GLOBAL_PATTERN, "")
.toUpperCase();

export const normalizeStep1TemplateSequence = (rawSequence: string) =>
sanitizeStep1TemplateSequenceInput(rawSequence);

export const isUppercaseAtgcOnlySequence = (value: string) =>
UPPERCASE_ATGC_ONLY_PATTERN.test(value);

export const getInvalidStep1TemplateSequenceChar = (rawSequence: string) =>
stripFastaHeadersAndWhitespace(rawSequence).match(NON_ATGC_PATTERN)?.[0] ?? null;
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

새로 추가된 파서 함수들에 대한 단위 테스트가 없습니다. 코드베이스에 vitest를 사용한 테스트 인프라가 있으므로(tests/visibleRange.test.ts 참조), 다음과 같은 케이스를 테스트하는 파일을 추가하세요: 1) 소문자 입력의 대문자 변환, 2) 잘못된 문자 제거, 3) FASTA 헤더 제거, 4) 빈 문자열 처리, 5) 유효한 시퀀스 검증.

Copilot uses AI. Check for mistakes.

const currentValue = sequenceRef.current;
const appendedValue = currentValue ? `${currentValue}\n${sanitized}` : sanitized;
const appendedValue = `${currentValue}${sanitizedChunk}`;
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

기존 로직이 변경되었습니다. 이전에는 currentValue와 새로운 내용 사이에 개행 문자(\n)를 추가했지만, 현재는 바로 연결합니다. 이 변경이 의도된 것인지 확인하세요. 여러 파일을 연속으로 업로드하거나 붙여넣을 때 시퀀스가 구분 없이 합쳐질 수 있습니다.

Suggested change
const appendedValue = `${currentValue}${sanitizedChunk}`;
const needsSeparator =
currentValue.length > 0 &&
!currentValue.endsWith("\n") &&
!sanitizedChunk.startsWith("\n");
const appendedValue = needsSeparator
? `${currentValue}\n${sanitizedChunk}`
: `${currentValue}${sanitizedChunk}`;

Copilot uses AI. Check for mistakes.
app/page.tsx Outdated
Comment on lines +122 to +129
if (!isUppercaseAtgcOnlySequence(targetSeq)) {
const warningMessage =
"전송 전 검증에 실패했습니다. 시퀀스는 대문자 A, T, G, C만 포함해야 합니다.";
setStep1WarningMessage(warningMessage);
setErrorMessage(warningMessage);
alert(warningMessage);
return;
}
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleGenerate 함수에 중복된 검증 로직이 있습니다. Line 76-87의 validateStep1Sequence에서 이미 잘못된 문자를 검사하고, line 108-115에서 빈 시퀀스를 검사하며, line 122-129에서 다시 대문자 ATGC만 포함하는지 검사합니다. sanitizeStep1TemplateSequenceInput이 이미 모든 비-ATGC 문자를 제거하고 대문자로 변환하므로, line 122-129의 검증은 불필요합니다. 검증 로직을 단순화하세요.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@7hyunii 7hyunii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A, T, G, C 이외 문자는 입력 시 자동으로 제거됩니다. Paste 버튼, Ctrl+V, Upload FASTA에서는 제거 전에 확인을 요청합니다. 멘트 두 줄로 줄바꿈하는게 보기 좋을 것 같습니다

Copy link
Copy Markdown
Contributor

@7hyunii 7hyunii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정 끝난건가요

@cnvxlns
Copy link
Copy Markdown
Collaborator Author

cnvxlns commented Feb 21, 2026

수정 끝난건가요

네, 코파일럿 한판만 더 해주세요

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 7 comments.

Comment on lines 87 to +113
@@ -74,11 +102,22 @@ export default function Home() {
);

const handleGenerate = async () => {
const inputSequence = sequenceInputRef.current;
const rawInputSequence = sequenceInputRef.current;
const inputSequence = normalizeStep1TemplateSequence(rawInputSequence);
if (rawInputSequence.trim().length > 0 && inputSequence.length === 0) {
const warningMessage =
"전송할 수 있는 유효한 염기서열이 없습니다. A, T, G, C 문자만 입력해 주세요.";
setStep1WarningMessage(warningMessage);
setErrorMessage(warningMessage);
alert(warningMessage);
return;
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사용자가 Step 1에서 다음 단계로 이동할 때와 Generate 버튼을 클릭할 때 중복된 검증 로직이 실행됩니다. handleNext (88번 줄)와 handleGenerate (105-113번 줄) 모두에서 유효성 검증을 수행하는데, 이는 일관성이 부족하고 유지보수를 어렵게 만듭니다. 검증 로직을 한 곳에서 수행하거나, 각각의 검증 목적이 다르다면 주석으로 명확히 구분해 주세요.

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +40
export const getInvalidStep1TemplateSequenceChar = (rawSequence: string) =>
stripFastaHeadersAndWhitespace(rawSequence).match(NON_ATGC_PATTERN)?.[0] ?? null;
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트 커버리지가 부족합니다. 새로 추가된 step1TemplateSequence.ts 파일의 함수들(sanitizeStep1TemplateSequenceInput, getInvalidStep1TemplateSequenceChars, getInvalidStep1TemplateSequenceChar 등)에 대한 단위 테스트를 추가해 주세요. 특히 FASTA 헤더 제거, 공백 처리, 잘못된 문자 감지, 대소문자 변환 등 핵심 기능에 대한 테스트가 필요합니다.

Suggested change
export const getInvalidStep1TemplateSequenceChar = (rawSequence: string) =>
stripFastaHeadersAndWhitespace(rawSequence).match(NON_ATGC_PATTERN)?.[0] ?? null;
export const getInvalidStep1TemplateSequenceChar = (rawSequence: string) => {
const invalidChars = getInvalidStep1TemplateSequenceChars(rawSequence);
return invalidChars.length > 0 ? invalidChars[0] : null;
};

Copilot uses AI. Check for mistakes.
Comment on lines +211 to +217
@@ -160,27 +212,37 @@ export default function Step1TemplateEssential({

const pastedText = event.clipboardData.getData("text");
if (!pastedText) return;
if (!confirmInvalidRemoval(pastedText)) {
focusTextarea();
return;
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

event.preventDefault()가 사용자 확인(confirm) 전에 호출되어 잘못된 동작이 발생합니다. 현재 211번 줄에서 기본 paste 동작을 차단한 후, 215번 줄에서 사용자에게 확인을 요청합니다. 사용자가 "취소"를 클릭하면 아무것도 붙여넣어지지 않습니다 (기본 동작도, 정제된 데이터도 아님). event.preventDefault()를 215번 줄 확인 이후로 이동하여, 사용자가 확인한 경우에만 기본 동작을 차단하고 정제된 데이터를 삽입하도록 수정해 주세요.

Copilot uses AI. Check for mistakes.
app/page.tsx Outdated
Comment on lines +111 to +112
setErrorMessage(warningMessage);
alert(warningMessage);
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

동일한 경고 메시지를 여러 상태에 설정하고 있습니다 (110-112번 줄). setStep1WarningMessage, setErrorMessage, 그리고 alert로 세 번 표시되는데, 이는 사용자에게 혼란을 줄 수 있습니다. 각 메커니즘의 역할을 명확히 하거나, 불필요한 중복을 제거해 주세요.

Suggested change
setErrorMessage(warningMessage);
alert(warningMessage);

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +15
export const toUpperCaseAtgcOnly = (value: string) =>
ATGC_ONLY_PATTERN.test(value) ? value.toUpperCase() : value;
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toUpperCaseAtgcOnly 함수가 정의되어 있지만 코드베이스에서 실제로 사용되지 않고 있습니다. 사용되지 않는 export를 제거하거나, 실제로 사용할 계획이 있다면 해당 위치에서 사용하도록 수정해 주세요.

Copilot uses AI. Check for mistakes.

export const normalizeStep1TemplateSequence = (rawSequence: string) =>
sanitizeStep1TemplateSequenceInput(rawSequence);

Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isUppercaseAtgcOnlySequence 함수가 정의되어 있지만 코드베이스에서 사용되지 않고 있습니다. 사용하지 않는 export를 제거하거나, 향후 사용할 계획이 있다면 그 의도를 주석으로 명확히 해 주세요.

Suggested change
// NOTE: 현재 코드베이스에서는 사용되지 않지만, 시퀀스 입력 검증/밸리데이션 로직에서
// 재사용하기 위해 의도적으로 export를 유지합니다.

Copilot uses AI. Check for mistakes.
Comment on lines +123 to +125
return window.confirm(
`붙여넣으려는 데이터에 A, T, G, C 이외 문자가 포함되어 있습니다 (${previewInvalidChars}${extraKinds}). 해당 문자를 제거하고 계속할까요?`,
);
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사용자 경험 개선을 위해 경고 메시지를 window.alertwindow.confirm 대신 더 현대적인 UI 컴포넌트(예: toast, modal, inline alert)를 사용하는 것을 고려해 주세요. 현재 alertconfirm은 브라우저 네이티브 대화상자를 사용하여 UX가 일관되지 않고, 스타일링이 불가능하며, 모바일에서 사용성이 떨어집니다.

Copilot uses AI. Check for mistakes.
@cnvxlns
Copy link
Copy Markdown
Collaborator Author

cnvxlns commented Feb 21, 2026

일단 수정할 만큼 한것 같습니다

@7hyunii
Copy link
Copy Markdown
Contributor

7hyunii commented Feb 22, 2026

일단 수정할 만큼 한것 같습니다

확인했습니다. 머지하겠습니다

@7hyunii 7hyunii merged commit d322375 into Seq-Lab:develop Feb 22, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants