๋ฌธ์ ์ ์ : ์ ์ ๋ฆฌ์คํธ num_list๊ฐ ์ฃผ์ด์ง๋๋ค. ๊ฐ์ฅ ์ฒซ ๋ฒ์งธ ์์๋ฅผ 1๋ฒ ์์๋ผ๊ณ ํ ๋, ํ์ ๋ฒ์งธ ์์๋ค์ ํฉ๊ณผ ์ง์ ๋ฒ์งธ ์์๋ค์ ํฉ ์ค ํฐ ๊ฐ์ return ํ๋๋ก solution ํจ์๋ฅผ ์์ฑํด์ฃผ์ธ์. ๋ ๊ฐ์ด ๊ฐ์ ๊ฒฝ์ฐ ๊ทธ ๊ฐ์ returnํฉ๋๋ค.
์ ํ์ฌํญ
5 โค num_list์ ๊ธธ์ด โค 50
-9 โค num_list์ ์์ โค 9
์
์ถ๋ ฅ ์์ ๋ฐ ์ค๋ช

๋์ ํ์ด
function solution(num_list) {
let evenNumber = 0;
let oddNumber = 0;
for(let i = 0; i < num_list.length; i++) {
if((i + 1) % 2 === 0) {
evenNumber += num_list[i]
} else {
oddNumber += num_list[i]
};
}
return evenNumber > oddNumber ? evenNumber : oddNumber;
}
๋ค๋ฅธ ์ฌ๋์ ํ์ด
function solution(num_list) {
let even = 0;
let odd = 0
num_list.map((v, idx) => {
!(idx % 2) ? even += v : odd += v;
})
return odd > even ? odd : even;
}
map ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ํ์ดํ ์๋ ์๊ตฌ๋ ํ๊ณ ๋ฐฐ์๊ฐ๋ค. ๊ทธ๋ฌ๊ณ ๋ณด๋ ๋๋ ์๊ณ ๋ฆฌ์ฆ์ ํ๋ฉด ๊ฑฐ์ง for๋ฌธ์ ๋ง์ด ์ ์ฉํ๋ ๊ฑฐ ๊ฐ์๋ฐ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ํธ๋ ๋ฐฉ๋ฒ๋ ์ฐ์ต์ ์ข ํด์ผ๊ฒ ๋ค๊ณ ๋๊ผ๋ค.
ํค๋ ๋ถ๋ถ์ ๋ํ
์ผ์ ์ธ ๊ฒฐํจ์ด ์์๋๋ฐ, ํด๋น ์ญํ ์ ๋งก์ ํ์ ๋ถ์ด ๋ค๋ฅธ ๊ธฐ๋ฅ์ ๊ตฌํํ์๋๋ผ ๋์ค์ ํ์ ๋ค ํ์
จ์๋๋ฐ
๊ทธ๋ ๊ฒ ์ด๋ ค์ด ๋ถ๋ถ๋ ์๋๊ณ ํด์ ๋์ ์์ ์ ์งํํ๋ค.
๋ชจ๋ ๋ผ์ฐํฐ๋ค์ ๊ฐ์ธ์ฃผ๋ HomeHeader ๋ถ๋ถ์ธ๋ฐ props๋ก signIn, signOut์ ๋ฐ์์์ ํ์ฌ ๋ก๊ทธ์ธ์ด ๋ผ์๋ ์ํ๋ฉด ํค๋ ๋ถ๋ถ์ ๋ฒํผ์ ๋ก๊ทธ์์ ๋ฒํผ์ผ๋ก, ๋ก๊ทธ์์ ์ํ๋ฉด ๋ก๊ทธ์ธ ๋ฒํผ์ผ๋ก ๋ณด์ด๊ฒ๋ ํ๋ค.

