GitLab의 URL
GitLab v19.5요약
GitLab은 URL 생성과 해석 방식에 영향을 주는 여러 배포 구성을 지원합니다. 모든 배포 구성에서 URL 이 올바르게 동작하도록 아래 가이드라인을 따릅니다. URL 생성에는 Rails 경로 및 URL 헬퍼를 사용합니다.
개요#
GitLab은 URL 생성과 해석 방식에 영향을 주는 여러 배포 구성을 지원합니다. 하드코딩된 URL 이나 절대 URL을 사용하면 다음과 같은 상황에서 기능이 동작하지 않을 수 있습니다.
- 상대 URL 설치 - 경로 접두사를 사용하는 GitLab 배포입니다. 예를 들면
https://example.com/gitlab/입니다. - Geo 배포 - URL 이 서로 다른 기본 사이트와 보조 사이트
- 조직 범위 라우트 - 조직 컨텍스트에 따라 달라지는 동적 URL 구조
모든 배포 구성에서 URL 이 올바르게 동작하도록 아래 가이드라인을 따릅니다.
일반 가이드라인#
- URL 생성의 단일 진실 공급원(Single Source Of Truth, SSOT)으로 Rails를 사용합니다. 프론트엔드에서 URL 이 필요하면 Rails에서 생성해 프론트엔드로 전달합니다.
- 애플리케이션 내부 링크에는 상대 URL을 사용합니다. 절대 URL은 다음 경우에만 사용합니다.
- 이메일용 링크를 생성하는 경우.
- 외부 서비스용 URL을 구성하는 경우.
- 웹 인터페이스 밖에서도 동작해야 하는 클론 또는 다운로드 URL을 만드는 경우.
백엔드 가이드라인#
경로 및 URL 헬퍼#
URL 생성에는 Rails 경로 및 URL 헬퍼를 사용합니다.
- 애플리케이션 내부 링크에는 모두
*_path헬퍼를 사용합니다. *_url헬퍼는 다음과 같이 애플리케이션 밖에서 사용되어야 하는 링크에만 사용합니다.- 이메일용 링크.
- 외부 서비스용 URL.
- 웹 인터페이스 밖에서도 동작해야 하는 클론 또는 다운로드 URL.
# Correct - Relative path
redirect_to project_path(@project)
# Incorrect - Absolute URL
redirect_to project_url(@project)
프론트엔드 가이드라인#
JavaScript 및 Vue#
JavaScript 나 Vue에서 URL을 하드코딩하거나 조립하지 않습니다. URL은 Rails에서 생성해 데이터 속성, GraphQL 쿼리, REST API를 통해 프론트엔드로 전달합니다.
// Incorrect - Do not construct URLs on the frontend
const endpoint = `${gon.relative_url_root}/${projectPath}/-/refs`;
올바른 대안은 다음 섹션에서 설명합니다.
JavaScript 경로 헬퍼#
GitLab은 js-routes를 사용해 백엔드 경로 헬퍼와 대응되는 JavaScript 경로 헬퍼를 생성합니다. 이 헬퍼는 app/assets/javascripts/lib/utils/path_helpers 디렉터리에 있습니다. 경로 헬퍼는 상대 URL 설치를 지원하며, 이는 app/assets/javascripts/behaviors/configure_path_helpers.js에서 전역으로 구성됩니다.
올바른 경로 헬퍼 찾기#
올바른 경로 헬퍼를 찾는 가장 쉬운 방법은 필요한 경로의 일부 문자열로 app/assets/javascripts/lib/utils/path_helpers 디렉터리를 검색하는 것입니다. 예를 들어 /<project path>/-/snippets/new가 필요하다면 프로젝트 경로를 파라미터로 받는 헬퍼를 찾을 때까지 /-/snippets/new 또는 new_project_snippet_path를 검색합니다.
경로 헬퍼는 Rails에서 정의된 위치에 따라 정리되어 있습니다. 예를 들어 config/routes/project.rb에 정의된 라우트는 프론트엔드에서 app/assets/javascripts/lib/utils/path_helpers/project.js로 제공됩니다. EE 전용 경로 헬퍼도 마찬가지입니다. 예를 들어 ee/config/routes/project.rb에 정의된 라우트는 프론트엔드에서 ee/app/assets/javascripts/lib/utils/path_helpers/project.js로 제공됩니다.
더 복잡한 경우에는 bin/rails routes -c name_of_controller --expanded를 실행해 특정 컨트롤러의 라우트를 확인할 수 있습니다. 예를 들어 프로젝트 스니펫의 라우트를 보려면 bin/rails routes -c projects/snippets --expanded를 실행합니다. 출력은 다음과 같습니다.
--[ Route 6 ]--------------------------------------------------------------------------------------------------------------
Prefix | new_snippet
Verb | GET
URI | /-/snippets/new(.:format)
Controller#Action | snippets#new
Source Location | /config/routes/snippets.rb:3
위 예시에서는 newSnippetPath가 됩니다. Source Location은 경로 헬퍼가 어느 파일에 있는지 알려 줍니다. 위 예시에서는 app/assets/javascripts/lib/utils/path_helpers/snippets.js에 있습니다.
Rails 라우트를 갱신할 때는 해당 라우트의 JavaScript 경로 헬퍼를 생성해 커밋해야 합니다. 이를 위해 bin/rake gitlab:js:routes를 실행합니다.
프로젝트 경로 헬퍼#
사용성을 높이고 config/routes.rb#L368의 Rails 동작과 맞추기 위해 프로젝트 경로 헬퍼는 축약된 이름과 인수를 사용합니다. namespacePath와 projectPath를 따로 받는 newNamespaceProjectSnippetPath 대신, projectFullPath 인수 하나를 받는 newProjectSnippetPath를 사용합니다. 예시는 경로 헬퍼 사용을 참고합니다.
경로 헬퍼 사용#
<script>
import { GlLink } from '@gitlab/ui';
import { newProjectSnippetPath } from '~/lib/utils/path_helpers/project';
import { newSnippetPath } from '~/lib/utils/path_helpers/snippets';
export default {
components: {
GlLink
},
props: {
project: {
type: Object,
required: true,
}
},
methods: {
newSnippetPath,
newProjectSnippetPath,
}
};
</script>
<template>
<div>
<gl-link :href="newSnippetPath()">{{ __('New snippet') }}</gl-link>
<gl-link :href="newProjectSnippetPath(project.fullPath)">{{ __('New project snippet') }}</gl-link>
</div>
</template>
경로 헬퍼 옵션#
모든 경로 헬퍼는 마지막 인수로 선택적 options 객체를 받습니다. 이 객체는 라우트 파라미터와
별개입니다. 생성된 각 헬퍼는 이를
@param {object | undefined} options로 문서화합니다.
options 객체는 네 종류의 키를 받습니다.
format: 선택적 형식 세그먼트를 채웁니다. 예를 들어exploreCatalogIndexPath({ format: 'json' })는/explore/catalog.json을 반환합니다.- 예약된 URL 옵션:
anchor,trailing_slash,subdomain,host,port,protocol,script_name입니다. 이 옵션은 생성되는 URL의 형태를 정합니다. 예를 들어anchor는#fragment를 덧붙입니다. organizationPath: 하위에 중첩할 조직의 경로입니다. 조직 데이터 컨텍스트 밖에 있을 때 URL 파라미터에서 경로를 제거하려면null을 전달합니다. 조직 범위 경로를 참고합니다.- 쿼리 파라미터: 그 밖의 키는 모두 쿼리 문자열로 직렬화됩니다. 예를 들어
exploreCatalogIndexPath({ scope: 'all' })는/explore/catalog?scope=all을 반환합니다.
객체를 라우트 파라미터가 아니라 options로 처리하도록 강제하려면 _options 키를
true로 설정합니다. 이는 라우트 파라미터 이름이 예약된 옵션과 충돌할 때 필요합니다.
자세한 내용은 js-routes 문서를 참고합니다.
조직 범위 경로#
대부분의 전역 라우트에는 /o/:organization_path/ 아래에 중첩된 대응 라우트가 있습니다. 경로 헬퍼는
백엔드의 Routing::OrganizationsHelper::MappedHelpers.scoped_path_for와 동일한 규칙으로
어느 형태를 반환할지 다음 순서로 결정합니다.
- 현재 실행이 조직 컨텍스트 안에 있다면 데이터 컨텍스트가 적용됩니다. 이 조건이 항상 우선하며
호출자나 페이지 URL로 재정의할 수 없습니다. 홈 조직이 격리된 사용자에게 중요합니다. 그런
사용자는 해당 조직 밖에 존재하지 않으므로 항상 중첩된 경로에
머무릅니다. 프론트엔드에서는
gon.data_context_organization_path를 읽습니다. organizationPath옵션입니다. 중첩되지 않은 전역 경로를 강제하려면organizationPath: null을 전달합니다.- 현재 페이지의 URL 이 이미
/o/:organization_path/아래에 중첩되어 있는 경우입니다. 프론트엔드에서는gon.organization_path를 읽습니다.
이 중 어느 것도 해당하지 않으면 헬퍼는 전역 경로를 반환합니다.
예를 들어 페이지가 /o/acme/ 아래에 중첩되어 있거나 데이터 컨텍스트가 acme 이면
editGroupPath('foo/bar')는 /o/acme/groups/foo/bar/-/edit을 반환합니다. 데이터 컨텍스트가 설정되지 않은
상태에서 전역 경로를 강제하려면 organizationPath: null을 전달합니다.
import { editGroupPath } from '~/lib/utils/path_helpers/group';
editGroupPath('foo/bar', { organizationPath: null });
// => '/groups/foo/bar/-/edit'
조직 범위 대응 라우트가 없는 라우트는 중첩되지 않습니다. /admin의 인스턴스 관리자와
/o/:organization_path/admin의 조직 관리자처럼 서로 다른 컨트롤러로 해석되는 라우트 쌍도
마찬가지입니다. 이들은 이름 규칙만 공유하는 별개의 기능입니다. 현재 페이지의 URL도 데이터
컨텍스트도 이러한 라우트에는 영향을 주지 않습니다.
REST API 경로 헬퍼#
/api/:version/groups/:id와 같은 REST API 경로에는 JavaScript 경로 헬퍼가 생성되지 않습니다. REST API 경로에는 app/assets/javascripts/rest_api.js의 재사용 가능한 패턴과 유틸리티를 사용합니다.
데이터 속성으로 URL 전달#
이 방식도 여전히 사용할 수 있지만 경로 헬퍼 사용을 권장합니다.
data-* 속성을 사용해 Rails에서 프론트엔드로 URL을 전달합니다. 예를 들면 다음과 같습니다.
#js-my-app{ data: { base_path: project_iteration_cadences_path(project) } }
const initMyApp = () => {
const el = document.getElementById('js-my-app');
if (!el) return false;
const { basePath } = el.dataset
}
GraphQL 쿼리#
webUrl 필드는 사용하지 않습니다. 대신 webPath 나 adminEditPath와 같은 다른 상대 URL
필드를 사용합니다. 해당 GraphQL 타입에 webPath 필드가 없다면 추가합니다. 새 GraphQL 필드를
추가할 때는 업데이트 간 호환성에
유의합니다.
REST API#
web_url 필드는 사용하지 않습니다. 대신 web_path 나 admin_edit_path와 같은 다른 상대 URL
필드를 사용합니다. REST API 엔드포인트에 web_path가 없다면 추가합니다.
REST API 엔드포인트에 새 필드를 추가할 때는 업데이트 간 호환성에
유의합니다.
Vue 라우터#
Vue Router를 올바르게 구성하는 방법은 Vue Router를 참고합니다.
HAML 템플릿#
*_url 헬퍼 대신 *_path 헬퍼를 사용합니다.
-# Correct - Relative URL
= link_to _('Dashboard'), dashboard_projects_path
-# Incorrect - Absolute URL
= link_to _('Dashboard'), dashboard_projects_url
도움말 페이지 링크#
도움말 페이지에 링크하는 방법은 /help 링크를 참고합니다.