ตัวแปรสภาพแวดล้อมคือค่าที่เปลี่ยนแปลงได้ซึ่งส่งให้แอปพลิเคชันเมื่อเริ่มทำงานเพื่อกำหนดค่าพฤติกรรมโดยไม่ต้องเปลี่ยนโค้ด ตัวแปรเหล่านี้ช่วยแยกการกำหนดค่าสำหรับการพัฒนา การทดสอบ และการผลิต ตาม Twelve-Factor App, 2025 การกำหนดค่าควรถูกเก็บไว้ในตัวแปรสภาพแวดล้อม ไม่ใช่ในโค้ด ตัวแปรสภาพแวดล้อม ช่วยให้การจัดการคีย์ API, URL แบ็กเอนด์ และแฟลกคุณสมบัติเป็นไปอย่างปลอดภัย
ประเด็นสำคัญ
ตัวแปรสภาพแวดล้อมคือคู่ คีย์-ค่า ที่กระบวนการของแอปพลิเคชันสามารถเข้าถึงได้ผ่าน API ของระบบปฏิบัติการ ค่าเหล่านี้จะถูกส่งให้กระบวนการเมื่อสร้างขึ้นและมีอยู่เฉพาะในช่วงรันไทม์เท่านั้น ซึ่งแตกต่างจากพารามิเตอร์การกำหนดค่าที่ฝังอยู่ในซอร์สโค้ด ตัวแปรสภาพแวดล้อมไม่ต้องการการคอมไพล์ใหม่เพื่อเปลี่ยนค่า นี่คือหลักการพื้นฐานของ Twelve-Factor App ที่รับประกันการแยกส่วนระหว่างโค้ดและการกำหนดค่าอย่างชัดเจน
ในการพัฒนาโมบาย ตัวแปรสภาพแวดล้อมแก้ปัญหาการกำหนดค่าที่แตกต่างกันสำหรับสภาพแวดล้อมต่างๆ: นักพัฒนาใช้เซิร์ฟเวอร์ภายใน ผู้ทดสอบใช้ staging และผู้ใช้ใช้โปรดักชัน แทนที่จะเก็บ URL แบ็กเอนด์สามรายการในโค้ดพร้อมคำสั่งเงื่อนไข if-else นักพัฒนาส่ง URL เดียวผ่านตัวแปรสภาพแวดล้อมในเวลาสร้าง ซึ่งช่วยให้โค้ดง่ายขึ้นและกำจัดความเสี่ยงในการใช้เซิร์ฟเวอร์โปรดักชันโดยไม่ตั้งใจในสภาพแวดล้อมทดสอบ
ข้อได้เปรียบหลักคือ ความปลอดภัย: ข้อมูลที่ละเอียดอ่อนไม่รั่วไหลไปยังรีพอสิทอรีโค้ด คีย์ API, ความลับของ Firebase, โทเค็นการเข้าถึงแบ็กเอนด์ และใบรับรองจะถูกโหลดผ่าน CI/CD โดยตรงไปยังสภาพแวดล้อมการสร้าง หากผู้โจมตีเข้าถึงรีพอสิทอรีโค้ดได้ พวกเขาจะไม่พบความลับที่นั่น เนื่องจากถูกเก็บไว้ในพื้นที่เก็บข้อมูลที่ป้องกันของระบบ CI และจะถูกส่งเฉพาะในขั้นตอนการสร้างไฟล์ไบนารีเท่านั้น
โปรเจกต์โมบายมีอย่างน้อยสามสภาพแวดล้อม: การพัฒนา, staging และโปรดักชัน แต่ละสภาพแวดล้อมต้องการชุด การกำหนดค่า ของตัวเอง: URL เซิร์ฟเวอร์, ชื่อแพ็กเกจ, รูปแบบลายเซ็น และใบรับรองการแจ้งเตือนแบบพุช หากไม่มีตัวแปรสภาพแวดล้อม นักพัฒนาต้องเปลี่ยนการกำหนดค่าด้วยตนเองก่อนทุกการสร้าง ซึ่งนำไปสู่ข้อผิดพลาด: คีย์โปรดักชันที่ถูกลืมในการสร้างทดสอบอาจส่งการแจ้งเตือนไปยังผู้ใช้จริงหรือสิ้นเปลือง API แบบชำระเงิน
ตัวแปรสภาพแวดล้อมช่วยให้สลับ แบ็กเอนด์ ได้โดยไม่ต้องเปลี่ยนโค้ด: เพียงเปลี่ยนค่าในตัวแปร API_BASE_URL แฟลกคุณสมบัติถูกจัดการผ่านตัวแปรเช่น FEATURE_CHAT_ENABLED=true ซึ่งช่วยให้เปิดใช้คุณสมบัติใหม่ใน staging โดยไม่กระทบต่อโปรดักชัน แต่ละสภาพแวดล้อมมีไฟล์ .env ของตัวเองที่โหลดในเวลาสร้าง
class AppConfig {
static final String apiBaseUrl =
const String.fromEnvironment('API_BASE_URL',
defaultValue: 'http://localhost:8080');
}
คีย์ที่ถูกฮาร์ดโค้ดเป็น ช่องโหว่ ที่พบบ่อยในแอปพลิเคชันโมบาย ผู้โจมตีดีคอมไพล์ APK หรือ IPA โดยใช้เครื่องมือเช่น jadx หรือ Hopper และดึงความลับจากไฟล์ไบนารี แม้การทำให้โค้ดสับสนก็ไม่สามารถป้องกันสตริงลิเทอรัลได้ — สามารถพบได้ง่ายในโค้ดหลังการดีคอมไพล์ ตัวแปรสภาพแวดล้อมแก้ปัญหานี้โดยส่งคีย์ในเวลาสร้างผ่าน CI/CD ซึ่งจะถูกซ่อนในล็อก
object Config {
val apiKey: String =
System.getenv("API_KEY") ?: throw
IllegalStateException("API_KEY not set")
}
ตัวแปรสภาพแวดล้อมผสานรวมกับไปป์ไลน์การสร้าง: GitHub Actions, GitLab CI, Bitrise และ CircleCI รองรับ ตัวแปรลับ ที่ไม่แสดงในล็อก ในเวลาสร้าง CI จะแทนที่ค่าที่เหมาะสมตามแบรนช์หรือแท็ก: สำหรับแบรนช์ develop ใช้ staging, สำหรับแท็ก v* ใช้โปรดักชัน ซึ่งช่วยให้กระบวนการเป็นอัตโนมัติและกำจัดปัจจัยมนุษย์ รับประกันว่าการสร้างแต่ละครั้งจะได้รับการกำหนดค่าที่ถูกต้อง
ไฟล์ .env เป็นวิธีมาตรฐานในการเก็บตัวแปรสภาพแวดล้อมในรูปแบบ KEY=VALUE ไม่รวมอยู่ในรีพอสิทอรี แต่จะเพิ่ม .env.example พร้อมเทมเพลตของตัวแปรทั้งหมดและค่าว่างแทน นักพัฒนาแต่ละคนสร้างไฟล์ .env ของตัวเองด้วยการตั้งค่าภายในโดยไม่กระทบต่อการกำหนดค่าของสมาชิกทีมคนอื่น ใช้ไฟล์แยกสำหรับสภาพแวดล้อมต่างๆ: .env.dev, .env.stage, .env.prod
# .env.example — เทมเพลตสำหรับนักพัฒนา
API_BASE_URL=http://localhost:8080
FEATURE_CHAT_ENABLED=true
SENTRY_DSN=
สำหรับโปรเจกต์โมบาย มี ไลบรารี เฉพาะทางสำหรับทำงานกับไฟล์ .env:
การตั้งค่า การแตกแบรนช์ ใน CI/CD ช่วยให้แทนที่ไฟล์ .env ต่างๆ: .env.dev สำหรับเซิร์ฟเวอร์ทดสอบ, .env.stage สำหรับก่อนวางจำหน่าย และ .env.prod สำหรับเผยแพร่ในร้านค้าแอป ไฟล์ที่มีความลับจะถูกโหลดจากพื้นที่เก็บข้อมูลที่ปลอดภัย (Vault, AWS Secrets Manager) และไม่ถูกเก็บในรีพอสิทอรี ซึ่งรับประกันว่าแม้ระบบควบคุมเวอร์ชันถูกบุกรุก ความลับก็ยังคงได้รับการปกป้อง
ระบบนิเวศ iOS ใช้ไฟล์ xcconfig เพื่อจัดการตัวแปรในระดับการสร้าง ไฟล์เหล่านี้เชื่อมต่อกับสคีมา Xcode และอนุญาตให้แทนที่ค่าสำหรับการกำหนดค่า Debug และ Release ไฟล์ xcconfig รองรับการสืบทอด: คุณสามารถสร้างไฟล์ฐานที่มีการตั้งค่าร่วมและไฟล์เฉพาะสำหรับแต่ละสภาพแวดล้อม
ไฟล์ xcconfig เก็บตัวแปรในรูปแบบ KEY = VALUE และเชื่อมต่อกับสคีมาการสร้างใน Xcode ผ่านการตั้งค่า Configuration ตัวแปรจาก xcconfig พร้อมใช้งานใน Info.plist ผ่านไวยากรณ์ $(ชื่อ_ตัวแปร) ซึ่งช่วยให้ใช้ตัวระบุบันเดิลและชื่อแอปที่แตกต่างกันสำหรับสคีมาที่ต่างกัน เพื่อการระบุสภาพแวดล้อมอย่างรวดเร็ว จะเพิ่มส่วนต่อท้าย Dev หรือ Staging ต่อท้ายชื่อแอป
# Config/Dev.xcconfig — การกำหนดค่าการพัฒนา
API_BASE_URL = http://localhost:3000
BUNDLE_ID_SUFFIX = .dev
APP_DISPLAY_NAME = MyApp Dev
สำหรับการเข้าถึงตัวแปรในรันไทม์ใน iOS ใช้ไฟล์ Configuration.swift ซึ่งอ่านค่าจาก Info.plist ผ่าน Bundle.main.object(forInfoDictionaryKey:) วิธีการนี้รับประกันว่าตัวแปรถูกกำหนดในเวลาสร้างและพร้อมใช้งานสำหรับแอปพลิเคชันทันทีหลังจากเริ่มต้น ค่าจะถูกอ่านครั้งเดียวระหว่างการเริ่มต้นโมดูลและถูกแคชไว้เพื่อการเข้าถึงที่รวดเร็วตลอดวงจรชีวิตของแอปพลิเคชัน
enum AppEnvironment {
static var apiBaseURL: URL {
guard let urlString = Bundle.main
.object(forInfoDictionaryKey: "API_BASE_URL"),
let url = URL(string: urlString as! String)
else { fatalError("API_BASE_URL is not configured") }
return url
}
static var isChatEnabled: Bool {
Bundle.main.object(
forInfoDictionaryKey: "FEATURE_CHAT_ENABLED"
) as? Bool ?? false
}
}
Android รองรับตัวแปรสภาพแวดล้อมผ่าน BuildConfig — คลาสที่สร้างขึ้นโดยอัตโนมัติซึ่งฟิลด์ถูกกำหนดในไฟล์ build.gradle ของโมดูล BuildConfig ถูกสร้างในเวลาคอมไพล์สำหรับแต่ละ flavor และประเภทการสร้างแยกกัน ซึ่งช่วยให้มีค่าที่แตกต่างกันสำหรับ debug และ release โดยไม่ต้องใช้โอเปอเรเตอร์เงื่อนไขในโค้ด ช่วยเพิ่มประสิทธิภาพและความปลอดภัย
ฟิลด์ BuildConfig ถูกกำหนดผ่าน buildConfigField ใน defaultConfig หรือใน buildTypes เฉพาะ มีการสร้าง buildType หรือ productFlavor แยกสำหรับแต่ละสภาพแวดล้อม ซึ่งรับประกันการแยกการกำหนดค่าที่เข้มงวด: debug ใช้เซิร์ฟเวอร์ภายใน, release ใช้โปรดักชัน ฟิลด์ BuildConfig ถูกระบุชนิดแบบสแตติก ซึ่งกำจัดข้อผิดพลาดเมื่อเข้าถึงในโค้ด
// build.gradle (Module: app)
android {
defaultConfig {
buildConfigField "String", "API_BASE_URL",
"\"http://localhost:8080\""
}
buildTypes {
debug {
buildConfigField "String", "API_BASE_URL",
"\"http://dev.api.itsectr.com\""
}
release {
buildConfigField "String", "API_BASE_URL",
"\"https://api.itsectr.com\""
}
}
}
ไฟล์ gradle.properties ในรูทโปรเจกต์เก็บตัวแปร Gradle ส่วนกลาง ซึ่งพร้อมใช้งานในทุกโมดูลผ่านไวยากรณ์ $variableName และใช้สำหรับระบุเวอร์ชัน dependencies, แฟลกการสร้าง และคีย์ API แตกต่างจาก BuildConfig, gradle.properties ทำงานเฉพาะในขั้นตอนการกำหนดค่า Gradle ไม่ใช่ในรันไทม์ของแอปพลิเคชัน ดังนั้น รหัสผ่านและคีย์ API ที่ระบุใน gradle.properties จะไม่ปรากฏในโค้ดที่ถูกดีคอมไพล์ เนื่องจากใช้สำหรับสร้าง BuildConfig ในเวลาคอมไพล์เท่านั้น
# gradle.properties
SENTRY_DSN=https://key@sentry.io/project
MAPS_API_KEY=AIzaSy...
สำหรับการถ่ายโอนความลับอย่างปลอดภัยในโปรเจกต์ Android แนะนำให้ใช้ local.properties (แยกจาก VCS) หรือโหลดค่าจากตัวแปร CI/CD ใน build.gradle ผ่าน System.getenv() ซึ่งรับประกันว่าคีย์จะไม่รั่วไหลไปยังรีพอสิทอรี เมื่อเผยแพร่ใน Google Play Console ตรวจสอบให้แน่ใจว่าคีย์ debug ทั้งหมดถูกแทนที่ด้วยเวอร์ชันโปรดักชันผ่าน buildTypes หรือ productFlavors ที่แตกต่างกันด้วยค่า BuildConfig ที่สอดคล้องกัน
คำถามที่พบบ่อย
ได้, Flutter รองรับตัวแปรสภาพแวดล้อมผ่านแพ็กเกจ flutter_dotenv สำหรับการเข้าถึงในรันไทม์ หรือผ่านช่องทางเนทีฟสำหรับตัวแปรแพลตฟอร์ม Dart ยังมีคอนสตรักเตอร์ String.fromEnvironment สำหรับส่งค่าในเวลาคอมไพล์ผ่าน --dart-define ซึ่งเป็นวิธีที่แนะนำสำหรับโปรเจกต์ Flutter
BuildConfig คือคลาส Java ที่มีฟิลด์ระบุชนิดซึ่งสร้างในเวลาคอมไพล์สำหรับแต่ละ buildType และ flavor gradle.properties คือไฟล์ข้อความที่มีคู่คีย์-ค่าที่โมดูล Gradle ทั้งหมดสามารถเข้าถึงได้ในขั้นตอนการกำหนดค่าการสร้าง BuildConfig ทำงานในรันไทม์ของแอปพลิเคชัน, gradle.properties — เฉพาะในสคริปต์ Gradle
เพิ่ม .env ในไฟล์ .gitignore ของรีพอสิทอรีของคุณ ในรีพอสิทอรี ให้คอมมิตเฉพาะ .env.example ที่มีค่าว่างและคำอธิบายของแต่ละตัวแปร สำหรับ CI/CD ให้ใช้ความลับที่เข้ารหัสในการตั้งค่า GitHub Actions, GitLab CI หรือ Bitrise ซึ่งถูกซ่อนในล็อกและไม่สามารถอ่านได้หลังจากสร้างเสร็จ
ระบบ CI ส่วนใหญ่รองรับ ตัวแปรสภาพแวดล้อมลับ ใน GitHub Actions คือ Secrets, ใน GitLab CI — CI/CD Variables, ใน Bitrise — Secrets ในเวลาสร้าง ตัวแปรเหล่านี้จะถูกส่งไปยังสคริปต์สร้างผ่าน process.env หรือ System.getenv() ตัวแปรลับจะไม่แสดงในล็อกการสร้างและไม่สามารถใช้ได้ในฟอร์กของรีพอสิทอรี
แฟลกคุณสมบัติ คือตัวแปรบูลีนที่ควบคุมการเปิดหรือปิดการทำงานของฟีเจอร์โดยไม่ต้องคอมไพล์โค้ดใหม่ ตัวอย่าง: FEATURE_NEW_PAYMENT=true เปิดระบบชำระเงินใหม่ใน staging สำหรับการทดสอบ ในโปรดักชัน แฟลกเดียวกันถูกตั้งเป็น false จนกว่าแบ็กเอนด์จะถูกปรับใช้อย่างสมบูรณ์ ซึ่งช่วยให้ปรับใช้การเปลี่ยนแปลงอย่างปลอดภัยเป็นขั้นตอนและย้อนกลับได้หากมีปัญหา
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม