본문으로 건너뛰기

서비스

Netuno의 Web REST 서비스는 서버(백엔드)에서 실행되는 JavaScript 스크립트로, 애플리케이션의 데이터베이스와 직접 상호작용할 수 있게 해 줍니다. 이를 통해 다음을 할 수 있습니다:

  • 데이터베이스에서 데이터 읽기
  • 새 레코드 삽입
  • 기존 데이터 업데이트
  • 데이터 삭제
  • 계산이나 데이터 처리가 포함된 복잡한 로직 실행
  • 외부 시스템과 통합

각 서비스는 URL(엔드포인트)을 통해 접근되므로, 웹 인터페이스(프런트엔드), 모바일 애플리케이션 또는 다른 외부 시스템이 애플리케이션의 데이터를 안전하고 표준화된 방식으로 사용할 수 있습니다.

사전 요구 사항​

  • JavaScript, React.js 및 _HTML_에 대한 기본 개념이 있어야 합니다.
  • SQL과 애플리케이션의 폴더 구조에 익숙해야 합니다.
  • 양식, 필드, 관계에 대한 기본 지식이 있으면 좋습니다.

이 단계에서 궁금한 점이 있으면 다음을 참고하세요:

시작하기​

근무 시간 기록 애플리케이션을 사용하며, 목표는 각 근로자의 총 근무 시간을 계산하는 것입니다.

애플리케이션 구조:

애플리케이션 구조

참고

id 필드는 Netuno가 모든 테이블에서 자동으로 생성하고 관리하므로 수동으로 정의할 필요가 없습니다.

Netuno 애플리케이션의 서비스는 server/services/ 폴더에 위치합니다.

폴더 구조​

내-앱/
└── server/
└── services/
├── 근로자.js ← 서비스 파일
└──...

서비스 만들기​

server/services/ 폴더 안에 서비스의 URL을 정의할 새 파일을 만드세요. 이 예제에서는 파일 이름을 근로자.js로 지정합니다.

팁
  • 소문자만 사용하세요.
  • 이름이 복합어라면 단어를 **하이픈(-)**으로 구분하세요.
  • 예: 근로자.js, 시간-보고서.js, 출입-기록.js.

데이터베이스 조회​

Netuno는 데이터베이스와 기본적으로 상호작용할 수 있도록 전역 객체 _db를 제공합니다.

SQL 쿼리를 실행하려면 _db.query() 메서드를 사용합니다.

// 근로자별 총 시간을 그룹화하는 SQL 쿼리를 실행합니다
const db기록들 = _db.query(`
SELECT DISTINCT
근로자.이름, SUM(DATEDIFF(HOUR, 기록.시작, 기록.끝)) AS 총계
FROM 근로자 INNER JOIN 기록
ON 근로자.id = 기록.근로자_id
WHERE 근로자.active = true AND 기록.active = true
GROUP BY 근로자.이름
ORDER BY 총계 ASC
`);
SQL 쿼리 이해하기
  • INNER JOIN: 외래 키 근로자_id를 사용하여 근로자와 기록 테이블을 결합합니다.

  • DATEDIFF(HOUR, 시작, 끝): 시작과 끝 사이의 차이를 시간 단위로 계산합니다.

  • SUM(...) AS 총계: 각 근로자의 모든 시간을 합산합니다.

  • WHERE ... active = true: 삭제되지 않은(활성) 근로자와 기록만 고려하도록 검색을 필터링합니다.

  • GROUP BY 근로자.이름: 각 근로자의 이름별로 합계를 그룹화합니다.

  • ORDER BY 총계 ASC: 최종 결과를 총 근무 시간이 적은 순에서 많은 순으로 정렬합니다.

데이터 처리​

_db.query() 메서드는 Netuno의 내부 형식으로 데이터를 반환합니다.

JSON 형식의 깔끔한 응답을 보내려면 전역 객체 _val.list()(배열용)와 _val.map()(객체용)를 사용하여 이 데이터를 변환해야 합니다.

// 처리된 데이터를 저장할 빈 목록을 만듭니다
const 목록 = _val.list();

// SQL 쿼리에서 반환된 각 레코드를 반복합니다
for (const db기록 of db기록들) {
목록.add(
_val.map()
.set("이름", db기록.getString("이름")) // 이름을 텍스트로 추출합니다
.set("총계", db기록.getInt("총계")) // 총계를 정수로 추출합니다
);
}

사용된 메서드​