๊ทผ๋ฐ ๋ฌธ์ ๊ฐ ์์๋๋ฐ, ์ด ํค๋ ๋ถ๋ถ์ด ํํ์ด์ง์์ ๋ก๊ทธ์ธ์ ์ํ์ ๋ฐ๋ผ ์ ๋ํ๋๋๋ฐ ๊ธ์ฐ๊ธฐ ๋ฒํผ์ ๋๋ฌ์ commitdetail๋ก ํ์ด์ง๋ฅผ ์ฎ๊ฒจ๊ฐ๋ฉด ํค๋์์ ๋ก๊ทธ์์ ์ํ์ผ ๋๋ง ๋ณด์ฌ์ฃผ๋ ๋ก๊ทธ์ธ ๋ฒํผ์ ๋ณด์ฌ์ฃผ๋๋ฐ ์ฌ์ค์ signIn ์ํ๋ true์ด๋ฏ๋ก ํค๋ ๋ถ๋ถ์ ๋ฌธ์ ์๋ค.
์ด ๋ฌธ์ ๋ HomeHeader ์ปดํฌ๋ํธ์ ์ค๋ณต์ด ๋ฌธ์ ์๋ค.
HomeFeed, HomeHeader ์ปดํฌ๋ํธ๋ฅผ ๊ตฌ์ฑํ๊ณ ์๋ Home.jsx์์๋ HomeHeader๋ฅผ ์ฐ๊ณ ์์๊ธฐ์ Home.jsx์์ HomeHeader๋ฅผ ์์ ์ฃผ๋๊น ๋ฐ๋ก ์ ์ ์๋์ ํ๋ค.
์ผ๋จ supabase์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ด๋ฏธ ๋ฑ๋ก๋ ์ด๋ฉ์ผ์ ์ค๋ณต์ผ๋ก ํ์๊ฐ์ ์ด ์๋๊ฒ๋ ๋ผ์๋๋ฐ, ๊ธฐ๋ณธ ํ์ฌ๋ ๊ธฐ๋ฅ ์ธ์ ํ์๊ฐ์ ๋ฒํผ์ ๋๋ ์ ์์ ์ด๋ฉ์ผ ์ธํ์ฐฝ ์๋์ ์ค๋ณต ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ๋์์ฃผ๊ณ ์ถ์๋ค.
const SignUpPage = () => {
const navigate = useNavigate();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [mismatchPassword, setMismatchPassword] = useState(false);
const [confirmPassword, setConfirmPassword] = useState('');
const [nickname, setNickname] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const [emailError, setEmailError] = useState(false);
const [nicknameError, setNicknameError] = useState(false);
const signUpWithEmail = async (e) => {
e.preventDefault();
setIsSubmitting(true);
setEmailError(false);
setNicknameError(false);
setMismatchPassword(false);
if(password !== confirmPassword) {
setMismatchPassword(true);
setIsSubmitting(false);
return;
}
try {
const { data: existEmail, error: existEmailError } = await supabase
.from('users')
.select('email')
.eq('email', email)
.single();
if (existEmailError) {
throw existEmailError;
}
if (existEmail) {
setEmailError(true);
setIsSubmitting(false);
return;
}
const {data: existNickname, error: existNicknameError } = await supabase
.from('users')
.select('nickname')
.eq('nickname', nickname)
.single();
if(existNicknameError) {
throw existNicknameError;
}
if(existNickname) {
setNicknameError(true);
setIsSubmitting(false);
return;
}
const { error } = await supabase.auth.signUp({
email,
password,
options: {
data: {
nickname
}
}
});
if (error) {
throw error;
}
const { error: insertError } = await supabase
.from('users')
.insert({nickname, email})
if(insertError) {
throw insertError;
}
navigate('/login');
} catch (error) {
console.error('ํ์๊ฐ์
์ค๋ฅ ๋ฐ์', error);
} finally {
setIsSubmitting(false);
}
};
const handleSignUp = async () => {
try {
setIsSubmitting(true);
const { error } = await supabase.auth.signInWithOAuth({
provider: 'github'
});
if (error) {
throw error;
}
navigate('/');
} catch (error) {
console.error('GitHub ๋ก๊ทธ์ธ ์ค ์ค๋ฅ ๋ฐ์:', error.message);
} finally {
setIsSubmitting(false);
}
};
return (
<Container>
<Title>ํ์๊ฐ์
ํ์ด์ง</Title>
<Form onSubmit={signUpWithEmail}>
<Input
type="email"
name="email"
placeholder="์ด๋ฉ์ผ"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
{emailError && <DoubleCheck>์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ์ด๋ฉ์ผ์
๋๋ค ๋ค๋ฅธ ์ด๋ฉ์ผ์ ์
๋ ฅํด์ฃผ์ธ์.</DoubleCheck>}
<Input
type="password"
name="password"
placeholder="๋น๋ฐ๋ฒํธ"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<Input
type="password"
name="confirmPassword"
placeholder="๋น๋ฐ๋ฒํธ ํ์ธ"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
/>
{mismatchPassword && <DoubleCheck>๋น๋ฐ๋ฒํธ๊ฐ ์ผ์นํ์ง ์์ต๋๋ค ๋ค์ ์
๋ ฅํด์ฃผ์ธ์.</DoubleCheck>}
<Input
type="text"
name="nickname"
placeholder="๋๋ค์"
value={nickname}
onChange={(e) => setNickname(e.target.value)}
required
/>
{nicknameError && <DoubleCheck>์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ๋๋ค์์
๋๋ค ๋ค๋ฅธ ๋๋ค์์ ์ฌ์ฉํด์ฃผ์ธ์.</DoubleCheck>}
<Button type="submit" disabled={isSubmitting}>
{isSubmitting ? '๊ฐ์
์ค...' : 'ํ์๊ฐ์
'}
</Button>
</Form>
<Button onClick={handleSignUp} disabled={isSubmitting}>
{isSubmitting ? '๋ก๋ฉ ์ค...' : 'GitHub๋ก ํ์๊ฐ์
'}
</Button>
<Button onClick={() => navigate('/login')}>๋ก๊ทธ์ธ</Button>
</Container>
);
};
export default SignUpPage;
์ด๋ ๊ฒ ์ฝ๋๋ฅผ ์์ฑํ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. ๊ทธ๋์ ๋ฌธ์ ์ ๊ทผ์์ง๋ฅผ ์ฐพ์๋ณด๋ single() ๋ฉ์๋์ ๋ฌธ์ ์ธ ๊ฑฐ ๊ฐ์๋ค.
single() ๋ฉ์๋๋ ์ ํํ ํ๋์ ๋ฐ์ดํฐ ํ์ ๋ฐ๊ณ ์ถ์ ๋ ์ฌ์ฉ๋๋ค. ์ด ๋ฉ์๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํ๋์ ํ๋ง ๋ฐํ๋์ด์ผ ํ๋ฉฐ, ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ์ค๋ฅ๋ฅผ ๋ฐ์์ํจ๋ค.
์๊ฐํด ๋ณด๋ฉด ์ค๋ฅ๊ฐ ์๊ณ ๊ฒฐ๊ณผ๊ฐ์ด ์กด์ฌํ์ง ์๋๋ค๋ฉด ๊ทธ ์ด๋ฉ์ผ์ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค๊ณ ์ฒ๋ฆฌ๋ฅผ ํ๊ณ ์ถ์ ๊ฒ ๋ด ์๋์ธ๋ฐ
single() ๋ฉ์๋์ ํน์ฑ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์กด์ฌํ์ง ์์ผ๋ฉด ์ค๋ฅ๋ฅผ ๋ด๋ณด๋ด์ ๋ฌธ์ ๊ฐ ๋ ๊ฒ์ด๋ค.
๋ํ ์๋ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์ด๋ฏธ signUp์ ํตํด ๋๋ค์์ ๋ฐ๊ณ ์๋๋ฐ, ์๋์ insert๋ฅผ ํตํด ๋๋ค์์ ๋ ๋ฃ์ด์ฃผ๊ณ ์๊ธฐ์ ๋ก์ง์ ๋ฌธ์ ๊ฐ ์๋ ๊ฑฐ ๊ฐ์๋ค.
const { error } = await supabase.auth.signUp({
email,
password,
options: {
data: {
nickname
}
}
});
if (error) {
throw error;
}
const { error: insertError } = await supabase
.from('users')
.insert({nickname, email})
if(insertError) {
throw insertError;
}
ํด๋น ๋ฌธ์ ๋ฅผ ๊ณ ์น๊ธฐ ์ํด์ ์ค๋ณต๋ ๋ถ๋ถ์ ์ ๊ฑฐํ๊ณ , ์ธ๋ชจ์๋ ๋ณ์๋ช ์ ์ ๊ฑฐํด์คฌ๋ค.
const SignUpPage = () => {
const navigate = useNavigate();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [mismatchPassword, setMismatchPassword] = useState(false);
const [confirmPassword, setConfirmPassword] = useState('');
const [nickname, setNickname] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const [emailError, setEmailError] = useState(false);
const [nicknameError, setNicknameError] = useState(false);
const signUpWithEmail = async (e) => {
e.preventDefault();
setIsSubmitting(true);
setEmailError(false);
setNicknameError(false);
setMismatchPassword(false);
if(password !== confirmPassword) {
setMismatchPassword(true);
setIsSubmitting(false);
return;
}
try {
const { data: existEmail } = await supabase
.from('users')
.select('email')
.eq('email', email)
.single();
if (existEmail) {
setEmailError(true);
setIsSubmitting(false);
return;
}
const {data: existNickname } = await supabase
.from('users')
.select('nickname')
.eq('nickname', nickname)
.single();
if(existNickname) {
setNicknameError(true);
setIsSubmitting(false);
return;
}
const { error } = await supabase.auth.signUp({
email,
password,
});
if (error) {
throw error;
}
const { error: insertError } = await supabase
.from('users')
.insert({nickname, email})
if(insertError) {
throw insertError;
}
navigate('/');
alert(`ํ์๊ฐ์
์ด ์๋ฃ๋์์ต๋๋ค. ${nickname}๋ ํ์ํฉ๋๋ค!`);
} catch (error) {
console.error('ํ์๊ฐ์
์ค๋ฅ ๋ฐ์', error.message);
} finally {
setIsSubmitting(false);
}
};
const handleSignUp = async () => {
try {
setIsSubmitting(true);
const { error } = await supabase.auth.signInWithOAuth({
provider: 'github'
});
if (error) {
throw error;
}
navigate('/');
} catch (error) {
console.error('GitHub ๋ก๊ทธ์ธ ์ค ์ค๋ฅ ๋ฐ์:', error.message);
} finally {
setIsSubmitting(false);
}
};
return (
<Container>
<Title>ํ์๊ฐ์
ํ์ด์ง</Title>
<Form onSubmit={signUpWithEmail}>
<Input
type="email"
name="email"
placeholder="์ด๋ฉ์ผ"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
{emailError && <DoubleCheck>์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ์ด๋ฉ์ผ์
๋๋ค ๋ค๋ฅธ ์ด๋ฉ์ผ์ ์
๋ ฅํด์ฃผ์ธ์.</DoubleCheck>}
<Input
type="password"
name="password"
placeholder="๋น๋ฐ๋ฒํธ"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<Input
type="password"
name="confirmPassword"
placeholder="๋น๋ฐ๋ฒํธ ํ์ธ"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
/>
{mismatchPassword && <DoubleCheck>๋น๋ฐ๋ฒํธ๊ฐ ์ผ์นํ์ง ์์ต๋๋ค ๋ค์ ์
๋ ฅํด์ฃผ์ธ์.</DoubleCheck>}
<Input
type="text"
name="nickname"
placeholder="๋๋ค์"
value={nickname}
onChange={(e) => setNickname(e.target.value)}
required
/>
{nicknameError && <DoubleCheck>์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ๋๋ค์์
๋๋ค ๋ค๋ฅธ ๋๋ค์์ ์ฌ์ฉํด์ฃผ์ธ์.</DoubleCheck>}
<Button type="submit" disabled={isSubmitting}>
{isSubmitting ? '๊ฐ์
์ค...' : 'ํ์๊ฐ์
'}
</Button>
</Form>
<Button onClick={handleSignUp} disabled={isSubmitting}>
{isSubmitting ? '๋ก๋ฉ ์ค...' : 'GitHub๋ก ํ์๊ฐ์
'}
</Button>
<Button onClick={() => navigate('/login')}>๋ก๊ทธ์ธ</Button>
</Container>
);
};
export default SignUpPage;
์ค๋ณต ํ์ธ ๋ถ๋ถ ์ค๋ฅ๋ฅผ ์ฐพ๊ณ ๊ณ ์น๋๋ผ ๋จธ๋ฆฌ๊ฐ ์ค์๊ฐ์ผ๋ก ๋น ์ง๋ ๊ฒ ๋๊ปด์ง๋ ๊ฑฐ ๊ฐ๋ค.. ์ง๋์ง๋
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ 1๊ฐ์ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ํ ์คํธ๋ฅผ ํด๋ด

์ค๋ณต๋ ์ด๋ฉ์ผ์ ๊ฒฝ๊ณ ๋ฌธ๊ตฌ์ ๋ํด์ ์ ์ถ๋ ฅ์ด ๋๋๋ฐ ์ด๋ฏธ khj5 ๋ผ๋ ๋๋ค์์ด ์์์๋ ๋๋ค์์ ๋ํ ์ค๋ณต ๊ฒฝ๊ณ ๋ฌธ๊ตฌ๋ ์ถ๋ ฅ์ด ์ ๋๋ ์ํฉ์ด ์ผ์ด๋ฌ๋ค.
๋ฌธ์ ๋ฅผ ์ผ์ผํค๋ ์ฝ๋๋ฅผ ์ดํด๋ดค๋ค.
const { data: existEmail } = await supabase
.from('users')
.select('email')
.eq('email', email)
.single();
if (existEmail) {
setEmailError(true);
setIsSubmitting(false);
return;
}
const {data: existNickname } = await supabase
.from('users')
.select('nickname')
.eq('nickname', nickname)
.single();
if(existNickname) {
setNicknameError(true);
setIsSubmitting(false);
return;
}
ํด๋น ์ฝ๋๋ฅผ ๋ณด๋ฉด ์ด๋ฏธ ์กด์ฌํ๋ ์ด๋ฉ์ผ์ด ์์ ๊ฒฝ์ฐ์ ์ด๋ฉ์ผ ์ค๋ณต ๊ฒฝ๊ณ ๋ฌธ๊ตฌ๋ฅผ ์ถ๋ ฅํจ๊ณผ ๋์์ return์ ํด๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ ๊ทธ ์๋์ ์๋ ๋๋ค์ ์ค๋ณต ๋ฌธ๊ตฌ ์ถ๋ ฅ ์ฝ๋๊ฐ ์๋์ด ์ ํ๋ ๊ฑธ์๋ ์๊ฒ ๋ค ์ถ์ด์ ์ฝ๋์ ๋ก์ง์ ์ด์ง ์์ ํ๋ค.
const { data: existEmail } = await supabase
.from('users')
.select('email')
.eq('email', email)
.single();
const {data: existNickname } = await supabase
.from('users')
.select('nickname')
.eq('nickname', nickname)
.single();
if(existEmail || existNickname) {
if(existEmail) {
setEmailError(true);
}
if(existNickname) {
setNicknameError(true);
}
setIsSubmitting(false);
return;
}
๋ ผ๋ฆฌ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด์ ์ค๋ณต ํ์ธ ์ ์ฐจ๋ฅผ ๋์์ ์ํํ ์ ์๋๋ก ์์ ์ ์งํํ๋ค.
์ฝ๋๋ฅผ ์์ ํ๊ณ ๋ ํ ์๋ ๊ฒฐ๊ณผ๋ฌผ์ ์ดํด๋ณด๊ฒ ์
์ด๋ฉ์ผ๊ณผ ๋๋ค์์ ์ค๋ณต ํ์ธ ๋ฌธ๊ตฌ, ๋น๋ฐ๋ฒํธ ๋ถ์ผ์น ๋ฌธ๊ตฌ๊น์ง ๋ค ๋จ๋ ๊ฑธ ๋ณผ ์ ์๋ค!!

์ด๋ฉ์ผ๋ง ์ค๋ณต๋์ง ์๊ฒ ๋ฐ๊ฟ๋ดค๋๋ฐ ๊ฒฝ๊ณ ๋ฌธ๊ตฌ ์ถ๋ ฅ์ด ์ด์ ์์ผ ์ฌ๋ฐ๋ฅด๊ฒ ์ ์๋๋๋ ๊ฑฐ ๊ฐ๋ค.

๋ชจ๋ ๋ค ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ ฅํ๊ณ ํ์๊ฐ์ ์ ๋๋ฅด๋ฉด ์ด๋ ๊ฒ ์ฑ๊ณต์ ์ผ๋ก ํ์๊ฐ์ ์ฑ๊ณต ๋ฌธ๊ตฌ๊ฐ ๋จ๋ ๊ฒ๋ ๋ณผ ์๊ฐ ์๋ค.
supabase์ ๋ํ ์ดํด๋๊ฐ ์กฐ๊ธ๋ง ๋ ๊น์๋ค๋ฉด ๋ํ ์ผ์ ์ธ ๋ถ๋ถ์ ๋ ์ ์ด๋ฆด ์ ์์์ ํ ๋ฐ ํ๋ ์์ฌ์์ด ์๋ค.
์ค๋ redux๋ก ์ ์ญ ์ํ ๊ด๋ฆฌ๊น์ง ๋๋ด๋ณด๋ ค ํ๋๋ฐ redux๊ฐ ๋๋ฌด ๊ณจ์น์ํ๋ค?