소개
Odoo에서 영업 기회의 우선순위를 정하거나 결제 수단을 선택하고, 상품을 활성/비활성으로 표시할 때 대부분 Selection 필드와 상호작용합니다. 이 필드 타입은 Odoo 모델 설계에서 가장 실용적이면서도 기본이 되는 요소 중 하나로, 제대로 이해해야 데이터 구조가 깔끔하고 예측 가능하게 유지됩니다.
Selection 필드는 사용자가 자유롭게 텍스트를 입력하는 대신 미리 정의된 선택지 중 하나만 고르게 제한합니다. 이런 제한 덕분에 데이터가 일관되게 유지되고, 필터·집계·리포팅이 정확해지며 오타나 표현 차이로 인한 집계 오류를 예방할 수 있습니다.
이 가이드는 Selection 필드가 내부적으로 어떤 값을 저장하는지, 화면에서 어떻게 보이는지부터 Odoo Studio·파이썬 모듈·XML-RPC API로 만들고 확장하는 방법까지 폭넓게 다룹니다. 실제 비즈니스 워크플로 예제와 흔히 저지르는 실수도 함께 정리했습니다.
Odoo의 Selection 필드란 무엇인가
Odoo의 ORM에서는 Selection 필드가 고정된 옵션 목록에서 선택한 문자열(키)을 데이터베이스에 저장합니다. 각 옵션은 데이터에 저장되는 키와 사용자에게 보여지는 레이블의 쌍으로 정의됩니다.
예를 들어 우선순위 필드는 다음 같은 옵션들을 가질 수 있습니다.
priority = fields.Selection([
('0', 'Normal'),
('1', 'Low'),
('2', 'High'),
('3', 'Very High'),
], string='Priority', default='0')
위 코드에서 '0'~'3'은 DB에 저장되는 키이고, Normal·Low·High·Very High는 화면에 표시되는 라벨입니다. 이 키와 라벨의 분리는 나중에 레이블을 바꿔도 기존 데이터가 깨지지 않게 하는 핵심 포인트입니다.
화면에서는 폼 뷰에 드롭다운으로 나타나고, 리스트 뷰에서는 사람이 읽을 수 있는 라벨을 보여줍니다. badge 위젯을 사용하면 각 옵션이 색상 태그로 표현되어 복잡한 리스트에서도 즉시 상태를 파악할 수 있습니다.
Odoo Studio에서 이 타입은 Selection 필드로 불리며, Studio로 만들면 기술명에 x_studio_ 접두사가 붙습니다. 코드나 XML-RPC로 생성할 때는 원하는 기술명을 직접 지정합니다.
필드의 동작 방식
데이터베이스 관점에서 Selection 필드는 PostgreSQL의 VARCHAR 컬럼으로 저장되며, DB에는 항상 키만 저장됩니다. 도메인 필터나 서버 액션을 작성할 때는 사람이 보는 라벨이 아니라 키를 사용해야 한다는 점을 잊지 마세요.
예컨대 우선순위가 높은 리드를 찾는 도메인은 [('priority', '=', '2')]로 작성해야 하며, 'High' 라벨로 필터링하면 결과가 나오지 않습니다.
주요 필드 속성
다음은 Odoo에서 Selection 필드를 정의할 때 자주 확인하는 핵심 속성들입니다.
- selection: 사용 가능한 옵션들의
(key, label)리스트입니다. 또한 메서드 이름(문자열)을 전달하면 런타임에 동적으로 목록을 생성할 수 있습니다. - default: 값이 없을 때 자동으로 들어갈 키입니다. 지정하지 않으면 기본적으로 빈 값으로 시작합니다.
- required: 저장 전에 사용자가 반드시 선택하도록 강제합니다. 기본값과 함께 쓰면 상태 필드에서 흔히 쓰이는 패턴입니다.
- selection_add: 기존 Selection 필드에 옵션을 추가할 때 전체 목록을 다시 정의하지 않고 확장할 수 있게 해줍니다. 기본 필드를 확장할 때 올바른 방식입니다.
- ondelete: 모듈이 제거될 때 추가했던 옵션이 삭제되면 해당 키를 가진 레코드를 어떻게 처리할지 정의합니다.
selection_add와 함께 사용됩니다.
정적 목록과 동적 목록의 차이
보통 옵션 목록은 필드 선언에서 정적으로 정의하지만, selection에 메서드 이름(문자열)을 넣으면 Odoo가 런타임에 그 메서드를 호출해 목록을 만듭니다. 이를 통해 사용자 권한이나 회사 컨텍스트에 따라 다른 선택지를 보여줄 수 있습니다.
contract_type = fields.Selection(
selection='_get_contract_types',
string='Contract Type'
)
def _get_contract_types(self):
if self.env.user.has_group('hr.group_hr_manager'):
return [('permanent', 'Permanent'), ('fixed', 'Fixed Term'), ('interim', 'Interim')]
return [('permanent', 'Permanent'), ('fixed', 'Fixed Term')]
뷰에서의 표시 방식
폼 뷰에서는 기본 드롭다운으로 보이고, 리스트나 칸반에서 상태를 강조하려면 widget="badge"로 색태그를 적용합니다. 옵션 수가 적고 한눈에 전부 보이길 원할 때는 widget="radio"로 라디오 버튼 형태로 표시할 수 있습니다.
Odoo ORM과의 상호작용
ORM에서 Selection 필드를 읽고 쓰는 방법은 단순합니다. 필드에 키 값을 할당하면 프레임워크가 화면용 라벨 매핑을 처리합니다. XML-RPC로 fields_get를 호출하면 필드의 selection 속성에 모든 [key, label] 쌍이 포함되어 외부 도구에서 화면 표시 로직을 구성할 때 유용합니다.
비즈니스 적용 사례
Selection 필드는 표준 Odoo 설치의 거의 모든 모듈에서 광범위하게 사용됩니다. 다음은 실제 비즈니스 워크플로에서 흔히 보는 다섯 가지 예입니다.
CRM: 리드 우선순위와 파이프라인 단계 유형
CRM의 우선순위 필드는 네 단계(예: Normal, Low, High, Very High)로 구성되는 경우가 많습니다. 영업팀은 이를 바탕으로 중요한 리드에 우선순위를 두고 대응합니다. 칸반 색상 표시와 자동화 트리거(예: 우선순위 상향 시 후속 작업 생성)에 직결되기 때문에, 적절한 우선순위 분포를 설정하는 것이 데이터 품질 개선의 출발점입니다.
영업: 결제 조건과 인보이스 정책
제품의 invoice_policy 같은 Selection 필드는 청구 흐름을 좌우합니다(주문 수량 기준 청구 vs. 인도 수량 기준 청구 등). 구독 계약의 청구 모드도 Selection으로 구분되어 선불/후불 처리 로직을 결정합니다. 이처럼 Selection 한 필드가 회계·청구 프로세스의 핵심 규칙을 정의할 수 있습니다.
재고: 제품·로트의 품질 상태
제조나 품질 관리에서는 로트·시리얼·수리 주문의 상태를 Selection으로 관리합니다. 예컨대 수리 오더는 draft → confirmed → under repair → ready → done 같은 상태 전이가 있고, 각 전이는 자동 이메일, 재고 이동, 회계 항목 생성 등을 유발합니다. 즉 Selection 필드는 워크플로의 제어 포인트 역할을 합니다.
회계: 결제 수단과 저널 유형
회계의 저널 유형(journal type)은 sale/purchase/cash/bank 등으로 구분되는 Selection 필드입니다. 이 값에 따라 전표 처리 로직, 사용 가능한 계정, 특정 작업의 허용 여부가 결정되므로 단순한 라벨 이상의 비지니스 규칙을 통제합니다.
인사: 고용 형태와 계약 상태
인사 시스템에서는 고용 유형, 계약 상태, 휴가 요청 상태 등을 Selection으로 관리합니다. 예를 들어 계약 상태가 새로 생성 → 오픈 → 만료/취소로 이동하면, 만료 한 달 전 알림을 보내거나 신규 입사 시 온보딩 체크리스트를 자동 생성하고, 고용 형태에 따라 급여 규칙을 변경할 수 있습니다. Selection이 바로 이런 자동화의 상태 값을 담습니다.
Selection 필드 생성 및 커스터마이징 방법
Selection 필드를 모델에 추가하는 방법은 세 가지 주 경로가 있으며, 필요에 따라 버전 관리나 자동화 관점에서 선택하면 됩니다.
Odoo Studio 사용(코드 불필요)
Odoo Studio는 개발 없이 필드를 추가할 수 있는 저코드 도구입니다. Studio로 Selection 필드를 추가하는 기본 절차는 다음과 같습니다.
- 메인 메뉴에서 Odoo Studio를 엽니다.
- 필드를 추가하려는 폼으로 이동합니다.
- 사이드바에서 Selection 필드를 드래그해 폼에 넣습니다.
- 필드 속성 패널에 각 선택지의 레이블을 입력합니다.
- 필요하면 기본값을 설정하고 필드를 필수로 표시합니다.
- 저장하고 Studio를 닫습니다.
Studio는 각 옵션에 자동 생성 키와 사용자가 입력한 레이블을 함께 저장하며, 필드명에 x_studio_ 접두사를 붙입니다. 현장 분석 회의 중 빠르게 프로토타입을 만들 때 가장 편리한 방법입니다.
커스텀 모듈에서 파이썬 사용
개발자가 모듈을 만들 때는 파이썬 모델 파일에서 Selection을 정의합니다. 여러 환경에 배포하거나 코드로 버전 관리해야 할 경우 권장되는 방식입니다.
from odoo import fields, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
x_delivery_slot = fields.Selection([
('morning', 'Morning (8h - 12h)'),
('afternoon', 'Afternoon (13h - 17h)'),
('evening', 'Evening (18h - 20h)'),
], string='Delivery Slot', default='morning')
필드를 정의한 다음 관련 뷰 XML에 추가하면 인터페이스에 표시됩니다. 모듈 설치나 업그레이드 시 Odoo가 DB 컬럼을 자동 생성합니다.
네이티브 필드에 옵션을 추가할 때는 전체 필드를 재정의하지 말고 selection_add를 사용하세요.
class SaleOrder(models.Model):
_inherit = 'sale.order'
state = fields.Selection(
selection_add=[('custom_approval', 'Pending Approval')],
ondelete={'custom_approval': 'set default'}
)
XML-RPC API 사용
배포 파이프라인이나 원격 구성 스크립트에서 프로그램적으로 필드를 만들려면 XML-RPC API로 Selection 필드를 생성할 수 있습니다.
field_id = models.execute_kw(
ODOO_DB, uid, ODOO_API_KEY,
'ir.model.fields', 'create',
[{
'name': 'x_contract_category',
'field_description': 'Contract Category',
'model_id': model_id,
'ttype': 'selection',
'selection': "[('standard', 'Standard'), ('premium', 'Premium'), ('custom', 'Custom')]",
'state': 'manual',
}]
)
API로 생성할 때는 selection 값을 파이썬 리스트의 문자열 표현으로 전달해야 합니다. 또한 state: manual을 지정하면 Studio나 API로 생성된 수동 필드임을 표시합니다. 원격 구성 자동화에서 필드 생성 작업을 이렇게 처리하는 사례가 많습니다.
모범 사례
1. 의미 있고 안정적인 키를 사용하세요
키는 DB에 저장되고 도메인, 자동화, 서버 로직에서 사용됩니다. 나중에 바꿀 일이 없도록 명확한 키를 선택하세요. 소문자 짧은 문자열이 좋습니다(예: 'draft', 'confirmed', 'cancelled'). 숫자 키는 가독성을 떨어뜨리므로 실제 순서가 중요한 경우가 아니면 피하세요.
2. 목록은 짧고 포괄적으로 유지하세요
옵션이 8~10개를 넘으면 필드가 과도한 역할을 하는 신호일 수 있습니다. 자주 늘어난다면 설정 모델(Many2one)로 대체하는 것을 고려하세요. 관리 모델을 만들면 사용자가 직접 옵션을 추가/수정할 수 있어 개발자 개입을 줄일 수 있습니다.
3. 필수 필드에는 항상 기본값을 설정하세요
Selection이 required이면 합리적인 기본값도 함께 정하세요. 그렇지 않으면 API나 임포트로 레코드를 생성할 때 검증 오류가 발생할 수 있습니다. 기본값은 가장 흔한 상태나 덜 구속적인 상태로 설정하는 것이 일반적입니다.
4. 네이티브 필드 확장에는 selection_add를 사용하세요
기존 Odoo 필드에 옵션을 추가할 때는 전체 필드를 재정의하지 말고 selection_add를 쓰는 것이 안전합니다. 또한 모듈 제거 시 행동을 제어하기 위해 ondelete를 함께 설정하세요.
5. 리스트 뷰 가독성을 위해 badge 위젯을 사용하세요
리스트나 칸반에서는 기본 텍스트 표현보다 widget="badge"를 사용해 색 태그로 표시하면 스캔성이 훨씬 좋아집니다. 상태 필드처럼 시각적으로 빠르게 구분해야 할 때 특히 유용합니다.
자주 발생하는 실수
키를 변경하면 기존 데이터가 깨집니다
레이블은 언제든 바꿀 수 있지만 키는 레코드가 존재하면 절대 바꾸면 안 됩니다. 키를 바꾸면 기존 레코드는 비어 있거나 잘못된 값으로 보이고, 키 기반 도메인 필터와 자동화가 조용히 작동을 멈춥니다. 키를 변경해야 할 때는 반드시 데이터 마이그레이션 스크립트로 기존 값을 먼저 업데이트하세요.
옵션을 제거하면 그 키를 가진 레코드가 고아가 됩니다
목록에서 옵션을 제거할 때 해당 키를 가진 레코드가 남아있으면 값이 깨진 상태로 표시됩니다. 옵션을 삭제하기 전에 그 키를 사용하는 레코드를 찾아 유효한 값으로 업데이트하거나 보관해야 합니다. 데이터 정리 과정에서 흔히 발생하는 문제입니다.
라벨로 도메인 필터를 작성하는 실수
비기술 사용자들이 자동화 규칙을 만들 때 라벨로 필터를 지정하면 검색 결과가 0이 되지만 오류는 발생하지 않아 문제 원인 파악이 어렵습니다. 도메인을 작성하기 전에 필드 정의에서 어떤 키가 어떤 라벨에 대응하는지 반드시 확인하세요.
Many2one이 더 적절한데 Selection을 쓴 경우
옵션이 자주 바뀌거나 사용자가 직접 관리해야 하거나 옵션에 색·순서·계정 등 추가 속성이 필요한 경우에는 Many2one으로 구성 모델을 만들어 연결하는 편이 장기 유지관리에 유리합니다. Selection은 안정적이고 개발자가 관리하는 목록에 적합합니다.
서버 로직에서 빈 값을 처리하지 않는 문제
필수가 아닌 Selection은 값이 선택되지 않으면 False가 될 수 있습니다. 서버 액션이나 파이썬 코드에서 문자열과 비교하기 전에 False 케이스를 처리하지 않으면 예기치 않은 동작이나 오류가 발생할 수 있으니 빈 값 처리를 항상 명시하세요.
결론
Selection 필드는 단순해 보이지만 내부 동작을 이해하면 깊이가 있는 도구입니다. 키와 라벨의 차이, selection_add와 재정의의 차이, 언제 Many2one이 더 나은지 아는 것은 잘 설계된 Odoo 구현과 향후 문제를 일으키는 구현을 가르는 중요한 기준입니다.
Odoo Studio로 계약 유형을 추가하든, 커스텀 파이썬으로 배달 시간 슬롯을 정의하든, API로 품질 상태를 만들든 이 가이드의 패턴을 따르면 상황에 맞는 올바른 결정을 내리는 데 도움이 될 것입니다.
Odoo 데이터 모델에서 Selection 필드는 출처에서부터 데이터 품질을 지키는 주요 수단 중 하나입니다. 적절히 사용하면 레코드가 깨끗해지고 리포트가 정확해지며 자동화가 신뢰할 만해집니다.
저희 Dasolo는 기업들이 모든 부서에서 Odoo를 구현하고 맞춤화하며 최적화하도록 돕습니다. 깔끔한 데이터 모델 설계, 워크플로 필드 추가, 또는 모듈 전개 등 어떤 도움이 필요하든 지원해 드립니다. 문의하기 귀사의 Odoo 프로젝트에 관해 이야기해 보겠습니다.