리소스설명
_val.list()목록(JS의 Array와 동일)을 만듭니다.
_val.map()키-값 객체(Object 또는 JSON과 동일)를 만듭니다.
.add(...)목록 끝에 새 항목을 추가합니다.
.set("키", 값)맵에 새 속성과 해당 값을 정의합니다.
.getString("컬럼")지정된 컬럼의 값을 텍스트(String) 형식으로 추출합니다.
.getInt("컬럼")지정된 컬럼의 값을 정수(Integer) 형식으로 추출합니다.

데이터 반환​

_out 객체를 사용하여 처리된 목록을 JSON 형식으로 클라이언트에 보냅니다.

// 목록을 JSON 형식의 HTTP 응답으로 보냅니다
_out.json(목록);

실습 예제​

이 마지막 단계에서는 지금까지 배운 모든 개념을 종합하여 동작하는 서비스를 만듭니다.

아래 전체 코드는 데이터베이스에 쿼리를 실행하여 총 근무 시간을 계산하고, 해당 데이터를 JSON으로 형식화하여 반환합니다.

// 1. 활성 근로자별 총 근무 시간을 조회합니다
const db기록들 = _db.query(`
SELECT DISTINCT
근로자.이름, SUM(DATEDIFF(HOUR, 기록.시작, 기록.끝)) AS 총계
FROM 근로자 INNER JOIN 기록
ON 근로자.id = 기록.근로자_id
WHERE 근로자.active = true AND 기록.active = true
GROUP BY 근로자.이름
ORDER BY 총계 ASC
`);

// 2. 응답을 위한 데이터 구조를 만듭니다
const 목록 = _val.list();

// 3. 결과를 처리하고 매핑합니다
for (const db기록 of db기록들) {
목록.add(
_val.map()
.set("이름", db기록.getString("이름"))
.set("총계", db기록.getInt("총계"))
);
}

// 4. 데이터를 JSON 형식으로 반환합니다
_out.json(목록);

서비스 접근​

Netuno에서 서비스를 만들고 구성한 후에는 브라우저에서 직접 사용하고 테스트하거나 다른 애플리케이션과 통합할 준비가 됩니다.

접근 방법​

서비스는 다음을 사용하여 소비할 수 있습니다:

  • 브라우저: GET 메서드를 빠르게 테스트할 때 사용합니다.

  • HTTP 클라이언트: Postman, Insomnia 또는 Thunder Client 같은 도구입니다.

  • 프런트엔드: fetch 요청 또는 Axios 같은 라이브러리를 통해 사용합니다.

URL 구조​

기본적으로 Netuno는 서비스 폴더에 생성된 파일을 웹 주소로 자동 매핑합니다.

기본 포트에서 로컬로 실행 중이라면 주소는 다음 모델을 따릅니다:

http://localhost:9000/services/근로자

라우팅은 어떻게 동작하나요?

Netuno는 파일 시스템 기반의 자동 라우팅 시스템을 사용합니다:

원본 폴더: server/services/ 안의 모든 파일이 경로가 됩니다.

매핑: 근로자.js 파일은 /services/근로자 엔드포인트로 변환됩니다.

확장자: URL에서는 .js 확장자가 생략됩니다. 선택적으로 .netuno 접미사를 사용할 수 있습니다(예: /services/근로자.netuno). 하지만 확장자 없이 접근하는 것이 더 깔끔하므로 권장되는 기본 방식입니다.

HTTP 응답 예시: 데이터베이스에 호환되는 데이터가 있으면 서버가 반환하는 응답은 다음과 유사합니다:

[
{
"이름": "이서연",
"총계": 40
},
{
"이름": "김민준",
"총계": 35
},
{
"이름": "박지우",
"총계": 45
}
]

시스템 전역 객체​

Netuno에서 서비스를 개발하는 동안 데이터베이스 통신, 요청 제어, 정보 출력을 쉽게 해 주는 기본 객체를 자주 사용하게 됩니다.

이 객체들은 서버 스크립트 **( .js 파일)**에서 바로 사용할 수 있도록 미리 구성된 인스턴스입니다. SQL 쿼리나 매개변수 읽기 같은 기본 작업을 위해 외부 라이브러리를 가져올 필요가 없습니다.

객체설명
_db데이터베이스 작업(query, insert, update, delete)을 실행합니다.
_val데이터 구조(list, map)를 생성하고 조작합니다.
_out사용자에게 응답(JSON, HTML...)을 보냅니다.
_req사용자 요청으로 전송된 매개변수(GET, POST)에 접근합니다.
_log서버 콘솔에 오류 또는 디버그 메시지를 기록합니다.

어려움이 있거나 개선 제안이 있으면 연락해 주세요.

저희 팀과 커뮤니티가 기꺼이 도와드릴 준비가 되어 있습니다.

좋은 개발 되세요!