팀 코딩 규칙
서론
이 문서는 팀의 코딩 규칙을 담고 있습니다.
규칙을 수정하시고자 할 경우 팀과 의논 후 수정합시다.
1. 명명 규칙 (Naming Conventions)
1.1. 변수 명명 (Variable Naming)
-
CamelCase 사용: 모든 변수명은 소문자로 시작하는
camelCase형식을 원칙으로 합니다.- (O)
userName,orderCount - (X)
user_name(snake_case),UserName(PascalCase)
- (O)
-
헝가리안 표기법 금지: 변수명에 자료형을 접두어로 붙이는 방식을 사용하지 않습니다.
- (O)
name,age,isAvailable - (X)
strName,nAge,bAvailable
- (O)
-
의미 있는 이름 부여: 변수의 역할과 용도가 명확히 드러나도록 명명합니다.
a,b,temp등 의미 없는 단어는 지양합니다.- (O)
userList,totalPrice,expiredDate - (X)
list,val,temp,data1
TIP
반복문 내 인덱스(
i,j,k)는 예외적으로 허용합니다. - (O)
-
불리언(Boolean) 변수 접두사: 참/거짓을 나타내는 변수는 상태를 직관적으로 알 수 있는 접두사를 사용합니다.
- (O)
isLoggedIn,hasError,canExecute - (X)
loginCheck,errorStatus,successFlag
- (O)
-
매개변수 명명 (SNAKE_CASE): 메뉴 매개변수, 팝업 매개변수 등은 대문자
SNAKE_CASE를 사용합니다.- (O)
MENU_ID,POPUP_PARAM_NAME - (X)
menuId,popupParamName
- (O)
1.2. 함수/메소드 명명 (Function/Method Naming)
-
fn_접두사 사용: 일반적인 함수 및 메소드는fn_접두사로 시작하여 일반 변수와 명확히 구분합니다.- (O)
fn_search(),fn_saveData() - (X)
search(),save_data()
- (O)
-
CamelCase 사용:
fn_접두사 이후의 명칭은 소문자로 시작하는camelCase형식을 사용합니다.- (O)
fn_getUserInfo(),fn_calculateTotal() - (X)
fn_GetUserInfo(),fn_calculate_total()
- (O)
-
이벤트 핸들러 규칙:
- 자동 생성 명칭 유지: 넥사크로 프레임워크에서 자동 생성되는 이벤트 함수명은 임의로 수정하지 않고 그대로 사용합니다.
- (O)
btn_search_onclick,ds_list_oncolumnchanged
- (O)
NOTE
화면 로드 시 발생하는 이벤트는 예외적으로
form_onload명칭을 사용합니다. - 자동 생성 명칭 유지: 넥사크로 프레임워크에서 자동 생성되는 이벤트 함수명은 임의로 수정하지 않고 그대로 사용합니다.
-
동사 위주의 명명: 함수의 기능을 직관적으로 알 수 있도록
get,set,is,chk(또는check) 등의 동사를 조합하여 명명합니다.- (O)
fn_isExist(),fn_getParam()
- (O)
1.3. 파일 및 디렉터리 명명 (File & Directory Naming)
- 표준 가이드 준수: 프로젝트에서 정의된 '개발 표준 문서’의 파일, 디렉터리 및 컴포넌트(Component) 명명 규칙을 최우선적으로 따릅니다.
1.4. 상수 명명 (Constant Naming)
- UPPER_SNAKE_CASE 사용: 모든 전역 상수는 대문자와 언더바(
_)를 사용하는SNAKE_CASE형식을 사용합니다.- (O)
MAX_COUNT,API_URL,DEFAULT_PAGE_SIZE - (X)
maxCount,api_url,Max_Count
- (O)
2. 코드 스타일 및 포맷팅 (Code Style & Formatting)
2.1. 들여쓰기 및 공백
- 탭(Tab) 사용: 코드 들여쓰기는 탭(Tab) 사용을 원칙으로 합니다.
NOTE
넥사크로 스튜디오(Nexacro Studio) 환경에서 스페이스(Space)를 통한 들여쓰기 관리가 불편한 점을 고려한 규칙입니다.
2.2. 문장 끝 세미콜론
- 세미콜론(;) 필수 사용: 모든 문장의 끝에는 세미콜론을 반드시 작성합니다.
IMPORTANT
이는 코드의 명확성을 높이고 자바스크립트의 자동 세미콜론 삽입(ASI)으로 인한 예기치 않은 오류를 방지하기 위함입니다.
2.3. 괄호 스타일
- K&R 스타일 (Same Line Open): 중괄호(
{)는 함수 선언이나 제어문 키워드와 동일한 줄에서 시작하고, 닫는 중괄호(})는 새로운 줄에 작성합니다.- 함수 예시:
// 일반 함수 this.fn_search = function() { // 코드 작성 }; // 화살표 함수 const fn_update = () => { // 코드 작성 }; - 제어문 예시:
if (condition) { // 코드 작성 } else { // 코드 작성 }
- 함수 예시:
2.4. 최대 줄 길이
- 100자 제한: 한 줄의 최대 길이는 공백을 포함하여 100자 이내로 제한합니다.
TIP
가독성을 위해 100자가 넘어가는 코드는 적절히 개행하여 작성하는 것을 권장합니다.
2.5. 에디터 글꼴 설정
- D2Coding 사용: 팀 내 코드 리뷰 및 화면 공유 시 가독성 통일을 위해 에디터 글꼴은 D2Coding 사용을 원칙으로 합니다.
2.6. 연산자 주변 공백 사용
- 공백 필수 사용: 코드의 가독성을 높이기 위해 모든 연산자(산술, 비교, 논리, 대입 등)의 양쪽에는 반드시 공백을 추가합니다.
- (O)
const total = price + tax;,if (count > 0 && isValid) { ... } - (X)
const total=price+tax;,if(count>0&&isValid){ ... }
- (O)
2.7. 문자열 표기 (String Literals)
- 쌍따옴표(“”) 사용: 코드 내 문자열은 쌍따옴표(
") 사용을 원칙으로 합니다.- (O)
const mode = "SEARCH"; - (X)
const mode = 'SEARCH';
NOTE
단, 문자열 내부에 쌍따옴표가 포함되어야 하거나 MyBatis XML의
test속성 등 특수한 상황에서는 홑따옴표(')를 사용할 수 있습니다. - (O)
3. 주석 및 문서화 (Comments & Documentation)
3.1. 주석 작성 가이드
- 단일행 주석 (
//): 코드 한 줄에 대한 설명이나 간단한 코멘트를 작성할 때 사용합니다.// 사용자 이름 설정 const userName = "HongGilDong"; - 다중행 주석 (
/* ... */): 여러 줄에 걸친 상세 설명이나 함수/클래스에 대한 설명을 작성할 때 사용합니다./* * 공통 조회 함수 * @param {String} svcId 서비스 ID * @param {String} url 요청 URL */ this.fn_search = function(svcId, url) { // ... 코드 생략 }; - 공통코드 및 상태값 명시: 공통코드나 상태값 등 코드값만으로는 그 의미를 즉시 파악하기 어려운 경우, 주석으로 명칭(의미)을 명시합니다.
this.fn_initCombo = () => { return this.combo.setCombo({ action: "basic", svcId: "combo", comps: [ { comp: this.div_search.form.cmb_grde, sqlId: "@comcd.s01", mode: "a", param: "CLA_CD=1020", // 학년 mapping: { code: "CD", data: "CD_NM" }, }, { comp: this.div_search.form.cmb_facDvcd, sqlId: "@comcd.s01", mode: "a", param: "CLA_CD=1654", // 이수구분 mapping: { code: "CD", data: "CD_NM" }, }, ], }); }; - 주석 처리된 코드 금지: 비활성화된 코드(Commented-out code)를 파일 내에 방치하지 않습니다.
WARNING
불필요한 코드는 즉시 삭제하세요. 과거 이력이 필요하다면 형상 관리 도구(Git)를 활용해야 합니다.
- (X)
// const oldData = "test";
- (X)
4. 프로그래밍 권장 사항 (Programming Best Practices)
4.1. 변수 선언 및 유효범위 (Variable Declaration & Scope)
const[1]와let[2] 사용: 변수 선언 시const를 우선적으로 사용하며, 재할당이 필요한 경우에만let을 사용합니다.IMPORTANT
var키워드는 절대 사용하지 않습니다.- (O)
const MAX_TIMEOUT = 5000;,let currentStep = 0; - (X)
var name = "admin";
- (O)
4.2. 함수 설계 (Function Design)
-
async-await[3] 사용: 비동기 처리 시callback이나.then()방식의promise를 지양하고, 가독성이 높은async-await문법을 사용합니다.- (O)
this.fn_save = async function() { try { const result = await this.fn_callApi(); // 성공 처리 } catch (e) { // 에러 처리 } }; - (X)
this.fn_save = function() { this.fn_callApi().then(function(result) { // 성공 처리 }).catch(function(e) { // 에러 처리 }); };
- (O)
-
얼리 리턴(Early Return) 권장: 조건문이 중첩되어 코드의 깊이(Depth)가 깊어지는 것을 방지하기 위해, 예외 상황을 먼저 처리하고 함수를 일찍 반환(Return)합니다.
- (O)
this.fn_process = function(data) { if (!data) return; // 예외 우선 처리 if (data.status !== "OK") return; // 핵심 로직 수행 (들여쓰기 최소화) this.fn_execute(data); }; - (X)
this.fn_process = function(data) { if (data) { if (data.status === "OK") { // 핵심 로직이 깊은 Depth에 위치함 this.fn_execute(data); } } };
4.3. 제어문 중괄호(
{}) 필수 사용- 중괄호 생략 금지:
if,for,while등 제어문 사용 시, 실행되는 문장이 한 줄이라도 중괄호를 반드시 사용합니다. 이는 코드의 가독성을 높이고 향후 코드 추가 시 발생할 수 있는 논리적 오류를 방지하기 위함입니다. - (O)
if (condition) { this.fn_execute(); } - (X)
if (condition) this.fn_execute();
4.4. 삼항 연산자 중첩 금지
- 가독성 우선: 삼항 연산자는 간단한 조건 할당에만 사용하며, 두 번 이상 중첩하여 사용하지 않습니다. 복잡한 조건은
if-else문을 사용하거나 변수로 분리하여 가독성을 확보합니다. - (O)
const statusLabel = (status === "01") ? "성공" : "실패"; - (X)
const label = isMember ? (isValid ? "정상" : "만료") : "비회원";
5. SQL 작성 규칙 (SQL Writing Rules)
5.1. SQL 포맷팅 및 스타일
-
대문자 사용: SQL 예약어(Keywords)와 컬럼명(Columns)은 모두 대문자 작성을 원칙으로 합니다.
-
들여쓰기 및 정렬:
SELECT,FROM,WHERE,GROUP BY등의 주요 키워드는 우측 정렬 형태로 배치하여 코드의 가독성을 높입니다.- 컬럼이나 정렬 대상 나열 시 앞 콤마(Leading Comma) 방식을 사용합니다.
-
ANSI Join 필수 사용: 모든 조인 문법은
INNER JOIN,LEFT OUTER JOIN등 ANSI Join 문법을 반드시 사용합니다.IMPORTANT
Oracle 방식의 콤마 조인이나
(+)연산자를 사용한 아우터 조인 작성을 금지합니다. -
작업 예시:
SELECT A.YY AS YY , A.ORG_CD AS ORG_CD , B.UNIV_CD AS UNIV_CD FROM HSG0010 A INNER JOIN PKG_CSB_ORG B ON A.ORG_CD = B.ORG_CD WHERE A.YY = #{YY} AND B.UNIV_CD = #{UNIV_CD} ORDER BY B.ORD , A.YY -
MyBatis
<where>사용 금지: 동적 쿼리 작성 시 MyBatis에서 제공하는<where>태그 사용을 금지합니다. 대신WHERE 1=1형식을 사용하여 들여쓰기와 가독성을 유지합니다. -
연산자 주변 공백 사용: SQL 내의 모든 연산자(비교, 산술, 대입 등)의 양쪽에는 반드시 공백을 추가합니다.
- (O)
SELECT A.POINT + 1 AS NEXT_POINT FROM HSG0010 A WHERE A.YY = #{YY} AND A.ORG_CD != '0000' - (X)
SELECT A.POINT+1 AS NEXT_POINT FROM HSG0010 A WHERE A.YY=#{YY} AND A.ORG_CD!='0000'
- (O)
-
작업 예시:
SELECT A.USER_ID AS USER_ID , A.USER_NM AS USER_NM FROM CSB0101 A WHERE 1 = 1 <if test="USER_ID != null and USER_ID != ''"> AND A.USER_ID = #{USER_ID} </if> -
MyBatis OGNL 단일 문자 비교 주의: ‘1’, ‘0’, ‘Y’, ‘N’ 등 한 글자 값을 비교할 때 OGNL 표현식에서
char타입으로 오인되는 문제를 방지하기 위해, XML 속성(test)은 **홑따옴표(')**로 감싸고 내부 문자열 값은 **쌍따옴표(")**를 사용합니다. -
작업 예시:
<!-- (O) XML 속성을 홑따옴표로, 내부 값을 쌍따옴표로 사용 --> <if test='USE_YN == "Y"'> AND A.USE_YN = #{USE_YN} </if> <!-- (X) 한 글자를 홑따옴표로 감싸면 char 타입으로 식별되어 비교 실패 가능성 있음 --> <if test="USE_YN == 'Y'"> ... </if> -
필수 조건 동적 쿼리 처리 금지: SQL 작성 시 필수 조건(연도, 학기 등)에 대해서는 MyBatis의
<if>등 동적 쿼리 태그를 사용하지 않습니다. 이는 필수 파라미터 누락 시 의도치 않은 대량의 데이터 조회나 잘못된 결과가 반환되는 것을 방지하기 위함입니다. -
작업 예시:
<!-- (O) 필수 조건인 YY, SMT는 <if> 태그 없이 직접 작성 --> WHERE 1 = 1 AND A.YY = #{YY} AND A.SMT = #{SMT} <if test='USER_ID != null and USER_ID != ""'> AND A.USER_ID = #{USER_ID} </if> <!-- (X) 필수 조건을 <if> 태그로 감싸면 파라미터 누락 시 전체 데이터가 조회될 수 있음 --> WHERE 1 = 1 <if test='YY != null and YY != ""'> AND A.YY = #{YY} </if>
- (O)
5.2. SQL 명명 규칙
- 별칭(Alias) 필수 사용: 모든 테이블과 조회 컬럼에는 별칭을 반드시 부여합니다.
- 테이블 별칭:
A,B,C순으로 부여하거나 의미 있는 약어를 사용합니다. - 컬럼 별칭: 조회 결과의 가독성과 명확한 데이터 매핑을 위해 컬럼 별칭(
AS ...) 작성을 원칙으로 합니다.
- 테이블 별칭:
- 변수 사용: 마이바티스(MyBatis) 바인드 변수(
#{...}) 사용 시 변수명은 모두 대문자 SNAKE_CASE를 사용합니다.- (O)
#{USER_ID},#{MENU_ID} - (X)
#{userId},#{menuId}
- (O)
5.3. 성능 및 보안 고려 사항
SELECT *사용 금지: 필요한 컬럼만 명시적으로 작성하여 불필요한 데이터 전송을 방지합니다.- 바인드 변수 사용: SQL Injection 방지를 위해 리터럴 상수 대신 바인드 변수(
#{...}) 사용을 원칙으로 합니다.
6. 업무 개발 규칙 (Business Development Rules)
6.1. 메뉴 및 팝업 매개변수 처리
- 구조 분해 할당 사용: 메뉴 매개변수나 팝업 매개변수를 가져올 때는
$comp.getParam(this)메소드를 사용하며, 가독성과 기본값 설정을 위해 구조 분해 할당(Destructuring Assignment)[4] 방식으로 선언합니다. - 선언 위치: 매개변수 선언은 폼 상단의 전역 변수 선언 영역(
[ PART 1 ])에 작성합니다.- 작업 예시:
//_________________________________________________________________________________________________ // // [ PART 1 ] // form 전역변수 선언 //_________________________________________________________________________________________________ const { ATLEC_GBN = "XXX", MENU_ID } = $comp.getParam(this);
- 작업 예시:
6.2. 자동 조회 지양
- 서버 부하 및 속도 개선: 프로그램 오픈 시 대량의 데이터를 자동으로 조회하는 행위는 지양합니다. 불필요한 서버 부하를 줄이고 초기 로딩 속도를 높이기 위해, 사용자가 직접 조회 버튼을 클릭하거나 필수 검색 조건을 입력한 후 조회가 이루어지도록 설계합니다.
6.3. EzTitlebar SQL 처리 방식
-
스크립트 기반 요청 사용:
EzTitlebar컴포넌트 속성(예:selectSqlId,insertSqlId등)에 SQL ID를 직접 등록하지 않습니다. 대신 스크립트에서 별도의 트랜잭션 함수를 작성하고, Titlebar의 핸들러 함수를 오버라이드하여 연결합니다.TIP
이 방식은 복잡한 파라미터 처리나 트랜잭션 전/후 로직을 더 유연하게 관리할 수 있게 해줍니다.
-
작업 예시:
// [ PART 4 ] 사용자 TitleBar 버튼 함수, 이벤트 this.tit_main_onload = function(obj:nexacro.EzTitlebar, e:nexacro.EzTitlebarEventInfo) { obj.onsearch = this.fn_searchMain; // 조회 핸들러 연결 obj.onsave = this.fn_saveMain; // 저장 핸들러 연결 }; // [ PART 5 ] Transaction 함수 this.fn_searchMain = function() { return this.tx.search({ action: "basic", svcId: "searchMain", sqlId: "sample_01.s01", outDs: "ds_main", param: $f.mkArg({ YY: this.div_search.form.spn_yy, // ... 기타 파라미터 }), }); };
6.4. 엔터(Enter) 키 조회 기능 구현
-
사용자 편의성 제고: 성명, 사번, 키워드 등 텍스트 방식으로 검색하는 조회 조건이 포함된 경우, 사용자가 텍스트 입력 후 즉시 조회를 수행할 수 있도록 Enter 키 입력 시 조회 함수가 호출되도록 구현합니다.
-
구현 방법: 컴포넌트의
onkeydown이벤트 등에서 입력된 키가 Enter(13)인 경우 조회 버튼의 클릭 이벤트나 조회 함수(fn_search)를 호출합니다. -
작업 예시:
this.div_search_edt_name_onkeydown = function(obj:nexacro.Edit, e:nexacro.KeyEventInfo) { // 엔터 키 입력 시 조회 함수 호출 if (e.keycode === 13) { this.fn_search(); } };
6.5. 최대 입력 길이(maxlength) 설정
- 데이터 정합성 및 오류 방지: 사용자로부터 입력을 받는 컴포넌트(Edit, MaskEdit, TextArea 등)는 해당 데이터가 저장될 DB 컬럼의 길이를 고려하여 최대 입력 길이(
maxlength)를 반드시 설정합니다. - 사용자 경험(UX) 개선: 입력 단계에서 길이를 제한함으로써 저장 시 발생하는 길이 초과 에러(Data too long)를 사전에 방지하고 데이터의 정합성을 확보합니다.
6.6. 입력 문자 제한 및 타입 설정
- 유효 데이터 입력 유도: 학번, 사번, 연락처 등 입력받을 문자의 범위가 정해져 있는 경우, 사용자가 의도하지 않은 문자를 입력하지 못하도록 명확한 타입을 설정합니다.
- 설정 방법:
- 일반 컴포넌트:
inputtype속성을 설정합니다. (예: 숫자만 입력 시number또는digit) - 그리드(Grid): 컬럼의
edittype설정에 따라 다음 속성을 연결하여 설정합니다.edittype="text"인 경우:editinputtype속성 설정edittype="textarea"인 경우:textareainputtype속성 설정
- 일반 컴포넌트:
6.7. 자동 선택(autoselect) 기능 활용
- 편집 편의성 제공: 정렬 순서, 수량 등 기존 입력된 텍스트 전체를 한꺼번에 변경하는 것이 빈번할 것으로 예상되는 경우, 컴포넌트 진입 시 내용이 즉시 드래그(선택)된 상태가 되어 바로 수정할 수 있도록 설정합니다.
- 설정 방법:
- 일반 컴포넌트:
autoselect속성을 활용합니다. - 그리드(Grid): 컬럼의
edittype설정에 따라 다음 속성을 활용합니다.edittype="text"인 경우:editautoselect속성 설정edittype="textarea"인 경우:textareaautoselect속성 설정
7. 형상 관리 및 커밋 규칙 (Version Control & Commit Rules)
7.1. 커밋 규칙 (Commit Rules)
- 작업 단위별 커밋: 한 번에 너무 많은 변경 사항을 커밋하지 않고, 논리적인 수정 작업 단위(기능 추가, 버그 수정 등)로 나누어 커밋합니다.
- 간결하고 명확한 메시지: 커밋 메시지에는 작업 내용을 타인이 쉽게 이해할 수 있도록 간략하고 명확하게 작성합니다.
7.2. 브랜치 전략 (Branch Strategy)
- 개인 브랜치 활용: 모든 작업은 개인별로 생성한 브랜치에서 진행하며, 작업 완료 후 원격 저장소에 Push합니다.
- 병합 절차: 개인 브랜치 작업이 완료되면 Pull Request(PR) 또는 Merge Request(MR)를 생성하여 주 브랜치(
main)에 병합하는 것을 원칙으로 합니다.IMPORTANT
main브랜치에 직접 Push하는 행위는 금지됩니다.
7.3. 파일 점유 및 병합 주의사항
- 파일 점유 해제 후 Git 작업 수행: 넥사크로 스튜디오(Nexacro Studio) 및 클립리포트 디자이너(ClipReport Designer) 등의 툴은 작업 중인 파일을 쓰기 상태로 점유합니다.
WARNING
git pull이나merge수행 시 파일 점유로 인해 오류가 발생할 수 있습니다. 툴 전체를 종료할 필요는 없으나, 반드시 수정 중인 파일의 탭을 닫아 점유를 해제한 후 작업을 진행하시기 바랍니다.
7.4. 대용량 바이너리 파일 커밋 금지
- 저장소 최적화: 설치 파일(
.exe,.msi), 대용량 라이브러리, 빌드 결과물 등 큰 용량의 바이너리 파일은 Git 저장소에 커밋하지 않습니다.IMPORTANT
이러한 파일들은 저장소의 크기를 불필요하게 키우고 성능을 저하시키므로, 프로젝트 파일 서버 등 별도의 공유 공간을 활용하시기 바랍니다.