diff --git a/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/ArrowRight.imageset/Contents.json b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/ArrowRight.imageset/Contents.json
new file mode 100644
index 0000000..2859e21
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/ArrowRight.imageset/Contents.json
@@ -0,0 +1,16 @@
+{
+ "images" : [
+ {
+ "filename" : "arrow_right.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "preserves-vector-representation" : true,
+ "template-rendering-intent" : "template"
+ }
+}
diff --git a/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/ArrowRight.imageset/arrow_right.svg b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/ArrowRight.imageset/arrow_right.svg
new file mode 100644
index 0000000..b9d4778
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/ArrowRight.imageset/arrow_right.svg
@@ -0,0 +1,3 @@
+
diff --git a/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/Contents.json b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/Contents.json
new file mode 100644
index 0000000..73c0059
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/MissionLogo.imageset/Background.svg b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/MissionLogo.imageset/Background.svg
new file mode 100644
index 0000000..3dd1231
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/MissionLogo.imageset/Background.svg
@@ -0,0 +1,12 @@
+
diff --git a/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/MissionLogo.imageset/Contents.json b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/MissionLogo.imageset/Contents.json
new file mode 100644
index 0000000..6182ee5
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/MissionLogo.imageset/Contents.json
@@ -0,0 +1,16 @@
+{
+ "images" : [
+ {
+ "filename" : "Background.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "preserves-vector-representation" : true,
+ "template-rendering-intent" : "template"
+ }
+}
diff --git a/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamAgreementLogo.imageset/Contents.json b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamAgreementLogo.imageset/Contents.json
new file mode 100644
index 0000000..5e1282e
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamAgreementLogo.imageset/Contents.json
@@ -0,0 +1,16 @@
+{
+ "images" : [
+ {
+ "filename" : "team_agreement_logo.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "preserves-vector-representation" : true,
+ "template-rendering-intent" : "original"
+ }
+}
diff --git a/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamAgreementLogo.imageset/team_agreement_logo.svg b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamAgreementLogo.imageset/team_agreement_logo.svg
new file mode 100644
index 0000000..5641c87
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamAgreementLogo.imageset/team_agreement_logo.svg
@@ -0,0 +1,5 @@
+
diff --git a/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamBlogLogo.imageset/Contents.json b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamBlogLogo.imageset/Contents.json
new file mode 100644
index 0000000..0aab595
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamBlogLogo.imageset/Contents.json
@@ -0,0 +1,16 @@
+{
+ "images" : [
+ {
+ "filename" : "team_blog_logo.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "preserves-vector-representation" : true,
+ "template-rendering-intent" : "original"
+ }
+}
diff --git a/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamBlogLogo.imageset/team_blog_logo.svg b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamBlogLogo.imageset/team_blog_logo.svg
new file mode 100644
index 0000000..ce017f3
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamBlogLogo.imageset/team_blog_logo.svg
@@ -0,0 +1,6 @@
+
diff --git a/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamIntroductionLogo.imageset/Contents.json b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamIntroductionLogo.imageset/Contents.json
new file mode 100644
index 0000000..d73e4e2
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamIntroductionLogo.imageset/Contents.json
@@ -0,0 +1,16 @@
+{
+ "images" : [
+ {
+ "filename" : "team_introduction_logo.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "preserves-vector-representation" : true,
+ "template-rendering-intent" : "original"
+ }
+}
diff --git a/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamIntroductionLogo.imageset/team_introduction_logo.svg b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamIntroductionLogo.imageset/team_introduction_logo.svg
new file mode 100644
index 0000000..3ebaabf
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Resources/Assets.xcassets/Images/TeamIntroductionLogo.imageset/team_introduction_logo.svg
@@ -0,0 +1,7 @@
+
diff --git a/TeamIntroduce/TeamIntroduce/Sources/DesignSytstem/Color/Extension+ShapeStyle.swift b/TeamIntroduce/TeamIntroduce/Sources/DesignSytstem/Color/Extension+ShapeStyle.swift
index 5841e07..15cfe68 100644
--- a/TeamIntroduce/TeamIntroduce/Sources/DesignSytstem/Color/Extension+ShapeStyle.swift
+++ b/TeamIntroduce/TeamIntroduce/Sources/DesignSytstem/Color/Extension+ShapeStyle.swift
@@ -16,8 +16,8 @@ extension ShapeStyle where Self == Color {
// MARK: - Static Text
- static var textPrimary: Color { .init(hex: "FFFFFF") }
- static var textSecondary: Color { .init(hex: "EAEAEA") }
+ static var textPrimary: Color { .init(hex: "0A0A0A") }
+ static var textSecondary: Color { .init(hex: "717182") }
static var textSecondary100: Color { .init(hex: "525252") }
static var textInactive: Color { .init(hex: "70737C47").opacity(0.28) }
diff --git a/TeamIntroduce/TeamIntroduce/Sources/DesignSytstem/Font/PretendardFontFamily.swift b/TeamIntroduce/TeamIntroduce/Sources/DesignSytstem/Font/PretendardFontFamily.swift
index 5471098..215384a 100644
--- a/TeamIntroduce/TeamIntroduce/Sources/DesignSytstem/Font/PretendardFontFamily.swift
+++ b/TeamIntroduce/TeamIntroduce/Sources/DesignSytstem/Font/PretendardFontFamily.swift
@@ -8,35 +8,35 @@
import Foundation
enum PretendardFontFamily: CustomStringConvertible {
- case Black
- case Bold
- case ExtraBold
- case ExtraLight
- case Light
- case Medium
- case Regular
- case SemiBold
- case Thin
+ case black
+ case bold
+ case extraBold
+ case extraLight
+ case light
+ case medium
+ case regular
+ case semiBold
+ case thin
public var description: String {
switch self {
- case .Black:
+ case .black:
return "Black"
- case .Bold:
+ case .bold:
return "Bold"
- case .ExtraBold:
+ case .extraBold:
return "ExtraBold"
- case .ExtraLight:
+ case .extraLight:
return "ExtraLight"
- case .Light:
+ case .light:
return "Light"
- case .Medium:
+ case .medium:
return "Medium"
- case .Regular:
+ case .regular:
return "Regular"
- case .SemiBold:
+ case .semiBold:
return "SemiBold"
- case .Thin:
+ case .thin:
return "Thin"
}
}
diff --git a/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/IntroductionRow/IntroductionRowModel.swift b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/IntroductionRow/IntroductionRowModel.swift
new file mode 100644
index 0000000..4a6a9b5
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/IntroductionRow/IntroductionRowModel.swift
@@ -0,0 +1,62 @@
+//
+// IntroductionRowModel.swift
+// TeamIntroduce
+//
+// Created by 홍석현 on 8/11/25.
+//
+
+import Foundation
+
+struct IntroductionRowModel: Identifiable, Hashable {
+ let id = UUID()
+ let name: String
+ let role: String // subTitle 대신 role로 더 명확하게
+ let imageName: String
+ let mbti: MBTI
+ let introduction: String? // 간단한 소개글 추가
+ let isLeader: Bool
+
+ init(
+ name: String,
+ role: String,
+ imageName: String,
+ mbti: MBTI,
+ introduction: String? = nil,
+ isLeader: Bool = false
+ ) {
+ self.name = name
+ self.role = role
+ self.imageName = imageName
+ self.mbti = mbti
+ self.introduction = introduction
+ self.isLeader = isLeader
+ }
+}
+
+// MARK: - Mock Data
+extension IntroductionRowModel {
+ static let mockData: [IntroductionRowModel] = [
+ IntroductionRowModel(
+ name: "김민희",
+ role: "iOS Developer",
+ imageName: "profile_kim",
+ mbti: .estp,
+ introduction: "서버 아키텍처에 관심이 많습니다",
+ isLeader: true
+ ),
+ IntroductionRowModel(
+ name: "서원지",
+ role: "iOS Developer",
+ imageName: "profile_lee",
+ mbti: .intp,
+ introduction: "사용자 경험을 최우선으로 생각합니다"
+ ),
+ IntroductionRowModel(
+ name: "홍석현",
+ role: "iOS Developer",
+ imageName: "profile_hong",
+ mbti: .enfj,
+ introduction: "SwiftUI와 iOS 개발을 좋아합니다"
+ )
+ ]
+}
diff --git a/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/IntroductionRow/IntroductionRowView.swift b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/IntroductionRow/IntroductionRowView.swift
new file mode 100644
index 0000000..80652e8
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/IntroductionRow/IntroductionRowView.swift
@@ -0,0 +1,55 @@
+//
+// IntroductionRowView.swift
+// TeamIntroduce
+//
+// Created by 홍석현 on 8/11/25.
+//
+
+import SwiftUI
+
+struct IntroductionRowView: View {
+ private let model: IntroductionRowModel
+
+ init(model: IntroductionRowModel) {
+ self.model = model
+ }
+
+ var body: some View {
+ HStack {
+ Circle()
+ .frame(width: 42, height: 42)
+ VStack(alignment: .leading, spacing: 4) {
+ HStack(spacing: 4) {
+ Text(model.name)
+ .pretendardFont(family: .semiBold, size: 14)
+ .foregroundStyle(.textPrimary)
+
+ if model.isLeader {
+ Image(systemName: "crown.fill")
+ .foregroundStyle(Color.yellow)
+ .font(.system(size: 12))
+ }
+ }
+
+ Text(model.role)
+ .pretendardFont(family: .regular, size: 12)
+ .foregroundStyle(.textSecondary)
+
+ MBTILabel(mbti: model.mbti)
+ }
+
+ Spacer()
+
+ Image("ArrowRight")
+ .foregroundStyle(Color(hex: "717182"))
+ }
+ .padding(16)
+ .background(Color.staticWhite)
+ .clipShape(RoundedRectangle(cornerRadius: 12))
+ .shadow(radius: 1)
+ }
+}
+
+#Preview {
+ IntroductionRowView(model: IntroductionRowModel.mockData[0])
+}
diff --git a/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/MBTILabel.swift b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/MBTILabel.swift
new file mode 100644
index 0000000..65c1055
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/MBTILabel.swift
@@ -0,0 +1,70 @@
+//
+// MBTILabel.swift
+// TeamIntroduce
+//
+// Created by 홍석현 on 8/11/25.
+//
+
+import SwiftUI
+
+public enum MBTI: String, CaseIterable {
+ case enfp = "ENFP"
+ case estp = "ESTP"
+ case infj = "INFJ"
+ case intj = "INTJ"
+ case isfj = "ISFJ"
+ case enfj = "ENFJ"
+ case infp = "INFP"
+ case intp = "INTP"
+ case isfp = "ISFP"
+}
+
+struct MBTILabel: View {
+
+ private let mbti: MBTI
+
+ private var backgroundColor: Color {
+ switch mbti {
+ case .enfp: return Color(hex: "FF6B6B")
+ case .estp: return Color(hex: "E17055")
+ case .infj: return Color(hex: "4ECDC4")
+ case .intj: return Color(hex: "6C5CE7")
+ case .isfj: return Color(hex: "A8E6CF")
+ case .enfj: return Color(hex: "FFD93D")
+ case .infp: return Color(hex: "DDA0DD")
+ case .intp: return Color(hex: "74B9FF")
+ case .isfp: return Color(hex: "FDCB6E")
+ }
+ }
+
+ private var textColor: Color {
+ switch mbti {
+ case .enfp, .estp, .infj, .intj, .intp:
+ return .white
+ case .isfj, .enfj, .infp, .isfp:
+ return Color(hex: "2D3436")
+ }
+ }
+
+ init(mbti: MBTI) {
+ self.mbti = mbti
+ }
+
+ var body: some View {
+ Text(mbti.rawValue)
+ .pretendardFont(family: .regular, size: 10)
+ .foregroundStyle(textColor)
+ .padding(.horizontal, 7)
+ .padding(.vertical, 5)
+ .background(backgroundColor)
+ .clipShape(RoundedRectangle(cornerRadius: 8))
+ }
+}
+
+#Preview {
+ VStack {
+ MBTILabel(mbti: .enfj)
+ MBTILabel(mbti: .estp)
+ MBTILabel(mbti: .intp)
+ }
+}
diff --git a/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/MissionView.swift b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/MissionView.swift
new file mode 100644
index 0000000..81bbc47
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/MissionView.swift
@@ -0,0 +1,34 @@
+//
+// MissionView.swift
+// TeamIntroduce
+//
+// Created by 홍석현 on 8/11/25.
+//
+
+import SwiftUI
+
+struct MissionView: View {
+ var body: some View {
+ VStack(alignment: .center, spacing: 12) {
+ Image("MissionLogo")
+ .renderingMode(.original)
+
+ Text("우리의 미션")
+ .pretendardFont(family: .bold, size: 14)
+ .foregroundStyle(.textPrimary)
+
+ Text("혁신적인 기술로 사용자의 삶을 더 편리하고 풍요롭게 만드는 것")
+ .pretendardFont(family: .regular, size: 12)
+ .foregroundStyle(.textSecondary)
+ }
+ .frame(maxWidth: .infinity)
+ .padding(16)
+ .background(Color(hex: "E9EBEF"))
+ .clipShape(RoundedRectangle(cornerRadius: 12))
+ .shadow(radius: 1, x: 2, y: 2)
+ }
+}
+
+#Preview {
+ MissionView()
+}
diff --git a/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/SkeletonRowView.swift b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/SkeletonRowView.swift
new file mode 100644
index 0000000..efa7ce5
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/SkeletonRowView.swift
@@ -0,0 +1,58 @@
+//
+// SkeletonRowView.swift
+// TeamIntroduce
+//
+// Created by 홍석현 on 8/11/25.
+//
+
+import SwiftUI
+
+struct SkeletonRowView: View {
+ @State private var isAnimating = false
+
+ var body: some View {
+ HStack {
+ Circle()
+ .frame(width: 42, height: 42)
+ .foregroundColor(.gray.opacity(0.3))
+
+ VStack(alignment: .leading, spacing: 4) {
+ RoundedRectangle(cornerRadius: 4)
+ .frame(width: 80, height: 16)
+ .foregroundColor(.gray.opacity(0.3))
+
+ RoundedRectangle(cornerRadius: 4)
+ .frame(width: 120, height: 12)
+ .foregroundColor(.gray.opacity(0.2))
+
+ RoundedRectangle(cornerRadius: 8)
+ .frame(width: 50, height: 20)
+ .foregroundColor(.gray.opacity(0.2))
+ }
+
+ Spacer()
+
+ RoundedRectangle(cornerRadius: 4)
+ .frame(width: 16, height: 16)
+ .foregroundColor(.gray.opacity(0.2))
+ }
+ .padding(16)
+ .background(Color.staticWhite)
+ .clipShape(RoundedRectangle(cornerRadius: 12))
+ .shadow(radius: 1)
+ .opacity(isAnimating ? 0.5 : 1.0)
+ .animation(.easeInOut(duration: 1.0).repeatForever(autoreverses: true), value: isAnimating)
+ .onAppear {
+ isAnimating = true
+ }
+ }
+}
+
+#Preview {
+ VStack {
+ SkeletonRowView()
+ SkeletonRowView()
+ SkeletonRowView()
+ }
+ .padding()
+}
diff --git a/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/TeamExploreRowView.swift b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/TeamExploreRowView.swift
new file mode 100644
index 0000000..fa7649c
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/Components/TeamExploreRowView.swift
@@ -0,0 +1,92 @@
+//
+// TeamExploreRowView.swift
+// TeamIntroduce
+//
+// Created by 홍석현 on 8/11/25.
+//
+
+import SwiftUI
+
+enum TeamExploreItem: CaseIterable, Identifiable {
+ case introduction
+ case agreement
+ case blog
+
+ var id: Self { self }
+
+
+ var title: String {
+ switch self {
+ case .introduction:
+ return "팀 소개"
+ case .agreement:
+ return "팀 약속"
+ case .blog:
+ return "팀 블로그"
+ }
+ }
+
+ var subtitle: String {
+ switch self {
+ case .introduction:
+ return "우리 팀의 특징과 목표"
+ case .agreement:
+ return "함께 지켜나갈 소중한 약속들"
+ case .blog:
+ return "팀원들의 블로그 모음"
+ }
+ }
+
+ var imageName: String {
+ switch self {
+ case .introduction:
+ return "TeamIntroductionLogo"
+ case .agreement:
+ return "TeamAgreementLogo"
+ case .blog:
+ return "TeamBlogLogo"
+ }
+ }
+}
+
+struct TeamExploreRowView: View {
+
+ private let item: TeamExploreItem
+
+ init(item: TeamExploreItem) {
+ self.item = item
+ }
+
+ var body: some View {
+ HStack {
+ Image(item.imageName)
+ .frame(width: 42, height: 42)
+ VStack(alignment: .leading, spacing: 4) {
+ Text(item.title)
+ .pretendardFont(family: .semiBold, size: 14)
+ .foregroundStyle(.textPrimary)
+
+ Text(item.subtitle)
+ .pretendardFont(family: .regular, size: 12)
+ .foregroundStyle(.textSecondary)
+ }
+
+ Spacer()
+
+ Image("ArrowRight")
+ .foregroundStyle(Color(hex: "717182"))
+ }
+ .padding(16)
+ .background(Color.staticWhite)
+ .clipShape(RoundedRectangle(cornerRadius: 12))
+ .shadow(radius: 1)
+ }
+}
+
+#Preview {
+ VStack {
+ TeamExploreRowView(item: .introduction)
+ TeamExploreRowView(item: .agreement)
+ TeamExploreRowView(item: .blog)
+ }
+}
diff --git a/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/IntroductionMainView.swift b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/IntroductionMainView.swift
new file mode 100644
index 0000000..af42da3
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/IntroductionMainView.swift
@@ -0,0 +1,61 @@
+//
+// IntroductionMainView.swift
+// TeamIntroduce
+//
+// Created by 홍석현 on 8/11/25.
+//
+
+import SwiftUI
+
+struct IntroductionMainView: View {
+ @ObservedObject var viewModel: IntroductionViewModel
+
+ init(viewModel: IntroductionViewModel) {
+ self.viewModel = viewModel
+ }
+
+ var body: some View {
+ ScrollView {
+ VStack(spacing: 16) {
+ MissionView()
+
+ VStack {
+ Text("팀원 소개")
+ .pretendardFont(family: .bold, size: 14)
+ .foregroundStyle(.textPrimary)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ .padding(.horizontal, 8)
+ if viewModel.isLoading {
+ ForEach(0..<3, id: \.self) { _ in
+ SkeletonRowView()
+ }
+ } else {
+ ForEach(viewModel.introductions) { model in
+ IntroductionRowView(model: model)
+ }
+ }
+ }
+
+ VStack {
+ Text("더 알아보기")
+ .pretendardFont(family: .bold, size: 14)
+ .foregroundStyle(.textPrimary)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ .padding(.horizontal, 8)
+
+ ForEach(TeamExploreItem.allCases) { item in
+ TeamExploreRowView(item: item)
+ }
+ }
+ }
+ .padding(.horizontal, 16)
+ .onAppear {
+ viewModel.onAppear()
+ }
+ }
+ }
+}
+
+#Preview {
+ IntroductionMainView(viewModel: IntroductionViewModel())
+}
diff --git a/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/IntroductionViewModel.swift b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/IntroductionViewModel.swift
new file mode 100644
index 0000000..4fbf61a
--- /dev/null
+++ b/TeamIntroduce/TeamIntroduce/Sources/Presnetaion/IntroduceMain/View/IntroductionViewModel.swift
@@ -0,0 +1,53 @@
+//
+// IntroductionViewModel.swift
+// TeamIntroduce
+//
+// Created by 홍석현 on 8/11/25.
+//
+
+import Foundation
+import SwiftUI
+
+@MainActor
+final class IntroductionViewModel: ObservableObject {
+
+ // MARK: - Published Properties
+ @Published private(set) var introductions: [IntroductionRowModel] = []
+ @Published private(set) var isLoading = false
+
+ // MARK: - Public Methods
+
+ /// onAppear 시 호출되는 데이터 페치 메서드
+ func onAppear() {
+ Task {
+ await fetchIntroductions()
+ }
+ }
+
+ /// 데이터를 새로고침하는 메서드
+ func refresh() {
+ Task {
+ await fetchIntroductions()
+ }
+ }
+
+ // MARK: - Private Methods
+
+ /// 팀원 소개 데이터를 가져오는 메서드
+ private func fetchIntroductions() async {
+ isLoading = true
+
+ do {
+ // 실제 API 호출 시뮬레이션 (2초 딜레이)
+ try await Task.sleep(nanoseconds: 2_000_000_000)
+
+ // Mock 데이터 로드
+ introductions = IntroductionRowModel.mockData
+
+ } catch {
+ introductions = []
+ }
+
+ isLoading = false
+ }
+}